@@ -78,22 +78,26 @@ class IncrementalCompilerBuilder {
78
78
llvm::StringRef CudaSDKPath;
79
79
};
80
80
81
- // / Generate glue code between the Interpreter's built-in runtime and user code.
82
- class RuntimeInterfaceBuilder {
83
- public:
84
- virtual ~RuntimeInterfaceBuilder () = default ;
81
+ class Interpreter ;
82
+ // / Provides a callback class allowing to listen to interpreter events and to
83
+ // / specialize some operations.
84
+ class InterpreterCallbacks {
85
+ Interpreter &Interp;
85
86
86
- using TransformExprFunction = ExprResult(RuntimeInterfaceBuilder *Builder,
87
- Expr *, ArrayRef<Expr *>);
88
- virtual TransformExprFunction *getPrintValueTransformer () = 0;
87
+ public:
88
+ InterpreterCallbacks (Interpreter &I) : Interp(I) {}
89
+ virtual ~InterpreterCallbacks ();
90
+ virtual void ProcessingTopLevelStmtDecl (TopLevelStmtDecl *D);
89
91
};
90
92
91
93
// / Provides top-level interfaces for incremental compilation and execution.
92
94
class Interpreter {
95
+ friend Value;
96
+
93
97
std::unique_ptr<llvm::orc::ThreadSafeContext> TSCtx;
98
+ std::unique_ptr<InterpreterCallbacks> InterpreterCB;
94
99
std::unique_ptr<IncrementalParser> IncrParser;
95
100
std::unique_ptr<IncrementalExecutor> IncrExecutor;
96
- std::unique_ptr<RuntimeInterfaceBuilder> RuntimeIB;
97
101
98
102
// An optional parser for CUDA offloading
99
103
std::unique_ptr<IncrementalParser> DeviceParser;
@@ -105,10 +109,16 @@ class Interpreter {
105
109
// printing happens, it's in an invalid state.
106
110
Value LastValue;
107
111
108
- // Add a call to an Expr to report its result. We query the function from
109
- // RuntimeInterfaceBuilder once and store it as a function pointer to avoid
110
- // frequent virtual function calls.
111
- RuntimeInterfaceBuilder::TransformExprFunction *AddPrintValueCall = nullptr ;
112
+ // The cached declaration of std::string used as a return type for the built
113
+ // trampoline. This is done in C++ to simplify the memory management for
114
+ // user-defined printing functions.
115
+ Decl *StdString = nullptr ;
116
+
117
+ // A cache for the compiled destructors used to for de-allocation of managed
118
+ // clang::Values.
119
+ llvm::DenseMap<CXXRecordDecl *, llvm::orc::ExecutorAddr> Dtors;
120
+
121
+ std::array<Expr *, 4 > ValuePrintingInfo = {0 };
112
122
113
123
protected:
114
124
// Derived classes can use an extended interface of the Interpreter.
@@ -123,23 +133,8 @@ class Interpreter {
123
133
// JIT engine. In particular, it doesn't run cleanup or destructors.
124
134
void ResetExecutor ();
125
135
126
- // Lazily construct the RuntimeInterfaceBuilder. The provided instance will be
127
- // used for the entire lifetime of the interpreter. The default implementation
128
- // targets the in-process __clang_Interpreter runtime. Override this to use a
129
- // custom runtime.
130
- virtual std::unique_ptr<RuntimeInterfaceBuilder> FindRuntimeInterface ();
131
-
132
136
public:
133
137
virtual ~Interpreter ();
134
-
135
- // class SynthesizingCodeRAII {
136
-
137
- // };
138
-
139
- // SynthesizingCodeRAII EnterCodeSynthesisScope() {
140
-
141
- // }
142
-
143
138
static llvm::Expected<std::unique_ptr<Interpreter>>
144
139
create (std::unique_ptr<CompilerInstance> CI);
145
140
static llvm::Expected<std::unique_ptr<Interpreter>>
@@ -154,7 +149,6 @@ class Interpreter {
154
149
llvm::Expected<PartialTranslationUnit &> Parse (llvm::StringRef Code);
155
150
llvm::Error Execute (PartialTranslationUnit &T);
156
151
llvm::Error ParseAndExecute (llvm::StringRef Code, Value *V = nullptr );
157
- llvm::Expected<llvm::orc::ExecutorAddr> CompileDtorCall (CXXRecordDecl *CXXRD);
158
152
159
153
// / Undo N previous incremental inputs.
160
154
llvm::Error Undo (unsigned N = 1 );
@@ -176,25 +170,32 @@ class Interpreter {
176
170
llvm::Expected<llvm::orc::ExecutorAddr>
177
171
getSymbolAddressFromLinkerName (llvm::StringRef LinkerName) const ;
178
172
179
- enum InterfaceKind { NoAlloc, WithAlloc, CopyArray, NewTag };
180
-
181
- const llvm::SmallVectorImpl<Expr *> &getValuePrintingInfo () const {
182
- return ValuePrintingInfo;
173
+ InterpreterCallbacks *getInterpreterCallbacks () {
174
+ return InterpreterCB.get ();
175
+ }
176
+ const InterpreterCallbacks *getInterpreterCallbacks () const {
177
+ return const_cast <Interpreter *>(this )->getInterpreterCallbacks ();
178
+ }
179
+ void setInterpreterCallbacks (std::unique_ptr<InterpreterCallbacks> CB) {
180
+ InterpreterCB = std::move (CB);
183
181
}
184
182
185
- Expr *SynthesizeExpr (Expr *E);
183
+ llvm::Expected< Expr *> SynthesizeExpr (Expr *E);
186
184
187
185
std::unique_ptr<llvm::Module> GenModule ();
188
186
189
187
private:
190
188
size_t getEffectivePTUSize () const ;
191
189
void markUserCodeStart ();
192
190
193
- llvm::DenseMap<CXXRecordDecl *, llvm::orc::ExecutorAddr> Dtors ;
191
+ std::unique_ptr< llvm::orc::LLJITBuilder> JITBuilder ;
194
192
195
- llvm::SmallVector<Expr *, 4 > ValuePrintingInfo;
193
+ std::string ValueDataToString (const Value &V);
194
+ std::string ValueTypeToString (const Value &V) const ;
196
195
197
- std::unique_ptr<llvm::orc::LLJITBuilder> JITBuilder;
196
+ // When we deallocate clang::Value we need to run the destructor of the type.
197
+ // This function forces emission of the needed dtor.
198
+ llvm::Expected<llvm::orc::ExecutorAddr> CompileDtorCall (CXXRecordDecl *CXXRD);
198
199
};
199
200
} // namespace clang
200
201
0 commit comments