xref: /llvm-project/clang/include/clang/Interpreter/Interpreter.h (revision a8744066e9ef252b687c1206ccbd1a6e3ae1c890)
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