summaryrefslogtreecommitdiffstats
path: root/llvm/lib/ExecutionEngine
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/ExecutionEngine')
-rw-r--r--llvm/lib/ExecutionEngine/CMakeLists.txt1
-rw-r--r--llvm/lib/ExecutionEngine/ExecutionEngine.cpp17
-rw-r--r--llvm/lib/ExecutionEngine/LLVMBuild.txt2
-rw-r--r--llvm/lib/ExecutionEngine/MCJIT/MCJIT.h2
-rw-r--r--llvm/lib/ExecutionEngine/Makefile2
-rw-r--r--llvm/lib/ExecutionEngine/Orc/CMakeLists.txt6
-rw-r--r--llvm/lib/ExecutionEngine/Orc/CloneSubModule.cpp112
-rw-r--r--llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp157
-rw-r--r--llvm/lib/ExecutionEngine/Orc/LLVMBuild.txt22
-rw-r--r--llvm/lib/ExecutionEngine/Orc/Makefile13
-rw-r--r--llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.cpp124
-rw-r--r--llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h328
-rw-r--r--llvm/lib/ExecutionEngine/Orc/OrcTargetSupport.cpp102
-rw-r--r--llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp6
14 files changed, 886 insertions, 8 deletions
diff --git a/llvm/lib/ExecutionEngine/CMakeLists.txt b/llvm/lib/ExecutionEngine/CMakeLists.txt
index dc2fe9bf97f..2332795fc4c 100644
--- a/llvm/lib/ExecutionEngine/CMakeLists.txt
+++ b/llvm/lib/ExecutionEngine/CMakeLists.txt
@@ -10,6 +10,7 @@ add_llvm_library(LLVMExecutionEngine
add_subdirectory(Interpreter)
add_subdirectory(MCJIT)
+add_subdirectory(Orc)
add_subdirectory(RuntimeDyld)
if( LLVM_USE_OPROFILE )
diff --git a/llvm/lib/ExecutionEngine/ExecutionEngine.cpp b/llvm/lib/ExecutionEngine/ExecutionEngine.cpp
index 32d20ea0e30..8be399e510e 100644
--- a/llvm/lib/ExecutionEngine/ExecutionEngine.cpp
+++ b/llvm/lib/ExecutionEngine/ExecutionEngine.cpp
@@ -46,6 +46,11 @@ ExecutionEngine *(*ExecutionEngine::MCJITCtor)(
std::unique_ptr<Module> M, std::string *ErrorStr,
std::unique_ptr<RTDyldMemoryManager> MCJMM,
std::unique_ptr<TargetMachine> TM) = nullptr;
+
+ExecutionEngine *(*ExecutionEngine::OrcMCJITReplacementCtor)(
+ std::string *ErrorStr, std::unique_ptr<RTDyldMemoryManager> OrcJMM,
+ std::unique_ptr<TargetMachine> TM) = nullptr;
+
ExecutionEngine *(*ExecutionEngine::InterpCtor)(std::unique_ptr<Module> M,
std::string *ErrorStr) =nullptr;
@@ -393,6 +398,10 @@ int ExecutionEngine::runFunctionAsMain(Function *Fn,
return runFunction(Fn, GVArgs).IntVal.getZExtValue();
}
+EngineBuilder::EngineBuilder() {
+ InitEngine();
+}
+
EngineBuilder::EngineBuilder(std::unique_ptr<Module> M)
: M(std::move(M)), MCJMM(nullptr) {
InitEngine();
@@ -414,6 +423,7 @@ void EngineBuilder::InitEngine() {
Options = TargetOptions();
RelocModel = Reloc::Default;
CMModel = CodeModel::JITDefault;
+ UseOrcMCJITReplacement = false;
// IR module verification is enabled by default in debug builds, and disabled
// by default in release builds.
@@ -456,9 +466,14 @@ ExecutionEngine *EngineBuilder::create(TargetMachine *TM) {
}
ExecutionEngine *EE = nullptr;
- if (ExecutionEngine::MCJITCtor)
+ if (ExecutionEngine::OrcMCJITReplacementCtor && UseOrcMCJITReplacement) {
+ EE = ExecutionEngine::OrcMCJITReplacementCtor(ErrorStr, std::move(MCJMM),
+ std::move(TheTM));
+ EE->addModule(std::move(M));
+ } else if (ExecutionEngine::MCJITCtor)
EE = ExecutionEngine::MCJITCtor(std::move(M), ErrorStr, std::move(MCJMM),
std::move(TheTM));
+
if (EE) {
EE->setVerifyModules(VerifyModules);
return EE;
diff --git a/llvm/lib/ExecutionEngine/LLVMBuild.txt b/llvm/lib/ExecutionEngine/LLVMBuild.txt
index 7d041cef843..de8918c806b 100644
--- a/llvm/lib/ExecutionEngine/LLVMBuild.txt
+++ b/llvm/lib/ExecutionEngine/LLVMBuild.txt
@@ -16,7 +16,7 @@
;===------------------------------------------------------------------------===;
[common]
-subdirectories = Interpreter MCJIT RuntimeDyld IntelJITEvents OProfileJIT
+subdirectories = Interpreter MCJIT RuntimeDyld IntelJITEvents OProfileJIT Orc
[component_0]
type = Library
diff --git a/llvm/lib/ExecutionEngine/MCJIT/MCJIT.h b/llvm/lib/ExecutionEngine/MCJIT/MCJIT.h
index f55dd60ecba..de4a8f6a60d 100644
--- a/llvm/lib/ExecutionEngine/MCJIT/MCJIT.h
+++ b/llvm/lib/ExecutionEngine/MCJIT/MCJIT.h
@@ -10,12 +10,12 @@
#ifndef LLVM_LIB_EXECUTIONENGINE_MCJIT_MCJIT_H
#define LLVM_LIB_EXECUTIONENGINE_MCJIT_MCJIT_H
-#include "ObjectBuffer.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/ExecutionEngine/ObjectCache.h"
+#include "llvm/ExecutionEngine/ObjectMemoryBuffer.h"
#include "llvm/ExecutionEngine/RuntimeDyld.h"
#include "llvm/IR/Module.h"
diff --git a/llvm/lib/ExecutionEngine/Makefile b/llvm/lib/ExecutionEngine/Makefile
index cf714324e3b..e9a5b79ddf6 100644
--- a/llvm/lib/ExecutionEngine/Makefile
+++ b/llvm/lib/ExecutionEngine/Makefile
@@ -11,7 +11,7 @@ LIBRARYNAME = LLVMExecutionEngine
include $(LEVEL)/Makefile.config
-PARALLEL_DIRS = Interpreter MCJIT RuntimeDyld
+PARALLEL_DIRS = Interpreter MCJIT Orc RuntimeDyld
ifeq ($(USE_INTEL_JITEVENTS), 1)
PARALLEL_DIRS += IntelJITEvents
diff --git a/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt b/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt
new file mode 100644
index 00000000000..3fadb931200
--- /dev/null
+++ b/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt
@@ -0,0 +1,6 @@
+add_llvm_library(LLVMOrcJIT
+ CloneSubModule.cpp
+ IndirectionUtils.cpp
+ OrcMCJITReplacement.cpp
+ OrcTargetSupport.cpp
+ )
diff --git a/llvm/lib/ExecutionEngine/Orc/CloneSubModule.cpp b/llvm/lib/ExecutionEngine/Orc/CloneSubModule.cpp
new file mode 100644
index 00000000000..54acb78153e
--- /dev/null
+++ b/llvm/lib/ExecutionEngine/Orc/CloneSubModule.cpp
@@ -0,0 +1,112 @@
+#include "llvm/ExecutionEngine/Orc/CloneSubModule.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/GlobalVariable.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Transforms/Utils/Cloning.h"
+
+using namespace llvm;
+
+void llvm::copyGVInitializer(GlobalVariable &New, const GlobalVariable &Orig,
+ ValueToValueMapTy &VMap) {
+ if (Orig.hasInitializer())
+ New.setInitializer(MapValue(Orig.getInitializer(), VMap));
+}
+
+void llvm::copyFunctionBody(Function &New, const Function &Orig,
+ ValueToValueMapTy &VMap) {
+ if (!Orig.isDeclaration()) {
+ Function::arg_iterator DestI = New.arg_begin();
+ for (Function::const_arg_iterator J = Orig.arg_begin(); J != Orig.arg_end();
+ ++J) {
+ DestI->setName(J->getName());
+ VMap[J] = DestI++;
+ }
+
+ SmallVector<ReturnInst *, 8> Returns; // Ignore returns cloned.
+ CloneFunctionInto(&New, &Orig, VMap, /*ModuleLevelChanges=*/true, Returns);
+ }
+}
+
+std::unique_ptr<Module>
+llvm::CloneSubModule(const Module &M,
+ HandleGlobalVariableFtor HandleGlobalVariable,
+ HandleFunctionFtor HandleFunction, bool KeepInlineAsm) {
+
+ ValueToValueMapTy VMap;
+
+ // First off, we need to create the new module.
+ std::unique_ptr<Module> New =
+ llvm::make_unique<Module>(M.getModuleIdentifier(), M.getContext());
+
+ New->setDataLayout(M.getDataLayout());
+ New->setTargetTriple(M.getTargetTriple());
+ if (KeepInlineAsm)
+ New->setModuleInlineAsm(M.getModuleInlineAsm());
+
+ // Copy global variables (but not initializers, yet).
+ for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
+ I != E; ++I) {
+ GlobalVariable *GV = new GlobalVariable(
+ *New, I->getType()->getElementType(), I->isConstant(), I->getLinkage(),
+ (Constant *)nullptr, I->getName(), (GlobalVariable *)nullptr,
+ I->getThreadLocalMode(), I->getType()->getAddressSpace());
+ GV->copyAttributesFrom(I);
+ VMap[I] = GV;
+ }
+
+ // Loop over the functions in the module, making external functions as before
+ for (Module::const_iterator I = M.begin(), E = M.end(); I != E; ++I) {
+ Function *NF =
+ Function::Create(cast<FunctionType>(I->getType()->getElementType()),
+ I->getLinkage(), I->getName(), &*New);
+ NF->copyAttributesFrom(I);
+ VMap[I] = NF;
+ }
+
+ // Loop over the aliases in the module
+ for (Module::const_alias_iterator I = M.alias_begin(), E = M.alias_end();
+ I != E; ++I) {
+ auto *PTy = cast<PointerType>(I->getType());
+ auto *GA =
+ GlobalAlias::create(PTy->getElementType(), PTy->getAddressSpace(),
+ I->getLinkage(), I->getName(), &*New);
+ GA->copyAttributesFrom(I);
+ VMap[I] = GA;
+ }
+
+ // Now that all of the things that global variable initializer can refer to
+ // have been created, loop through and copy the global variable referrers
+ // over... We also set the attributes on the global now.
+ for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
+ I != E; ++I) {
+ GlobalVariable &GV = *cast<GlobalVariable>(VMap[I]);
+ HandleGlobalVariable(GV, *I, VMap);
+ }
+
+ // Similarly, copy over function bodies now...
+ //
+ for (Module::const_iterator I = M.begin(), E = M.end(); I != E; ++I) {
+ Function &F = *cast<Function>(VMap[I]);
+ HandleFunction(F, *I, VMap);
+ }
+
+ // And aliases
+ for (Module::const_alias_iterator I = M.alias_begin(), E = M.alias_end();
+ I != E; ++I) {
+ GlobalAlias *GA = cast<GlobalAlias>(VMap[I]);
+ if (const Constant *C = I->getAliasee())
+ GA->setAliasee(MapValue(C, VMap));
+ }
+
+ // And named metadata....
+ for (Module::const_named_metadata_iterator I = M.named_metadata_begin(),
+ E = M.named_metadata_end();
+ I != E; ++I) {
+ const NamedMDNode &NMD = *I;
+ NamedMDNode *NewNMD = New->getOrInsertNamedMetadata(NMD.getName());
+ for (unsigned i = 0, e = NMD.getNumOperands(); i != e; ++i)
+ NewNMD->addOperand(MapMetadata(NMD.getOperand(i), VMap));
+ }
+
+ return New;
+}
diff --git a/llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp b/llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp
new file mode 100644
index 00000000000..e75092b2485
--- /dev/null
+++ b/llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp
@@ -0,0 +1,157 @@
+#include "llvm/ADT/Triple.h"
+#include "llvm/ExecutionEngine/Orc/IndirectionUtils.h"
+#include "llvm/ExecutionEngine/Orc/CloneSubModule.h"
+#include "llvm/IR/CallSite.h"
+#include "llvm/IR/IRBuilder.h"
+#include <set>
+
+using namespace llvm;
+
+namespace llvm {
+
+JITIndirections makeCallsSingleIndirect(
+ Module &M, const std::function<bool(const Function &)> &ShouldIndirect,
+ const char *JITImplSuffix, const char *JITAddrSuffix) {
+ std::vector<Function *> Worklist;
+ std::vector<std::string> FuncNames;
+
+ for (auto &F : M)
+ if (ShouldIndirect(F) && (F.user_begin() != F.user_end())) {
+ Worklist.push_back(&F);
+ FuncNames.push_back(F.getName());
+ }
+
+ for (auto *F : Worklist) {
+ GlobalVariable *FImplAddr = new GlobalVariable(
+ M, F->getType(), false, GlobalValue::ExternalLinkage,
+ Constant::getNullValue(F->getType()), F->getName() + JITAddrSuffix,
+ nullptr, GlobalValue::NotThreadLocal, 0, true);
+ FImplAddr->setVisibility(GlobalValue::HiddenVisibility);
+
+ for (auto *U : F->users()) {
+ assert(isa<Instruction>(U) && "Cannot indirect non-instruction use");
+ IRBuilder<> Builder(cast<Instruction>(U));
+ U->replaceUsesOfWith(F, Builder.CreateLoad(FImplAddr));
+ }
+ }
+
+ return JITIndirections(
+ FuncNames, [=](StringRef S) -> std::string { return std::string(S); },
+ [=](StringRef S)
+ -> std::string { return std::string(S) + JITAddrSuffix; });
+}
+
+JITIndirections makeCallsDoubleIndirect(
+ Module &M, const std::function<bool(const Function &)> &ShouldIndirect,
+ const char *JITImplSuffix, const char *JITAddrSuffix) {
+
+ std::vector<Function *> Worklist;
+ std::vector<std::string> FuncNames;
+
+ for (auto &F : M)
+ if (!F.isDeclaration() && !F.hasAvailableExternallyLinkage() &&
+ ShouldIndirect(F))
+ Worklist.push_back(&F);
+
+ for (auto *F : Worklist) {
+ std::string OrigName = F->getName();
+ F->setName(OrigName + JITImplSuffix);
+ FuncNames.push_back(OrigName);
+
+ GlobalVariable *FImplAddr = new GlobalVariable(
+ M, F->getType(), false, GlobalValue::ExternalLinkage,
+ Constant::getNullValue(F->getType()), OrigName + JITAddrSuffix, nullptr,
+ GlobalValue::NotThreadLocal, 0, true);
+ FImplAddr->setVisibility(GlobalValue::HiddenVisibility);
+
+ Function *FRedirect =
+ Function::Create(F->getFunctionType(), F->getLinkage(), OrigName, &M);
+
+ F->replaceAllUsesWith(FRedirect);
+
+ BasicBlock *EntryBlock =
+ BasicBlock::Create(M.getContext(), "entry", FRedirect);
+
+ IRBuilder<> Builder(EntryBlock);
+ LoadInst *FImplLoadedAddr = Builder.CreateLoad(FImplAddr);
+
+ std::vector<Value *> CallArgs;
+ for (Value &Arg : FRedirect->args())
+ CallArgs.push_back(&Arg);
+ CallInst *Call = Builder.CreateCall(FImplLoadedAddr, CallArgs);
+ Call->setTailCall();
+ Builder.CreateRet(Call);
+ }
+
+ return JITIndirections(
+ FuncNames, [=](StringRef S)
+ -> std::string { return std::string(S) + JITImplSuffix; },
+ [=](StringRef S)
+ -> std::string { return std::string(S) + JITAddrSuffix; });
+}
+
+std::vector<std::unique_ptr<Module>>
+explode(const Module &OrigMod,
+ const std::function<bool(const Function &)> &ShouldExtract) {
+
+ std::vector<std::unique_ptr<Module>> NewModules;
+
+ // Split all the globals, non-indirected functions, etc. into a single module.
+ auto ExtractGlobalVars = [&](GlobalVariable &New, const GlobalVariable &Orig,
+ ValueToValueMapTy &VMap) {
+ copyGVInitializer(New, Orig, VMap);
+ if (New.getLinkage() == GlobalValue::PrivateLinkage) {
+ New.setLinkage(GlobalValue::ExternalLinkage);
+ New.setVisibility(GlobalValue::HiddenVisibility);
+ }
+ };
+
+ auto ExtractNonImplFunctions =
+ [&](Function &New, const Function &Orig, ValueToValueMapTy &VMap) {
+ if (!ShouldExtract(New))
+ copyFunctionBody(New, Orig, VMap);
+ };
+
+ NewModules.push_back(CloneSubModule(OrigMod, ExtractGlobalVars,
+ ExtractNonImplFunctions, true));
+
+ // Preserve initializers for Common linkage vars, and make private linkage
+ // globals external: they are now provided by the globals module extracted
+ // above.
+ auto DropGlobalVars = [&](GlobalVariable &New, const GlobalVariable &Orig,
+ ValueToValueMapTy &VMap) {
+ if (New.getLinkage() == GlobalValue::CommonLinkage)
+ copyGVInitializer(New, Orig, VMap);
+ else if (New.getLinkage() == GlobalValue::PrivateLinkage)
+ New.setLinkage(GlobalValue::ExternalLinkage);
+ };
+
+ // Split each 'impl' function out in to its own module.
+ for (const auto &Func : OrigMod) {
+ if (Func.isDeclaration() || !ShouldExtract(Func))
+ continue;
+
+ auto ExtractNamedFunction =
+ [&](Function &New, const Function &Orig, ValueToValueMapTy &VMap) {
+ if (New.getName() == Func.getName())
+ copyFunctionBody(New, Orig, VMap);
+ };
+
+ NewModules.push_back(
+ CloneSubModule(OrigMod, DropGlobalVars, ExtractNamedFunction, false));
+ }
+
+ return NewModules;
+}
+
+std::vector<std::unique_ptr<Module>>
+explode(const Module &OrigMod, const JITIndirections &Indirections) {
+ std::set<std::string> ImplNames;
+
+ for (const auto &FuncName : Indirections.IndirectedNames)
+ ImplNames.insert(Indirections.GetImplName(FuncName));
+
+ return explode(
+ OrigMod, [&](const Function &F) { return ImplNames.count(F.getName()); });
+}
+}
diff --git a/llvm/lib/ExecutionEngine/Orc/LLVMBuild.txt b/llvm/lib/ExecutionEngine/Orc/LLVMBuild.txt
new file mode 100644
index 00000000000..620449405b5
--- /dev/null
+++ b/llvm/lib/ExecutionEngine/Orc/LLVMBuild.txt
@@ -0,0 +1,22 @@
+;===- ./lib/ExecutionEngine/MCJIT/LLVMBuild.txt ----------------*- Conf -*--===;
+;
+; The LLVM Compiler Infrastructure
+;
+; This file is distributed under the University of Illinois Open Source
+; License. See LICENSE.TXT for details.
+;
+;===------------------------------------------------------------------------===;
+;
+; This is an LLVMBuild description file for the components in this subdirectory.
+;
+; For more information on the LLVMBuild system, please see:
+;
+; http://llvm.org/docs/LLVMBuild.html
+;
+;===------------------------------------------------------------------------===;
+
+[component_0]
+type = Library
+name = OrcJIT
+parent = ExecutionEngine
+required_libraries = Core ExecutionEngine Object RuntimeDyld Support Target
diff --git a/llvm/lib/ExecutionEngine/Orc/Makefile b/llvm/lib/ExecutionEngine/Orc/Makefile
new file mode 100644
index 00000000000..ac302348ee7
--- /dev/null
+++ b/llvm/lib/ExecutionEngine/Orc/Makefile
@@ -0,0 +1,13 @@
+##===- lib/ExecutionEngine/OrcJIT/Makefile -----------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../../..
+LIBRARYNAME = LLVMOrcJIT
+
+include $(LEVEL)/Makefile.common
diff --git a/llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.cpp b/llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.cpp
new file mode 100644
index 00000000000..f658ab2b298
--- /dev/null
+++ b/llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.cpp
@@ -0,0 +1,124 @@
+//===-------- OrcMCJITReplacement.cpp - Orc-based MCJIT replacement -------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "OrcMCJITReplacement.h"
+#include "llvm/ExecutionEngine/GenericValue.h"
+
+namespace {
+
+static struct RegisterJIT {
+ RegisterJIT() { llvm::OrcMCJITReplacement::Register(); }
+} JITRegistrator;
+
+extern "C" void LLVMLinkInOrcMCJITReplacement() {}
+}
+
+namespace llvm {
+
+GenericValue
+OrcMCJITReplacement::runFunction(Function *F,
+ const std::vector<GenericValue> &ArgValues) {
+ assert(F && "Function *F was null at entry to run()");
+
+ void *FPtr = getPointerToFunction(F);
+ assert(FPtr && "Pointer to fn's code was null after getPointerToFunction");
+ FunctionType *FTy = F->getFunctionType();
+ Type *RetTy = FTy->getReturnType();
+
+ assert((FTy->getNumParams() == ArgValues.size() ||
+ (FTy->isVarArg() && FTy->getNumParams() <= ArgValues.size())) &&
+ "Wrong number of arguments passed into function!");
+ assert(FTy->getNumParams() == ArgValues.size() &&
+ "This doesn't support passing arguments through varargs (yet)!");
+
+ // Handle some common cases first. These cases correspond to common `main'
+ // prototypes.
+ if (RetTy->isIntegerTy(32) || RetTy->isVoidTy()) {
+ switch (ArgValues.size()) {
+ case 3:
+ if (FTy->getParamType(0)->isIntegerTy(32) &&
+ FTy->getParamType(1)->isPointerTy() &&
+ FTy->getParamType(2)->isPointerTy()) {
+ int (*PF)(int, char **, const char **) =
+ (int (*)(int, char **, const char **))(intptr_t)FPtr;
+
+ // Call the function.
+ GenericValue rv;
+ rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue(),
+ (char **)GVTOP(ArgValues[1]),
+ (const char **)GVTOP(ArgValues[2])));
+ return rv;
+ }
+ break;
+ case 2:
+ if (FTy->getParamType(0)->isIntegerTy(32) &&
+ FTy->getParamType(1)->isPointerTy()) {
+ int (*PF)(int, char **) = (int (*)(int, char **))(intptr_t)FPtr;
+
+ // Call the function.
+ GenericValue rv;
+ rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue(),
+ (char **)GVTOP(ArgValues[1])));
+ return rv;
+ }
+ break;
+ case 1:
+ if (FTy->getNumParams() == 1 && FTy->getParamType(0)->isIntegerTy(32)) {
+ GenericValue rv;
+ int (*PF)(int) = (int (*)(int))(intptr_t)FPtr;
+ rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue()));
+ return rv;
+ }
+ break;
+ }
+ }
+
+ // Handle cases where no arguments are passed first.
+ if (ArgValues.empty()) {
+ GenericValue rv;
+ switch (RetTy->getTypeID()) {
+ default:
+ llvm_unreachable("Unknown return type for function call!");
+ case Type::IntegerTyID: {
+ unsigned BitWidth = cast<IntegerType>(RetTy)->getBitWidth();
+ if (BitWidth == 1)
+ rv.IntVal = APInt(BitWidth, ((bool (*)())(intptr_t)FPtr)());
+ else if (BitWidth <= 8)
+ rv.IntVal = APInt(BitWidth, ((char (*)())(intptr_t)FPtr)());
+ else if (BitWidth <= 16)
+ rv.IntVal = APInt(BitWidth, ((short (*)())(intptr_t)FPtr)());
+ else if (BitWidth <= 32)
+ rv.IntVal = APInt(BitWidth, ((int (*)())(intptr_t)FPtr)());
+ else if (BitWidth <= 64)
+ rv.IntVal = APInt(BitWidth, ((int64_t (*)())(intptr_t)FPtr)());
+ else
+ llvm_unreachable("Integer types > 64 bits not supported");
+ return rv;
+ }
+ case Type::VoidTyID:
+ rv.IntVal = APInt(32, ((int (*)())(intptr_t)FPtr)());
+ return rv;
+ case Type::FloatTyID:
+ rv.FloatVal = ((float (*)())(intptr_t)FPtr)();
+ return rv;
+ case Type::DoubleTyID:
+ rv.DoubleVal = ((double (*)())(intptr_t)FPtr)();
+ return rv;
+ case Type::X86_FP80TyID:
+ case Type::FP128TyID:
+ case Type::PPC_FP128TyID:
+ llvm_unreachable("long double not supported yet");
+ case Type::PointerTyID:
+ return PTOGV(((void *(*)())(intptr_t)FPtr)());
+ }
+ }
+
+ llvm_unreachable("Full-featured argument passing not supported yet!");
+}
+}
diff --git a/llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h b/llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h
new file mode 100644
index 00000000000..9fdf0efdd90
--- /dev/null
+++ b/llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h
@@ -0,0 +1,328 @@
+//===---- OrcMCJITReplacement.h - Orc based MCJIT replacement ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Orc based MCJIT replacement.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_EXECUTIONENGINE_ORC_ORCMCJITREPLACEMENT_H
+#define LLVM_LIB_EXECUTIONENGINE_ORC_ORCMCJITREPLACEMENT_H
+
+#include "llvm/ExecutionEngine/ExecutionEngine.h"
+#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
+#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
+#include "llvm/ExecutionEngine/Orc/LazyEmittingLayer.h"
+#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
+#include "llvm/Object/Archive.h"
+#include "llvm/Target/TargetSubtargetInfo.h"
+
+namespace llvm {
+
+class OrcMCJITReplacement : public ExecutionEngine {
+
+ class ForwardingRTDyldMM : public RTDyldMemoryManager {
+ public:
+ ForwardingRTDyldMM(OrcMCJITReplacement &M) : M(M) {}
+
+ uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
+ unsigned SectionID,
+ StringRef SectionName) override {
+ uint8_t *Addr =
+ M.MM->allocateCodeSection(Size, Alignment, SectionID, SectionName);
+ M.SectionsAllocatedSinceLastLoad.insert(Addr);
+ return Addr;
+ }
+
+ uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
+ unsigned SectionID, StringRef SectionName,
+ bool IsReadOnly) override {
+ uint8_t *Addr = M.MM->allocateDataSection(Size, Alignment, SectionID,
+ SectionName, IsReadOnly);
+ M.SectionsAllocatedSinceLastLoad.insert(Addr);
+ return Addr;
+ }
+
+ void reserveAllocationSpace(uintptr_t CodeSize, uintptr_t DataSizeRO,
+ uintptr_t DataSizeRW) override {
+ return M.MM->reserveAllocationSpace(CodeSize, DataSizeRO, DataSizeRW);
+ }
+
+ bool needsToReserveAllocationSpace() override {
+ return M.MM->needsToReserveAllocationSpace();
+ }
+
+ void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr,
+ size_t Size) override {
+ return M.MM->registerEHFrames(Addr, LoadAddr, Size);
+ }
+
+ void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr,
+ size_t Size) override {
+ return M.MM->deregisterEHFrames(Addr, LoadAddr, Size);
+ }
+
+ uint64_t getSymbolAddress(const std::string &Name) override {
+ return M.getSymbolAddressWithoutMangling(Name);
+ }
+
+ void *getPointerToNamedFunction(const std::string &Name,
+ bool AbortOnFailure = true) override {
+ return M.MM->getPointerToNamedFunction(Name, AbortOnFailure);
+ }
+
+ void notifyObjectLoaded(ExecutionEngine *EE,
+ const object::ObjectFile &O) override {
+ return M.MM->notifyObjectLoaded(EE, O);
+ }
+
+ bool finalizeMemory(std::string *ErrMsg = nullptr) override {
+ // Each set of objects loaded will be finalized exactly once, but since
+ // symbol lookup during relocation may recursively trigger the
+ // loading/relocation of other modules, and since we're forwarding all
+ // finalizeMemory calls to a single underlying memory manager, we need to
+ // defer forwarding the call on until all necessary objects have been
+ // loaded. Otherwise, during the relocation of a leaf object, we will end
+ // up finalizing memory, causing a crash further up the stack when we
+ // attempt to apply relocations to finalized memory.
+ // To avoid finalizing too early, look at how many objects have been
+ // loaded but not yet finalized. This is a bit of a hack that relies on
+ // the fact that we're lazily emitting object files: The only way you can
+ // get more than one set of objects loaded but not yet finalized is if
+ // they were loaded during relocation of another set.
+ if (M.UnfinalizedSections.size() == 1)
+ return M.MM->finalizeMemory(ErrMsg);
+ return false;
+ }
+
+ private:
+ OrcMCJITReplacement &M;
+ };
+
+private:
+ static ExecutionEngine *
+ createOrcMCJITReplacement(std::string *ErrorMsg,
+ std::unique_ptr<RTDyldMemoryManager> OrcJMM,
+ std::unique_ptr<llvm::TargetMachine> TM) {
+ return new llvm::OrcMCJITReplacement(std::move(OrcJMM), std::move(TM));
+ }
+
+public:
+ static void Register() {
+ OrcMCJITReplacementCtor = createOrcMCJITReplacement;
+ }
+
+ OrcMCJITReplacement(std::unique_ptr<RTDyldMemoryManager> MM,
+ std::unique_ptr<TargetMachine> TM)
+ : TM(std::move(TM)), MM(std::move(MM)),
+ Mang(this->TM->getSubtargetImpl()->getDataLayout()),
+ NotifyObjectLoaded(*this), NotifyFinalized(*this),
+ ObjectLayer(NotifyObjectLoaded, NotifyFinalized),
+ CompileLayer(ObjectLayer, SimpleCompiler(*this->TM)),
+ LazyEmitLayer(CompileLayer) {
+ setDataLayout(this->TM->getSubtargetImpl()->getDataLayout());
+ }
+
+ void addModule(std::unique_ptr<Module> M) {
+
+ // If this module doesn't have a DataLayout attached then attach the
+ // default.
+ if (!M->getDataLayout())
+ M->setDataLayout(getDataLayout());
+
+ OwnedModules.push_back(std::move(M));
+ std::vector<Module *> Ms;
+ Ms.push_back(&*OwnedModules.back());
+ LazyEmitLayer.addModuleSet(std::move(Ms),
+ llvm::make_unique<ForwardingRTDyldMM>(*this));
+ }
+
+ void addObjectFile(std::unique_ptr<object::ObjectFile> O) override {
+ std::vector<std::unique_ptr<object::ObjectFile>> Objs;
+ Objs.push_back(std::move(O));
+ ObjectLayer.addObjectSet(std::move(Objs),
+ llvm::make_unique<ForwardingRTDyldMM>(*this));
+ }
+
+ void addObjectFile(object::OwningBinary<object::ObjectFile> O) override {
+ std::unique_ptr<object::ObjectFile> Obj;
+ std::unique_ptr<MemoryBuffer> Buf;
+ std::tie(Obj, Buf) = O.takeBinary();
+ std::vector<std::unique_ptr<object::ObjectFile>> Objs;
+ Objs.push_back(std::move(Obj));
+ ObjectLayer.addObjectSet(std::move(Objs),
+ llvm::make_unique<ForwardingRTDyldMM>(*this));
+ }
+
+ void addArchive(object::OwningBinary<object::Archive> A) override {
+ Archives.push_back(std::move(A));
+ }
+
+ uint64_t getSymbolAddress(StringRef Name) {
+ return getSymbolAddressWithoutMangling(Mangle(Name));
+ }
+
+ void finalizeObject() override {
+ // This is deprecated - Aim to remove in ExecutionEngine.
+ // REMOVE IF POSSIBLE - Doesn't make sense for New JIT.
+ }
+
+ void mapSectionAddress(const void *LocalAddress,
+ uint64_t TargetAddress) override {
+ for (auto &P : UnfinalizedSections)
+ if (P.second.count(LocalAddress))
+ ObjectLayer.mapSectionAddress(P.first, LocalAddress, TargetAddress);
+ }
+
+ uint64_t getGlobalValueAddress(const std::string &Name) override {
+ return getSymbolAddress(Name);
+ }
+
+ uint64_t getFunctionAddress(const std::string &Name) override {
+ return getSymbolAddress(Name);
+ }
+
+ void *getPointerToFunction(Function *F) override {
+ uint64_t FAddr = getSymbolAddress(F->getName());
+ return reinterpret_cast<void *>(static_cast<uintptr_t>(FAddr));
+ }
+
+ void *getPointerToNamedFunction(StringRef Name,
+ bool AbortOnFailure = true) override {
+ uint64_t Addr = getSymbolAddress(Name);
+ if (!Addr && AbortOnFailure)
+ llvm_unreachable("Missing symbol!");
+ return reinterpret_cast<void *>(static_cast<uintptr_t>(Addr));
+ }
+
+ GenericValue runFunction(Function *F,
+ const std::vector<GenericValue> &ArgValues) override;
+
+ void setObjectCache(ObjectCache *NewCache) override {
+ CompileLayer.setObjectCache(NewCache);
+ }
+
+private:
+ uint64_t getSymbolAddressWithoutMangling(StringRef Name) {
+ if (uint64_t Addr = LazyEmitLayer.getSymbolAddress(Name, false))
+ return Addr;
+ if (uint64_t Addr = MM->getSymbolAddress(Name))
+ return Addr;
+ if (uint64_t Addr = scanArchives(Name))
+ return Addr;
+
+ return 0;
+ }
+
+ uint64_t scanArchives(StringRef Name) {
+ for (object::OwningBinary<object::Archive> &OB : Archives) {
+ object::Archive *A = OB.getBinary();
+ // Look for our symbols in each Archive
+ object::Archive::child_iterator ChildIt = A->findSym(Name);
+ if (ChildIt != A->child_end()) {
+ // FIXME: Support nested archives?
+ ErrorOr<std::unique_ptr<object::Binary>> ChildBinOrErr =
+ ChildIt->getAsBinary();
+ if (ChildBinOrErr.getError())
+ continue;
+ std::unique_ptr<object::Binary> &ChildBin = ChildBinOrErr.get();
+ if (ChildBin->isObject()) {
+ std::vector<std::unique_ptr<object::ObjectFile>> ObjSet;
+ ObjSet.push_back(std::unique_ptr<object::ObjectFile>(
+ static_cast<object::ObjectFile *>(ChildBin.release())));
+ ObjectLayer.addObjectSet(
+ std::move(ObjSet), llvm::make_unique<ForwardingRTDyldMM>(*this));
+ if (uint64_t Addr = ObjectLayer.getSymbolAddress(Name, true))
+ return Addr;
+ }
+ }
+ }
+ return 0;
+ }
+
+ class NotifyObjectLoadedT {
+ public:
+ typedef std::vector<std::unique_ptr<object::ObjectFile>> ObjListT;
+ typedef std::vector<std::unique_ptr<RuntimeDyld::LoadedObjectInfo>>
+ LoadedObjInfoListT;
+
+ NotifyObjectLoadedT(OrcMCJITReplacement &M) : M(M) {}
+
+ void operator()(ObjectLinkingLayerBase::ObjSetHandleT H,
+ const ObjListT &Objects,
+ const LoadedObjInfoListT &Infos) const {
+ M.UnfinalizedSections[H] = std::move(M.SectionsAllocatedSinceLastLoad);
+ M.SectionsAllocatedSinceLastLoad = {};
+ assert(Objects.size() == Infos.size() &&
+ "Incorrect number of Infos for Objects.");
+ for (unsigned I = 0; I < Objects.size(); ++I)
+ M.MM->notifyObjectLoaded(&M, *Objects[I]);
+ };
+
+ private:
+ OrcMCJITReplacement &M;
+ };
+
+ class NotifyFinalizedT {
+ public:
+ NotifyFinalizedT(OrcMCJITReplacement &M) : M(M) {}
+ void operator()(ObjectLinkingLayerBase::ObjSetHandleT H) {
+ M.UnfinalizedSections.erase(H);
+ }
+
+ private:
+ OrcMCJITReplacement &M;
+ };
+
+ std::string Mangle(StringRef Name) {
+ std::string MangledName;
+ {
+ raw_string_ostream MangledNameStream(MangledName);
+ Mang.getNameWithPrefix(MangledNameStream, Name);
+ }
+ return MangledName;
+ }
+
+ typedef ObjectLinkingLayer<NotifyObjectLoadedT> ObjectLayerT;
+ typedef IRCompileLayer<ObjectLayerT> CompileLayerT;
+ typedef LazyEmittingLayer<CompileLayerT> LazyEmitLayerT;
+
+ std::unique_ptr<TargetMachine> TM;
+ std::unique_ptr<RTDyldMemoryManager> MM;
+ Mangler Mang;
+
+ NotifyObjectLoadedT NotifyObjectLoaded;
+ NotifyFinalizedT NotifyFinalized;
+
+ ObjectLayerT ObjectLayer;
+ CompileLayerT CompileLayer;
+ LazyEmitLayerT LazyEmitLayer;
+
+ // MCJIT keeps modules alive - we need to do the same for backwards
+ // compatibility.
+ std::vector<std::unique_ptr<Module>> OwnedModules;
+
+ // We need to store ObjLayerT::ObjSetHandles for each of the object sets
+ // that have been emitted but not yet finalized so that we can forward the
+ // mapSectionAddress calls appropriately.
+ typedef std::set<const void *> SectionAddrSet;
+ struct ObjSetHandleCompare {
+ bool operator()(ObjectLayerT::ObjSetHandleT H1,
+ ObjectLayerT::ObjSetHandleT H2) const {
+ return &*H1 < &*H2;
+ }
+ };
+ SectionAddrSet SectionsAllocatedSinceLastLoad;
+ std::map<ObjectLayerT::ObjSetHandleT, SectionAddrSet, ObjSetHandleCompare>
+ UnfinalizedSections;
+
+ std::vector<object::OwningBinary<object::Archive>> Archives;
+};
+}
+
+#endif // LLVM_LIB_EXECUTIONENGINE_ORC_MCJITREPLACEMENT_H
diff --git a/llvm/lib/ExecutionEngine/Orc/OrcTargetSupport.cpp b/llvm/lib/ExecutionEngine/Orc/OrcTargetSupport.cpp
new file mode 100644
index 00000000000..4a83a6c0b0c
--- /dev/null
+++ b/llvm/lib/ExecutionEngine/Orc/OrcTargetSupport.cpp
@@ -0,0 +1,102 @@
+#include "llvm/ADT/Triple.h"
+#include "llvm/ExecutionEngine/Orc/IndirectionUtils.h"
+
+#include <array>
+
+using namespace llvm;
+
+namespace {
+
+const char *JITCallbackFuncName = "call_jit_for_lazy_compile";
+const char *JITCallbackIndexLabelPrefix = "jit_resolve_";
+
+std::array<const char *, 12> X86GPRsToSave = {{
+ "rbp", "rbx", "r12", "r13", "r14", "r15", // Callee saved.
+ "rdi", "rsi", "rdx", "rcx", "r8", "r9", // Int args.
+}};
+
+std::array<const char *, 8> X86XMMsToSave = {{
+ "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7" // FP args
+}};
+
+template <typename OStream> unsigned saveX86Regs(OStream &OS) {
+ for (const auto &GPR : X86GPRsToSave)
+ OS << " pushq %" << GPR << "\n";
+
+ OS << " subq $" << (16 * X86XMMsToSave.size()) << ", %rsp\n";
+
+ for (unsigned i = 0; i < X86XMMsToSave.size(); ++i)
+ OS << " movdqu %" << X86XMMsToSave[i] << ", "
+ << (16 * (X86XMMsToSave.size() - i - 1)) << "(%rsp)\n";
+
+ return (8 * X86GPRsToSave.size()) + (16 * X86XMMsToSave.size());
+}
+
+template <typename OStream> void restoreX86Regs(OStream &OS) {
+ for (unsigned i = 0; i < X86XMMsToSave.size(); ++i)
+ OS << " movdqu " << (16 * i) << "(%rsp), %"
+ << X86XMMsToSave[(X86XMMsToSave.size() - i - 1)] << "\n";
+ OS << " addq $" << (16 * X86XMMsToSave.size()) << ", %rsp\n";
+
+ for (unsigned i = 0; i < X86GPRsToSave.size(); ++i)
+ OS << " popq %" << X86GPRsToSave[X86GPRsToSave.size() - i - 1] << "\n";
+}
+
+uint64_t call_jit_for_fn(JITResolveCallbackHandler *J, uint64_t FuncIdx) {
+ return J->resolve(FuncIdx);
+}
+}
+
+namespace llvm {
+
+std::string getJITResolveCallbackIndexLabel(unsigned I) {
+ std::ostringstream LabelStream;
+ LabelStream << JITCallbackIndexLabelPrefix << I;
+ return LabelStream.str();
+}
+
+void insertX86CallbackAsm(Module &M, JITResolveCallbackHandler &J) {
+ uint64_t CallbackAddr =
+ static_cast<uint64_t>(reinterpret_cast<uintptr_t>(call_jit_for_fn));
+
+ std::ostringstream JITCallbackAsm;
+ Triple TT(M.getTargetTriple());
+
+ if (TT.getOS() == Triple::Darwin)
+ JITCallbackAsm << ".section __TEXT,__text,regular,pure_instructions\n"
+ << ".align 4, 0x90\n";
+ else
+ JITCallbackAsm << ".text\n"
+ << ".align 16, 0x90\n";
+
+ JITCallbackAsm << "jit_object_addr:\n"
+ << " .quad " << &J << "\n" << JITCallbackFuncName << ":\n";
+
+ uint64_t ReturnAddrOffset = saveX86Regs(JITCallbackAsm);
+
+ // Compute index, load object address, and call JIT.
+ JITCallbackAsm << " movq " << ReturnAddrOffset << "(%rsp), %rax\n"
+ << " leaq (jit_indices_start+5)(%rip), %rbx\n"
+ << " subq %rbx, %rax\n"
+ << " xorq %rdx, %rdx\n"
+ << " movq $5, %rbx\n"
+ << " divq %rbx\n"
+ << " movq %rax, %rsi\n"
+ << " leaq jit_object_addr(%rip), %rdi\n"
+ << " movq (%rdi), %rdi\n"
+ << " movabsq $" << CallbackAddr << ", %rax\n"
+ << " callq *%rax\n"
+ << " movq %rax, " << ReturnAddrOffset << "(%rsp)\n";
+
+ restoreX86Regs(JITCallbackAsm);
+
+ JITCallbackAsm << " retq\n"
+ << "jit_indices_start:\n";
+
+ for (JITResolveCallbackHandler::StubIndex I = 0; I < J.getNumFuncs(); ++I)
+ JITCallbackAsm << getJITResolveCallbackIndexLabel(I) << ":\n"
+ << " callq " << JITCallbackFuncName << "\n";
+
+ M.appendModuleInlineAsm(JITCallbackAsm.str());
+}
+}
diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
index b47b56cc0d9..fb53ba96055 100644
--- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
+++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
@@ -449,11 +449,9 @@ void RuntimeDyldImpl::emitCommonSymbols(const ObjectFile &Obj,
StringRef Name;
Check(Sym.getName(Name));
- assert((GlobalSymbolTable.find(Name) == GlobalSymbolTable.end()) &&
- "Common symbol in global symbol table.");
-
// Skip common symbols already elsewhere.
- if (GlobalSymbolTable.count(Name)) {
+ if (GlobalSymbolTable.count(Name) ||
+ MemMgr->getSymbolAddressInLogicalDylib(Name)) {
DEBUG(dbgs() << "\tSkipping already emitted common symbol '" << Name
<< "'\n");
continue;
OpenPOWER on IntegriCloud