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/Decl.h" 18 #include "clang/AST/GlobalDecl.h" 19 #include "clang/Interpreter/PartialTranslationUnit.h" 20 #include "clang/Interpreter/Value.h" 21 #include "clang/Sema/Ownership.h" 22 23 #include "llvm/ADT/DenseMap.h" 24 #include "llvm/ExecutionEngine/JITSymbol.h" 25 #include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h" 26 #include "llvm/Support/Error.h" 27 #include <memory> 28 #include <vector> 29 30 namespace llvm { 31 namespace orc { 32 class LLJIT; 33 class LLJITBuilder; 34 class ThreadSafeContext; 35 } // namespace orc 36 } // namespace llvm 37 38 namespace clang { 39 40 class CompilerInstance; 41 class IncrementalExecutor; 42 class IncrementalParser; 43 44 /// Create a pre-configured \c CompilerInstance for incremental processing. 45 class IncrementalCompilerBuilder { 46 public: IncrementalCompilerBuilder()47 IncrementalCompilerBuilder() {} 48 SetCompilerArgs(const std::vector<const char * > & Args)49 void SetCompilerArgs(const std::vector<const char *> &Args) { 50 UserArgs = Args; 51 } 52 SetTargetTriple(std::string TT)53 void SetTargetTriple(std::string TT) { TargetTriple = TT; } 54 55 // General C++ 56 llvm::Expected<std::unique_ptr<CompilerInstance>> CreateCpp(); 57 58 // Offload options SetOffloadArch(llvm::StringRef Arch)59 void SetOffloadArch(llvm::StringRef Arch) { OffloadArch = Arch; }; 60 61 // CUDA specific SetCudaSDK(llvm::StringRef path)62 void SetCudaSDK(llvm::StringRef path) { CudaSDKPath = path; }; 63 64 llvm::Expected<std::unique_ptr<CompilerInstance>> CreateCudaHost(); 65 llvm::Expected<std::unique_ptr<CompilerInstance>> CreateCudaDevice(); 66 67 private: 68 static llvm::Expected<std::unique_ptr<CompilerInstance>> 69 create(std::string TT, std::vector<const char *> &ClangArgv); 70 71 llvm::Expected<std::unique_ptr<CompilerInstance>> createCuda(bool device); 72 73 std::vector<const char *> UserArgs; 74 std::optional<std::string> TargetTriple; 75 76 llvm::StringRef OffloadArch; 77 llvm::StringRef CudaSDKPath; 78 }; 79 80 /// Generate glue code between the Interpreter's built-in runtime and user code. 81 class RuntimeInterfaceBuilder { 82 public: 83 virtual ~RuntimeInterfaceBuilder() = default; 84 85 using TransformExprFunction = ExprResult(RuntimeInterfaceBuilder *Builder, 86 Expr *, ArrayRef<Expr *>); 87 virtual TransformExprFunction *getPrintValueTransformer() = 0; 88 }; 89 90 /// Provides top-level interfaces for incremental compilation and execution. 91 class Interpreter { 92 std::unique_ptr<llvm::orc::ThreadSafeContext> TSCtx; 93 std::unique_ptr<IncrementalParser> IncrParser; 94 std::unique_ptr<IncrementalExecutor> IncrExecutor; 95 std::unique_ptr<RuntimeInterfaceBuilder> RuntimeIB; 96 97 // An optional parser for CUDA offloading 98 std::unique_ptr<IncrementalParser> DeviceParser; 99 100 unsigned InitPTUSize = 0; 101 102 // This member holds the last result of the value printing. It's a class 103 // member because we might want to access it after more inputs. If no value 104 // printing happens, it's in an invalid state. 105 Value LastValue; 106 107 // Add a call to an Expr to report its result. We query the function from 108 // RuntimeInterfaceBuilder once and store it as a function pointer to avoid 109 // frequent virtual function calls. 110 RuntimeInterfaceBuilder::TransformExprFunction *AddPrintValueCall = nullptr; 111 112 protected: 113 // Derived classes can use an extended interface of the Interpreter. 114 Interpreter(std::unique_ptr<CompilerInstance> CI, llvm::Error &Err, 115 std::unique_ptr<llvm::orc::LLJITBuilder> JITBuilder = nullptr); 116 117 // Create the internal IncrementalExecutor, or re-create it after calling 118 // ResetExecutor(). 119 llvm::Error CreateExecutor(); 120 121 // Delete the internal IncrementalExecutor. This causes a hard shutdown of the 122 // JIT engine. In particular, it doesn't run cleanup or destructors. 123 void ResetExecutor(); 124 125 // Lazily construct the RuntimeInterfaceBuilder. The provided instance will be 126 // used for the entire lifetime of the interpreter. The default implementation 127 // targets the in-process __clang_Interpreter runtime. Override this to use a 128 // custom runtime. 129 virtual std::unique_ptr<RuntimeInterfaceBuilder> FindRuntimeInterface(); 130 131 public: 132 virtual ~Interpreter(); 133 134 static llvm::Expected<std::unique_ptr<Interpreter>> 135 create(std::unique_ptr<CompilerInstance> CI); 136 static llvm::Expected<std::unique_ptr<Interpreter>> 137 createWithCUDA(std::unique_ptr<CompilerInstance> CI, 138 std::unique_ptr<CompilerInstance> DCI); 139 const ASTContext &getASTContext() const; 140 ASTContext &getASTContext(); 141 const CompilerInstance *getCompilerInstance() const; 142 CompilerInstance *getCompilerInstance(); 143 llvm::Expected<llvm::orc::LLJIT &> getExecutionEngine(); 144 145 llvm::Expected<PartialTranslationUnit &> Parse(llvm::StringRef Code); 146 llvm::Error Execute(PartialTranslationUnit &T); 147 llvm::Error ParseAndExecute(llvm::StringRef Code, Value *V = nullptr); 148 llvm::Expected<llvm::orc::ExecutorAddr> CompileDtorCall(CXXRecordDecl *CXXRD); 149 150 /// Undo N previous incremental inputs. 151 llvm::Error Undo(unsigned N = 1); 152 153 /// Link a dynamic library 154 llvm::Error LoadDynamicLibrary(const char *name); 155 156 /// \returns the \c ExecutorAddr of a \c GlobalDecl. This interface uses 157 /// the CodeGenModule's internal mangling cache to avoid recomputing the 158 /// mangled name. 159 llvm::Expected<llvm::orc::ExecutorAddr> getSymbolAddress(GlobalDecl GD) const; 160 161 /// \returns the \c ExecutorAddr of a given name as written in the IR. 162 llvm::Expected<llvm::orc::ExecutorAddr> 163 getSymbolAddress(llvm::StringRef IRName) const; 164 165 /// \returns the \c ExecutorAddr of a given name as written in the object 166 /// file. 167 llvm::Expected<llvm::orc::ExecutorAddr> 168 getSymbolAddressFromLinkerName(llvm::StringRef LinkerName) const; 169 170 enum InterfaceKind { NoAlloc, WithAlloc, CopyArray, NewTag }; 171 getValuePrintingInfo()172 const llvm::SmallVectorImpl<Expr *> &getValuePrintingInfo() const { 173 return ValuePrintingInfo; 174 } 175 176 Expr *SynthesizeExpr(Expr *E); 177 178 private: 179 size_t getEffectivePTUSize() const; 180 void markUserCodeStart(); 181 182 llvm::DenseMap<CXXRecordDecl *, llvm::orc::ExecutorAddr> Dtors; 183 184 llvm::SmallVector<Expr *, 4> ValuePrintingInfo; 185 186 std::unique_ptr<llvm::orc::LLJITBuilder> JITBuilder; 187 }; 188 } // namespace clang 189 190 #endif // LLVM_CLANG_INTERPRETER_INTERPRETER_H 191