diff options
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/CodeGen/LLVMTargetMachine.cpp | 9 | ||||
-rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/FastISel.cpp | 7 | ||||
-rw-r--r-- | llvm/lib/MC/MCContext.cpp | 4 | ||||
-rw-r--r-- | llvm/lib/Target/PowerPC/PPCFastISel.cpp | 7 | ||||
-rw-r--r-- | llvm/lib/Target/PowerPC/PPCISelLowering.cpp | 61 | ||||
-rw-r--r-- | llvm/lib/Target/PowerPC/PPCInstr64Bit.td | 6 | ||||
-rw-r--r-- | llvm/lib/Target/PowerPC/PPCInstrInfo.td | 8 |
7 files changed, 82 insertions, 20 deletions
diff --git a/llvm/lib/CodeGen/LLVMTargetMachine.cpp b/llvm/lib/CodeGen/LLVMTargetMachine.cpp index 1d10a6c9afd..886ae7e94ad 100644 --- a/llvm/lib/CodeGen/LLVMTargetMachine.cpp +++ b/llvm/lib/CodeGen/LLVMTargetMachine.cpp @@ -201,6 +201,15 @@ bool LLVMTargetMachine::addPassesToEmitFile(PassManagerBase &PM, return true; if (!TargetPassConfig::willCompleteCodeGenPipeline()) { + if (this->getTargetTriple().isOSAIX()) { + // On AIX, we might manifest MCSymbols during SDAG lowering. For MIR + // testing to be meaningful, we need to ensure that the symbols created + // are MCSymbolXCOFF variants, which requires that + // the TargetLoweringObjectFile instance has been initialized. + MCContext &Ctx = MMI->getContext(); + const_cast<TargetLoweringObjectFile &>(*this->getObjFileLowering()) + .Initialize(Ctx, *this); + } PM.add(createPrintMIRPass(Out)); } else if (addAsmPrinter(PM, Out, DwoOut, FileType, MMI->getContext())) return true; diff --git a/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp b/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp index d887ed73c44..72c4c0d8293 100644 --- a/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp @@ -1877,6 +1877,13 @@ bool FastISel::selectOperator(const User *I, unsigned Opcode) { return false; case Instruction::Call: + // On AIX, call lowering uses the DAG-ISEL path currently so that the + // callee of the direct function call instruction will be mapped to the + // symbol for the function's entry point, which is distinct from the + // function descriptor symbol. The latter is the symbol whose XCOFF symbol + // name is the C-linkage name of the source level function. + if (TM.getTargetTriple().isOSAIX()) + return false; return selectCall(I); case Instruction::BitCast: diff --git a/llvm/lib/MC/MCContext.cpp b/llvm/lib/MC/MCContext.cpp index e83702eebe0..43a7e8a64af 100644 --- a/llvm/lib/MC/MCContext.cpp +++ b/llvm/lib/MC/MCContext.cpp @@ -32,6 +32,7 @@ #include "llvm/MC/MCSymbolELF.h" #include "llvm/MC/MCSymbolMachO.h" #include "llvm/MC/MCSymbolWasm.h" +#include "llvm/MC/MCSymbolXCOFF.h" #include "llvm/MC/SectionKind.h" #include "llvm/Support/Casting.h" #include "llvm/Support/CommandLine.h" @@ -162,8 +163,7 @@ MCSymbol *MCContext::createSymbolImpl(const StringMapEntry<bool> *Name, case MCObjectFileInfo::IsWasm: return new (Name, *this) MCSymbolWasm(Name, IsTemporary); case MCObjectFileInfo::IsXCOFF: - // TODO: Need to implement class MCSymbolXCOFF. - break; + return new (Name, *this) MCSymbolXCOFF(Name, IsTemporary); } } return new (Name, *this) MCSymbol(MCSymbol::SymbolKindUnset, Name, diff --git a/llvm/lib/Target/PowerPC/PPCFastISel.cpp b/llvm/lib/Target/PowerPC/PPCFastISel.cpp index e22e682bc57..264d6b590f9 100644 --- a/llvm/lib/Target/PowerPC/PPCFastISel.cpp +++ b/llvm/lib/Target/PowerPC/PPCFastISel.cpp @@ -1964,6 +1964,13 @@ bool PPCFastISel::fastSelectInstruction(const Instruction *I) { case Instruction::Sub: return SelectBinaryIntOp(I, ISD::SUB); case Instruction::Call: + // On AIX, call lowering uses the DAG-ISEL path currently so that the + // callee of the direct function call instruction will be mapped to the + // symbol for the function's entry point, which is distinct from the + // function descriptor symbol. The latter is the symbol whose XCOFF symbol + // name is the C-linkage name of the source level function. + if (TM.getTargetTriple().isOSAIX()) + break; return selectCall(I); case Instruction::Ret: return SelectRet(I); 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; } diff --git a/llvm/lib/Target/PowerPC/PPCInstr64Bit.td b/llvm/lib/Target/PowerPC/PPCInstr64Bit.td index 78f1cc66a40..e17bc25ac21 100644 --- a/llvm/lib/Target/PowerPC/PPCInstr64Bit.td +++ b/llvm/lib/Target/PowerPC/PPCInstr64Bit.td @@ -192,6 +192,12 @@ def : Pat<(PPCcall (i64 texternalsym:$dst)), def : Pat<(PPCcall_nop (i64 texternalsym:$dst)), (BL8_NOP texternalsym:$dst)>; +// Calls for AIX +def : Pat<(PPCcall (i64 mcsym:$dst)), + (BL8 mcsym:$dst)>; +def : Pat<(PPCcall_nop (i64 mcsym:$dst)), + (BL8_NOP mcsym:$dst)>; + // Atomic operations // FIXME: some of these might be used with constant operands. This will result // in constant materialization instructions that may be redundant. We currently diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.td b/llvm/lib/Target/PowerPC/PPCInstrInfo.td index c32357239d9..2ec6d6ba3c5 100644 --- a/llvm/lib/Target/PowerPC/PPCInstrInfo.td +++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.td @@ -3032,12 +3032,16 @@ def : Pat<(and (rotl i32:$in, i32:$sh), maskimm32:$imm), // Calls def : Pat<(PPCcall (i32 tglobaladdr:$dst)), (BL tglobaladdr:$dst)>; -def : Pat<(PPCcall_nop (i32 tglobaladdr:$dst)), - (BL_NOP tglobaladdr:$dst)>; def : Pat<(PPCcall (i32 texternalsym:$dst)), (BL texternalsym:$dst)>; +// Calls for AIX only +def : Pat<(PPCcall (i32 mcsym:$dst)), + (BL mcsym:$dst)>; +def : Pat<(PPCcall_nop (i32 mcsym:$dst)), + (BL_NOP mcsym:$dst)>; + def : Pat<(PPCtc_return (i32 tglobaladdr:$dst), imm:$imm), (TCRETURNdi tglobaladdr:$dst, imm:$imm)>; |