Author: Anubhab Ghosh Date: 2023-03-29T08:04:50+05:30 New Revision: d978730d8e2c10c76867b83bec2f1143d895ee7d
URL: https://github.com/llvm/llvm-project/commit/d978730d8e2c10c76867b83bec2f1143d895ee7d DIFF: https://github.com/llvm/llvm-project/commit/d978730d8e2c10c76867b83bec2f1143d895ee7d.diff LOG: [clang-repl] Add a command to load dynamic libraries This commit adds the %lib <file> command to load a dynamic library to be used by the currently running interpreted code. For example `%lib libSDL2.so`. Differential Revision: https://reviews.llvm.org/D141824 Added: clang/test/Interpreter/Inputs/dynamic-library-test.cpp clang/test/Interpreter/dynamic-library.cpp Modified: clang/include/clang/Interpreter/Interpreter.h clang/lib/Interpreter/IncrementalExecutor.h clang/lib/Interpreter/Interpreter.cpp clang/tools/clang-repl/ClangRepl.cpp Removed: ################################################################################ diff --git a/clang/include/clang/Interpreter/Interpreter.h b/clang/include/clang/Interpreter/Interpreter.h index fd22af976613..b20d77e8ef85 100644 --- a/clang/include/clang/Interpreter/Interpreter.h +++ b/clang/include/clang/Interpreter/Interpreter.h @@ -28,7 +28,7 @@ namespace llvm { namespace orc { class LLJIT; class ThreadSafeContext; -} +} // namespace orc } // namespace llvm namespace clang { @@ -52,12 +52,15 @@ class Interpreter { Interpreter(std::unique_ptr<CompilerInstance> CI, llvm::Error &Err); + llvm::Error CreateExecutor(); + public: ~Interpreter(); static llvm::Expected<std::unique_ptr<Interpreter>> create(std::unique_ptr<CompilerInstance> CI); const CompilerInstance *getCompilerInstance() const; - const llvm::orc::LLJIT *getExecutionEngine() const; + llvm::Expected<llvm::orc::LLJIT &> getExecutionEngine(); + llvm::Expected<PartialTranslationUnit &> Parse(llvm::StringRef Code); llvm::Error Execute(PartialTranslationUnit &T); llvm::Error ParseAndExecute(llvm::StringRef Code) { @@ -72,6 +75,9 @@ class Interpreter { /// Undo N previous incremental inputs. llvm::Error Undo(unsigned N = 1); + /// Link a dynamic library + llvm::Error LoadDynamicLibrary(const char *name); + /// \returns the \c JITTargetAddress of a \c GlobalDecl. This interface uses /// the CodeGenModule's internal mangling cache to avoid recomputing the /// mangled name. diff --git a/clang/lib/Interpreter/IncrementalExecutor.h b/clang/lib/Interpreter/IncrementalExecutor.h index 54d37c76326b..f7922ecb5380 100644 --- a/clang/lib/Interpreter/IncrementalExecutor.h +++ b/clang/lib/Interpreter/IncrementalExecutor.h @@ -53,7 +53,8 @@ class IncrementalExecutor { llvm::Error cleanUp(); llvm::Expected<llvm::JITTargetAddress> getSymbolAddress(llvm::StringRef Name, SymbolNameKind NameKind) const; - llvm::orc::LLJIT *getExecutionEngine() const { return Jit.get(); } + + llvm::orc::LLJIT &GetExecutionEngine() { return *Jit; } }; } // end namespace clang diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp index 3f0842c567da..76d5f162a34a 100644 --- a/clang/lib/Interpreter/Interpreter.cpp +++ b/clang/lib/Interpreter/Interpreter.cpp @@ -29,6 +29,7 @@ #include "clang/Frontend/TextDiagnosticBuffer.h" #include "clang/Lex/PreprocessorOptions.h" +#include "llvm/ExecutionEngine/Orc/LLJIT.h" #include "llvm/IR/Module.h" #include "llvm/Support/Errc.h" #include "llvm/TargetParser/Host.h" @@ -203,10 +204,13 @@ const CompilerInstance *Interpreter::getCompilerInstance() const { return IncrParser->getCI(); } -const llvm::orc::LLJIT *Interpreter::getExecutionEngine() const { - if (IncrExecutor) - return IncrExecutor->getExecutionEngine(); - return nullptr; +llvm::Expected<llvm::orc::LLJIT &> Interpreter::getExecutionEngine() { + if (!IncrExecutor) { + if (auto Err = CreateExecutor()) + return Err; + } + + return IncrExecutor->GetExecutionEngine(); } llvm::Expected<PartialTranslationUnit &> @@ -214,14 +218,21 @@ Interpreter::Parse(llvm::StringRef Code) { return IncrParser->Parse(Code); } +llvm::Error Interpreter::CreateExecutor() { + const clang::TargetInfo &TI = + getCompilerInstance()->getASTContext().getTargetInfo(); + llvm::Error Err = llvm::Error::success(); + auto Executor = std::make_unique<IncrementalExecutor>(*TSCtx, Err, TI); + if (!Err) + IncrExecutor = std::move(Executor); + + return Err; +} + llvm::Error Interpreter::Execute(PartialTranslationUnit &T) { assert(T.TheModule); if (!IncrExecutor) { - const clang::TargetInfo &TI = - getCompilerInstance()->getASTContext().getTargetInfo(); - llvm::Error Err = llvm::Error::success(); - IncrExecutor = std::make_unique<IncrementalExecutor>(*TSCtx, Err, TI); - + auto Err = CreateExecutor(); if (Err) return Err; } @@ -283,3 +294,19 @@ llvm::Error Interpreter::Undo(unsigned N) { } return llvm::Error::success(); } + +llvm::Error Interpreter::LoadDynamicLibrary(const char *name) { + auto EE = getExecutionEngine(); + if (!EE) + return EE.takeError(); + + auto &DL = EE->getDataLayout(); + + if (auto DLSG = llvm::orc::DynamicLibrarySearchGenerator::Load( + name, DL.getGlobalPrefix())) + EE->getMainJITDylib().addGenerator(std::move(*DLSG)); + else + return DLSG.takeError(); + + return llvm::Error::success(); +} diff --git a/clang/test/Interpreter/Inputs/dynamic-library-test.cpp b/clang/test/Interpreter/Inputs/dynamic-library-test.cpp new file mode 100644 index 000000000000..1f143ba040cb --- /dev/null +++ b/clang/test/Interpreter/Inputs/dynamic-library-test.cpp @@ -0,0 +1,6 @@ +int ultimate_answer = 0; + +int calculate_answer() { + ultimate_answer = 42; + return 5; +} diff --git a/clang/test/Interpreter/dynamic-library.cpp b/clang/test/Interpreter/dynamic-library.cpp new file mode 100644 index 000000000000..794ccccf72d5 --- /dev/null +++ b/clang/test/Interpreter/dynamic-library.cpp @@ -0,0 +1,19 @@ +// REQUIRES: host-supports-jit, system-linux + +// RUN: %clang -xc++ -o %T/libdynamic-library-test.so -fPIC -shared -DLIBRARY %S/Inputs/dynamic-library-test.cpp +// RUN: cat %s | env LD_LIBRARY_PATH=%T:$LD_LIBRARY_PATH clang-repl | FileCheck %s + +#include <cstdio> + +extern int ultimate_answer; +int calculate_answer(); + +%lib libdynamic-library-test.so + +printf("Return value: %d\n", calculate_answer()); +// CHECK: Return value: 5 + +printf("Variable: %d\n", ultimate_answer); +// CHECK-NEXT: Variable: 42 + +%quit diff --git a/clang/tools/clang-repl/ClangRepl.cpp b/clang/tools/clang-repl/ClangRepl.cpp index 401a31d34063..33faf3fab58f 100644 --- a/clang/tools/clang-repl/ClangRepl.cpp +++ b/clang/tools/clang-repl/ClangRepl.cpp @@ -123,6 +123,13 @@ int main(int argc, const char **argv) { } continue; } + if (Line->rfind("%lib ", 0) == 0) { + if (auto Err = Interp->LoadDynamicLibrary(Line->data() + 5)) { + llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), "error: "); + HasError = true; + } + continue; + } if (auto Err = Interp->ParseAndExecute(*Line)) { llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), "error: "); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits