Skip to content

Commit cb7995a

Browse files
[clang-repl] Set up executor implicitly to account for init PTUs (#84758)
Until now the IncrExecutor was created lazily on the first execution request. In order to process the PTUs that come from initialization, we have to do it upfront implicitly.
1 parent 1383cb6 commit cb7995a

File tree

5 files changed

+73
-118
lines changed

5 files changed

+73
-118
lines changed

clang/include/clang/Interpreter/Interpreter.h

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -110,9 +110,9 @@ class Interpreter {
110110
RuntimeInterfaceBuilder::TransformExprFunction *AddPrintValueCall = nullptr;
111111

112112
protected:
113-
// Derived classes can make use an extended interface of the Interpreter.
114-
// That's useful for testing and out-of-tree clients.
115-
Interpreter(std::unique_ptr<CompilerInstance> CI, llvm::Error &Err);
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);
116116

117117
// Create the internal IncrementalExecutor, or re-create it after calling
118118
// ResetExecutor().
@@ -128,13 +128,6 @@ class Interpreter {
128128
// custom runtime.
129129
virtual std::unique_ptr<RuntimeInterfaceBuilder> FindRuntimeInterface();
130130

131-
// Lazily construct thev ORCv2 JITBuilder. This called when the internal
132-
// IncrementalExecutor is created. The default implementation populates an
133-
// in-process JIT with debugging support. Override this to configure the JIT
134-
// engine used for execution.
135-
virtual llvm::Expected<std::unique_ptr<llvm::orc::LLJITBuilder>>
136-
CreateJITBuilder(CompilerInstance &CI);
137-
138131
public:
139132
virtual ~Interpreter();
140133

@@ -189,6 +182,8 @@ class Interpreter {
189182
llvm::DenseMap<CXXRecordDecl *, llvm::orc::ExecutorAddr> Dtors;
190183

191184
llvm::SmallVector<Expr *, 4> ValuePrintingInfo;
185+
186+
std::unique_ptr<llvm::orc::LLJITBuilder> JITBuilder;
192187
};
193188
} // namespace clang
194189

clang/lib/Interpreter/Interpreter.cpp

Lines changed: 41 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -229,12 +229,32 @@ IncrementalCompilerBuilder::CreateCudaHost() {
229229
}
230230

231231
Interpreter::Interpreter(std::unique_ptr<CompilerInstance> CI,
232-
llvm::Error &Err) {
233-
llvm::ErrorAsOutParameter EAO(&Err);
232+
llvm::Error &ErrOut,
233+
std::unique_ptr<llvm::orc::LLJITBuilder> JITBuilder)
234+
: JITBuilder(std::move(JITBuilder)) {
235+
llvm::ErrorAsOutParameter EAO(&ErrOut);
234236
auto LLVMCtx = std::make_unique<llvm::LLVMContext>();
235237
TSCtx = std::make_unique<llvm::orc::ThreadSafeContext>(std::move(LLVMCtx));
236-
IncrParser = std::make_unique<IncrementalParser>(*this, std::move(CI),
237-
*TSCtx->getContext(), Err);
238+
IncrParser = std::make_unique<IncrementalParser>(
239+
*this, std::move(CI), *TSCtx->getContext(), ErrOut);
240+
if (ErrOut)
241+
return;
242+
243+
// Not all frontends support code-generation, e.g. ast-dump actions don't
244+
if (IncrParser->getCodeGen()) {
245+
if (llvm::Error Err = CreateExecutor()) {
246+
ErrOut = joinErrors(std::move(ErrOut), std::move(Err));
247+
return;
248+
}
249+
250+
// Process the PTUs that came from initialization. For example -include will
251+
// give us a header that's processed at initialization of the preprocessor.
252+
for (PartialTranslationUnit &PTU : IncrParser->getPTUs())
253+
if (llvm::Error Err = Execute(PTU)) {
254+
ErrOut = joinErrors(std::move(ErrOut), std::move(Err));
255+
return;
256+
}
257+
}
238258
}
239259

240260
Interpreter::~Interpreter() {
@@ -382,25 +402,29 @@ createJITTargetMachineBuilder(const std::string &TT) {
382402
return llvm::orc::JITTargetMachineBuilder(llvm::Triple(TT));
383403
}
384404

385-
llvm::Expected<std::unique_ptr<llvm::orc::LLJITBuilder>>
386-
Interpreter::CreateJITBuilder(CompilerInstance &CI) {
387-
auto JTMB = createJITTargetMachineBuilder(CI.getTargetOpts().Triple);
388-
if (!JTMB)
389-
return JTMB.takeError();
390-
return IncrementalExecutor::createDefaultJITBuilder(std::move(*JTMB));
391-
}
392-
393405
llvm::Error Interpreter::CreateExecutor() {
394406
if (IncrExecutor)
395407
return llvm::make_error<llvm::StringError>("Operation failed. "
396408
"Execution engine exists",
397409
std::error_code());
398-
llvm::Expected<std::unique_ptr<llvm::orc::LLJITBuilder>> JB =
399-
CreateJITBuilder(*getCompilerInstance());
400-
if (!JB)
401-
return JB.takeError();
410+
if (!IncrParser->getCodeGen())
411+
return llvm::make_error<llvm::StringError>("Operation failed. "
412+
"No code generator available",
413+
std::error_code());
414+
if (!JITBuilder) {
415+
const std::string &TT = getCompilerInstance()->getTargetOpts().Triple;
416+
auto JTMB = createJITTargetMachineBuilder(TT);
417+
if (!JTMB)
418+
return JTMB.takeError();
419+
auto JB = IncrementalExecutor::createDefaultJITBuilder(std::move(*JTMB));
420+
if (!JB)
421+
return JB.takeError();
422+
JITBuilder = std::move(*JB);
423+
}
424+
402425
llvm::Error Err = llvm::Error::success();
403-
auto Executor = std::make_unique<IncrementalExecutor>(*TSCtx, **JB, Err);
426+
auto Executor =
427+
std::make_unique<IncrementalExecutor>(*TSCtx, *JITBuilder, Err);
404428
if (!Err)
405429
IncrExecutor = std::move(Executor);
406430

clang/test/Interpreter/execute.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77

88
// RUN: cat %s | clang-repl | FileCheck %s
99
// RUN: cat %s | clang-repl -Xcc -O2 | FileCheck %s
10+
// RUN: clang-repl -Xcc -include -Xcc %s | FileCheck %s
11+
// RUN: clang-repl -Xcc -fsyntax-only -Xcc -include -Xcc %s
1012
extern "C" int printf(const char *, ...);
1113
int i = 42;
1214
auto r1 = printf("i = %d\n", i);
@@ -19,5 +21,3 @@ auto r2 = printf("S[f=%f, m=0x%llx]\n", s.f, reinterpret_cast<unsigned long long
1921

2022
inline int foo() { return 42; }
2123
int r3 = foo();
22-
23-
%quit

clang/test/Interpreter/inline-virtual.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ struct A { int a; A(int a) : a(a) {} virtual ~A(); };
1414
// PartialTranslationUnit.
1515
inline A::~A() { printf("~A(%d)\n", a); }
1616

17-
// Create one instance with new and delete it.
17+
// Create one instance with new and delete it. We crash here now:
1818
A *a1 = new A(1);
1919
delete a1;
2020
// CHECK: ~A(1)

clang/unittests/Interpreter/InterpreterExtensionsTest.cpp

Lines changed: 24 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -66,58 +66,6 @@ struct LLVMInitRAII {
6666
~LLVMInitRAII() { llvm::llvm_shutdown(); }
6767
} LLVMInit;
6868

69-
class TestCreateResetExecutor : public Interpreter {
70-
public:
71-
TestCreateResetExecutor(std::unique_ptr<CompilerInstance> CI,
72-
llvm::Error &Err)
73-
: Interpreter(std::move(CI), Err) {}
74-
75-
llvm::Error testCreateJITBuilderError() {
76-
JB = nullptr;
77-
return Interpreter::CreateExecutor();
78-
}
79-
80-
llvm::Error testCreateExecutor() {
81-
JB = std::make_unique<llvm::orc::LLJITBuilder>();
82-
return Interpreter::CreateExecutor();
83-
}
84-
85-
void resetExecutor() { Interpreter::ResetExecutor(); }
86-
87-
private:
88-
llvm::Expected<std::unique_ptr<llvm::orc::LLJITBuilder>>
89-
CreateJITBuilder(CompilerInstance &CI) override {
90-
if (JB)
91-
return std::move(JB);
92-
return llvm::make_error<llvm::StringError>("TestError", std::error_code());
93-
}
94-
95-
std::unique_ptr<llvm::orc::LLJITBuilder> JB;
96-
};
97-
98-
#ifdef CLANG_INTERPRETER_PLATFORM_CANNOT_CREATE_LLJIT
99-
TEST(InterpreterExtensionsTest, DISABLED_ExecutorCreateReset) {
100-
#else
101-
TEST(InterpreterExtensionsTest, ExecutorCreateReset) {
102-
#endif
103-
// Make sure we can create the executer on the platform.
104-
if (!HostSupportsJit())
105-
GTEST_SKIP();
106-
107-
clang::IncrementalCompilerBuilder CB;
108-
llvm::Error ErrOut = llvm::Error::success();
109-
TestCreateResetExecutor Interp(cantFail(CB.CreateCpp()), ErrOut);
110-
cantFail(std::move(ErrOut));
111-
EXPECT_THAT_ERROR(Interp.testCreateJITBuilderError(),
112-
llvm::FailedWithMessage("TestError"));
113-
cantFail(Interp.testCreateExecutor());
114-
Interp.resetExecutor();
115-
cantFail(Interp.testCreateExecutor());
116-
EXPECT_THAT_ERROR(Interp.testCreateExecutor(),
117-
llvm::FailedWithMessage("Operation failed. "
118-
"Execution engine exists"));
119-
}
120-
12169
class RecordRuntimeIBMetrics : public Interpreter {
12270
struct NoopRuntimeInterfaceBuilder : public RuntimeInterfaceBuilder {
12371
NoopRuntimeInterfaceBuilder(Sema &S) : S(S) {}
@@ -173,25 +121,15 @@ class CustomJBInterpreter : public Interpreter {
173121
CustomJITBuilderCreatorFunction JBCreator = nullptr;
174122

175123
public:
176-
CustomJBInterpreter(std::unique_ptr<CompilerInstance> CI, llvm::Error &ErrOut)
177-
: Interpreter(std::move(CI), ErrOut) {}
124+
CustomJBInterpreter(std::unique_ptr<CompilerInstance> CI, llvm::Error &ErrOut,
125+
std::unique_ptr<llvm::orc::LLJITBuilder> JB)
126+
: Interpreter(std::move(CI), ErrOut, std::move(JB)) {}
178127

179128
~CustomJBInterpreter() override {
180129
// Skip cleanUp() because it would trigger LLJIT default dtors
181130
Interpreter::ResetExecutor();
182131
}
183132

184-
void setCustomJITBuilderCreator(CustomJITBuilderCreatorFunction Fn) {
185-
JBCreator = std::move(Fn);
186-
}
187-
188-
llvm::Expected<std::unique_ptr<llvm::orc::LLJITBuilder>>
189-
CreateJITBuilder(CompilerInstance &CI) override {
190-
if (JBCreator)
191-
return JBCreator();
192-
return Interpreter::CreateJITBuilder(CI);
193-
}
194-
195133
llvm::Error CreateExecutor() { return Interpreter::CreateExecutor(); }
196134
};
197135

@@ -207,9 +145,8 @@ TEST(InterpreterExtensionsTest, DefaultCrossJIT) {
207145
CB.SetTargetTriple("armv6-none-eabi");
208146
auto CI = cantFail(CB.CreateCpp());
209147
llvm::Error ErrOut = llvm::Error::success();
210-
CustomJBInterpreter Interp(std::move(CI), ErrOut);
148+
CustomJBInterpreter Interp(std::move(CI), ErrOut, nullptr);
211149
cantFail(std::move(ErrOut));
212-
cantFail(Interp.CreateExecutor());
213150
}
214151

215152
#ifdef CLANG_INTERPRETER_PLATFORM_CANNOT_CREATE_LLJIT
@@ -225,35 +162,34 @@ TEST(InterpreterExtensionsTest, CustomCrossJIT) {
225162
IncrementalCompilerBuilder CB;
226163
CB.SetTargetTriple(TargetTriple);
227164
auto CI = cantFail(CB.CreateCpp());
228-
llvm::Error ErrOut = llvm::Error::success();
229-
CustomJBInterpreter Interp(std::move(CI), ErrOut);
230-
cantFail(std::move(ErrOut));
231165

232166
using namespace llvm::orc;
233167
LLJIT *JIT = nullptr;
234168
std::vector<std::unique_ptr<llvm::MemoryBuffer>> Objs;
235-
Interp.setCustomJITBuilderCreator([&]() {
236-
auto JTMB = JITTargetMachineBuilder(llvm::Triple(TargetTriple));
237-
JTMB.setCPU("cortex-m0plus");
238-
auto JB = std::make_unique<LLJITBuilder>();
239-
JB->setJITTargetMachineBuilder(JTMB);
240-
JB->setPlatformSetUp(setUpInactivePlatform);
241-
JB->setNotifyCreatedCallback([&](LLJIT &J) {
242-
ObjectLayer &ObjLayer = J.getObjLinkingLayer();
243-
auto *JITLinkObjLayer = llvm::dyn_cast<ObjectLinkingLayer>(&ObjLayer);
244-
JITLinkObjLayer->setReturnObjectBuffer(
245-
[&Objs](std::unique_ptr<llvm::MemoryBuffer> MB) {
246-
Objs.push_back(std::move(MB));
247-
});
248-
JIT = &J;
249-
return llvm::Error::success();
250-
});
251-
return JB;
169+
auto JTMB = JITTargetMachineBuilder(llvm::Triple(TargetTriple));
170+
JTMB.setCPU("cortex-m0plus");
171+
172+
auto JB = std::make_unique<LLJITBuilder>();
173+
JB->setJITTargetMachineBuilder(JTMB);
174+
JB->setPlatformSetUp(setUpInactivePlatform);
175+
JB->setNotifyCreatedCallback([&](LLJIT &J) {
176+
ObjectLayer &ObjLayer = J.getObjLinkingLayer();
177+
auto *JITLinkObjLayer = llvm::dyn_cast<ObjectLinkingLayer>(&ObjLayer);
178+
JITLinkObjLayer->setReturnObjectBuffer(
179+
[&Objs](std::unique_ptr<llvm::MemoryBuffer> MB) {
180+
Objs.push_back(std::move(MB));
181+
});
182+
JIT = &J;
183+
return llvm::Error::success();
252184
});
253185

186+
llvm::Error ErrOut = llvm::Error::success();
187+
CustomJBInterpreter Interp(std::move(CI), ErrOut, std::move(JB));
188+
cantFail(std::move(ErrOut));
189+
254190
EXPECT_EQ(0U, Objs.size());
255-
cantFail(Interp.CreateExecutor());
256191
cantFail(Interp.ParseAndExecute("int a = 1;"));
192+
ASSERT_NE(JIT, nullptr); // But it is, because JBCreator was never called
257193
ExecutorAddr Addr = cantFail(JIT->lookup("a"));
258194
EXPECT_NE(0U, Addr.getValue());
259195
EXPECT_EQ(1U, Objs.size());

0 commit comments

Comments
 (0)