diff options
Diffstat (limited to 'llvm/lib/Target/PowerPC/PPCISelLowering.cpp')
-rw-r--r-- | llvm/lib/Target/PowerPC/PPCISelLowering.cpp | 61 |
1 files changed, 45 insertions, 16 deletions
diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp index fcfe32bdfc6..fa5099daf90 100644 --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -44,6 +44,7 @@ #include "llvm/CodeGen/MachineJumpTableInfo.h" #include "llvm/CodeGen/MachineLoopInfo.h" #include "llvm/CodeGen/MachineMemOperand.h" +#include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineOperand.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/RuntimeLibcalls.h" @@ -69,8 +70,10 @@ #include "llvm/IR/Type.h" #include "llvm/IR/Use.h" #include "llvm/IR/Value.h" +#include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCSymbolXCOFF.h" #include "llvm/Support/AtomicOrdering.h" #include "llvm/Support/BranchProbability.h" #include "llvm/Support/Casting.h" @@ -4402,9 +4405,23 @@ static bool isFunctionGlobalAddress(SDValue Callee); static bool callsShareTOCBase(const Function *Caller, SDValue Callee, const TargetMachine &TM) { - // If !G, Callee can be an external symbol. - GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee); - if (!G) + // Need a GlobalValue to determine if a Caller and Callee share the same + // TOCBase. + const GlobalValue *GV = nullptr; + + if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) { + GV = G->getGlobal(); + } else if (MCSymbolSDNode *M = dyn_cast<MCSymbolSDNode>(Callee)) { + // On AIX only, we replace GlobalAddressSDNode with MCSymbolSDNode for + // the callee of a direct function call. The MCSymbolSDNode contains the + // MCSymbol for the funtion entry point. + const auto *S = cast<MCSymbolXCOFF>(M->getMCSymbol()); + GV = S->getGlobalValue(); + } + + // If we failed to get a GlobalValue, then pessimistically assume they do not + // share a TOCBase. + if (!GV) return false; // The medium and large code models are expected to provide a sufficiently @@ -4413,13 +4430,12 @@ callsShareTOCBase(const Function *Caller, SDValue Callee, // only need to check that caller and callee don't cross dso boundaries. if (CodeModel::Medium == TM.getCodeModel() || CodeModel::Large == TM.getCodeModel()) - return TM.shouldAssumeDSOLocal(*Caller->getParent(), G->getGlobal()); + return TM.shouldAssumeDSOLocal(*Caller->getParent(), GV); // Otherwise we need to ensure callee and caller are in the same section, // since the linker may allocate multiple TOCs, and we don't know which // sections will belong to the same TOC base. - const GlobalValue *GV = G->getGlobal(); if (!GV->isStrongDefinitionForLinker()) return false; @@ -4891,7 +4907,8 @@ PrepareCall(SelectionDAG &DAG, SDValue &Callee, SDValue &InFlag, SDValue &Chain, // we're building with the leopard linker or later, which automatically // synthesizes these stubs. const TargetMachine &TM = DAG.getTarget(); - const Module *Mod = DAG.getMachineFunction().getFunction().getParent(); + MachineFunction &MF = DAG.getMachineFunction(); + const Module *Mod = MF.getFunction().getParent(); const GlobalValue *GV = nullptr; if (auto *G = dyn_cast<GlobalAddressSDNode>(Callee)) GV = G->getGlobal(); @@ -4900,17 +4917,29 @@ PrepareCall(SelectionDAG &DAG, SDValue &Callee, SDValue &InFlag, SDValue &Chain, if (isFunctionGlobalAddress(Callee)) { GlobalAddressSDNode *G = cast<GlobalAddressSDNode>(Callee); - // A call to a TLS address is actually an indirect call to a - // thread-specific pointer. - unsigned OpFlags = 0; - if (UsePlt) - OpFlags = PPCII::MO_PLT; - // 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. - Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, - Callee.getValueType(), 0, OpFlags); + if (TM.getTargetTriple().isOSAIX()) { + // Direct function calls reference the symbol for the function's entry + // point, which is named by inserting a "." before the function's + // C-linkage name. + auto &Context = MF.getMMI().getContext(); + MCSymbol *S = Context.getOrCreateSymbol(Twine(".") + + Twine(G->getGlobal()->getName())); + cast<MCSymbolXCOFF>(S)->setGlobalValue(GV); + Callee = DAG.getMCSymbol(S, PtrVT); + } else { + // A call to a TLS address is actually an indirect call to a + // thread-specific pointer. + unsigned OpFlags = 0; + if (UsePlt) + OpFlags = PPCII::MO_PLT; + + // 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. + Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, + Callee.getValueType(), 0, OpFlags); + } needIndirectCall = false; } |