1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
|
---
ExecutionEngine/JIT/JIT.cpp | 37 +++++++++++++++++++++++++++++++++++--
Target/PowerPC/PPCISelLowering.cpp | 26 ++++++++++++++++++++++++++
2 files changed, 61 insertions(+), 2 deletions(-)
--- a/lib/ExecutionEngine/JIT/JIT.cpp
+++ b/lib/ExecutionEngine/JIT/JIT.cpp
@@ -254,7 +254,12 @@
MutexGuard guard(Lock);
JITs.erase(jit);
}
- void *getPointerToNamedFunction(const char *Name) const {
+ bool empty() {
+ MutexGuard guard(Lock);
+ return JITs.empty();
+ }
+ void *getPointerToNamedFunction(const char *Name,
+ bool AbortOnFailure = true) const {
MutexGuard guard(Lock);
assert(JITs.size() != 0 && "No Jit registered");
//search function in every instance of JIT
@@ -266,7 +271,19 @@
}
// The function is not available : fallback on the first created (will
// search in symbol of the current program/library)
- return (*JITs.begin())->getPointerToNamedFunction(Name);
+ return (*JITs.begin())->getPointerToNamedFunction(Name, AbortOnFailure);
+ }
+ void *getPointerToGlobalIfAvailable(GlobalValue *V) const {
+ MutexGuard guard(Lock);
+ assert(JITs.size() != 0 && "No Jit registered");
+ //search function in every instance of JIT
+ for (SmallPtrSet<JIT*, 1>::const_iterator Jit = JITs.begin(),
+ end = JITs.end();
+ Jit != end; ++Jit) {
+ if (void *Ptr = (*Jit)->getPointerToGlobalIfAvailable(V))
+ return Ptr;
+ }
+ return 0;
}
};
ManagedStatic<JitPool> AllJits;
@@ -282,6 +299,22 @@
}
}
+extern "C" {
+ // getPointerToNamedFunctionOrNull - same as the above, but returns
+ // NULL instead of aborting if the function cannot be found.
+ void *getPointerToNamedFunctionOrNull(const char *Name) {
+ return !AllJits->empty() ? AllJits->getPointerToNamedFunction(Name, false) : 0;
+ }
+}
+
+extern "C" {
+ // getPointerToGlobalIfAvailable - same as the above, but for global
+ // variables, and only for those that have been codegened already.
+ void *getPointerToGlobalIfAvailable(GlobalValue *V) {
+ return !AllJits->empty() ? AllJits->getPointerToGlobalIfAvailable(V) : 0;
+ }
+}
+
JIT::JIT(Module *M, TargetMachine &tm, TargetJITInfo &tji,
JITMemoryManager *JMM, CodeGenOpt::Level OptLevel, bool GVsWithCode)
: ExecutionEngine(M), TM(tm), TJI(tji), AllocateGVsWithCode(GVsWithCode),
--- a/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -2450,6 +2450,9 @@
InFlag = Chain.getValue(1);
}
+extern "C" void *getPointerToNamedFunctionOrNull(const char *Name);
+extern "C" void *getPointerToGlobalIfAvailable(GlobalValue *Value);
+
static
unsigned PrepareCall(SelectionDAG &DAG, SDValue &Callee, SDValue &InFlag,
SDValue &Chain, DebugLoc dl, int SPDiff, bool isTailCall,
@@ -2462,6 +2465,29 @@
unsigned CallOpc = isSVR4ABI ? PPCISD::CALL_SVR4 : PPCISD::CALL_Darwin;
+ // XXX Work around for http://llvm.org/bugs/show_bug.cgi?id=5201
+ // and http://icedtea.classpath.org/bugzilla/show_bug.cgi?id=399
+ // for Shark.
+ //
+ // If the callee is an ExternalSymbol node, and the symbol can be
+ // resolved to a function pointer, then insert that pointer as a
+ // constant. This causes the next block of code to fall into the
+ // block that emits an indirect call. This works around
+ //
+ // This works for Shark because the only kinds of call that Shark
+ // makes that do not already fall into the indirect call block are
+ // calls to pre-existing external functions.
+ if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) {
+ void *FuncPtr = getPointerToNamedFunctionOrNull(S->getSymbol());
+ if (FuncPtr)
+ Callee = DAG.getConstant((uint64_t) FuncPtr, PtrVT);
+ }
+ if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
+ void *FuncPtr = getPointerToGlobalIfAvailable(G->getGlobal());
+ if (FuncPtr)
+ Callee = DAG.getConstant((uint64_t) FuncPtr, PtrVT);
+ }
+
// If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
// direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
// node so that legalize doesn't hack it.
|