mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-24 04:16:08 +00:00
[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.
This commit is contained in:
parent
1383cb6e64
commit
cb7995a130
@ -110,9 +110,9 @@ class Interpreter {
|
||||
RuntimeInterfaceBuilder::TransformExprFunction *AddPrintValueCall = nullptr;
|
||||
|
||||
protected:
|
||||
// Derived classes can make use an extended interface of the Interpreter.
|
||||
// That's useful for testing and out-of-tree clients.
|
||||
Interpreter(std::unique_ptr<CompilerInstance> CI, llvm::Error &Err);
|
||||
// Derived classes can use an extended interface of the Interpreter.
|
||||
Interpreter(std::unique_ptr<CompilerInstance> CI, llvm::Error &Err,
|
||||
std::unique_ptr<llvm::orc::LLJITBuilder> JITBuilder = nullptr);
|
||||
|
||||
// Create the internal IncrementalExecutor, or re-create it after calling
|
||||
// ResetExecutor().
|
||||
@ -128,13 +128,6 @@ protected:
|
||||
// custom runtime.
|
||||
virtual std::unique_ptr<RuntimeInterfaceBuilder> FindRuntimeInterface();
|
||||
|
||||
// Lazily construct thev ORCv2 JITBuilder. This called when the internal
|
||||
// IncrementalExecutor is created. The default implementation populates an
|
||||
// in-process JIT with debugging support. Override this to configure the JIT
|
||||
// engine used for execution.
|
||||
virtual llvm::Expected<std::unique_ptr<llvm::orc::LLJITBuilder>>
|
||||
CreateJITBuilder(CompilerInstance &CI);
|
||||
|
||||
public:
|
||||
virtual ~Interpreter();
|
||||
|
||||
@ -189,6 +182,8 @@ private:
|
||||
llvm::DenseMap<CXXRecordDecl *, llvm::orc::ExecutorAddr> Dtors;
|
||||
|
||||
llvm::SmallVector<Expr *, 4> ValuePrintingInfo;
|
||||
|
||||
std::unique_ptr<llvm::orc::LLJITBuilder> JITBuilder;
|
||||
};
|
||||
} // namespace clang
|
||||
|
||||
|
@ -229,12 +229,32 @@ IncrementalCompilerBuilder::CreateCudaHost() {
|
||||
}
|
||||
|
||||
Interpreter::Interpreter(std::unique_ptr<CompilerInstance> CI,
|
||||
llvm::Error &Err) {
|
||||
llvm::ErrorAsOutParameter EAO(&Err);
|
||||
llvm::Error &ErrOut,
|
||||
std::unique_ptr<llvm::orc::LLJITBuilder> JITBuilder)
|
||||
: JITBuilder(std::move(JITBuilder)) {
|
||||
llvm::ErrorAsOutParameter EAO(&ErrOut);
|
||||
auto LLVMCtx = std::make_unique<llvm::LLVMContext>();
|
||||
TSCtx = std::make_unique<llvm::orc::ThreadSafeContext>(std::move(LLVMCtx));
|
||||
IncrParser = std::make_unique<IncrementalParser>(*this, std::move(CI),
|
||||
*TSCtx->getContext(), Err);
|
||||
IncrParser = std::make_unique<IncrementalParser>(
|
||||
*this, std::move(CI), *TSCtx->getContext(), ErrOut);
|
||||
if (ErrOut)
|
||||
return;
|
||||
|
||||
// Not all frontends support code-generation, e.g. ast-dump actions don't
|
||||
if (IncrParser->getCodeGen()) {
|
||||
if (llvm::Error Err = CreateExecutor()) {
|
||||
ErrOut = joinErrors(std::move(ErrOut), std::move(Err));
|
||||
return;
|
||||
}
|
||||
|
||||
// Process the PTUs that came from initialization. For example -include will
|
||||
// give us a header that's processed at initialization of the preprocessor.
|
||||
for (PartialTranslationUnit &PTU : IncrParser->getPTUs())
|
||||
if (llvm::Error Err = Execute(PTU)) {
|
||||
ErrOut = joinErrors(std::move(ErrOut), std::move(Err));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Interpreter::~Interpreter() {
|
||||
@ -382,25 +402,29 @@ createJITTargetMachineBuilder(const std::string &TT) {
|
||||
return llvm::orc::JITTargetMachineBuilder(llvm::Triple(TT));
|
||||
}
|
||||
|
||||
llvm::Expected<std::unique_ptr<llvm::orc::LLJITBuilder>>
|
||||
Interpreter::CreateJITBuilder(CompilerInstance &CI) {
|
||||
auto JTMB = createJITTargetMachineBuilder(CI.getTargetOpts().Triple);
|
||||
if (!JTMB)
|
||||
return JTMB.takeError();
|
||||
return IncrementalExecutor::createDefaultJITBuilder(std::move(*JTMB));
|
||||
}
|
||||
|
||||
llvm::Error Interpreter::CreateExecutor() {
|
||||
if (IncrExecutor)
|
||||
return llvm::make_error<llvm::StringError>("Operation failed. "
|
||||
"Execution engine exists",
|
||||
std::error_code());
|
||||
llvm::Expected<std::unique_ptr<llvm::orc::LLJITBuilder>> JB =
|
||||
CreateJITBuilder(*getCompilerInstance());
|
||||
if (!JB)
|
||||
return JB.takeError();
|
||||
if (!IncrParser->getCodeGen())
|
||||
return llvm::make_error<llvm::StringError>("Operation failed. "
|
||||
"No code generator available",
|
||||
std::error_code());
|
||||
if (!JITBuilder) {
|
||||
const std::string &TT = getCompilerInstance()->getTargetOpts().Triple;
|
||||
auto JTMB = createJITTargetMachineBuilder(TT);
|
||||
if (!JTMB)
|
||||
return JTMB.takeError();
|
||||
auto JB = IncrementalExecutor::createDefaultJITBuilder(std::move(*JTMB));
|
||||
if (!JB)
|
||||
return JB.takeError();
|
||||
JITBuilder = std::move(*JB);
|
||||
}
|
||||
|
||||
llvm::Error Err = llvm::Error::success();
|
||||
auto Executor = std::make_unique<IncrementalExecutor>(*TSCtx, **JB, Err);
|
||||
auto Executor =
|
||||
std::make_unique<IncrementalExecutor>(*TSCtx, *JITBuilder, Err);
|
||||
if (!Err)
|
||||
IncrExecutor = std::move(Executor);
|
||||
|
||||
|
@ -7,6 +7,8 @@
|
||||
|
||||
// RUN: cat %s | clang-repl | FileCheck %s
|
||||
// RUN: cat %s | clang-repl -Xcc -O2 | FileCheck %s
|
||||
// RUN: clang-repl -Xcc -include -Xcc %s | FileCheck %s
|
||||
// RUN: clang-repl -Xcc -fsyntax-only -Xcc -include -Xcc %s
|
||||
extern "C" int printf(const char *, ...);
|
||||
int i = 42;
|
||||
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
|
||||
|
||||
inline int foo() { return 42; }
|
||||
int r3 = foo();
|
||||
|
||||
%quit
|
||||
|
@ -14,7 +14,7 @@ struct A { int a; A(int a) : a(a) {} virtual ~A(); };
|
||||
// PartialTranslationUnit.
|
||||
inline A::~A() { printf("~A(%d)\n", a); }
|
||||
|
||||
// Create one instance with new and delete it.
|
||||
// Create one instance with new and delete it. We crash here now:
|
||||
A *a1 = new A(1);
|
||||
delete a1;
|
||||
// CHECK: ~A(1)
|
||||
|
@ -66,58 +66,6 @@ struct LLVMInitRAII {
|
||||
~LLVMInitRAII() { llvm::llvm_shutdown(); }
|
||||
} LLVMInit;
|
||||
|
||||
class TestCreateResetExecutor : public Interpreter {
|
||||
public:
|
||||
TestCreateResetExecutor(std::unique_ptr<CompilerInstance> CI,
|
||||
llvm::Error &Err)
|
||||
: Interpreter(std::move(CI), Err) {}
|
||||
|
||||
llvm::Error testCreateJITBuilderError() {
|
||||
JB = nullptr;
|
||||
return Interpreter::CreateExecutor();
|
||||
}
|
||||
|
||||
llvm::Error testCreateExecutor() {
|
||||
JB = std::make_unique<llvm::orc::LLJITBuilder>();
|
||||
return Interpreter::CreateExecutor();
|
||||
}
|
||||
|
||||
void resetExecutor() { Interpreter::ResetExecutor(); }
|
||||
|
||||
private:
|
||||
llvm::Expected<std::unique_ptr<llvm::orc::LLJITBuilder>>
|
||||
CreateJITBuilder(CompilerInstance &CI) override {
|
||||
if (JB)
|
||||
return std::move(JB);
|
||||
return llvm::make_error<llvm::StringError>("TestError", std::error_code());
|
||||
}
|
||||
|
||||
std::unique_ptr<llvm::orc::LLJITBuilder> JB;
|
||||
};
|
||||
|
||||
#ifdef CLANG_INTERPRETER_PLATFORM_CANNOT_CREATE_LLJIT
|
||||
TEST(InterpreterExtensionsTest, DISABLED_ExecutorCreateReset) {
|
||||
#else
|
||||
TEST(InterpreterExtensionsTest, ExecutorCreateReset) {
|
||||
#endif
|
||||
// Make sure we can create the executer on the platform.
|
||||
if (!HostSupportsJit())
|
||||
GTEST_SKIP();
|
||||
|
||||
clang::IncrementalCompilerBuilder CB;
|
||||
llvm::Error ErrOut = llvm::Error::success();
|
||||
TestCreateResetExecutor Interp(cantFail(CB.CreateCpp()), ErrOut);
|
||||
cantFail(std::move(ErrOut));
|
||||
EXPECT_THAT_ERROR(Interp.testCreateJITBuilderError(),
|
||||
llvm::FailedWithMessage("TestError"));
|
||||
cantFail(Interp.testCreateExecutor());
|
||||
Interp.resetExecutor();
|
||||
cantFail(Interp.testCreateExecutor());
|
||||
EXPECT_THAT_ERROR(Interp.testCreateExecutor(),
|
||||
llvm::FailedWithMessage("Operation failed. "
|
||||
"Execution engine exists"));
|
||||
}
|
||||
|
||||
class RecordRuntimeIBMetrics : public Interpreter {
|
||||
struct NoopRuntimeInterfaceBuilder : public RuntimeInterfaceBuilder {
|
||||
NoopRuntimeInterfaceBuilder(Sema &S) : S(S) {}
|
||||
@ -173,25 +121,15 @@ class CustomJBInterpreter : public Interpreter {
|
||||
CustomJITBuilderCreatorFunction JBCreator = nullptr;
|
||||
|
||||
public:
|
||||
CustomJBInterpreter(std::unique_ptr<CompilerInstance> CI, llvm::Error &ErrOut)
|
||||
: Interpreter(std::move(CI), ErrOut) {}
|
||||
CustomJBInterpreter(std::unique_ptr<CompilerInstance> CI, llvm::Error &ErrOut,
|
||||
std::unique_ptr<llvm::orc::LLJITBuilder> JB)
|
||||
: Interpreter(std::move(CI), ErrOut, std::move(JB)) {}
|
||||
|
||||
~CustomJBInterpreter() override {
|
||||
// Skip cleanUp() because it would trigger LLJIT default dtors
|
||||
Interpreter::ResetExecutor();
|
||||
}
|
||||
|
||||
void setCustomJITBuilderCreator(CustomJITBuilderCreatorFunction Fn) {
|
||||
JBCreator = std::move(Fn);
|
||||
}
|
||||
|
||||
llvm::Expected<std::unique_ptr<llvm::orc::LLJITBuilder>>
|
||||
CreateJITBuilder(CompilerInstance &CI) override {
|
||||
if (JBCreator)
|
||||
return JBCreator();
|
||||
return Interpreter::CreateJITBuilder(CI);
|
||||
}
|
||||
|
||||
llvm::Error CreateExecutor() { return Interpreter::CreateExecutor(); }
|
||||
};
|
||||
|
||||
@ -207,9 +145,8 @@ TEST(InterpreterExtensionsTest, DefaultCrossJIT) {
|
||||
CB.SetTargetTriple("armv6-none-eabi");
|
||||
auto CI = cantFail(CB.CreateCpp());
|
||||
llvm::Error ErrOut = llvm::Error::success();
|
||||
CustomJBInterpreter Interp(std::move(CI), ErrOut);
|
||||
CustomJBInterpreter Interp(std::move(CI), ErrOut, nullptr);
|
||||
cantFail(std::move(ErrOut));
|
||||
cantFail(Interp.CreateExecutor());
|
||||
}
|
||||
|
||||
#ifdef CLANG_INTERPRETER_PLATFORM_CANNOT_CREATE_LLJIT
|
||||
@ -225,35 +162,34 @@ TEST(InterpreterExtensionsTest, CustomCrossJIT) {
|
||||
IncrementalCompilerBuilder CB;
|
||||
CB.SetTargetTriple(TargetTriple);
|
||||
auto CI = cantFail(CB.CreateCpp());
|
||||
llvm::Error ErrOut = llvm::Error::success();
|
||||
CustomJBInterpreter Interp(std::move(CI), ErrOut);
|
||||
cantFail(std::move(ErrOut));
|
||||
|
||||
using namespace llvm::orc;
|
||||
LLJIT *JIT = nullptr;
|
||||
std::vector<std::unique_ptr<llvm::MemoryBuffer>> Objs;
|
||||
Interp.setCustomJITBuilderCreator([&]() {
|
||||
auto JTMB = JITTargetMachineBuilder(llvm::Triple(TargetTriple));
|
||||
JTMB.setCPU("cortex-m0plus");
|
||||
auto JB = std::make_unique<LLJITBuilder>();
|
||||
JB->setJITTargetMachineBuilder(JTMB);
|
||||
JB->setPlatformSetUp(setUpInactivePlatform);
|
||||
JB->setNotifyCreatedCallback([&](LLJIT &J) {
|
||||
ObjectLayer &ObjLayer = J.getObjLinkingLayer();
|
||||
auto *JITLinkObjLayer = llvm::dyn_cast<ObjectLinkingLayer>(&ObjLayer);
|
||||
JITLinkObjLayer->setReturnObjectBuffer(
|
||||
[&Objs](std::unique_ptr<llvm::MemoryBuffer> MB) {
|
||||
Objs.push_back(std::move(MB));
|
||||
});
|
||||
JIT = &J;
|
||||
return llvm::Error::success();
|
||||
});
|
||||
return JB;
|
||||
auto JTMB = JITTargetMachineBuilder(llvm::Triple(TargetTriple));
|
||||
JTMB.setCPU("cortex-m0plus");
|
||||
|
||||
auto JB = std::make_unique<LLJITBuilder>();
|
||||
JB->setJITTargetMachineBuilder(JTMB);
|
||||
JB->setPlatformSetUp(setUpInactivePlatform);
|
||||
JB->setNotifyCreatedCallback([&](LLJIT &J) {
|
||||
ObjectLayer &ObjLayer = J.getObjLinkingLayer();
|
||||
auto *JITLinkObjLayer = llvm::dyn_cast<ObjectLinkingLayer>(&ObjLayer);
|
||||
JITLinkObjLayer->setReturnObjectBuffer(
|
||||
[&Objs](std::unique_ptr<llvm::MemoryBuffer> MB) {
|
||||
Objs.push_back(std::move(MB));
|
||||
});
|
||||
JIT = &J;
|
||||
return llvm::Error::success();
|
||||
});
|
||||
|
||||
llvm::Error ErrOut = llvm::Error::success();
|
||||
CustomJBInterpreter Interp(std::move(CI), ErrOut, std::move(JB));
|
||||
cantFail(std::move(ErrOut));
|
||||
|
||||
EXPECT_EQ(0U, Objs.size());
|
||||
cantFail(Interp.CreateExecutor());
|
||||
cantFail(Interp.ParseAndExecute("int a = 1;"));
|
||||
ASSERT_NE(JIT, nullptr); // But it is, because JBCreator was never called
|
||||
ExecutorAddr Addr = cantFail(JIT->lookup("a"));
|
||||
EXPECT_NE(0U, Addr.getValue());
|
||||
EXPECT_EQ(1U, Objs.size());
|
||||
|
Loading…
x
Reference in New Issue
Block a user