summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLang Hames <lhames@gmail.com>2019-12-02 01:45:49 -0800
committerLang Hames <lhames@gmail.com>2019-12-02 01:52:52 -0800
commitece8fed609061638bc867ecb74e179cb86426d60 (patch)
tree50eea950e0965b32d2bdb961456c88c580f81c2d
parent0e7ecc651a47f818abafdfe5f928923f789fe0bc (diff)
downloadbcm5719-llvm-ece8fed609061638bc867ecb74e179cb86426d60.tar.gz
bcm5719-llvm-ece8fed609061638bc867ecb74e179cb86426d60.zip
[ORC] Add a runAsMain utility function to ExecutionUtils.
The runAsMain function takes a pointer to a function with a standard C main signature, int(*)(int, char*[]), and invokes it using the given arguments and program name. The arguments are copied into writable temporary storage as required by the C and C++ specifications, so runAsMain safe to use when calling main functions that modify their arguments in-place. This patch also uses the new runAsMain function to replace hand-rolled versions in lli, llvm-jitlink, and the SpeculativeJIT example.
-rw-r--r--llvm/examples/SpeculativeJIT/SpeculativeJIT.cpp15
-rw-r--r--llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h11
-rw-r--r--llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp26
-rw-r--r--llvm/tools/lli/lli.cpp15
-rw-r--r--llvm/tools/llvm-jitlink/llvm-jitlink.cpp23
5 files changed, 48 insertions, 42 deletions
diff --git a/llvm/examples/SpeculativeJIT/SpeculativeJIT.cpp b/llvm/examples/SpeculativeJIT/SpeculativeJIT.cpp
index 1fd1fc92a73..5a0ad376bcd 100644
--- a/llvm/examples/SpeculativeJIT/SpeculativeJIT.cpp
+++ b/llvm/examples/SpeculativeJIT/SpeculativeJIT.cpp
@@ -176,20 +176,11 @@ int main(int argc, char *argv[]) {
ThreadSafeModule(std::move(M), std::move(Ctx))));
}
- // Build an argv array for the JIT'd main.
- std::vector<const char *> ArgV;
- ArgV.push_back(argv[0]);
- for (const auto &InputArg : InputArgv)
- ArgV.push_back(InputArg.data());
- ArgV.push_back(nullptr);
-
- // Look up the JIT'd main, cast it to a function pointer, then call it.
-
auto MainSym = ExitOnErr(SJ->lookup("main"));
- int (*Main)(int, const char *[]) =
- (int (*)(int, const char *[]))MainSym.getAddress();
+ auto Main =
+ jitTargetAddressToFunction<int (*)(int, char *[])>(MainSym.getAddress());
- Main(ArgV.size() - 1, ArgV.data());
+ return runAsMain(Main, InputArgv, StringRef(InputFiles.front()));
return 0;
}
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h b/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h
index 7d051ed9906..c797dbbbdfd 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h
@@ -40,6 +40,17 @@ namespace orc {
class ObjectLayer;
+/// Run a main function, returning the result.
+///
+/// If the optional ProgramName argument is given then it will be inserted
+/// before the strings in Args as the first argument to the called function.
+///
+/// It is legal to have an empty argument list and no program name, however
+/// many main functions will expect a name argument at least, and will fail
+/// if none is provided.
+int runAsMain(int (*Main)(int, char *[]), ArrayRef<std::string> Args,
+ Optional<StringRef> ProgramName = None);
+
/// This iterator provides a convenient way to iterate over the elements
/// of an llvm.global_ctors/llvm.global_dtors instance.
///
diff --git a/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp b/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp
index 4a3482242db..0a3fef207ac 100644
--- a/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp
@@ -19,6 +19,32 @@
namespace llvm {
namespace orc {
+int runAsMain(int (*Main)(int, char *[]), ArrayRef<std::string> Args,
+ Optional<StringRef> ProgramName) {
+ std::vector<std::unique_ptr<char[]>> ArgVStorage;
+ std::vector<char *> ArgV;
+
+ ArgVStorage.reserve(Args.size() + (ProgramName ? 1 : 0));
+ ArgV.reserve(Args.size() + 1 + (ProgramName ? 1 : 0));
+
+ if (ProgramName) {
+ ArgVStorage.push_back(std::make_unique<char[]>(ProgramName->size() + 1));
+ llvm::copy(*ProgramName, &ArgVStorage.back()[0]);
+ ArgVStorage.back()[ProgramName->size()] = '\0';
+ ArgV.push_back(ArgVStorage.back().get());
+ }
+
+ for (auto &Arg : Args) {
+ ArgVStorage.push_back(std::make_unique<char[]>(Arg.size() + 1));
+ llvm::copy(Arg, &ArgVStorage.back()[0]);
+ ArgVStorage.back()[Arg.size()] = '\0';
+ ArgV.push_back(ArgVStorage.back().get());
+ }
+ ArgV.push_back(nullptr);
+
+ return Main(Args.size(), ArgV.data());
+}
+
CtorDtorIterator::CtorDtorIterator(const GlobalVariable *GV, bool End)
: InitList(
GV ? dyn_cast_or_null<ConstantArray>(GV->getInitializer()) : nullptr),
diff --git a/llvm/tools/lli/lli.cpp b/llvm/tools/lli/lli.cpp
index ccad0672141..9aaeef08592 100644
--- a/llvm/tools/lli/lli.cpp
+++ b/llvm/tools/lli/lli.cpp
@@ -871,16 +871,11 @@ int runOrcLazyJIT(const char *ProgName) {
// Run main.
auto MainSym = ExitOnErr(J->lookup("main"));
- typedef int (*MainFnPtr)(int, const char *[]);
- std::vector<const char *> ArgV;
- for (auto &Arg : Args)
- ArgV.push_back(Arg.c_str());
- ArgV.push_back(nullptr);
-
- int ArgC = ArgV.size() - 1;
- auto Main =
- reinterpret_cast<MainFnPtr>(static_cast<uintptr_t>(MainSym.getAddress()));
- auto Result = Main(ArgC, (const char **)ArgV.data());
+
+ typedef int (*MainFnPtr)(int, char *[]);
+ auto Result = orc::runAsMain(
+ jitTargetAddressToFunction<MainFnPtr>(MainSym.getAddress()), Args,
+ StringRef("lli"));
// Wait for -entry-point threads.
for (auto &AltEntryThread : AltEntryThreads)
diff --git a/llvm/tools/llvm-jitlink/llvm-jitlink.cpp b/llvm/tools/llvm-jitlink/llvm-jitlink.cpp
index 003a333d956..0e0953d37b6 100644
--- a/llvm/tools/llvm-jitlink/llvm-jitlink.cpp
+++ b/llvm/tools/llvm-jitlink/llvm-jitlink.cpp
@@ -769,25 +769,6 @@ static Expected<JITEvaluatedSymbol> getMainEntryPoint(Session &S) {
return S.ES.lookup(S.JDSearchOrder, EntryPointName);
}
-Expected<int> runEntryPoint(Session &S, JITEvaluatedSymbol EntryPoint) {
- assert(EntryPoint.getAddress() && "Entry point address should not be null");
-
- constexpr const char *JITProgramName = "<llvm-jitlink jit'd code>";
- auto PNStorage = std::make_unique<char[]>(strlen(JITProgramName) + 1);
- strcpy(PNStorage.get(), JITProgramName);
-
- std::vector<const char *> EntryPointArgs;
- EntryPointArgs.push_back(PNStorage.get());
- for (auto &InputArg : InputArgv)
- EntryPointArgs.push_back(InputArg.data());
- EntryPointArgs.push_back(nullptr);
-
- using MainTy = int (*)(int, const char *[]);
- MainTy EntryPointPtr = reinterpret_cast<MainTy>(EntryPoint.getAddress());
-
- return EntryPointPtr(EntryPointArgs.size() - 1, EntryPointArgs.data());
-}
-
struct JITLinkTimers {
TimerGroup JITLinkTG{"llvm-jitlink timers", "timers for llvm-jitlink phases"};
Timer LoadObjectsTimer{"load", "time to load/add object files", JITLinkTG};
@@ -841,8 +822,10 @@ int main(int argc, char *argv[]) {
int Result = 0;
{
+ using MainTy = int (*)(int, char *[]);
+ auto EntryFn = jitTargetAddressToFunction<MainTy>(EntryPoint.getAddress());
TimeRegion TR(Timers ? &Timers->RunTimer : nullptr);
- Result = ExitOnErr(runEntryPoint(S, EntryPoint));
+ Result = runAsMain(EntryFn, InputArgv, StringRef(InputFiles.front()));
}
return Result;
OpenPOWER on IntegriCloud