Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
ee0a991
Add task ids
dmitrii-artuhov Dec 11, 2024
71a0719
Add round replay
dmitrii-artuhov Dec 11, 2024
2dfa7b7
Implement dumb minimization
dmitrii-artuhov Dec 11, 2024
899487e
Cleanup code
dmitrii-artuhov Dec 11, 2024
d7e7e86
Add fix to dumb minimization
dmitrii-artuhov Dec 17, 2024
e735ae2
Remove useless hashmap
dmitrii-artuhov Dec 17, 2024
aa84d7a
Add nonlinearized round minimization with threads rescheduling (for r…
dmitrii-artuhov Dec 18, 2024
c96f4be
Add comment
dmitrii-artuhov Dec 18, 2024
abfe8ae
Extract task removal callbacks to classes
dmitrii-artuhov Jan 2, 2025
9b2552d
Add common base for pct and pick strategies
dmitrii-artuhov Jan 2, 2025
6a3e8aa
Add NextSchedule method for pct
dmitrii-artuhov Jan 4, 2025
7231690
Extract minimizors to separate classes
dmitrii-artuhov Jan 4, 2025
af6c7b3
Rename minimizors
dmitrii-artuhov Jan 4, 2025
33c99bc
Add 'pragma once' to minimization.h
dmitrii-artuhov Jan 8, 2025
27ccfce
Fix compilation
dmitrii-artuhov Jan 14, 2025
456dc7c
Enhance smart minimization
dmitrii-artuhov Jan 22, 2025
82996c4
Remove some comments
dmitrii-artuhov Feb 5, 2025
4a2c263
Refactor some code
dmitrii-artuhov Feb 8, 2025
b497fc8
Minor code-style fixes
dmitrii-artuhov Feb 8, 2025
10f4cbb
Add new printing to scheduler after each minimization step
dmitrii-artuhov Feb 9, 2025
1b1dd07
Add nonlinearized tests for minimization (#4)
dmitrii-artuhov Feb 26, 2025
5af654a
Fix UB with global variables intialization order from the macros expa…
dmitrii-artuhov Feb 26, 2025
3eeb9a0
Run clang-format script
dmitrii-artuhov Feb 27, 2025
4cb805e
Remove build-cmake folder from .gitignore
dmitrii-artuhov Feb 27, 2025
f315844
Remove scheduler.cpp file
dmitrii-artuhov Feb 27, 2025
cb8afaf
Run new nonlinear data structures on CI with minimization
dmitrii-artuhov Feb 27, 2025
a6ce6da
Fix CI
dmitrii-artuhov Feb 27, 2025
5ffaeff
Update CI
dmitrii-artuhov Feb 27, 2025
cb696e6
Update CI
dmitrii-artuhov Feb 27, 2025
847581f
Fix hanging bugs with simple mutex
dmitrii-artuhov Feb 27, 2025
62e610d
Bug fixes
dmitrii-artuhov Feb 27, 2025
6e373a1
Modify TerminateTasks, so it does not finish blocked tasks
dmitrii-artuhov Feb 27, 2025
935f95f
Fix tasks termination order (first terminate tasks, then reset the st…
dmitrii-artuhov Mar 26, 2025
eca5b6f
Add some minor fixes
dmitrii-artuhov Mar 26, 2025
ef59d68
Change how schedulers terminate their tasks
dmitrii-artuhov Mar 27, 2025
c103a8d
Add clangpass sources
dmitrii-artuhov Mar 19, 2025
2879d78
Setup clangpass in cmake
dmitrii-artuhov Mar 19, 2025
cc7987f
Setup clangpass in cmake
dmitrii-artuhov Mar 19, 2025
0b466e9
Add some comments
dmitrii-artuhov Mar 19, 2025
775223c
Add comments
dmitrii-artuhov Mar 19, 2025
4540df9
Fix clangpass shared lib compilation
dmitrii-artuhov Mar 27, 2025
988d9ba
Mirrow the std::atomic<T> public API
dmitrii-artuhov Mar 27, 2025
6370af2
Comment out ambigious overload for T*. Add todo for fixing that
dmitrii-artuhov Mar 27, 2025
f2b8044
Comment out ambigious overload for T*. Add todo for fixing that
dmitrii-artuhov Mar 27, 2025
70ffe4d
Fix github actions (take from master)
dmitrii-artuhov Apr 1, 2025
16ee54c
Fix github actions
dmitrii-artuhov Apr 1, 2025
fc03f76
Take CI & Dockerfile from PR #18
dmitrii-artuhov Apr 1, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/clang-format.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ jobs:
- name: Run clang-format style check
uses: jidicula/clang-format-action@v4.13.0
with:
clang-format-version: '14'
clang-format-version: '19'
check-path: '.'
fallback-style: 'Google'
13 changes: 7 additions & 6 deletions .github/workflows/run-tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,19 @@ on:
push:
pull_request:
branches: [ "master" ]

jobs:
unit-tests:
runs-on: ubuntu-latest
defaults:
run:
shell: bash
container:
image: silkeh/clang:18
image: silkeh/clang:19
options: --user root
steps:
- name: Install deps
run: apt update && apt install -y git ninja-build valgrind libboost-context-dev libgflags-dev
run: apt update && apt install -y git ninja-build valgrind libboost-context-dev libgflags-dev libclang-19-dev
- name: Check out repository code
uses: actions/checkout@v4
- name: Build
Expand All @@ -29,12 +30,12 @@ jobs:
run:
shell: bash
container:
image: silkeh/clang:18
image: silkeh/clang:19
options: --user root
steps:
- name: Install deps
run: |
apt update && apt install -y git ninja-build valgrind libgoogle-glog-dev libsnappy-dev protobuf-compiler libboost-context-dev pkg-config libcapstone-dev && \
apt update && apt install -y git ninja-build valgrind libgoogle-glog-dev libsnappy-dev protobuf-compiler libboost-context-dev pkg-config libcapstone-dev libclang-19-dev && \
git clone https://github.com/Kirillog/syscall_intercept.git && \
cmake syscall_intercept -G Ninja -B syscall_intercept/build -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=clang && \
cmake --build syscall_intercept/build --target install
Expand Down Expand Up @@ -100,12 +101,12 @@ jobs:
run:
shell: bash
container:
image: silkeh/clang:18
image: silkeh/clang:19
options: --user root
steps:
- name: Install deps
run: |
apt update && apt install -y git ninja-build valgrind libgoogle-glog-dev libsnappy-dev protobuf-compiler libboost-context-dev pkg-config libcapstone-dev && \
apt update && apt install -y git ninja-build valgrind libgoogle-glog-dev libsnappy-dev protobuf-compiler libboost-context-dev pkg-config libcapstone-dev libclang-19-dev && \
git clone https://github.com/Kirillog/syscall_intercept.git && \
cmake syscall_intercept -G Ninja -B syscall_intercept/build -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=clang && \
cmake --build syscall_intercept/build --target install
Expand Down
6 changes: 6 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,13 @@ project(lintest)

set(CMAKE_CXX_STANDARD 20)

# in order for clang tool to work, this must be ON (it will generate the compilation database)
# see https://clang.llvm.org/docs/JSONCompilationDatabase.html
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

# set this to ON in order to substitute std::atomic<T> with custom implementation
set(APPLY_CLANG_TOOL OFF)

# TODO(kmitkin): require to understand, what is it considered to be "optimized" build
# set(CMAKE_CXX_FLAGS_RELEASE "???")
set(CMAKE_CXX_FLAGS_DEBUG "-g -ggdb3 -O0 -fno-omit-frame-pointer")
Expand All @@ -24,6 +29,7 @@ include(GoogleTest)
fuzztest_setup_fuzzing_flags()
enable_testing()

add_subdirectory(clangpass)
add_subdirectory(codegen)
add_subdirectory(runtime)

Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
FROM silkeh/clang:19 AS ltest

RUN apt update && apt install -y git ninja-build valgrind libboost-context-dev libgflags-dev libstdc++-11-dev
RUN apt update && apt install -y git ninja-build valgrind libboost-context-dev libgflags-dev libstdc++-11-dev libclang-19-dev
RUN mv /usr/lib/gcc/x86_64-linux-gnu/12 /usr/lib/gcc/x86_64-linux-gnu/_12

FROM ltest as blocking
Expand Down
64 changes: 64 additions & 0 deletions clangpass/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#===============================================================================
# SETUP CLANG PLUGIN
#===============================================================================
find_package(Clang REQUIRED CONFIG)
if("${LLVM_VERSION_MAJOR}" VERSION_LESS 19)
message(FATAL_ERROR "Found LLVM ${LLVM_VERSION_MAJOR}, but need LLVM 19 or above")
endif()

include_directories(SYSTEM "${LLVM_INCLUDE_DIRS};${CLANG_INCLUDE_DIRS}")

if(NOT LLVM_ENABLE_RTTI)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti")
endif()

# -fvisibility-inlines-hidden is set when building LLVM and on Darwin warnings
# are triggered if llvm-tutor is built without this flag (though otherwise it
# builds fine). For consistency, add it here too.
include(CheckCXXCompilerFlag)
check_cxx_compiler_flag("-fvisibility-inlines-hidden"
SUPPORTS_FVISIBILITY_INLINES_HIDDEN_FLAG)
if(${SUPPORTS_FVISIBILITY_INLINES_HIDDEN_FLAG} EQUAL "1")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility-inlines-hidden")
endif()

add_library(ClangPass SHARED "${CMAKE_CURRENT_SOURCE_DIR}/clangpass.cpp")

target_include_directories(
ClangPass
PRIVATE
"${CMAKE_CURRENT_SOURCE_DIR}/include"
)

# Allow undefined symbols in shared objects on Darwin (this is the default
# behaviour on Linux)
target_link_libraries(ClangPass
"$<$<PLATFORM_ID:Darwin>:-undefined dynamic_lookup>")


#===============================================================================
# SETUP CLANG TOOL
#===============================================================================
set(CLANG_TOOL "ClangPassTool")
set(CLANG_TOOL_SOURCES
"${CMAKE_CURRENT_SOURCE_DIR}/clangpass_tool.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/clangpass.cpp"
)

add_executable(
${CLANG_TOOL}
${CLANG_TOOL_SOURCES}
)

# Configure include directories for 'tool'
target_include_directories(
${CLANG_TOOL}
PRIVATE
"${CMAKE_CURRENT_SOURCE_DIR}/include"
)

# Link in the required libraries
target_link_libraries(
${CLANG_TOOL}
clangTooling
)
218 changes: 218 additions & 0 deletions clangpass/clangpass.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
//==============================================================================
// FILE:
// clangpass.cpp
//
// DESCRIPTION:
// Substitutes all input files std::atomic<T> usages with LTestAtomic<T> with
// the same API.
//
// USAGE:
// clang++ -Xclang -load -Xclang ./build/lib/libClangPass.so -Xclang -add-plugin -Xclang ClangPass ./AtomicsReplacer/test-project/main.cpp
//
// License: The Unlicense
//==============================================================================

#include "clang/AST/ASTConsumer.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Rewrite/Core/Rewriter.h"
#include "clang/Rewrite/Frontend/FixItRewriter.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendPluginRegistry.h"
#include "clang/Tooling/Refactoring/Rename/RenamingAction.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/raw_ostream.h"

#include "clangpass.h"

using namespace clang;
using namespace ast_matchers;
using namespace llvm;

//-----------------------------------------------------------------------------
// ASTFinder callback
//-----------------------------------------------------------------------------
CodeRefactorMatcher::CodeRefactorMatcher(
ASTContext& Context,
clang::Rewriter &RewriterForCodeRefactor,
std::string ClassNameToReplace,
std::string ClassNameToInsert
) : Context(Context),
CodeRefactorRewriter(RewriterForCodeRefactor),
ClassNameToReplace(ClassNameToReplace),
ClassNameToInsert(ClassNameToInsert) {}

void CodeRefactorMatcher::onEndOfTranslationUnit() {
const SourceManager& SM = CodeRefactorRewriter.getSourceMgr();
FileID MainFileID = SM.getMainFileID();
const RewriteBuffer& Buffer = CodeRefactorRewriter.getEditBuffer(MainFileID);

// Output to stdout
llvm::outs() << "Transformed code:\n";
Buffer.write(llvm::outs());
llvm::outs() << "\n";

// Output to file
const FileEntry *Entry = SM.getFileEntryForID(MainFileID);
StringRef OriginalFilename = Entry->tryGetRealPathName();

size_t slashIndex = OriginalFilename.rfind("/");
// the path should be absolute, so in the worst case we will get '/' as index 0
assert(slashIndex != std::string::npos);
slashIndex += 1; // include the '/' itself

std::string Path = std::string(OriginalFilename.begin(), OriginalFilename.begin() + slashIndex);
std::string SourceFilename = std::string(OriginalFilename.begin() + slashIndex, OriginalFilename.end());

llvm::outs() << "Original filename: " << OriginalFilename << "\n";
std::string OutputFilename = Path + "__tmp_" + SourceFilename;

std::error_code EC;
llvm::raw_fd_ostream OS(OutputFilename, EC, llvm::sys::fs::OF_None);

if (EC) {
llvm::errs() << "Error: Could not open output file: " << EC.message() << "\n";
return;
}

llvm::outs() << "Writing to file: " << OutputFilename << "\n";
//OS << std::string(Buffer->begin(), Buffer->end());
Buffer.write(OS);
OS.close();
}

void CodeRefactorMatcher::run(const clang::ast_matchers::MatchFinder::MatchResult &Result) {
if (const auto* ETL = Result.Nodes.getNodeAs<ElaboratedTypeLoc>("ElaboratedTypeLoc")) {
const auto* TemplType = ETL->getType()->getAs<TemplateSpecializationType>();
if (!TemplType) {
return;
}

CodeRefactorRewriter.ReplaceText(ETL->getSourceRange(), ClassNameToInsert + GetArgumentsFromTemplateType(TemplType));
}

if (const auto* QTL = Result.Nodes.getNodeAs<QualifiedTypeLoc>("QualifiedTypeLoc")) {
const auto* TemplType = QTL->getType()->getAs<TemplateSpecializationType>();
if (!TemplType) {
return;
}

CodeRefactorRewriter.ReplaceText(QTL->getSourceRange(), ClassNameToInsert + GetArgumentsFromTemplateType(TemplType));
}
}

std::string CodeRefactorMatcher::GetArgumentsFromTemplateType(const TemplateSpecializationType *TST) {
std::string args;
llvm::raw_string_ostream os(args);
printTemplateArgumentList(os, TST->template_arguments(), Context.getPrintingPolicy());
return args;
}

// Util function for debugging purposes
std::string CodeRefactorMatcher::getSourceRangeAsString(const SourceRange& SR) const {
auto& sm = CodeRefactorRewriter.getSourceMgr();
auto& langOpts = CodeRefactorRewriter.getLangOpts();

clang::SourceLocation start = SR.getBegin();
clang::SourceLocation end = SR.getEnd();
end = clang::Lexer::getLocForEndOfToken(end, 0, sm, langOpts);

bool isInvalid = false;
const char *startData = sm.getCharacterData(start, &isInvalid);

if (isInvalid) {
return "<invalid begin>";
isInvalid = false;
}

const char *endData = sm.getCharacterData(end, &isInvalid);

if (isInvalid) {
return "<invalid end>";
isInvalid = false;
}
size_t length = endData - startData;

return std::string(startData, length);
}


//-----------------------------------------------------------------------------
// ASTConsumer
//-----------------------------------------------------------------------------
CodeRefactorASTConsumer::CodeRefactorASTConsumer(
ASTContext& Context,
clang::Rewriter &R,
std::string ClassNameToReplace,
std::string ClassNameToInsert
): CodeRefactorHandler(Context, R, ClassNameToReplace, ClassNameToInsert),
ClassNameToReplace(ClassNameToReplace),
ClassNameToInsert(ClassNameToInsert) {
// Does not support matching the parameters of the functions
const auto MatcherForFQTemplateTypes = elaboratedTypeLoc(
hasNamedTypeLoc(
loc(
templateSpecializationType(
hasDeclaration(
classTemplateSpecializationDecl(
hasName(ClassNameToReplace)
)
)
)
)
)
);

// Uses previous matcher inside, but returns a wrapping QualifiedTypeLoc node
// which is used in the function parameters
const auto MatcherForFQTemplateParams = qualifiedTypeLoc(
hasUnqualifiedLoc(
MatcherForFQTemplateTypes
)
);

Finder.addMatcher(MatcherForFQTemplateTypes.bind("ElaboratedTypeLoc"), &CodeRefactorHandler);
Finder.addMatcher(MatcherForFQTemplateParams.bind("QualifiedTypeLoc"), &CodeRefactorHandler);
}

void CodeRefactorASTConsumer::HandleTranslationUnit(clang::ASTContext &Ctx) {
Finder.matchAST(Ctx);
}


//-----------------------------------------------------------------------------
// FrontendAction
//-----------------------------------------------------------------------------
class CodeRefactorAddPluginAction : public PluginASTAction {
public:
bool ParseArgs(const CompilerInstance &CI, const std::vector<std::string> &Args) override {
return true;
}

// Returns our ASTConsumer per translation unit.
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
StringRef file) override {
RewriterForCodeRefactor.setSourceMgr(CI.getSourceManager(),
CI.getLangOpts());
return std::make_unique<CodeRefactorASTConsumer>(
CI.getASTContext(), RewriterForCodeRefactor, ClassNameToReplace, ClassNameToInsert);
}

private:
Rewriter RewriterForCodeRefactor;
// The shared library has predefined replace- and insert-class names,
// users are intended to use clangpass_tool.cpp instead.
std::string ClassNameToReplace = "::std::atomic";
std::string ClassNameToInsert = "LTestAtomic";
};


static FrontendPluginRegistry::Add<CodeRefactorAddPluginAction> X(
"ClangPass",
"Replace all std::atomic usages with LTestAtomic"
);
Loading