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