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 22 #include "llvm/ADT/DenseMap.h" 23 #include "llvm/ExecutionEngine/JITSymbol.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 ThreadSafeContext; 33 } // namespace orc 34 } // namespace llvm 35 36 namespace clang { 37 38 class CompilerInstance; 39 class IncrementalExecutor; 40 class IncrementalParser; 41 42 /// Create a pre-configured \c CompilerInstance for incremental processing. 43 class IncrementalCompilerBuilder { 44 public: 45 IncrementalCompilerBuilder() {} 46 47 void SetCompilerArgs(const std::vector<const char *> &Args) { 48 UserArgs = Args; 49 } 50 51 // General C++ 52 llvm::Expected<std::unique_ptr<CompilerInstance>> CreateCpp(); 53 54 // Offload options 55 void SetOffloadArch(llvm::StringRef Arch) { OffloadArch = Arch; }; 56 57 // CUDA specific 58 void SetCudaSDK(llvm::StringRef path) { CudaSDKPath = path; }; 59 60 llvm::Expected<std::unique_ptr<CompilerInstance>> CreateCudaHost(); 61 llvm::Expected<std::unique_ptr<CompilerInstance>> CreateCudaDevice(); 62 63 private: 64 static llvm::Expected<std::unique_ptr<CompilerInstance>> 65 create(std::vector<const char *> &ClangArgv); 66 67 llvm::Expected<std::unique_ptr<CompilerInstance>> createCuda(bool device); 68 69 std::vector<const char *> UserArgs; 70 71 llvm::StringRef OffloadArch; 72 llvm::StringRef CudaSDKPath; 73 }; 74 75 /// Provides top-level interfaces for incremental compilation and execution. 76 class Interpreter { 77 std::unique_ptr<llvm::orc::ThreadSafeContext> TSCtx; 78 std::unique_ptr<IncrementalParser> IncrParser; 79 std::unique_ptr<IncrementalExecutor> IncrExecutor; 80 81 // An optional parser for CUDA offloading 82 std::unique_ptr<IncrementalParser> DeviceParser; 83 84 Interpreter(std::unique_ptr<CompilerInstance> CI, llvm::Error &Err); 85 86 llvm::Error CreateExecutor(); 87 unsigned InitPTUSize = 0; 88 89 // This member holds the last result of the value printing. It's a class 90 // member because we might want to access it after more inputs. If no value 91 // printing happens, it's in an invalid state. 92 Value LastValue; 93 94 public: 95 ~Interpreter(); 96 static llvm::Expected<std::unique_ptr<Interpreter>> 97 create(std::unique_ptr<CompilerInstance> CI); 98 static llvm::Expected<std::unique_ptr<Interpreter>> 99 createWithCUDA(std::unique_ptr<CompilerInstance> CI, 100 std::unique_ptr<CompilerInstance> DCI); 101 const ASTContext &getASTContext() const; 102 ASTContext &getASTContext(); 103 const CompilerInstance *getCompilerInstance() const; 104 CompilerInstance *getCompilerInstance(); 105 llvm::Expected<llvm::orc::LLJIT &> getExecutionEngine(); 106 107 llvm::Expected<PartialTranslationUnit &> Parse(llvm::StringRef Code); 108 llvm::Error Execute(PartialTranslationUnit &T); 109 llvm::Error ParseAndExecute(llvm::StringRef Code, Value *V = nullptr); 110 llvm::Expected<llvm::orc::ExecutorAddr> CompileDtorCall(CXXRecordDecl *CXXRD); 111 112 /// Undo N previous incremental inputs. 113 llvm::Error Undo(unsigned N = 1); 114 115 /// Link a dynamic library 116 llvm::Error LoadDynamicLibrary(const char *name); 117 118 /// \returns the \c ExecutorAddr of a \c GlobalDecl. This interface uses 119 /// the CodeGenModule's internal mangling cache to avoid recomputing the 120 /// mangled name. 121 llvm::Expected<llvm::orc::ExecutorAddr> getSymbolAddress(GlobalDecl GD) const; 122 123 /// \returns the \c ExecutorAddr of a given name as written in the IR. 124 llvm::Expected<llvm::orc::ExecutorAddr> 125 getSymbolAddress(llvm::StringRef IRName) const; 126 127 /// \returns the \c ExecutorAddr of a given name as written in the object 128 /// file. 129 llvm::Expected<llvm::orc::ExecutorAddr> 130 getSymbolAddressFromLinkerName(llvm::StringRef LinkerName) const; 131 132 enum InterfaceKind { NoAlloc, WithAlloc, CopyArray, NewTag }; 133 134 const llvm::SmallVectorImpl<Expr *> &getValuePrintingInfo() const { 135 return ValuePrintingInfo; 136 } 137 138 Expr *SynthesizeExpr(Expr *E); 139 140 private: 141 size_t getEffectivePTUSize() const; 142 143 bool FindRuntimeInterface(); 144 145 llvm::DenseMap<CXXRecordDecl *, llvm::orc::ExecutorAddr> Dtors; 146 147 llvm::SmallVector<Expr *, 4> ValuePrintingInfo; 148 }; 149 } // namespace clang 150 151 #endif // LLVM_CLANG_INTERPRETER_INTERPRETER_H 152