argentite updated this revision to Diff 507046.
argentite marked 3 inline comments as done.
argentite edited the summary of this revision.
argentite added a comment.
Added a simple test and removed the automatic OS specific library filenames
Full name/path of the library must be provided. This makes the command more
flexible especially when dealing with multiple versions of a library or SDK.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D141824/new/
https://reviews.llvm.org/D141824
Files:
clang/include/clang/Interpreter/Interpreter.h
clang/lib/Interpreter/IncrementalExecutor.h
clang/lib/Interpreter/Interpreter.cpp
clang/test/Interpreter/dynamic-library.cpp
clang/tools/clang-repl/ClangRepl.cpp
Index: clang/tools/clang-repl/ClangRepl.cpp
===================================================================
--- clang/tools/clang-repl/ClangRepl.cpp
+++ clang/tools/clang-repl/ClangRepl.cpp
@@ -123,6 +123,13 @@
}
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: ");
Index: clang/test/Interpreter/dynamic-library.cpp
===================================================================
--- /dev/null
+++ clang/test/Interpreter/dynamic-library.cpp
@@ -0,0 +1,24 @@
+// RUN: head -n 7 %s | %clang -xc++ -o %T/libdynamic-library-test.so -fPIC -shared -
+int ultimate_answer = 0;
+
+int calculate_answer() {
+ ultimate_answer = 42;
+ return 5;
+}
+
+// REQUIRES: host-supports-jit, system-linux
+// RUN: tail -n 16 %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
Index: clang/lib/Interpreter/Interpreter.cpp
===================================================================
--- clang/lib/Interpreter/Interpreter.cpp
+++ 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 @@
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 @@
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 @@
}
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();
+}
Index: clang/lib/Interpreter/IncrementalExecutor.h
===================================================================
--- clang/lib/Interpreter/IncrementalExecutor.h
+++ clang/lib/Interpreter/IncrementalExecutor.h
@@ -53,7 +53,8 @@
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
Index: clang/include/clang/Interpreter/Interpreter.h
===================================================================
--- clang/include/clang/Interpreter/Interpreter.h
+++ clang/include/clang/Interpreter/Interpreter.h
@@ -28,7 +28,7 @@
namespace orc {
class LLJIT;
class ThreadSafeContext;
-}
+} // namespace orc
} // namespace llvm
namespace clang {
@@ -52,12 +52,15 @@
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 @@
/// 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.
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits