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