mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-27 04:36:06 +00:00
[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
This commit is contained in:
parent
504df554d2
commit
d978730d8e
@ -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 @@ public:
|
||||
/// 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.
|
||||
|
@ -53,7 +53,8 @@ public:
|
||||
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
|
||||
|
@ -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();
|
||||
}
|
||||
|
6
clang/test/Interpreter/Inputs/dynamic-library-test.cpp
Normal file
6
clang/test/Interpreter/Inputs/dynamic-library-test.cpp
Normal file
@ -0,0 +1,6 @@
|
||||
int ultimate_answer = 0;
|
||||
|
||||
int calculate_answer() {
|
||||
ultimate_answer = 42;
|
||||
return 5;
|
||||
}
|
19
clang/test/Interpreter/dynamic-library.cpp
Normal file
19
clang/test/Interpreter/dynamic-library.cpp
Normal file
@ -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
|
@ -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: ");
|
||||
|
Loading…
x
Reference in New Issue
Block a user