1 //===--- Interpreter.h - Incremental Compilation and Execution---*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file defines the component which performs incremental code 10 // compilation and execution. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_CLANG_INTERPRETER_INTERPRETER_H 15 #define LLVM_CLANG_INTERPRETER_INTERPRETER_H 16 17 #include "clang/AST/GlobalDecl.h" 18 #include "clang/Interpreter/PartialTranslationUnit.h" 19 #include "clang/Interpreter/Value.h" 20 21 #include "llvm/ADT/DenseMap.h" 22 #include "llvm/ExecutionEngine/JITSymbol.h" 23 #include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h" 24 #include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h" 25 #include "llvm/Support/Error.h" 26 #include <memory> 27 #include <vector> 28 29 namespace llvm { 30 namespace orc { 31 class LLJIT; 32 class LLJITBuilder; 33 class ThreadSafeContext; 34 } // namespace orc 35 } // namespace llvm 36 37 namespace clang { 38 39 class CompilerInstance; 40 class CodeGenerator; 41 class CXXRecordDecl; 42 class Decl; 43 class IncrementalExecutor; 44 class IncrementalParser; 45 class IncrementalCUDADeviceParser; 46 47 /// Create a pre-configured \c CompilerInstance for incremental processing. 48 class IncrementalCompilerBuilder { 49 public: IncrementalCompilerBuilder()50 IncrementalCompilerBuilder() {} 51 SetCompilerArgs(const std::vector<const char * > & Args)52 void SetCompilerArgs(const std::vector<const char *> &Args) { 53 UserArgs = Args; 54 } 55 SetTargetTriple(std::string TT)56 void SetTargetTriple(std::string TT) { TargetTriple = TT; } 57 58 // General C++ 59 llvm::Expected<std::unique_ptr<CompilerInstance>> CreateCpp(); 60 61 // Offload options SetOffloadArch(llvm::StringRef Arch)62 void SetOffloadArch(llvm::StringRef Arch) { OffloadArch = Arch; }; 63 64 // CUDA specific SetCudaSDK(llvm::StringRef path)65 void SetCudaSDK(llvm::StringRef path) { CudaSDKPath = path; }; 66 67 llvm::Expected<std::unique_ptr<CompilerInstance>> CreateCudaHost(); 68 llvm::Expected<std::unique_ptr<CompilerInstance>> CreateCudaDevice(); 69 70 private: 71 static llvm::Expected<std::unique_ptr<CompilerInstance>> 72 create(std::string TT, std::vector<const char *> &ClangArgv); 73 74 llvm::Expected<std::unique_ptr<CompilerInstance>> createCuda(bool device); 75 76 std::vector<const char *> UserArgs; 77 std::optional<std::string> TargetTriple; 78 79 llvm::StringRef OffloadArch; 80 llvm::StringRef CudaSDKPath; 81 }; 82 83 class IncrementalAction; 84 class InProcessPrintingASTConsumer; 85 86 /// Provides top-level interfaces for incremental compilation and execution. 87 class Interpreter { 88 friend class Value; 89 friend InProcessPrintingASTConsumer; 90 91 std::unique_ptr<llvm::orc::ThreadSafeContext> TSCtx; 92 /// Long-lived, incremental parsing action. 93 std::unique_ptr<IncrementalAction> Act; 94 std::unique_ptr<IncrementalParser> IncrParser; 95 std::unique_ptr<IncrementalExecutor> IncrExecutor; 96 97 // An optional parser for CUDA offloading 98 std::unique_ptr<IncrementalCUDADeviceParser> DeviceParser; 99 100 // An optional action for CUDA offloading 101 std::unique_ptr<IncrementalAction> DeviceAct; 102 103 /// List containing information about each incrementally parsed piece of code. 104 std::list<PartialTranslationUnit> PTUs; 105 106 unsigned InitPTUSize = 0; 107 108 // This member holds the last result of the value printing. It's a class 109 // member because we might want to access it after more inputs. If no value 110 // printing happens, it's in an invalid state. 111 Value LastValue; 112 113 /// When CodeGen is created the first llvm::Module gets cached in many places 114 /// and we must keep it alive. 115 std::unique_ptr<llvm::Module> CachedInCodeGenModule; 116 117 /// Compiler instance performing the incremental compilation. 118 std::unique_ptr<CompilerInstance> CI; 119 120 /// An optional compiler instance for CUDA offloading 121 std::unique_ptr<CompilerInstance> DeviceCI; 122 123 protected: 124 // Derived classes can use an extended interface of the Interpreter. 125 Interpreter(std::unique_ptr<CompilerInstance> Instance, llvm::Error &Err, 126 std::unique_ptr<llvm::orc::LLJITBuilder> JITBuilder = nullptr, 127 std::unique_ptr<clang::ASTConsumer> Consumer = nullptr); 128 129 // Create the internal IncrementalExecutor, or re-create it after calling 130 // ResetExecutor(). 131 llvm::Error CreateExecutor(); 132 133 // Delete the internal IncrementalExecutor. This causes a hard shutdown of the 134 // JIT engine. In particular, it doesn't run cleanup or destructors. 135 void ResetExecutor(); 136 137 public: 138 virtual ~Interpreter(); 139 static llvm::Expected<std::unique_ptr<Interpreter>> 140 create(std::unique_ptr<CompilerInstance> CI, 141 std::unique_ptr<llvm::orc::LLJITBuilder> JITBuilder = nullptr); 142 static llvm::Expected<std::unique_ptr<Interpreter>> 143 createWithCUDA(std::unique_ptr<CompilerInstance> CI, 144 std::unique_ptr<CompilerInstance> DCI); 145 static llvm::Expected<std::unique_ptr<llvm::orc::LLJITBuilder>> 146 createLLJITBuilder(std::unique_ptr<llvm::orc::ExecutorProcessControl> EPC, 147 llvm::StringRef OrcRuntimePath); 148 const ASTContext &getASTContext() const; 149 ASTContext &getASTContext(); 150 const CompilerInstance *getCompilerInstance() const; 151 CompilerInstance *getCompilerInstance(); 152 llvm::Expected<llvm::orc::LLJIT &> getExecutionEngine(); 153 154 llvm::Expected<PartialTranslationUnit &> Parse(llvm::StringRef Code); 155 llvm::Error Execute(PartialTranslationUnit &T); 156 llvm::Error ParseAndExecute(llvm::StringRef Code, Value *V = nullptr); 157 158 /// Undo N previous incremental inputs. 159 llvm::Error Undo(unsigned N = 1); 160 161 /// Link a dynamic library 162 llvm::Error LoadDynamicLibrary(const char *name); 163 164 /// \returns the \c ExecutorAddr of a \c GlobalDecl. This interface uses 165 /// the CodeGenModule's internal mangling cache to avoid recomputing the 166 /// mangled name. 167 llvm::Expected<llvm::orc::ExecutorAddr> getSymbolAddress(GlobalDecl GD) const; 168 169 /// \returns the \c ExecutorAddr of a given name as written in the IR. 170 llvm::Expected<llvm::orc::ExecutorAddr> 171 getSymbolAddress(llvm::StringRef IRName) const; 172 173 /// \returns the \c ExecutorAddr of a given name as written in the object 174 /// file. 175 llvm::Expected<llvm::orc::ExecutorAddr> 176 getSymbolAddressFromLinkerName(llvm::StringRef LinkerName) const; 177 getValuePrintingInfo()178 const llvm::SmallVectorImpl<Expr *> &getValuePrintingInfo() const { 179 return ValuePrintingInfo; 180 } 181 182 Expr *SynthesizeExpr(Expr *E); 183 184 private: 185 size_t getEffectivePTUSize() const; 186 void markUserCodeStart(); 187 llvm::Expected<Expr *> ExtractValueFromExpr(Expr *E); 188 llvm::Expected<llvm::orc::ExecutorAddr> CompileDtorCall(CXXRecordDecl *CXXRD); 189 190 CodeGenerator *getCodeGen(IncrementalAction *Action = nullptr) const; 191 std::unique_ptr<llvm::Module> GenModule(IncrementalAction *Action = nullptr); 192 PartialTranslationUnit &RegisterPTU(TranslationUnitDecl *TU, 193 std::unique_ptr<llvm::Module> M = {}, 194 IncrementalAction *Action = nullptr); 195 196 // A cache for the compiled destructors used to for de-allocation of managed 197 // clang::Values. 198 llvm::DenseMap<CXXRecordDecl *, llvm::orc::ExecutorAddr> Dtors; 199 200 llvm::SmallVector<Expr *, 4> ValuePrintingInfo; 201 202 std::unique_ptr<llvm::orc::LLJITBuilder> JITBuilder; 203 }; 204 } // namespace clang 205 206 #endif // LLVM_CLANG_INTERPRETER_INTERPRETER_H 207