diff --git a/.github/actions/Build_LLVM/action.yml b/.github/actions/Build_LLVM/action.yml index 4a1618175..23847a997 100644 --- a/.github/actions/Build_LLVM/action.yml +++ b/.github/actions/Build_LLVM/action.yml @@ -43,14 +43,10 @@ runs: ninja LLVMOrcDebugging -j ${{ env.ncpus }} ninja clingInterpreter -j ${{ env.ncpus }} else - if [[ "${{ matrix.oop-jit }}" == "On" ]]; then - git apply -v ../patches/llvm/clang20-1-out-of-process.patch - echo "Apply clang20-1-out-of-process.patch:" - fi cd build cmake -DLLVM_ENABLE_PROJECTS="${{ matrix.llvm_enable_projects}}" \ -DLLVM_TARGETS_TO_BUILD="${{ matrix.llvm_targets_to_build }}" \ - -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_BUILD_TYPE=Release \ -DLLVM_ENABLE_ASSERTIONS=ON \ -DCLANG_ENABLE_STATIC_ANALYZER=OFF \ -DCLANG_ENABLE_ARCMT=OFF \ diff --git a/.github/actions/Build_and_Test_CppInterOp/action.yml b/.github/actions/Build_and_Test_CppInterOp/action.yml index 92f44c543..92c4d4847 100644 --- a/.github/actions/Build_and_Test_CppInterOp/action.yml +++ b/.github/actions/Build_and_Test_CppInterOp/action.yml @@ -60,7 +60,7 @@ runs: os="${{ matrix.os }}" if [[ "${os}" != "macos"* && "${{ matrix.Valgrind }}" == "On" ]]; then CLANG_VERSION="${{ matrix.clang-runtime }}" - if [[ "$CLANG_VERSION" == "20" && "${{ matrix.cling }}" == "Off" ]]; then + if [[ "${{ matrix.oop }}" == "On" ]]; then SUPPRESSION_FILE="../etc/clang${CLANG_VERSION}-valgrind.supp" valgrind --show-error-list=yes --track-origins=yes --error-exitcode=1 \ --show-leak-kinds=definite,possible \ diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index e904f1f04..dda5d15ad 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -23,35 +23,35 @@ jobs: matrix: include: # Ubuntu Arm Jobs - - name: ubu24-arm-gcc12-clang-repl-21 + - name: ubu24-arm-gcc12-clang-repl-22 os: ubuntu-24.04-arm compiler: gcc-12 - clang-runtime: '21' + clang-runtime: '22' cling: Off cppyy: On llvm_enable_projects: "clang" llvm_targets_to_build: "host;NVPTX" Valgrind: On - - name: ubu24-arm-gcc12-clang-repl-20 + - name: ubu24-arm-gcc12-clang-repl-21 os: ubuntu-24.04-arm compiler: gcc-12 - clang-runtime: '20' + clang-runtime: '21' cling: Off cppyy: On llvm_enable_projects: "clang" llvm_targets_to_build: "host;NVPTX" - - name: ubu24-arm-gcc12-clang-repl-19-cppyy + - name: ubu24-arm-gcc12-clang-repl-20 os: ubuntu-24.04-arm compiler: gcc-12 - clang-runtime: '19' + clang-runtime: '20' cling: Off - cppyy: On + cppyy: Off llvm_enable_projects: "clang" llvm_targets_to_build: "host;NVPTX" - - name: ubu24-arm-gcc12-clang-repl-18 + - name: ubu24-arm-gcc12-clang-repl-19-cppyy os: ubuntu-24.04-arm compiler: gcc-12 - clang-runtime: '18' + clang-runtime: '19' cling: Off cppyy: Off llvm_enable_projects: "clang" @@ -66,56 +66,56 @@ jobs: llvm_enable_projects: "clang" llvm_targets_to_build: "host;NVPTX" # Ubuntu X86 Jobs - - name: ubu24-x86-gcc12-clang-repl-21 + - name: ubu24-x86-gcc12-clang-repl-22-out-of-process os: ubuntu-24.04 compiler: gcc-12 - clang-runtime: '21' + clang-runtime: '22' cling: Off - cppyy: On - llvm_enable_projects: "clang" + cppyy: Off + llvm_enable_projects: "clang;compiler-rt" llvm_targets_to_build: "host;NVPTX" + oop-jit: On + coverage: true Valgrind: On - - name: ubu24-x86-gcc12-clang-repl-20 + - name: ubu24-x86-gcc12-clang-repl-22-out-of-process-coverage os: ubuntu-24.04 compiler: gcc-12 - clang-runtime: '20' + clang-runtime: '22' cling: Off - cppyy: On - llvm_enable_projects: "clang" + cppyy: Off + llvm_enable_projects: "clang;compiler-rt" llvm_targets_to_build: "host;NVPTX" - - name: ubu24-x86-gcc12-clang-repl-20-out-of-process + oop-jit: On + coverage: true + - name: ubu24-x86-gcc12-clang-repl-22 os: ubuntu-24.04 compiler: gcc-12 - clang-runtime: '20' + clang-runtime: '22' cling: Off cppyy: Off - llvm_enable_projects: "clang;compiler-rt" + llvm_enable_projects: "clang" llvm_targets_to_build: "host;NVPTX" - oop-jit: On - coverage: true Valgrind: On - - name: ubu24-x86-gcc12-clang-repl-20-out-of-process-coverage + - name: ubu24-x86-gcc12-clang-repl-21 os: ubuntu-24.04 compiler: gcc-12 - clang-runtime: '20' + clang-runtime: '21' cling: Off cppyy: Off - llvm_enable_projects: "clang;compiler-rt" + llvm_enable_projects: "clang" llvm_targets_to_build: "host;NVPTX" - oop-jit: On - coverage: true - - name: ubu24-x86-gcc12-clang-repl-19-cppyy + - name: ubu24-x86-gcc12-clang-repl-20 os: ubuntu-24.04 compiler: gcc-12 - clang-runtime: '19' + clang-runtime: '20' cling: Off - cppyy: On + cppyy: Off llvm_enable_projects: "clang" llvm_targets_to_build: "host;NVPTX" - - name: ubu24-x86-gcc12-clang-repl-18 + - name: ubu24-x86-gcc12-clang-repl-19-cppyy os: ubuntu-24.04 compiler: gcc-12 - clang-runtime: '18' + clang-runtime: '19' cling: Off cppyy: Off llvm_enable_projects: "clang" @@ -130,43 +130,43 @@ jobs: llvm_enable_projects: "clang" llvm_targets_to_build: "host;NVPTX" # MacOS Arm Jobs - - name: osx26-arm-clang-clang-repl-21 + - name: osx26-arm-clang-clang-repl-22-out-of-process os: macos-26 compiler: clang - clang-runtime: '21' + clang-runtime: '22' cling: Off - cppyy: On - llvm_enable_projects: "clang" + cppyy: Off + llvm_enable_projects: "clang;compiler-rt" llvm_targets_to_build: "host" - - name: osx26-arm-clang-clang-repl-20-out-of-process + oop-jit: On + - name: osx26-arm-clang-clang-repl-22 os: macos-26 compiler: clang - clang-runtime: '20' + clang-runtime: '22' cling: Off cppyy: Off - llvm_enable_projects: "clang;compiler-rt" + llvm_enable_projects: "clang" llvm_targets_to_build: "host" - oop-jit: On - - name: osx26-arm-clang-clang-repl-20 + - name: osx26-arm-clang-clang-repl-21 os: macos-26 compiler: clang - clang-runtime: '20' + clang-runtime: '21' cling: Off cppyy: On llvm_enable_projects: "clang" llvm_targets_to_build: "host" - - name: osx26-arm-clang-clang-repl-19-cppyy + - name: osx26-arm-clang-clang-repl-20 os: macos-26 compiler: clang - clang-runtime: '19' + clang-runtime: '20' cling: Off - cppyy: On + cppyy: Off llvm_enable_projects: "clang" llvm_targets_to_build: "host" - - name: osx26-arm-clang-clang-repl-18 + - name: osx26-arm-clang-clang-repl-19-cppyy os: macos-26 compiler: clang - clang-runtime: '18' + clang-runtime: '19' cling: Off cppyy: Off llvm_enable_projects: "clang" @@ -181,6 +181,14 @@ jobs: llvm_enable_projects: "clang" llvm_targets_to_build: "host;NVPTX" # MacOS X86 Jobs + - name: osx15-x86-clang-clang-repl-22 + os: macos-15-intel + compiler: clang + clang-runtime: '22' + cling: Off + cppyy: Off + llvm_enable_projects: "clang" + llvm_targets_to_build: "host" - name: osx15-x86-clang-clang-repl-21 os: macos-15-intel compiler: clang @@ -205,14 +213,6 @@ jobs: cppyy: On llvm_enable_projects: "clang" llvm_targets_to_build: "host" - - name: osx15-x86-clang-clang-repl-18 - os: macos-15-intel - compiler: clang - clang-runtime: '18' - cling: Off - cppyy: Off - llvm_enable_projects: "clang" - llvm_targets_to_build: "host" - name: osx15-x86-clang-clang18-cling-cppyy os: macos-15-intel compiler: clang @@ -223,10 +223,10 @@ jobs: llvm_enable_projects: "clang" llvm_targets_to_build: "host;NVPTX" # Windows Arm Jobs - - name: win11-msvc-clang-repl-21 + - name: win11-msvc-clang-repl-22 os: windows-11-arm compiler: msvc - clang-runtime: '21' + clang-runtime: '22' cling: Off llvm_enable_projects: "clang" llvm_targets_to_build: "host;NVPTX" @@ -239,10 +239,10 @@ jobs: llvm_enable_projects: "clang" llvm_targets_to_build: "host;NVPTX" # Windows X86 Jobs - - name: win2025-msvc-clang-repl-21 + - name: win2025-msvc-clang-repl-22 os: windows-2025 compiler: msvc - clang-runtime: '21' + clang-runtime: '22' cling: Off llvm_enable_projects: "clang" llvm_targets_to_build: "host;NVPTX" @@ -291,15 +291,6 @@ jobs: with: cache-hit: ${{ steps.cache.outputs.cache-hit }} - - name: Cache LLVM-${{ matrix.clang-runtime }} and ${{ matrix.cling == 'On' && 'Cling' || 'Clang-REPL' }} build - uses: actions/cache/save@v4 - if: ${{ steps.cache.outputs.cache-hit != 'true' }} - with: - path: | - llvm-project - ${{ matrix.cling=='On' && 'cling' || '' }} - key: ${{ steps.cache.outputs.cache-primary-key }} - - name: Setup code coverage if: ${{ success() && (matrix.coverage == true) }} run: | @@ -347,6 +338,3 @@ jobs: uses: mxschmitt/action-tmate@v3 # When debugging increase to a suitable value! timeout-minutes: 30 - - - diff --git a/CMakeLists.txt b/CMakeLists.txt index fc9813b6e..086ae3ca9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -70,15 +70,15 @@ if( CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR ) include(GNUInstallDirs) ## Define supported version of clang and llvm - set(CLANG_MIN_SUPPORTED 18.0) - set(CLANG_MAX_SUPPORTED "21.1.x") - set(CLANG_VERSION_UPPER_BOUND 22.0.0) - set(LLD_MIN_SUPPORTED 18.0) - set(LLD_MAX_SUPPORTED "21.1.x") - set(LLD_VERSION_UPPER_BOUND 22.0.0) - set(LLVM_MIN_SUPPORTED 18.0) - set(LLVM_MAX_SUPPORTED "21.1.x") - set(LLVM_VERSION_UPPER_BOUND 22.0.0) + set(CLANG_MIN_SUPPORTED 19.0) + set(CLANG_MAX_SUPPORTED "22.1.x") + set(CLANG_VERSION_UPPER_BOUND 23.0.0) + set(LLD_MIN_SUPPORTED 19.0) + set(LLD_MAX_SUPPORTED "22.1.x") + set(LLD_VERSION_UPPER_BOUND 23.0.0) + set(LLVM_MIN_SUPPORTED 19.0) + set(LLVM_MAX_SUPPORTED "22.1.x") + set(LLVM_VERSION_UPPER_BOUND 23.0.0) ## Set Cmake packages search order diff --git a/lib/CppInterOp/CXCppInterOp.cpp b/lib/CppInterOp/CXCppInterOp.cpp index a7f7008ba..b9214e4d0 100644 --- a/lib/CppInterOp/CXCppInterOp.cpp +++ b/lib/CppInterOp/CXCppInterOp.cpp @@ -184,8 +184,10 @@ CXTypeKind cxtype_GetTypeKind(QualType T) { TKCASE(Vector); TKCASE(ExtVector); TKCASE(MemberPointer); - TKCASE(Auto); + TKCASE(Auto); +#if CLANG_VERSION_MAJOR < 22 TKCASE(Elaborated); +#endif TKCASE(Pipe); TKCASE(Attributed); TKCASE(BTFTagAttributed); diff --git a/lib/CppInterOp/Compatibility.h b/lib/CppInterOp/Compatibility.h index e8bd64864..ebc6e90a8 100644 --- a/lib/CppInterOp/Compatibility.h +++ b/lib/CppInterOp/Compatibility.h @@ -13,6 +13,19 @@ #include "clang/Config/config.h" #include "clang/Sema/Sema.h" +#if CLANG_VERSION_MAJOR < 22 +#define Suppress_Elab SuppressElaboration +#else +#define Suppress_Elab FullyQualifiedName +#endif + + +#if CLANG_VERSION_MAJOR < 22 +#define Get_Tag_Type getTagDeclType +#else +#define Get_Tag_Type getCanonicalTagType +#endif + #ifdef _MSC_VER #define dup _dup #define dup2 _dup2 @@ -48,38 +61,6 @@ static inline char* GetEnv(const char* Var_Name) { clang::LookupResultKind::FoundOverloaded #endif -#if CLANG_VERSION_MAJOR < 19 -#define Template_Deduction_Result Sema::TemplateDeductionResult -#define Template_Deduction_Result_Success \ - Sema::TemplateDeductionResult::TDK_Success -#else -#define Template_Deduction_Result TemplateDeductionResult -#define Template_Deduction_Result_Success TemplateDeductionResult::Success -#endif - -#if CLANG_VERSION_MAJOR < 19 -#define For_Visible_Redeclaration Sema::ForVisibleRedeclaration -#define Clang_For_Visible_Redeclaration clang::Sema::ForVisibleRedeclaration -#else -#define For_Visible_Redeclaration RedeclarationKind::ForVisibleRedeclaration -#define Clang_For_Visible_Redeclaration \ - RedeclarationKind::ForVisibleRedeclaration -#endif - -#if CLANG_VERSION_MAJOR < 19 -#define CXXSpecialMemberKindDefaultConstructor \ - clang::Sema::CXXDefaultConstructor -#define CXXSpecialMemberKindCopyConstructor clang::Sema::CXXCopyConstructor -#define CXXSpecialMemberKindMoveConstructor clang::Sema::CXXMoveConstructor -#else -#define CXXSpecialMemberKindDefaultConstructor \ - CXXSpecialMemberKind::DefaultConstructor -#define CXXSpecialMemberKindCopyConstructor \ - CXXSpecialMemberKind::CopyConstructor -#define CXXSpecialMemberKindMoveConstructor \ - CXXSpecialMemberKind::MoveConstructor -#endif - #define STRINGIFY(s) STRINGIFY_X(s) #define STRINGIFY_X(...) #__VA_ARGS__ @@ -223,6 +204,10 @@ inline void codeComplete(std::vector& Results, #include "llvm/Support/Error.h" +#if CLANG_VERSION_MAJOR > 21 +#include "clang/Interpreter/IncrementalExecutor.h" +#endif + #ifdef LLVM_BUILT_WITH_OOP_JIT #include "clang/Basic/Version.h" #include "llvm/TargetParser/Host.h" @@ -380,8 +365,20 @@ inline void maybeMangleDeclName(const clang::GlobalDecl& GD, // Clang 18 - Add new Interpreter methods: CodeComplete inline llvm::orc::LLJIT* getExecutionEngine(clang::Interpreter& I) { - auto* engine = &llvm::cantFail(I.getExecutionEngine()); - return const_cast(engine); +#if CLANG_VERSION_MAJOR < 22 + auto* engine = &llvm::cantFail(I.getExecutionEngine()); + return const_cast(engine); +#else + // FIXME: Remove the need of exposing the low-level execution engine and kill + // this horrible hack. + struct OrcIncrementalExecutor : public clang::IncrementalExecutor { + std::unique_ptr Jit; + }; + + auto &engine = static_cast(llvm::cantFail(I.getExecutionEngine())); + return engine.Jit.get(); + +#endif } inline llvm::Expected diff --git a/lib/CppInterOp/CppInterOp.cpp b/lib/CppInterOp/CppInterOp.cpp index c45db4cec..9ade83ee3 100644 --- a/lib/CppInterOp/CppInterOp.cpp +++ b/lib/CppInterOp/CppInterOp.cpp @@ -42,9 +42,7 @@ #include "clang/Sema/Overload.h" #include "clang/Sema/Ownership.h" #include "clang/Sema/Sema.h" -#if CLANG_VERSION_MAJOR >= 19 #include "clang/Sema/Redeclaration.h" -#endif #include "clang/Sema/TemplateDeduction.h" #include "llvm/ADT/SmallString.h" @@ -117,18 +115,8 @@ void* __clang_Interpreter_SetValueWithAlloc(void* This, void* OutVal, void* OpaqueType); #endif -#if CLANG_VERSION_MAJOR > 18 extern "C" void __clang_Interpreter_SetValueNoAlloc(void* This, void* OutVal, void* OpaqueType, ...); -#else -void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*); -void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, void*); -void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, float); -void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, double); -void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, long double); -void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, - unsigned long long); -#endif #endif // CPPINTEROP_USE_CLING namespace CppImpl { @@ -615,7 +603,7 @@ std::string GetCompleteName(TCppType_t klass) { if (auto* ND = llvm::dyn_cast_or_null(D)) { if (auto* TD = llvm::dyn_cast(ND)) { std::string type_name; - QualType QT = C.getTagDeclType(TD); + QualType QT = C.Get_Tag_Type(TD); QT.getAsStringInternal(type_name, Policy); return type_name; } @@ -658,11 +646,11 @@ std::string GetQualifiedCompleteName(TCppType_t klass) { if (auto* ND = llvm::dyn_cast_or_null(D)) { if (auto* TD = llvm::dyn_cast(ND)) { std::string type_name; - QualType QT = C.getTagDeclType(TD); + QualType QT = C.Get_Tag_Type(TD); PrintingPolicy PP = C.getPrintingPolicy(); PP.FullyQualifiedName = true; PP.SuppressUnwrittenScope = true; - PP.SuppressElaboration = true; + PP.Suppress_Elab = true; QT.getAsStringInternal(type_name, PP); return type_name; @@ -1055,7 +1043,7 @@ std::vector GetFunctionsUsingName(TCppScope_t scope, auto& S = getSema(); DeclarationName DName = &getASTContext().Idents.get(name); clang::LookupResult R(S, DName, SourceLocation(), Sema::LookupOrdinaryName, - For_Visible_Redeclaration); + RedeclarationKind::ForVisibleRedeclaration); CppInternal::utils::Lookup::Named(&S, R, Decl::castToDeclContext(D)); @@ -1244,7 +1232,7 @@ bool GetClassTemplatedMethods(const std::string& name, TCppScope_t parent, llvm::StringRef Name(name); DeclarationName DName = &getASTContext().Idents.get(name); clang::LookupResult R(S, DName, SourceLocation(), Sema::LookupOrdinaryName, - For_Visible_Redeclaration); + RedeclarationKind::ForVisibleRedeclaration); auto* DC = clang::Decl::castToDeclContext(D); CppInternal::utils::Lookup::Named(&S, R, DC); @@ -1837,7 +1825,7 @@ std::string GetTypeAsString(TCppType_t var) { PrintingPolicy Policy((LangOptions())); Policy.Bool = true; // Print bool instead of _Bool. Policy.SuppressTagKeyword = true; // Do not print `class std::string`. - Policy.SuppressElaboration = true; + Policy.Suppress_Elab = true; Policy.FullyQualifiedName = true; return QT.getAsString(Policy); } @@ -2034,7 +2022,7 @@ void get_type_as_string(QualType QT, std::string& type_name, ASTContext& C, // cling::utils::Transform::GetPartiallyDesugaredType() if (!QT->isTypedefNameType() || QT->isBuiltinType()) QT = QT.getDesugaredType(C); - Policy.SuppressElaboration = true; + Policy.Suppress_Elab = true; Policy.SuppressTagKeyword = !QT->isEnumeralType(); Policy.FullyQualifiedName = true; Policy.UsePreferredNames = false; @@ -2076,7 +2064,7 @@ void collect_type_info(const FunctionDecl* FD, QualType& QT, // ASTContext& C = FD->getASTContext(); PrintingPolicy Policy(C.getPrintingPolicy()); - Policy.SuppressElaboration = true; + Policy.Suppress_Elab = true; refType = kNotReference; if (QT->isRecordType()) { if (forArgument) { @@ -2305,7 +2293,7 @@ void make_narg_call(const FunctionDecl* FD, const std::string& return_type, PrintingPolicy PP = FD->getASTContext().getPrintingPolicy(); PP.FullyQualifiedName = true; PP.SuppressUnwrittenScope = true; - PP.SuppressElaboration = true; + PP.Suppress_Elab = true; FD->getNameForDiagnostic(stream, PP, /*Qualified=*/false); name = complete_name; @@ -2495,9 +2483,9 @@ void make_narg_call_with_return(compat::Interpreter& I, const FunctionDecl* FD, if (const CXXConstructorDecl* CD = dyn_cast(FD)) { if (N <= 1 && llvm::isa(FD)) { auto SpecMemKind = I.getCI()->getSema().getSpecialMember(CD); - if ((N == 0 && SpecMemKind == CXXSpecialMemberKindDefaultConstructor) || - (N == 1 && (SpecMemKind == CXXSpecialMemberKindCopyConstructor || - SpecMemKind == CXXSpecialMemberKindMoveConstructor))) { + if ((N == 0 && SpecMemKind == CXXSpecialMemberKind::DefaultConstructor) || + (N == 1 && (SpecMemKind == CXXSpecialMemberKind::CopyConstructor || + SpecMemKind == CXXSpecialMemberKind::MoveConstructor))) { // Using declarations cannot inject special members; do not call // them as such. This might happen by using `Base(Base&, int = 12)`, // which is fine to be called as `Derived d(someBase, 42)` but not @@ -3459,65 +3447,10 @@ TInterp_t CreateInterpreter(const std::vector& Args /*={}*/, reinterpret_cast(&__clang_Interpreter_SetValueWithAlloc)); } #endif -// llvm < 19 has multiple overloads of __clang_Interpreter_SetValueNoAlloc -#if CLANG_VERSION_MAJOR < 19 - // obtain all 6 candidates, and obtain the correct Decl for each overload - // using BestOverloadFunctionMatch. We then map the decl to the correct - // function pointer (force the compiler to find the right declarion by casting - // to the corresponding function pointer signature) and then register it. - const std::vector Methods = Cpp::GetFunctionsUsingName( - Cpp::GetGlobalScope(), "__clang_Interpreter_SetValueNoAlloc"); - std::string mangledName; - ASTContext& Ctxt = I->getSema().getASTContext(); - auto* TAI = Ctxt.VoidPtrTy.getAsOpaquePtr(); - - // possible parameter lists for __clang_Interpreter_SetValueNoAlloc overloads - // in LLVM 18 - const std::vector> a_params = { - {TAI, TAI, TAI}, - {TAI, TAI, TAI, TAI}, - {TAI, TAI, TAI, Ctxt.FloatTy.getAsOpaquePtr()}, - {TAI, TAI, TAI, Ctxt.DoubleTy.getAsOpaquePtr()}, - {TAI, TAI, TAI, Ctxt.LongDoubleTy.getAsOpaquePtr()}, - {TAI, TAI, TAI, Ctxt.UnsignedLongLongTy.getAsOpaquePtr()}}; - - using FP0 = void (*)(void*, void*, void*); - using FP1 = void (*)(void*, void*, void*, void*); - using FP2 = void (*)(void*, void*, void*, float); - using FP3 = void (*)(void*, void*, void*, double); - using FP4 = void (*)(void*, void*, void*, long double); - using FP5 = void (*)(void*, void*, void*, unsigned long long); - - const std::vector func_pointers = { - reinterpret_cast( - static_cast(&__clang_Interpreter_SetValueNoAlloc)), - reinterpret_cast( - static_cast(&__clang_Interpreter_SetValueNoAlloc)), - reinterpret_cast( - static_cast(&__clang_Interpreter_SetValueNoAlloc)), - reinterpret_cast( - static_cast(&__clang_Interpreter_SetValueNoAlloc)), - reinterpret_cast( - static_cast(&__clang_Interpreter_SetValueNoAlloc)), - reinterpret_cast( - static_cast(&__clang_Interpreter_SetValueNoAlloc))}; - - // these symbols are not externed, so we need to mangle their names - for (size_t i = 0; i < a_params.size(); ++i) { - auto* decl = static_cast( - Cpp::BestOverloadFunctionMatch(Methods, {}, a_params[i])); - if (auto* fd = llvm::dyn_cast(decl)) { - auto gd = clang::GlobalDecl(fd); - compat::maybeMangleDeclName(gd, mangledName); - DefineAbsoluteSymbol(*I, mangledName.c_str(), - reinterpret_cast(func_pointers[i])); - } - } -#else + DefineAbsoluteSymbol( *I, "__clang_Interpreter_SetValueNoAlloc", reinterpret_cast(&__clang_Interpreter_SetValueNoAlloc)); -#endif #endif return I; } @@ -3811,10 +3744,10 @@ static Decl* InstantiateTemplate(TemplateDecl* TemplateD, if (auto* FunctionTemplate = dyn_cast(TemplateD)) { FunctionDecl* Specialization = nullptr; clang::sema::TemplateDeductionInfo Info(fakeLoc); - Template_Deduction_Result Result = + TemplateDeductionResult Result = S.DeduceTemplateArguments(FunctionTemplate, &TLI, Specialization, Info, /*IsAddressOfFunction*/ true); - if (Result != Template_Deduction_Result_Success) { + if (Result != TemplateDeductionResult::Success) { // FIXME: Diagnose what happened. (void)Result; } @@ -3824,7 +3757,11 @@ static Decl* InstantiateTemplate(TemplateDecl* TemplateD, } if (auto* VarTemplate = dyn_cast(TemplateD)) { +#if CLANG_VERSION_MAJOR < 22 DeclResult R = S.CheckVarTemplateId(VarTemplate, fakeLoc, fakeLoc, TLI); +#else + DeclResult R = S.CheckVarTemplateId(VarTemplate, fakeLoc, fakeLoc, TLI, /*SetWrittenArgs=*/true); +#endif if (R.isInvalid()) { // FIXME: Diagnose } @@ -3833,7 +3770,11 @@ static Decl* InstantiateTemplate(TemplateDecl* TemplateD, // This will instantiate tape type and return it. SourceLocation noLoc; +#if CLANG_VERSION_MAJOR < 22 QualType TT = S.CheckTemplateIdType(TemplateName(TemplateD), noLoc, TLI); +#else + QualType TT = S.CheckTemplateIdType(ElaboratedTypeKeyword::None, TemplateName(TemplateD), noLoc, TLI, /*Scope=*/nullptr, /*ForNestedNameSpecifier=*/false); +#endif if (TT.isNull()) return nullptr; diff --git a/lib/CppInterOp/CppInterOpInterpreter.h b/lib/CppInterOp/CppInterOpInterpreter.h index 83f17df7d..000ce9727 100644 --- a/lib/CppInterOp/CppInterOpInterpreter.h +++ b/lib/CppInterOp/CppInterOpInterpreter.h @@ -23,9 +23,7 @@ #include "clang/Lex/Preprocessor.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/Sema.h" -#if CLANG_VERSION_MAJOR >= 19 #include "clang/Sema/Redeclaration.h" -#endif #include "clang/Serialization/ModuleFileExtension.h" #include "llvm/ADT/DenseMap.h" @@ -123,7 +121,7 @@ inline clang::NamedDecl* Named(clang::Sema* S, const clang::DeclContext* Within = nullptr) { clang::LookupResult R(*S, Name, clang::SourceLocation(), clang::Sema::LookupOrdinaryName, - Clang_For_Visible_Redeclaration); + RedeclarationKind::ForVisibleRedeclaration); Named(S, R, Within); return LookupResult2Decl(R); } diff --git a/patches/llvm/clang20-1-out-of-process.patch b/patches/llvm/clang20-1-out-of-process.patch deleted file mode 100644 index 198afb99a..000000000 --- a/patches/llvm/clang20-1-out-of-process.patch +++ /dev/null @@ -1,966 +0,0 @@ -diff --git a/clang/include/clang/Interpreter/Interpreter.h b/clang/include/clang/Interpreter/Interpreter.h -index f8663e319..1f9553e68 100644 ---- a/clang/include/clang/Interpreter/Interpreter.h -+++ b/clang/include/clang/Interpreter/Interpreter.h -@@ -20,8 +20,10 @@ - - #include "llvm/ADT/DenseMap.h" - #include "llvm/ExecutionEngine/JITSymbol.h" -+#include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h" - #include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h" - #include "llvm/Support/Error.h" -+#include - #include - #include - -@@ -35,6 +37,10 @@ class ThreadSafeContext; - - namespace clang { - -+namespace driver { -+class ToolChain; -+} // namespace driver -+ - class CompilerInstance; - class CodeGenerator; - class CXXRecordDecl; -@@ -119,15 +125,40 @@ class Interpreter { - /// An optional compiler instance for CUDA offloading - std::unique_ptr DeviceCI; - -+public: -+ struct JITConfig { -+ /// Indicates whether out-of-process JIT execution is enabled. -+ bool IsOutOfProcess = false; -+ /// Path to the out-of-process JIT executor. -+ std::string OOPExecutor = ""; -+ std::string OOPExecutorConnect = ""; -+ /// Indicates whether to use shared memory for communication. -+ bool UseSharedMemory = false; -+ /// Representing the slab allocation size for memory management in kb. -+ unsigned SlabAllocateSize = 0; -+ /// Path to the ORC runtime library. -+ std::string OrcRuntimePath = ""; -+ /// PID of the out-of-process JIT executor. -+ uint32_t ExecutorPID = 0; -+ /// Custom lambda to be executed inside child process/executor -+ std::function CustomizeFork = nullptr; -+ -+ JITConfig() -+ : IsOutOfProcess(false), OOPExecutor(""), OOPExecutorConnect(""), -+ UseSharedMemory(false), SlabAllocateSize(0), OrcRuntimePath(""), -+ ExecutorPID(0), CustomizeFork(nullptr) {} -+ }; -+ - protected: - // Derived classes can use an extended interface of the Interpreter. - Interpreter(std::unique_ptr Instance, llvm::Error &Err, - std::unique_ptr JITBuilder = nullptr, -- std::unique_ptr Consumer = nullptr); -+ std::unique_ptr Consumer = nullptr, -+ JITConfig Config = JITConfig()); - - // Create the internal IncrementalExecutor, or re-create it after calling - // ResetExecutor(). -- llvm::Error CreateExecutor(); -+ llvm::Error CreateExecutor(JITConfig Config = JITConfig()); - - // Delete the internal IncrementalExecutor. This causes a hard shutdown of the - // JIT engine. In particular, it doesn't run cleanup or destructors. -@@ -136,10 +167,19 @@ protected: - public: - virtual ~Interpreter(); - static llvm::Expected> -- create(std::unique_ptr CI); -+ create(std::unique_ptr CI, JITConfig Config = {}); - static llvm::Expected> - createWithCUDA(std::unique_ptr CI, - std::unique_ptr DCI); -+ static llvm::Expected> -+ createLLJITBuilder(std::unique_ptr EPC, -+ llvm::StringRef OrcRuntimePath); -+ static llvm::Expected< -+ std::pair, uint32_t>> -+ outOfProcessJITBuilder(JITConfig Config); -+ static llvm::Expected -+ getOrcRuntimePath(const driver::ToolChain &TC); -+ - const ASTContext &getASTContext() const; - ASTContext &getASTContext(); - const CompilerInstance *getCompilerInstance() const; -@@ -170,6 +210,8 @@ public: - llvm::Expected - getSymbolAddressFromLinkerName(llvm::StringRef LinkerName) const; - -+ uint32_t getOutOfProcessExecutorPID() const; -+ - const llvm::SmallVectorImpl &getValuePrintingInfo() const { - return ValuePrintingInfo; - } -diff --git a/clang/lib/Interpreter/IncrementalExecutor.cpp b/clang/lib/Interpreter/IncrementalExecutor.cpp -index 4d2adecaa..45620fcd3 100644 ---- a/clang/lib/Interpreter/IncrementalExecutor.cpp -+++ b/clang/lib/Interpreter/IncrementalExecutor.cpp -@@ -15,19 +15,36 @@ - #include "clang/Basic/TargetInfo.h" - #include "clang/Basic/TargetOptions.h" - #include "clang/Interpreter/PartialTranslationUnit.h" -+#include "llvm/ADT/StringExtras.h" - #include "llvm/ExecutionEngine/ExecutionEngine.h" - #include "llvm/ExecutionEngine/Orc/CompileUtils.h" -+#include "llvm/ExecutionEngine/Orc/DebugObjectManagerPlugin.h" - #include "llvm/ExecutionEngine/Orc/Debugging/DebuggerSupport.h" -+#include "llvm/ExecutionEngine/Orc/EPCDebugObjectRegistrar.h" -+#include "llvm/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.h" - #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h" - #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" - #include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h" - #include "llvm/ExecutionEngine/Orc/LLJIT.h" -+#include "llvm/ExecutionEngine/Orc/MapperJITLinkMemoryManager.h" - #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h" -+#include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h" -+#include "llvm/ExecutionEngine/Orc/Shared/SimpleRemoteEPCUtils.h" - #include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.h" - #include "llvm/ExecutionEngine/SectionMemoryManager.h" - #include "llvm/IR/Module.h" -+#include "llvm/Support/FileSystem.h" - #include "llvm/Support/ManagedStatic.h" -+#include "llvm/Support/Path.h" - #include "llvm/Support/TargetSelect.h" -+#include "llvm/TargetParser/Host.h" -+ -+#ifdef LLVM_ON_UNIX -+#include -+#include -+#include -+#include -+#endif // LLVM_ON_UNIX - - // Force linking some of the runtimes that helps attaching to a debugger. - LLVM_ATTRIBUTE_USED void linkComponents() { -@@ -55,8 +72,9 @@ IncrementalExecutor::createDefaultJITBuilder( - - IncrementalExecutor::IncrementalExecutor(llvm::orc::ThreadSafeContext &TSC, - llvm::orc::LLJITBuilder &JITBuilder, -+ Interpreter::JITConfig Config, - llvm::Error &Err) -- : TSCtx(TSC) { -+ : TSCtx(TSC), OutOfProcessChildPid(Config.ExecutorPID) { - using namespace llvm::orc; - llvm::ErrorAsOutParameter EAO(&Err); - -@@ -118,4 +136,229 @@ IncrementalExecutor::getSymbolAddress(llvm::StringRef Name, - return SymOrErr->getAddress(); - } - -+Expected> -+createSharedMemoryManager(llvm::orc::SimpleRemoteEPC &SREPC, -+ unsigned SlabAllocateSize) { -+ llvm::orc::SharedMemoryMapper::SymbolAddrs SAs; -+ if (auto Err = SREPC.getBootstrapSymbols( -+ {{SAs.Instance, -+ llvm::orc::rt::ExecutorSharedMemoryMapperServiceInstanceName}, -+ {SAs.Reserve, -+ llvm::orc::rt::ExecutorSharedMemoryMapperServiceReserveWrapperName}, -+ {SAs.Initialize, -+ llvm::orc::rt:: -+ ExecutorSharedMemoryMapperServiceInitializeWrapperName}, -+ {SAs.Deinitialize, -+ llvm::orc::rt:: -+ ExecutorSharedMemoryMapperServiceDeinitializeWrapperName}, -+ {SAs.Release, -+ llvm::orc::rt:: -+ ExecutorSharedMemoryMapperServiceReleaseWrapperName}})) -+ return std::move(Err); -+ -+ size_t SlabSize; -+ if (llvm::Triple(llvm::sys::getProcessTriple()).isOSWindows()) -+ SlabSize = 1024 * 1024; -+ else -+ SlabSize = 1024 * 1024 * 1024; -+ -+ if (SlabAllocateSize > 0) -+ SlabSize = SlabAllocateSize; -+ -+ return llvm::orc::MapperJITLinkMemoryManager::CreateWithMapper< -+ llvm::orc::SharedMemoryMapper>(SlabSize, SREPC, SAs); -+} -+ -+llvm::Expected, uint32_t>> -+IncrementalExecutor::launchExecutor(llvm::StringRef ExecutablePath, -+ bool UseSharedMemory, -+ unsigned SlabAllocateSize, -+ std::function CustomizeFork) { -+#ifndef LLVM_ON_UNIX -+ // FIXME: Add support for Windows. -+ return llvm::make_error( -+ "-" + ExecutablePath + " not supported on non-unix platforms", -+ llvm::inconvertibleErrorCode()); -+#elif !LLVM_ENABLE_THREADS -+ // Out of process mode using SimpleRemoteEPC depends on threads. -+ return llvm::make_error( -+ "-" + ExecutablePath + -+ " requires threads, but LLVM was built with " -+ "LLVM_ENABLE_THREADS=Off", -+ llvm::inconvertibleErrorCode()); -+#else -+ -+ if (!llvm::sys::fs::can_execute(ExecutablePath)) -+ return llvm::make_error( -+ llvm::formatv("Specified executor invalid: {0}", ExecutablePath), -+ llvm::inconvertibleErrorCode()); -+ -+ constexpr int ReadEnd = 0; -+ constexpr int WriteEnd = 1; -+ -+ // Pipe FDs. -+ int ToExecutor[2]; -+ int FromExecutor[2]; -+ -+ uint32_t ChildPID; -+ -+ // Create pipes to/from the executor.. -+ if (pipe(ToExecutor) != 0 || pipe(FromExecutor) != 0) -+ return llvm::make_error( -+ "Unable to create pipe for executor", llvm::inconvertibleErrorCode()); -+ -+ ChildPID = fork(); -+ -+ if (ChildPID == 0) { -+ // In the child... -+ -+ // Close the parent ends of the pipes -+ close(ToExecutor[WriteEnd]); -+ close(FromExecutor[ReadEnd]); -+ -+ if (CustomizeFork) -+ CustomizeFork(); -+ -+ // Execute the child process. -+ std::unique_ptr ExecutorPath, FDSpecifier; -+ { -+ ExecutorPath = std::make_unique(ExecutablePath.size() + 1); -+ strcpy(ExecutorPath.get(), ExecutablePath.data()); -+ -+ std::string FDSpecifierStr("filedescs="); -+ FDSpecifierStr += llvm::utostr(ToExecutor[ReadEnd]); -+ FDSpecifierStr += ','; -+ FDSpecifierStr += llvm::utostr(FromExecutor[WriteEnd]); -+ FDSpecifier = std::make_unique(FDSpecifierStr.size() + 1); -+ strcpy(FDSpecifier.get(), FDSpecifierStr.c_str()); -+ } -+ -+ char *const Args[] = {ExecutorPath.get(), FDSpecifier.get(), nullptr}; -+ int RC = execvp(ExecutorPath.get(), Args); -+ if (RC != 0) { -+ llvm::errs() << "unable to launch out-of-process executor \"" -+ << ExecutorPath.get() << "\"\n"; -+ exit(1); -+ } -+ } -+ // else we're the parent... -+ -+ // Close the child ends of the pipes -+ close(ToExecutor[ReadEnd]); -+ close(FromExecutor[WriteEnd]); -+ -+ llvm::orc::SimpleRemoteEPC::Setup S = llvm::orc::SimpleRemoteEPC::Setup(); -+ if (UseSharedMemory) -+ S.CreateMemoryManager = -+ [SlabAllocateSize](llvm::orc::SimpleRemoteEPC &EPC) { -+ return createSharedMemoryManager(EPC, SlabAllocateSize); -+ }; -+ -+ auto EPCOrErr = -+ llvm::orc::SimpleRemoteEPC::Create( -+ std::make_unique( -+ std::nullopt), -+ std::move(S), FromExecutor[ReadEnd], ToExecutor[WriteEnd]); -+ if (!EPCOrErr) -+ return EPCOrErr.takeError(); -+ return std::make_pair(std::move(*EPCOrErr), ChildPID); -+#endif -+} -+ -+#if LLVM_ON_UNIX && LLVM_ENABLE_THREADS -+ -+static Expected connectTCPSocketImpl(std::string Host, -+ std::string PortStr) { -+ addrinfo *AI; -+ addrinfo Hints{}; -+ Hints.ai_family = AF_INET; -+ Hints.ai_socktype = SOCK_STREAM; -+ Hints.ai_flags = AI_NUMERICSERV; -+ -+ if (int EC = getaddrinfo(Host.c_str(), PortStr.c_str(), &Hints, &AI)) -+ return llvm::make_error( -+ llvm::formatv("address resolution failed ({0})", strerror(EC)), -+ llvm::inconvertibleErrorCode()); -+ // Cycle through the returned addrinfo structures and connect to the first -+ // reachable endpoint. -+ int SockFD; -+ addrinfo *Server; -+ for (Server = AI; Server != nullptr; Server = Server->ai_next) { -+ // socket might fail, e.g. if the address family is not supported. Skip to -+ // the next addrinfo structure in such a case. -+ if ((SockFD = socket(AI->ai_family, AI->ai_socktype, AI->ai_protocol)) < 0) -+ continue; -+ -+ // If connect returns null, we exit the loop with a working socket. -+ if (connect(SockFD, Server->ai_addr, Server->ai_addrlen) == 0) -+ break; -+ -+ close(SockFD); -+ } -+ freeaddrinfo(AI); -+ -+ // If we reached the end of the loop without connecting to a valid endpoint, -+ // dump the last error that was logged in socket() or connect(). -+ if (Server == nullptr) -+ return llvm::make_error("invalid hostname", -+ llvm::inconvertibleErrorCode()); -+ -+ return SockFD; -+} -+ -+llvm::Expected> -+IncrementalExecutor::connectTCPSocket(llvm::StringRef NetworkAddress, -+ bool UseSharedMemory, -+ unsigned SlabAllocateSize) { -+#ifndef LLVM_ON_UNIX -+ // FIXME: Add TCP support for Windows. -+ return llvm::make_error( -+ "-" + NetworkAddress + " not supported on non-unix platforms", -+ llvm::inconvertibleErrorCode()); -+#elif !LLVM_ENABLE_THREADS -+ // Out of process mode using SimpleRemoteEPC depends on threads. -+ return llvm::make_error( -+ "-" + NetworkAddress + -+ " requires threads, but LLVM was built with " -+ "LLVM_ENABLE_THREADS=Off", -+ llvm::inconvertibleErrorCode()); -+#else -+ -+ auto CreateErr = [NetworkAddress](Twine Details) { -+ return llvm::make_error( -+ formatv("Failed to connect TCP socket '{0}': {1}", NetworkAddress, -+ Details), -+ llvm::inconvertibleErrorCode()); -+ }; -+ -+ StringRef Host, PortStr; -+ std::tie(Host, PortStr) = NetworkAddress.split(':'); -+ if (Host.empty()) -+ return CreateErr("Host name for -" + NetworkAddress + " can not be empty"); -+ if (PortStr.empty()) -+ return CreateErr("Port number in -" + NetworkAddress + " can not be empty"); -+ int Port = 0; -+ if (PortStr.getAsInteger(10, Port)) -+ return CreateErr("Port number '" + PortStr + "' is not a valid integer"); -+ -+ Expected SockFD = connectTCPSocketImpl(Host.str(), PortStr.str()); -+ if (!SockFD) -+ return SockFD.takeError(); -+ -+ llvm::orc::SimpleRemoteEPC::Setup S = llvm::orc::SimpleRemoteEPC::Setup(); -+ if (UseSharedMemory) -+ S.CreateMemoryManager = -+ [SlabAllocateSize](llvm::orc::SimpleRemoteEPC &EPC) { -+ return createSharedMemoryManager(EPC, SlabAllocateSize); -+ }; -+ -+ return llvm::orc::SimpleRemoteEPC::Create< -+ llvm::orc::FDSimpleRemoteEPCTransport>( -+ std::make_unique( -+ std::nullopt), -+ std::move(S), *SockFD, *SockFD); -+#endif -+} -+#endif // _WIN32 -+ - } // namespace clang -diff --git a/clang/lib/Interpreter/IncrementalExecutor.h b/clang/lib/Interpreter/IncrementalExecutor.h -index 71d71bc38..56e83378f 100644 ---- a/clang/lib/Interpreter/IncrementalExecutor.h -+++ b/clang/lib/Interpreter/IncrementalExecutor.h -@@ -13,13 +13,20 @@ - #ifndef LLVM_CLANG_LIB_INTERPRETER_INCREMENTALEXECUTOR_H - #define LLVM_CLANG_LIB_INTERPRETER_INCREMENTALEXECUTOR_H - -+#include "clang/Interpreter/Interpreter.h" - #include "llvm/ADT/DenseMap.h" - #include "llvm/ADT/StringRef.h" -+#include "llvm/ExecutionEngine/Orc/Core.h" -+#include "llvm/ExecutionEngine/Orc/Core.h" - #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h" -+#include "llvm/ExecutionEngine/Orc/Layer.h" - #include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h" -+#include "llvm/ExecutionEngine/Orc/SimpleRemoteEPC.h" -+#include "llvm/Support/Error.h" - -+#include - #include -- -+#include - namespace llvm { - class Error; - namespace orc { -@@ -39,6 +46,7 @@ class IncrementalExecutor { - using CtorDtorIterator = llvm::orc::CtorDtorIterator; - std::unique_ptr Jit; - llvm::orc::ThreadSafeContext &TSCtx; -+ uint32_t OutOfProcessChildPid = -1; - - llvm::DenseMap - ResourceTrackers; -@@ -50,7 +58,8 @@ public: - enum SymbolNameKind { IRName, LinkerName }; - - IncrementalExecutor(llvm::orc::ThreadSafeContext &TSC, -- llvm::orc::LLJITBuilder &JITBuilder, llvm::Error &Err); -+ llvm::orc::LLJITBuilder &JITBuilder, -+ Interpreter::JITConfig Config, llvm::Error &Err); - virtual ~IncrementalExecutor(); - - virtual llvm::Error addModule(PartialTranslationUnit &PTU); -@@ -62,8 +71,22 @@ public: - - llvm::orc::LLJIT &GetExecutionEngine() { return *Jit; } - -+ uint32_t getOutOfProcessChildPid() const { return OutOfProcessChildPid; } -+ - static llvm::Expected> - createDefaultJITBuilder(llvm::orc::JITTargetMachineBuilder JTMB); -+ -+ static llvm::Expected< -+ std::pair, uint32_t>> -+ launchExecutor(llvm::StringRef ExecutablePath, bool UseSharedMemory, -+ unsigned SlabAllocateSize, -+ std::function CustomizeFork = nullptr); -+ -+#if LLVM_ON_UNIX && LLVM_ENABLE_THREADS -+ static llvm::Expected> -+ connectTCPSocket(llvm::StringRef NetworkAddress, bool UseSharedMemory, -+ unsigned SlabAllocateSize); -+#endif - }; - - } // end namespace clang -diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp -index 3b81f9d70..6ef46a942 100644 ---- a/clang/lib/Interpreter/Interpreter.cpp -+++ b/clang/lib/Interpreter/Interpreter.cpp -@@ -46,6 +46,7 @@ - #include "clang/Sema/Lookup.h" - #include "clang/Serialization/ObjectFilePCHContainerReader.h" - #include "llvm/ExecutionEngine/JITSymbol.h" -+#include "llvm/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.h" - #include "llvm/ExecutionEngine/Orc/LLJIT.h" - #include "llvm/IR/Module.h" - #include "llvm/Support/Errc.h" -@@ -365,7 +366,8 @@ public: - Interpreter::Interpreter(std::unique_ptr Instance, - llvm::Error &ErrOut, - std::unique_ptr JITBuilder, -- std::unique_ptr Consumer) -+ std::unique_ptr Consumer, -+ JITConfig Config) - : JITBuilder(std::move(JITBuilder)) { - CI = std::move(Instance); - llvm::ErrorAsOutParameter EAO(&ErrOut); -@@ -395,7 +397,7 @@ Interpreter::Interpreter(std::unique_ptr Instance, - ASTContext &C = CI->getASTContext(); - RegisterPTU(C.getTranslationUnitDecl(), std::move(M)); - } -- if (llvm::Error Err = CreateExecutor()) { -+ if (llvm::Error Err = CreateExecutor(Config)) { - ErrOut = joinErrors(std::move(ErrOut), std::move(Err)); - return; - } -@@ -454,19 +456,118 @@ const char *const Runtimes = R"( - EXTERN_C void __clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType, ...); - )"; - -+llvm::Expected, uint32_t>> -+Interpreter::outOfProcessJITBuilder(JITConfig Config) { -+ std::unique_ptr EPC; -+ uint32_t childPid = -1; -+ if (!Config.OOPExecutor.empty()) { -+ // Launch an out-of-process executor locally in a child process. -+ auto ResultOrErr = IncrementalExecutor::launchExecutor( -+ Config.OOPExecutor, Config.UseSharedMemory, Config.SlabAllocateSize, -+ Config.CustomizeFork); -+ if (!ResultOrErr) -+ return ResultOrErr.takeError(); -+ childPid = ResultOrErr->second; -+ auto EPCOrErr = std::move(ResultOrErr->first); -+ EPC = std::move(EPCOrErr); -+ } else if (Config.OOPExecutorConnect != "") { -+#if LLVM_ON_UNIX && LLVM_ENABLE_THREADS -+ auto EPCOrErr = IncrementalExecutor::connectTCPSocket( -+ Config.OOPExecutorConnect, Config.UseSharedMemory, -+ Config.SlabAllocateSize); -+ if (!EPCOrErr) -+ return EPCOrErr.takeError(); -+ EPC = std::move(*EPCOrErr); -+#else -+ return llvm::make_error( -+ "Out-of-process JIT over TCP is not supported on this platform", -+ std::error_code()); -+#endif -+ } -+ -+ std::unique_ptr JB; -+ if (EPC) { -+ auto JBOrErr = clang::Interpreter::createLLJITBuilder( -+ std::move(EPC), Config.OrcRuntimePath); -+ if (!JBOrErr) -+ return JBOrErr.takeError(); -+ JB = std::move(*JBOrErr); -+ } -+ -+ return std::make_pair(std::move(JB), childPid); -+} -+ -+llvm::Expected -+Interpreter::getOrcRuntimePath(const driver::ToolChain &TC) { -+ std::optional CompilerRTPath = TC.getCompilerRTPath(); -+ std::optional ResourceDir = TC.getRuntimePath(); -+ -+ if (!CompilerRTPath) { -+ return llvm::make_error("CompilerRT path not found", -+ std::error_code()); -+ } -+ -+ const std::array OrcRTLibNames = { -+ "liborc_rt.a", "liborc_rt_osx.a", "liborc_rt-x86_64.a"}; -+ -+ for (const char *LibName : OrcRTLibNames) { -+ llvm::SmallString<256> CandidatePath((*CompilerRTPath).c_str()); -+ llvm::sys::path::append(CandidatePath, LibName); -+ -+ if (llvm::sys::fs::exists(CandidatePath)) { -+ return CandidatePath.str().str(); -+ } -+ } -+ -+ return llvm::make_error( -+ llvm::Twine("OrcRuntime library not found in: ") + (*CompilerRTPath), -+ std::error_code()); -+} -+ - llvm::Expected> --Interpreter::create(std::unique_ptr CI) { -+Interpreter::create(std::unique_ptr CI, JITConfig Config) { - llvm::Error Err = llvm::Error::success(); -- auto Interp = -- std::unique_ptr(new Interpreter(std::move(CI), Err)); -- if (Err) -- return std::move(Err); -+ -+ std::unique_ptr JB; -+ -+ if (Config.IsOutOfProcess) { -+ const TargetInfo &TI = CI->getTarget(); -+ const llvm::Triple &Triple = TI.getTriple(); -+ -+ DiagnosticsEngine &Diags = CI->getDiagnostics(); -+ std::string BinaryName = llvm::sys::fs::getMainExecutable(nullptr, nullptr); -+ driver::Driver Driver(BinaryName, Triple.str(), Diags); -+ // Need fake args to get the driver to create a compilation. -+ std::vector Args = {"clang", "--version"}; -+ std::unique_ptr C( -+ Driver.BuildCompilation(Args)); -+ if (!C) { -+ return llvm::make_error( -+ "Failed to create driver compilation for out-of-process JIT", -+ std::error_code()); -+ } -+ if (Config.OrcRuntimePath == "") { -+ const clang::driver::ToolChain &TC = C->getDefaultToolChain(); -+ -+ auto OrcRuntimePathOrErr = getOrcRuntimePath(TC); -+ if (!OrcRuntimePathOrErr) { -+ return OrcRuntimePathOrErr.takeError(); -+ } -+ -+ Config.OrcRuntimePath = *OrcRuntimePathOrErr; -+ } -+ } -+ -+ auto Interp = std::unique_ptr(new Interpreter( -+ std::move(CI), Err, std::move(JB), /*Consumer=*/nullptr, Config)); -+ if (auto E = std::move(Err)) -+ return std::move(E); - - // Add runtime code and set a marker to hide it from user code. Undo will not - // go through that. -- auto PTU = Interp->Parse(Runtimes); -- if (!PTU) -- return PTU.takeError(); -+ if (auto E = Interp->ParseAndExecute(Runtimes)) -+ return std::move(E); -+ - Interp->markUserCodeStart(); - - Interp->ValuePrintingInfo.resize(4); -@@ -551,6 +652,12 @@ size_t Interpreter::getEffectivePTUSize() const { - return PTUs.size() - InitPTUSize; - } - -+uint32_t Interpreter::getOutOfProcessExecutorPID() const { -+ if (IncrExecutor) -+ return IncrExecutor->getOutOfProcessChildPid(); -+ return -1; -+} -+ - PartialTranslationUnit & - Interpreter::RegisterPTU(TranslationUnitDecl *TU, - std::unique_ptr M /*={}*/, -@@ -617,7 +724,26 @@ createJITTargetMachineBuilder(const std::string &TT) { - return llvm::orc::JITTargetMachineBuilder(llvm::Triple(TT)); - } - --llvm::Error Interpreter::CreateExecutor() { -+llvm::Expected> -+Interpreter::createLLJITBuilder( -+ std::unique_ptr EPC, -+ llvm::StringRef OrcRuntimePath) { -+ const std::string &TT = EPC->getTargetTriple().getTriple(); -+ auto JTMB = createJITTargetMachineBuilder(TT); -+ if (!JTMB) -+ return JTMB.takeError(); -+ auto JB = IncrementalExecutor::createDefaultJITBuilder(std::move(*JTMB)); -+ if (!JB) -+ return JB.takeError(); -+ -+ (*JB)->setExecutorProcessControl(std::move(EPC)); -+ (*JB)->setPlatformSetUp( -+ llvm::orc::ExecutorNativePlatform(OrcRuntimePath.str())); -+ -+ return std::move(*JB); -+} -+ -+llvm::Error Interpreter::CreateExecutor(JITConfig Config) { - if (IncrExecutor) - return llvm::make_error("Operation failed. " - "Execution engine exists", -@@ -626,8 +752,26 @@ llvm::Error Interpreter::CreateExecutor() { - return llvm::make_error("Operation failed. " - "No code generator available", - std::error_code()); -+ -+ const std::string &TT = getCompilerInstance()->getTargetOpts().Triple; -+ llvm::Triple TargetTriple(TT); -+ bool IsWindowsTarget = TargetTriple.isOSWindows(); -+ -+ if (!IsWindowsTarget && Config.IsOutOfProcess) { -+ if (!JITBuilder) { -+ auto ResOrErr = outOfProcessJITBuilder(Config); -+ if (!ResOrErr) -+ return ResOrErr.takeError(); -+ JITBuilder = std::move(ResOrErr->first); -+ Config.ExecutorPID = ResOrErr->second; -+ } -+ if (!JITBuilder) -+ return llvm::make_error( -+ "Operation failed. No LLJITBuilder for out-of-process JIT", -+ std::error_code()); -+ } -+ - if (!JITBuilder) { -- const std::string &TT = getCompilerInstance()->getTargetOpts().Triple; - auto JTMB = createJITTargetMachineBuilder(TT); - if (!JTMB) - return JTMB.takeError(); -@@ -638,11 +782,15 @@ llvm::Error Interpreter::CreateExecutor() { - } - - llvm::Error Err = llvm::Error::success(); -+ -+ // Fix: Declare Executor as the appropriate unique_ptr type -+ std::unique_ptr Executor; -+ - #ifdef __EMSCRIPTEN__ -- auto Executor = std::make_unique(*TSCtx); -+ Executor = std::make_unique(*TSCtx); - #else -- auto Executor = -- std::make_unique(*TSCtx, *JITBuilder, Err); -+ Executor = -+ std::make_unique(*TSCtx, *JITBuilder, Config, Err); - #endif - if (!Err) - IncrExecutor = std::move(Executor); -diff --git a/clang/tools/clang-repl/ClangRepl.cpp b/clang/tools/clang-repl/ClangRepl.cpp -index 7af8e4f25..c1a7ec397 100644 ---- a/clang/tools/clang-repl/ClangRepl.cpp -+++ b/clang/tools/clang-repl/ClangRepl.cpp -@@ -11,6 +11,8 @@ - //===----------------------------------------------------------------------===// - - #include "clang/Basic/Diagnostic.h" -+#include "clang/Basic/Version.h" -+#include "clang/Config/config.h" - #include "clang/Frontend/CompilerInstance.h" - #include "clang/Frontend/FrontendDiagnostic.h" - #include "clang/Interpreter/CodeCompletion.h" -@@ -18,14 +20,27 @@ - #include "clang/Lex/Preprocessor.h" - #include "clang/Sema/Sema.h" - -+#include "llvm/ADT/SmallString.h" -+#include "llvm/ADT/StringRef.h" - #include "llvm/ExecutionEngine/Orc/LLJIT.h" - #include "llvm/LineEditor/LineEditor.h" - #include "llvm/Support/CommandLine.h" -+#include "llvm/Support/FileSystem.h" - #include "llvm/Support/ManagedStatic.h" // llvm_shutdown -+#include "llvm/Support/Path.h" - #include "llvm/Support/Signals.h" - #include "llvm/Support/TargetSelect.h" -+#include "llvm/Support/VirtualFileSystem.h" -+#include "llvm/Support/raw_ostream.h" -+#include "llvm/TargetParser/Host.h" -+#include "llvm/TargetParser/Triple.h" - #include - -+#include -+#include -+ -+#include "llvm/ExecutionEngine/Orc/Debugging/DebuggerSupport.h" -+ - // Disable LSan for this test. - // FIXME: Re-enable once we can assume GCC 13.2 or higher. - // https://llvm.org/github.com/llvm/llvm-project/issues/67586. -@@ -34,10 +49,36 @@ - LLVM_ATTRIBUTE_USED int __lsan_is_turned_off() { return 1; } - #endif - -+#define DEBUG_TYPE "clang-repl" -+ - static llvm::cl::opt CudaEnabled("cuda", llvm::cl::Hidden); - static llvm::cl::opt CudaPath("cuda-path", llvm::cl::Hidden); - static llvm::cl::opt OffloadArch("offload-arch", llvm::cl::Hidden); -- -+static llvm::cl::OptionCategory OOPCategory("Out-of-process Execution Options"); -+static llvm::cl::opt SlabAllocateSizeString( -+ "slab-allocate", -+ llvm::cl::desc("Allocate from a slab of the given size " -+ "(allowable suffixes: Kb, Mb, Gb. default = " -+ "Kb)"), -+ llvm::cl::init(""), llvm::cl::cat(OOPCategory)); -+static llvm::cl::opt -+ OOPExecutor("oop-executor", -+ llvm::cl::desc("Launch an out-of-process executor to run code"), -+ llvm::cl::init(""), llvm::cl::ValueOptional, -+ llvm::cl::cat(OOPCategory)); -+static llvm::cl::opt OOPExecutorConnect( -+ "oop-executor-connect", -+ llvm::cl::desc( -+ "Connect to an out-of-process executor through a TCP socket"), -+ llvm::cl::value_desc(":")); -+static llvm::cl::opt -+ OrcRuntimePath("orc-runtime", llvm::cl::desc("Path to the ORC runtime"), -+ llvm::cl::init(""), llvm::cl::ValueOptional, -+ llvm::cl::cat(OOPCategory)); -+static llvm::cl::opt UseSharedMemory( -+ "use-shared-memory", -+ llvm::cl::desc("Use shared memory to transfer generated code and data"), -+ llvm::cl::init(false), llvm::cl::cat(OOPCategory)); - static llvm::cl::list - ClangArgs("Xcc", - llvm::cl::desc("Argument to pass to the CompilerInvocation"), -@@ -47,6 +88,79 @@ static llvm::cl::opt OptHostSupportsJit("host-supports-jit", - static llvm::cl::list OptInputs(llvm::cl::Positional, - llvm::cl::desc("[code to run]")); - -+static llvm::Error sanitizeOopArguments(const char *ArgV0) { -+ // Only one of -oop-executor and -oop-executor-connect can be used. -+ if (!!OOPExecutor.getNumOccurrences() && -+ !!OOPExecutorConnect.getNumOccurrences()) -+ return llvm::make_error( -+ "Only one of -" + OOPExecutor.ArgStr + " and -" + -+ OOPExecutorConnect.ArgStr + " can be specified", -+ llvm::inconvertibleErrorCode()); -+ -+ llvm::Triple SystemTriple(llvm::sys::getProcessTriple()); -+ // TODO: Remove once out-of-process execution support is implemented for -+ // non-Unix platforms. -+ if ((!SystemTriple.isOSBinFormatELF() && -+ !SystemTriple.isOSBinFormatMachO()) && -+ (OOPExecutor.getNumOccurrences() || -+ OOPExecutorConnect.getNumOccurrences())) -+ return llvm::make_error( -+ "Out-of-process execution is only supported on Unix platforms", -+ llvm::inconvertibleErrorCode()); -+ -+ // If -slab-allocate is passed, check that we're not trying to use it in -+ // -oop-executor or -oop-executor-connect mode. -+ // -+ // FIXME: Remove once we enable remote slab allocation. -+ if (SlabAllocateSizeString != "") { -+ if (OOPExecutor.getNumOccurrences() || -+ OOPExecutorConnect.getNumOccurrences()) -+ return llvm::make_error( -+ "-slab-allocate cannot be used with -oop-executor or " -+ "-oop-executor-connect", -+ llvm::inconvertibleErrorCode()); -+ } -+ -+ // Out-of-process executors require the ORC runtime. ORC Runtime Path -+ // resolution is done in Interpreter.cpp. -+ -+ // If -oop-executor was used but no value was specified then use a sensible -+ // default. -+ if (!!OOPExecutor.getNumOccurrences() && OOPExecutor.empty()) { -+ llvm::SmallString<256> OOPExecutorPath(llvm::sys::fs::getMainExecutable( -+ ArgV0, reinterpret_cast(&sanitizeOopArguments))); -+ llvm::sys::path::remove_filename(OOPExecutorPath); -+ llvm::sys::path::append(OOPExecutorPath, "llvm-jitlink-executor"); -+ OOPExecutor = OOPExecutorPath.str().str(); -+ } -+ -+ return llvm::Error::success(); -+} -+ -+static llvm::Expected getSlabAllocSize(llvm::StringRef SizeString) { -+ SizeString = SizeString.trim(); -+ -+ uint64_t Units = 1024; -+ -+ if (SizeString.ends_with_insensitive("kb")) -+ SizeString = SizeString.drop_back(2).rtrim(); -+ else if (SizeString.ends_with_insensitive("mb")) { -+ Units = 1024 * 1024; -+ SizeString = SizeString.drop_back(2).rtrim(); -+ } else if (SizeString.ends_with_insensitive("gb")) { -+ Units = 1024 * 1024 * 1024; -+ SizeString = SizeString.drop_back(2).rtrim(); -+ } else if (SizeString.empty()) -+ return 0; -+ -+ uint64_t SlabSize = 0; -+ if (SizeString.getAsInteger(10, SlabSize)) -+ return llvm::make_error( -+ "Invalid numeric format for slab size", llvm::inconvertibleErrorCode()); -+ -+ return SlabSize * Units; -+} -+ - static void LLVMErrorHandler(void *UserData, const char *Message, - bool GenCrashDiag) { - auto &Diags = *static_cast(UserData); -@@ -86,7 +200,7 @@ struct ReplListCompleter { - clang::Interpreter &MainInterp; - ReplListCompleter(clang::IncrementalCompilerBuilder &CB, - clang::Interpreter &Interp) -- : CB(CB), MainInterp(Interp){}; -+ : CB(CB), MainInterp(Interp) {}; - - std::vector operator()(llvm::StringRef Buffer, - size_t Pos) const; -@@ -183,6 +297,19 @@ int main(int argc, const char **argv) { - DeviceCI = ExitOnErr(CB.CreateCudaDevice()); - } - -+ ExitOnErr(sanitizeOopArguments(argv[0])); -+ -+ clang::Interpreter::JITConfig Config; -+ Config.IsOutOfProcess = !OOPExecutor.empty() || !OOPExecutorConnect.empty(); -+ Config.OOPExecutor = OOPExecutor; -+ auto SizeOrErr = getSlabAllocSize(SlabAllocateSizeString); -+ if (!SizeOrErr) { -+ llvm::logAllUnhandledErrors(SizeOrErr.takeError(), llvm::errs(), "error: "); -+ return EXIT_FAILURE; -+ } -+ Config.SlabAllocateSize = *SizeOrErr; -+ Config.UseSharedMemory = UseSharedMemory; -+ - // FIXME: Investigate if we could use runToolOnCodeWithArgs from tooling. It - // can replace the boilerplate code for creation of the compiler instance. - std::unique_ptr CI; -@@ -214,8 +341,9 @@ int main(int argc, const char **argv) { - auto CudaRuntimeLibPath = CudaPath + "/lib/libcudart.so"; - ExitOnErr(Interp->LoadDynamicLibrary(CudaRuntimeLibPath.c_str())); - } -- } else -- Interp = ExitOnErr(clang::Interpreter::create(std::move(CI))); -+ } else { -+ Interp = ExitOnErr(clang::Interpreter::create(std::move(CI), Config)); -+ } - - bool HasError = false; - -@@ -243,15 +371,34 @@ int main(int argc, const char **argv) { - } - - Input += L; -+ // If we add more % commands, there should be better architecture than -+ // this. - if (Input == R"(%quit)") { - break; - } - if (Input == R"(%undo)") { - if (auto Err = Interp->Undo()) - llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), "error: "); -+ } else if (Input == R"(%help)") { -+ llvm::outs() << "%help\t\tlist clang-repl %commands\n" -+ << "%undo\t\tundo the previous input\n" -+ << "%lib\t\tlink a dynamic library\n" -+ << "%quit\t\texit clang-repl\n"; -+ } else if (Input == R"(%lib)") { -+ auto Err = llvm::make_error( -+ "%lib expects 1 argument: the path to a dynamic library\n", -+ std::error_code()); -+ llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), "error: "); - } else if (Input.rfind("%lib ", 0) == 0) { - if (auto Err = Interp->LoadDynamicLibrary(Input.data() + 5)) - llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), "error: "); -+ } else if (Input[0] == '%') { -+ auto Err = llvm::make_error( -+ llvm::formatv( -+ "Invalid % command \"{0}\", use \"%help\" to list commands\n", -+ Input), -+ std::error_code()); -+ llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), "error: "); - } else if (auto Err = Interp->ParseAndExecute(Input)) { - llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), "error: "); - } -@@ -267,4 +414,4 @@ int main(int argc, const char **argv) { - llvm::remove_fatal_error_handler(); - - return checkDiagErrors(Interp->getCompilerInstance(), HasError); --} -+} -\ No newline at end of file -diff --git a/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp b/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp -index 972c24abc..a75a0afa7 100644 ---- a/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp -+++ b/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp -@@ -635,16 +635,19 @@ Error ORCPlatformSupport::initialize(orc::JITDylib &JD) { - int32_t result; - auto E = ES.callSPSWrapper(WrapperAddr->getAddress(), - result, DSOHandles[&JD]); -- if (result) -+ if (E) -+ return E; -+ else if (result) - return make_error("dlupdate failed", - inconvertibleErrorCode()); -- return E; -- } -- return ES.callSPSWrapper(WrapperAddr->getAddress(), -- DSOHandles[&JD], JD.getName(), -- int32_t(ORC_RT_RTLD_LAZY)); -+ } else -+ return ES.callSPSWrapper(WrapperAddr->getAddress(), -+ DSOHandles[&JD], JD.getName(), -+ int32_t(ORC_RT_RTLD_LAZY)); - } else - return WrapperAddr.takeError(); -+ -+ return Error::success(); - } - - Error ORCPlatformSupport::deinitialize(orc::JITDylib &JD) { diff --git a/unittests/CppInterOp/ScopeReflectionTest.cpp b/unittests/CppInterOp/ScopeReflectionTest.cpp index 5d828fc59..7db2bfaf4 100644 --- a/unittests/CppInterOp/ScopeReflectionTest.cpp +++ b/unittests/CppInterOp/ScopeReflectionTest.cpp @@ -234,7 +234,8 @@ TYPED_TEST(CPPINTEROP_TEST_MODE, ScopeReflection_IsBuiltin) { EXPECT_TRUE(Cpp::IsBuiltin(C.getComplexType(C.DoubleTy).getAsOpaquePtr())); EXPECT_TRUE(Cpp::IsBuiltin(C.getComplexType(C.LongDoubleTy).getAsOpaquePtr())); EXPECT_TRUE(Cpp::IsBuiltin(C.getComplexType(C.Float128Ty).getAsOpaquePtr())); - +// FIXME as part of llvm 22 PR. getTypeDeclType was deleted between llvm 21 and 22 +#if CLANG_VERSION_MAJOR < 22 // std::complex Interp->declare("#include "); Sema &S = Interp->getCI()->getSema(); @@ -242,6 +243,7 @@ TYPED_TEST(CPPINTEROP_TEST_MODE, ScopeReflection_IsBuiltin) { auto *CTD = cast(lookup.front()); for (ClassTemplateSpecializationDecl *CTSD : CTD->specializations()) EXPECT_TRUE(Cpp::IsBuiltin(C.getTypeDeclType(CTSD).getAsOpaquePtr())); +#endif } TYPED_TEST(CPPINTEROP_TEST_MODE, ScopeReflection_IsTemplate) { @@ -928,11 +930,7 @@ template constexpr T pi = T(3.1415926535897932385L); auto* VD = cast((Decl*)Instance1); VarTemplateDecl* VDTD1 = VD->getSpecializedTemplate(); EXPECT_TRUE(VDTD1->isThisDeclarationADefinition()); -#if CLANG_VERSION_MAJOR == 18 - TemplateArgument TA1 = (*VD->getTemplateArgsInfo())[0].getArgument(); -#else TemplateArgument TA1 = (*VD->getTemplateArgsAsWritten())[0].getArgument(); -#endif // CLANG_VERSION_MAJOR EXPECT_TRUE(TA1.getAsType()->isIntegerType()); }