[clang-repl] Support destructors of global objects.

Supports destructors of global objects by properly calling jitdylib deinitialize which calls the global dtors of ir modules.

This supersedes https://reviews.llvm.org/D127945. There was an issue when calling deinitialize on windows but it got fixed by https://reviews.llvm.org/D128037.

Reviewed By: v.g.vassilev

Differential Revision: https://reviews.llvm.org/D128589
This commit is contained in:
Sunho Kim 2022-07-29 02:37:16 +09:00
parent aeb1c98f4c
commit c619d4f840
7 changed files with 46 additions and 3 deletions

View File

@ -76,6 +76,12 @@ llvm::Error IncrementalExecutor::removeModule(PartialTranslationUnit &PTU) {
return llvm::Error::success();
}
// Clean up the JIT instance.
llvm::Error IncrementalExecutor::cleanUp() {
// This calls the global dtors of registered modules.
return Jit->deinitialize(Jit->getMainJITDylib());
}
llvm::Error IncrementalExecutor::runCtors() const {
return Jit->initialize(Jit->getMainJITDylib());
}

View File

@ -50,6 +50,7 @@ public:
llvm::Error addModule(PartialTranslationUnit &PTU);
llvm::Error removeModule(PartialTranslationUnit &PTU);
llvm::Error runCtors() const;
llvm::Error cleanUp();
llvm::Expected<llvm::JITTargetAddress>
getSymbolAddress(llvm::StringRef Name, SymbolNameKind NameKind) const;
llvm::orc::LLJIT *getExecutionEngine() const { return Jit.get(); }

View File

@ -183,7 +183,14 @@ Interpreter::Interpreter(std::unique_ptr<CompilerInstance> CI,
*TSCtx->getContext(), Err);
}
Interpreter::~Interpreter() {}
Interpreter::~Interpreter() {
if (IncrExecutor) {
if (llvm::Error Err = IncrExecutor->cleanUp())
llvm::report_fatal_error(
llvm::Twine("Failed to clean up IncrementalExecutor: ") +
toString(std::move(Err)));
}
}
llvm::Expected<std::unique_ptr<Interpreter>>
Interpreter::create(std::unique_ptr<CompilerInstance> CI) {

View File

@ -1,3 +1,4 @@
// clang-format off
// RUN: clang-repl "int x = 10;" "int y=7; err;" "int y = 10;"
// RUN: clang-repl "int i = 10;" 'extern "C" int printf(const char*,...);' \
// RUN: 'auto r1 = printf("i = %d\n", i);' | FileCheck --check-prefix=CHECK-DRIVER %s

View File

@ -0,0 +1,14 @@
// clang-format off
// FIXME: Merge into global-dtor.cpp when exception support arrives on windows-msvc
// REQUIRES: host-supports-jit && windows-msvc
//
// Tests that a global destructor is ran in windows-msvc platform.
//
// RUN: cat %s | clang-repl | FileCheck %s
extern "C" int printf(const char *, ... );
struct D { float f = 1.0; D *m = nullptr; D(){} ~D() { printf("D[f=%f, m=0x%llx]\n", f, reinterpret_cast<unsigned long long>(m)); }} d;
// CHECK: D[f=1.000000, m=0x0]
%quit

View File

@ -0,0 +1,14 @@
// clang-format off
// REQUIRES: host-supports-jit, host-supports-exception
// UNSUPPORTED: system-aix
//
// Tests that a global destructor is ran on platforms with gnu exception support.
//
// RUN: cat %s | clang-repl | FileCheck %s
extern "C" int printf(const char *, ...);
struct D { float f = 1.0; D *m = nullptr; D(){} ~D() { printf("D[f=%f, m=0x%llx]\n", f, reinterpret_cast<unsigned long long>(m)); }} d;
// CHECK: D[f=1.000000, m=0x0]
%quit

View File

@ -108,6 +108,8 @@ int main(int argc, const char **argv) {
ExitOnErr.setBanner("clang-repl: ");
llvm::cl::ParseCommandLineOptions(argc, argv);
llvm::llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
std::vector<const char *> ClangArgv(ClangArgs.size());
std::transform(ClangArgs.begin(), ClangArgs.end(), ClangArgv.begin(),
[](const std::string &s) -> const char * { return s.data(); });
@ -173,7 +175,5 @@ int main(int argc, const char **argv) {
// later errors use the default handling behavior instead.
llvm::remove_fatal_error_handler();
llvm::llvm_shutdown();
return checkDiagErrors(Interp->getCompilerInstance());
}