diff options
Diffstat (limited to 'lib/Target/PowerPC/PPCAsmPrinter.cpp')
-rw-r--r-- | lib/Target/PowerPC/PPCAsmPrinter.cpp | 475 |
1 files changed, 333 insertions, 142 deletions
diff --git a/lib/Target/PowerPC/PPCAsmPrinter.cpp b/lib/Target/PowerPC/PPCAsmPrinter.cpp index 2d92a112d5ef..6f67c598c754 100644 --- a/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ b/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -16,27 +16,29 @@ // //===----------------------------------------------------------------------===// -#define DEBUG_TYPE "asmprinter" #include "PPC.h" #include "InstPrinter/PPCInstPrinter.h" -#include "MCTargetDesc/PPCPredicates.h" +#include "PPCMachineFunctionInfo.h" #include "MCTargetDesc/PPCMCExpr.h" +#include "MCTargetDesc/PPCPredicates.h" #include "PPCSubtarget.h" #include "PPCTargetMachine.h" #include "PPCTargetStreamer.h" #include "llvm/ADT/MapVector.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" -#include "llvm/Assembly/Writer.h" #include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineModuleInfoImpls.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" -#include "llvm/DebugInfo.h" #include "llvm/IR/Constants.h" +#include "llvm/IR/DebugInfo.h" #include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Mangler.h" #include "llvm/IR/Module.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" @@ -54,12 +56,13 @@ #include "llvm/Support/MathExtras.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Target/Mangler.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetRegisterInfo.h" using namespace llvm; +#define DEBUG_TYPE "asmprinter" + namespace { class PPCAsmPrinter : public AsmPrinter { protected: @@ -71,22 +74,22 @@ namespace { : AsmPrinter(TM, Streamer), Subtarget(TM.getSubtarget<PPCSubtarget>()), TOCLabelID(0) {} - virtual const char *getPassName() const { + const char *getPassName() const override { return "PowerPC Assembly Printer"; } MCSymbol *lookUpOrCreateTOCEntry(MCSymbol *Sym); - virtual void EmitInstruction(const MachineInstr *MI); + void EmitInstruction(const MachineInstr *MI) override; void printOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O); bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, unsigned AsmVariant, const char *ExtraCode, - raw_ostream &O); + raw_ostream &O) override; bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, unsigned AsmVariant, const char *ExtraCode, - raw_ostream &O); + raw_ostream &O) override; }; /// PPCLinuxAsmPrinter - PowerPC assembly printer, customized for Linux @@ -95,15 +98,17 @@ namespace { explicit PPCLinuxAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) : PPCAsmPrinter(TM, Streamer) {} - virtual const char *getPassName() const { + const char *getPassName() const override { return "Linux PPC Assembly Printer"; } - bool doFinalization(Module &M); + bool doFinalization(Module &M) override; + void EmitStartOfAsmFile(Module &M) override; - virtual void EmitFunctionEntryLabel(); + void EmitFunctionEntryLabel() override; - void EmitFunctionBodyEnd(); + void EmitFunctionBodyStart() override; + void EmitFunctionBodyEnd() override; }; /// PPCDarwinAsmPrinter - PowerPC assembly printer, customized for Darwin/Mac @@ -113,12 +118,12 @@ namespace { explicit PPCDarwinAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) : PPCAsmPrinter(TM, Streamer) {} - virtual const char *getPassName() const { + const char *getPassName() const override { return "Darwin PPC Assembly Printer"; } - bool doFinalization(Module &M); - void EmitStartOfAsmFile(Module &M); + bool doFinalization(Module &M) override; + void EmitStartOfAsmFile(Module &M) override; void EmitFunctionStubs(const MachineModuleInfoMachO::SymbolListTy &Stubs); }; @@ -130,7 +135,10 @@ static const char *stripRegisterPrefix(const char *RegName) { switch (RegName[0]) { case 'r': case 'f': - case 'v': return RegName + 1; + case 'v': + if (RegName[1] == 's') + return RegName + 2; + return RegName + 1; case 'c': if (RegName[1] == 'r') return RegName + 2; } @@ -139,6 +147,7 @@ static const char *stripRegisterPrefix(const char *RegName) { void PPCAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) { + const DataLayout *DL = TM.getDataLayout(); const MachineOperand &MO = MI->getOperand(OpNo); switch (MO.getType()) { @@ -157,37 +166,13 @@ void PPCAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo, case MachineOperand::MO_MachineBasicBlock: O << *MO.getMBB()->getSymbol(); return; - case MachineOperand::MO_JumpTableIndex: - O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() - << '_' << MO.getIndex(); - // FIXME: PIC relocation model - return; case MachineOperand::MO_ConstantPoolIndex: - O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() + O << DL->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_' << MO.getIndex(); return; case MachineOperand::MO_BlockAddress: O << *GetBlockAddressSymbol(MO.getBlockAddress()); return; - case MachineOperand::MO_ExternalSymbol: { - // Computing the address of an external symbol, not calling it. - if (TM.getRelocationModel() == Reloc::Static) { - O << *GetExternalSymbolSymbol(MO.getSymbolName()); - return; - } - - MCSymbol *NLPSym = - OutContext.GetOrCreateSymbol(StringRef(MAI->getGlobalPrefix())+ - MO.getSymbolName()+"$non_lazy_ptr"); - MachineModuleInfoImpl::StubValueTy &StubSym = - MMI->getObjFileInfo<MachineModuleInfoMachO>().getGVStubEntry(NLPSym); - if (StubSym.getPointer() == 0) - StubSym = MachineModuleInfoImpl:: - StubValueTy(GetExternalSymbolSymbol(MO.getSymbolName()), true); - - O << *NLPSym; - return; - } case MachineOperand::MO_GlobalAddress: { // Computing the address of a global symbol, not calling it. const GlobalValue *GV = MO.getGlobal(); @@ -197,21 +182,21 @@ void PPCAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo, if (TM.getRelocationModel() != Reloc::Static && (GV->isDeclaration() || GV->isWeakForLinker())) { if (!GV->hasHiddenVisibility()) { - SymToPrint = GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr"); + SymToPrint = getSymbolWithGlobalValueBase(GV, "$non_lazy_ptr"); MachineModuleInfoImpl::StubValueTy &StubSym = MMI->getObjFileInfo<MachineModuleInfoMachO>() .getGVStubEntry(SymToPrint); - if (StubSym.getPointer() == 0) + if (!StubSym.getPointer()) StubSym = MachineModuleInfoImpl:: StubValueTy(getSymbol(GV), !GV->hasInternalLinkage()); } else if (GV->isDeclaration() || GV->hasCommonLinkage() || GV->hasAvailableExternallyLinkage()) { - SymToPrint = GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr"); + SymToPrint = getSymbolWithGlobalValueBase(GV, "$non_lazy_ptr"); MachineModuleInfoImpl::StubValueTy &StubSym = MMI->getObjFileInfo<MachineModuleInfoMachO>(). getHiddenGVStubEntry(SymToPrint); - if (StubSym.getPointer() == 0) + if (!StubSym.getPointer()) StubSym = MachineModuleInfoImpl:: StubValueTy(getSymbol(GV), !GV->hasInternalLinkage()); } else { @@ -228,7 +213,7 @@ void PPCAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo, } default: - O << "<unknown operand type: " << MO.getType() << ">"; + O << "<unknown operand type: " << (unsigned)MO.getType() << ">"; return; } } @@ -305,13 +290,13 @@ bool PPCAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, /// exists for it. If not, create one. Then return a symbol that references /// the TOC entry. MCSymbol *PPCAsmPrinter::lookUpOrCreateTOCEntry(MCSymbol *Sym) { - + const DataLayout *DL = TM.getDataLayout(); MCSymbol *&TOCEntry = TOC[Sym]; // To avoid name clash check if the name already exists. - while (TOCEntry == 0) { - if (OutContext.LookupSymbol(Twine(MAI->getPrivateGlobalPrefix()) + - "C" + Twine(TOCLabelID++)) == 0) { + while (!TOCEntry) { + if (OutContext.LookupSymbol(Twine(DL->getPrivateGlobalPrefix()) + + "C" + Twine(TOCLabelID++)) == nullptr) { TOCEntry = GetTempSymbol("C", TOCLabelID); } } @@ -325,6 +310,7 @@ MCSymbol *PPCAsmPrinter::lookUpOrCreateTOCEntry(MCSymbol *Sym) { /// void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) { MCInst TmpInst; + bool isPPC64 = Subtarget.isPPC64(); // Lower multi-instruction pseudo operations. switch (MI->getOpcode()) { @@ -340,7 +326,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) { MCSymbol *PICBase = MF->getPICBaseSymbol(); // Emit the 'bl'. - OutStreamer.EmitInstruction(MCInstBuilder(PPC::BL) + EmitToStreamer(OutStreamer, MCInstBuilder(PPC::BL) // FIXME: We would like an efficient form for this, so we don't have to do // a lot of extra uniquing. .addExpr(MCSymbolRefExpr::Create(PICBase, OutContext))); @@ -349,6 +335,66 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) { OutStreamer.EmitLabel(PICBase); return; } + case PPC::GetGBRO: { + // Get the offset from the GOT Base Register to the GOT + LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, Subtarget.isDarwin()); + MCSymbol *PICOffset = MF->getInfo<PPCFunctionInfo>()->getPICOffsetSymbol(); + TmpInst.setOpcode(PPC::LWZ); + const MCExpr *Exp = + MCSymbolRefExpr::Create(PICOffset, MCSymbolRefExpr::VK_None, OutContext); + const MCExpr *PB = + MCSymbolRefExpr::Create(MF->getPICBaseSymbol(), + MCSymbolRefExpr::VK_None, + OutContext); + const MCOperand MO = TmpInst.getOperand(1); + TmpInst.getOperand(1) = MCOperand::CreateExpr(MCBinaryExpr::CreateSub(Exp, + PB, + OutContext)); + TmpInst.addOperand(MO); + EmitToStreamer(OutStreamer, TmpInst); + return; + } + case PPC::UpdateGBR: { + // Update the GOT Base Register to point to the GOT. It may be possible to + // merge this with the PPC::GetGBRO, doing it all in one step. + LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, Subtarget.isDarwin()); + TmpInst.setOpcode(PPC::ADD4); + TmpInst.addOperand(TmpInst.getOperand(0)); + EmitToStreamer(OutStreamer, TmpInst); + return; + } + case PPC::LWZtoc: { + // Transform %X3 = LWZtoc <ga:@min1>, %X2 + LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, Subtarget.isDarwin()); + + // Change the opcode to LWZ, and the global address operand to be a + // reference to the GOT entry we will synthesize later. + TmpInst.setOpcode(PPC::LWZ); + const MachineOperand &MO = MI->getOperand(1); + + // Map symbol -> label of TOC entry + assert(MO.isGlobal() || MO.isCPI() || MO.isJTI()); + MCSymbol *MOSymbol = nullptr; + if (MO.isGlobal()) + MOSymbol = getSymbol(MO.getGlobal()); + else if (MO.isCPI()) + MOSymbol = GetCPISymbol(MO.getIndex()); + else if (MO.isJTI()) + MOSymbol = GetJTISymbol(MO.getIndex()); + + MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(MOSymbol); + + const MCExpr *Exp = + MCSymbolRefExpr::Create(TOCEntry, MCSymbolRefExpr::VK_None, + OutContext); + const MCExpr *PB = + MCSymbolRefExpr::Create(OutContext.GetOrCreateSymbol(Twine(".L.TOC.")), + OutContext); + Exp = MCBinaryExpr::CreateSub(Exp, PB, OutContext); + TmpInst.getOperand(1) = MCOperand::CreateExpr(Exp); + EmitToStreamer(OutStreamer, TmpInst); + return; + } case PPC::LDtocJTI: case PPC::LDtocCPT: case PPC::LDtoc: { @@ -362,7 +408,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) { // Map symbol -> label of TOC entry assert(MO.isGlobal() || MO.isCPI() || MO.isJTI()); - MCSymbol *MOSymbol = 0; + MCSymbol *MOSymbol = nullptr; if (MO.isGlobal()) MOSymbol = getSymbol(MO.getGlobal()); else if (MO.isCPI()) @@ -376,7 +422,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) { MCSymbolRefExpr::Create(TOCEntry, MCSymbolRefExpr::VK_PPC_TOC, OutContext); TmpInst.getOperand(1) = MCOperand::CreateExpr(Exp); - OutStreamer.EmitInstruction(TmpInst); + EmitToStreamer(OutStreamer, TmpInst); return; } @@ -384,45 +430,42 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) { // Transform %Xd = ADDIStocHA %X2, <ga:@sym> LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, Subtarget.isDarwin()); - // Change the opcode to ADDIS8. If the global address is external, - // has common linkage, is a function address, or is a jump table + // Change the opcode to ADDIS8. If the global address is external, has + // common linkage, is a non-local function address, or is a jump table // address, then generate a TOC entry and reference that. Otherwise // reference the symbol directly. TmpInst.setOpcode(PPC::ADDIS8); const MachineOperand &MO = MI->getOperand(2); assert((MO.isGlobal() || MO.isCPI() || MO.isJTI()) && "Invalid operand for ADDIStocHA!"); - MCSymbol *MOSymbol = 0; + MCSymbol *MOSymbol = nullptr; bool IsExternal = false; - bool IsFunction = false; + bool IsNonLocalFunction = false; bool IsCommon = false; bool IsAvailExt = false; if (MO.isGlobal()) { - const GlobalValue *GValue = MO.getGlobal(); - const GlobalAlias *GAlias = dyn_cast<GlobalAlias>(GValue); - const GlobalValue *RealGValue = GAlias ? - GAlias->resolveAliasedGlobal(false) : GValue; - MOSymbol = getSymbol(RealGValue); - const GlobalVariable *GVar = dyn_cast<GlobalVariable>(RealGValue); - IsExternal = GVar && !GVar->hasInitializer(); - IsCommon = GVar && RealGValue->hasCommonLinkage(); - IsFunction = !GVar; - IsAvailExt = GVar && RealGValue->hasAvailableExternallyLinkage(); + const GlobalValue *GV = MO.getGlobal(); + MOSymbol = getSymbol(GV); + IsExternal = GV->isDeclaration(); + IsCommon = GV->hasCommonLinkage(); + IsNonLocalFunction = GV->getType()->getElementType()->isFunctionTy() && + (GV->isDeclaration() || GV->isWeakForLinker()); + IsAvailExt = GV->hasAvailableExternallyLinkage(); } else if (MO.isCPI()) MOSymbol = GetCPISymbol(MO.getIndex()); else if (MO.isJTI()) MOSymbol = GetJTISymbol(MO.getIndex()); - if (IsExternal || IsFunction || IsCommon || IsAvailExt || MO.isJTI() || - TM.getCodeModel() == CodeModel::Large) + if (IsExternal || IsNonLocalFunction || IsCommon || IsAvailExt || + MO.isJTI() || TM.getCodeModel() == CodeModel::Large) MOSymbol = lookUpOrCreateTOCEntry(MOSymbol); const MCExpr *Exp = MCSymbolRefExpr::Create(MOSymbol, MCSymbolRefExpr::VK_PPC_TOC_HA, OutContext); TmpInst.getOperand(2) = MCOperand::CreateExpr(Exp); - OutStreamer.EmitInstruction(TmpInst); + EmitToStreamer(OutStreamer, TmpInst); return; } case PPC::LDtocL: { @@ -436,7 +479,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) { const MachineOperand &MO = MI->getOperand(1); assert((MO.isGlobal() || MO.isJTI() || MO.isCPI()) && "Invalid operand for LDtocL!"); - MCSymbol *MOSymbol = 0; + MCSymbol *MOSymbol = nullptr; if (MO.isJTI()) MOSymbol = lookUpOrCreateTOCEntry(GetJTISymbol(MO.getIndex())); @@ -447,14 +490,10 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) { } else if (MO.isGlobal()) { const GlobalValue *GValue = MO.getGlobal(); - const GlobalAlias *GAlias = dyn_cast<GlobalAlias>(GValue); - const GlobalValue *RealGValue = GAlias ? - GAlias->resolveAliasedGlobal(false) : GValue; - MOSymbol = getSymbol(RealGValue); - const GlobalVariable *GVar = dyn_cast<GlobalVariable>(RealGValue); - - if (!GVar || !GVar->hasInitializer() || RealGValue->hasCommonLinkage() || - RealGValue->hasAvailableExternallyLinkage() || + MOSymbol = getSymbol(GValue); + if (GValue->getType()->getElementType()->isFunctionTy() || + GValue->isDeclaration() || GValue->hasCommonLinkage() || + GValue->hasAvailableExternallyLinkage() || TM.getCodeModel() == CodeModel::Large) MOSymbol = lookUpOrCreateTOCEntry(MOSymbol); } @@ -463,7 +502,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) { MCSymbolRefExpr::Create(MOSymbol, MCSymbolRefExpr::VK_PPC_TOC_LO, OutContext); TmpInst.getOperand(1) = MCOperand::CreateExpr(Exp); - OutStreamer.EmitInstruction(TmpInst); + EmitToStreamer(OutStreamer, TmpInst); return; } case PPC::ADDItocL: { @@ -476,30 +515,28 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) { TmpInst.setOpcode(PPC::ADDI8); const MachineOperand &MO = MI->getOperand(2); assert((MO.isGlobal() || MO.isCPI()) && "Invalid operand for ADDItocL"); - MCSymbol *MOSymbol = 0; + MCSymbol *MOSymbol = nullptr; bool IsExternal = false; - bool IsFunction = false; + bool IsNonLocalFunction = false; if (MO.isGlobal()) { - const GlobalValue *GValue = MO.getGlobal(); - const GlobalAlias *GAlias = dyn_cast<GlobalAlias>(GValue); - const GlobalValue *RealGValue = GAlias ? - GAlias->resolveAliasedGlobal(false) : GValue; - MOSymbol = getSymbol(RealGValue); - const GlobalVariable *GVar = dyn_cast<GlobalVariable>(RealGValue); - IsExternal = GVar && !GVar->hasInitializer(); - IsFunction = !GVar; + const GlobalValue *GV = MO.getGlobal(); + MOSymbol = getSymbol(GV); + IsExternal = GV->isDeclaration(); + IsNonLocalFunction = GV->getType()->getElementType()->isFunctionTy() && + (GV->isDeclaration() || GV->isWeakForLinker()); } else if (MO.isCPI()) MOSymbol = GetCPISymbol(MO.getIndex()); - if (IsFunction || IsExternal || TM.getCodeModel() == CodeModel::Large) + if (IsNonLocalFunction || IsExternal || + TM.getCodeModel() == CodeModel::Large) MOSymbol = lookUpOrCreateTOCEntry(MOSymbol); const MCExpr *Exp = MCSymbolRefExpr::Create(MOSymbol, MCSymbolRefExpr::VK_PPC_TOC_LO, OutContext); TmpInst.getOperand(2) = MCOperand::CreateExpr(Exp); - OutStreamer.EmitInstruction(TmpInst); + EmitToStreamer(OutStreamer, TmpInst); return; } case PPC::ADDISgotTprelHA: { @@ -512,18 +549,19 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) { const MCExpr *SymGotTprel = MCSymbolRefExpr::Create(MOSymbol, MCSymbolRefExpr::VK_PPC_GOT_TPREL_HA, OutContext); - OutStreamer.EmitInstruction(MCInstBuilder(PPC::ADDIS8) + EmitToStreamer(OutStreamer, MCInstBuilder(PPC::ADDIS8) .addReg(MI->getOperand(0).getReg()) .addReg(PPC::X2) .addExpr(SymGotTprel)); return; } - case PPC::LDgotTprelL: { + case PPC::LDgotTprelL: + case PPC::LDgotTprelL32: { // Transform %Xd = LDgotTprelL <ga:@sym>, %Xs LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, Subtarget.isDarwin()); // Change the opcode to LD. - TmpInst.setOpcode(PPC::LD); + TmpInst.setOpcode(isPPC64 ? PPC::LD : PPC::LWZ); const MachineOperand &MO = MI->getOperand(1); const GlobalValue *GValue = MO.getGlobal(); MCSymbol *MOSymbol = getSymbol(GValue); @@ -531,7 +569,25 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) { MCSymbolRefExpr::Create(MOSymbol, MCSymbolRefExpr::VK_PPC_GOT_TPREL_LO, OutContext); TmpInst.getOperand(1) = MCOperand::CreateExpr(Exp); - OutStreamer.EmitInstruction(TmpInst); + EmitToStreamer(OutStreamer, TmpInst); + return; + } + + case PPC::PPC32GOT: { + MCSymbol *GOTSymbol = OutContext.GetOrCreateSymbol(StringRef("_GLOBAL_OFFSET_TABLE_")); + const MCExpr *SymGotTlsL = + MCSymbolRefExpr::Create(GOTSymbol, MCSymbolRefExpr::VK_PPC_LO, + OutContext); + const MCExpr *SymGotTlsHA = + MCSymbolRefExpr::Create(GOTSymbol, MCSymbolRefExpr::VK_PPC_HA, + OutContext); + EmitToStreamer(OutStreamer, MCInstBuilder(PPC::LI) + .addReg(MI->getOperand(0).getReg()) + .addExpr(SymGotTlsL)); + EmitToStreamer(OutStreamer, MCInstBuilder(PPC::ADDIS) + .addReg(MI->getOperand(0).getReg()) + .addReg(MI->getOperand(0).getReg()) + .addExpr(SymGotTlsHA)); return; } case PPC::ADDIStlsgdHA: { @@ -544,7 +600,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) { const MCExpr *SymGotTlsGD = MCSymbolRefExpr::Create(MOSymbol, MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HA, OutContext); - OutStreamer.EmitInstruction(MCInstBuilder(PPC::ADDIS8) + EmitToStreamer(OutStreamer, MCInstBuilder(PPC::ADDIS8) .addReg(MI->getOperand(0).getReg()) .addReg(PPC::X2) .addExpr(SymGotTlsGD)); @@ -560,7 +616,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) { const MCExpr *SymGotTlsGD = MCSymbolRefExpr::Create(MOSymbol, MCSymbolRefExpr::VK_PPC_GOT_TLSGD_LO, OutContext); - OutStreamer.EmitInstruction(MCInstBuilder(PPC::ADDI8) + EmitToStreamer(OutStreamer, MCInstBuilder(PPC::ADDI8) .addReg(MI->getOperand(0).getReg()) .addReg(MI->getOperand(1).getReg()) .addExpr(SymGotTlsGD)); @@ -581,7 +637,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) { const MCExpr *SymVar = MCSymbolRefExpr::Create(MOSymbol, MCSymbolRefExpr::VK_PPC_TLSGD, OutContext); - OutStreamer.EmitInstruction(MCInstBuilder(PPC::BL8_NOP_TLS) + EmitToStreamer(OutStreamer, MCInstBuilder(PPC::BL8_NOP_TLS) .addExpr(TlsRef) .addExpr(SymVar)); return; @@ -596,7 +652,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) { const MCExpr *SymGotTlsLD = MCSymbolRefExpr::Create(MOSymbol, MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HA, OutContext); - OutStreamer.EmitInstruction(MCInstBuilder(PPC::ADDIS8) + EmitToStreamer(OutStreamer, MCInstBuilder(PPC::ADDIS8) .addReg(MI->getOperand(0).getReg()) .addReg(PPC::X2) .addExpr(SymGotTlsLD)); @@ -612,7 +668,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) { const MCExpr *SymGotTlsLD = MCSymbolRefExpr::Create(MOSymbol, MCSymbolRefExpr::VK_PPC_GOT_TLSLD_LO, OutContext); - OutStreamer.EmitInstruction(MCInstBuilder(PPC::ADDI8) + EmitToStreamer(OutStreamer, MCInstBuilder(PPC::ADDI8) .addReg(MI->getOperand(0).getReg()) .addReg(MI->getOperand(1).getReg()) .addExpr(SymGotTlsLD)); @@ -633,7 +689,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) { const MCExpr *SymVar = MCSymbolRefExpr::Create(MOSymbol, MCSymbolRefExpr::VK_PPC_TLSLD, OutContext); - OutStreamer.EmitInstruction(MCInstBuilder(PPC::BL8_NOP_TLS) + EmitToStreamer(OutStreamer, MCInstBuilder(PPC::BL8_NOP_TLS) .addExpr(TlsRef) .addExpr(SymVar)); return; @@ -648,7 +704,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) { const MCExpr *SymDtprel = MCSymbolRefExpr::Create(MOSymbol, MCSymbolRefExpr::VK_PPC_DTPREL_HA, OutContext); - OutStreamer.EmitInstruction(MCInstBuilder(PPC::ADDIS8) + EmitToStreamer(OutStreamer, MCInstBuilder(PPC::ADDIS8) .addReg(MI->getOperand(0).getReg()) .addReg(PPC::X3) .addExpr(SymDtprel)); @@ -664,7 +720,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) { const MCExpr *SymDtprel = MCSymbolRefExpr::Create(MOSymbol, MCSymbolRefExpr::VK_PPC_DTPREL_LO, OutContext); - OutStreamer.EmitInstruction(MCInstBuilder(PPC::ADDI8) + EmitToStreamer(OutStreamer, MCInstBuilder(PPC::ADDI8) .addReg(MI->getOperand(0).getReg()) .addReg(MI->getOperand(1).getReg()) .addExpr(SymDtprel)); @@ -679,7 +735,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) { MI->getOpcode() == PPC::MFOCRF ? PPC::MFCR : PPC::MFCR8; OutStreamer.AddComment(PPCInstPrinter:: getRegisterName(MI->getOperand(1).getReg())); - OutStreamer.EmitInstruction(MCInstBuilder(NewOpcode) + EmitToStreamer(OutStreamer, MCInstBuilder(NewOpcode) .addReg(MI->getOperand(0).getReg())); return; } @@ -695,7 +751,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) { ->getEncodingValue(MI->getOperand(0).getReg()); OutStreamer.AddComment(PPCInstPrinter:: getRegisterName(MI->getOperand(0).getReg())); - OutStreamer.EmitInstruction(MCInstBuilder(NewOpcode) + EmitToStreamer(OutStreamer, MCInstBuilder(NewOpcode) .addImm(Mask) .addReg(MI->getOperand(1).getReg())); return; @@ -723,13 +779,76 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) { } LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, Subtarget.isDarwin()); - OutStreamer.EmitInstruction(TmpInst); + EmitToStreamer(OutStreamer, TmpInst); +} + +void PPCLinuxAsmPrinter::EmitStartOfAsmFile(Module &M) { + if (Subtarget.isELFv2ABI()) { + PPCTargetStreamer *TS = + static_cast<PPCTargetStreamer *>(OutStreamer.getTargetStreamer()); + + if (TS) + TS->emitAbiVersion(2); + } + + if (Subtarget.isPPC64() || TM.getRelocationModel() != Reloc::PIC_) + return AsmPrinter::EmitStartOfAsmFile(M); + + // FIXME: The use of .got2 assumes large GOT model (-fPIC), which is not + // optimal for some cases. We should consider supporting small model (-fpic) + // as well in the future. + assert(TM.getCodeModel() != CodeModel::Small && + "Small code model PIC is currently unsupported."); + OutStreamer.SwitchSection(OutContext.getELFSection(".got2", + ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC, + SectionKind::getReadOnly())); + + MCSymbol *TOCSym = OutContext.GetOrCreateSymbol(Twine(".L.TOC.")); + MCSymbol *CurrentPos = OutContext.CreateTempSymbol(); + + OutStreamer.EmitLabel(CurrentPos); + + // The GOT pointer points to the middle of the GOT, in order to reference the + // entire 64kB range. 0x8000 is the midpoint. + const MCExpr *tocExpr = + MCBinaryExpr::CreateAdd(MCSymbolRefExpr::Create(CurrentPos, OutContext), + MCConstantExpr::Create(0x8000, OutContext), + OutContext); + + OutStreamer.EmitAssignment(TOCSym, tocExpr); + + OutStreamer.SwitchSection(getObjFileLowering().getTextSection()); } void PPCLinuxAsmPrinter::EmitFunctionEntryLabel() { - if (!Subtarget.isPPC64()) // linux/ppc32 - Normal entry label. + // linux/ppc32 - Normal entry label. + if (!Subtarget.isPPC64() && TM.getRelocationModel() != Reloc::PIC_) return AsmPrinter::EmitFunctionEntryLabel(); - + + if (!Subtarget.isPPC64()) { + const PPCFunctionInfo *PPCFI = MF->getInfo<PPCFunctionInfo>(); + if (PPCFI->usesPICBase()) { + MCSymbol *RelocSymbol = PPCFI->getPICOffsetSymbol(); + MCSymbol *PICBase = MF->getPICBaseSymbol(); + OutStreamer.EmitLabel(RelocSymbol); + + const MCExpr *OffsExpr = + MCBinaryExpr::CreateSub( + MCSymbolRefExpr::Create(OutContext.GetOrCreateSymbol(Twine(".L.TOC.")), + OutContext), + MCSymbolRefExpr::Create(PICBase, OutContext), + OutContext); + OutStreamer.EmitValue(OffsExpr, 4); + OutStreamer.EmitLabel(CurrentFnSym); + return; + } else + return AsmPrinter::EmitFunctionEntryLabel(); + } + + // ELFv2 ABI - Normal entry label. + if (Subtarget.isELFv2ABI()) + return AsmPrinter::EmitFunctionEntryLabel(); + // Emit an official procedure descriptor. MCSectionSubPair Current = OutStreamer.getCurrentSection(); const MCSectionELF *Section = OutStreamer.getContext().getELFSection(".opd", @@ -766,10 +885,17 @@ bool PPCLinuxAsmPrinter::doFinalization(Module &M) { bool isPPC64 = TD->getPointerSizeInBits() == 64; PPCTargetStreamer &TS = - static_cast<PPCTargetStreamer &>(OutStreamer.getTargetStreamer()); + static_cast<PPCTargetStreamer &>(*OutStreamer.getTargetStreamer()); - if (isPPC64 && !TOC.empty()) { - const MCSectionELF *Section = OutStreamer.getContext().getELFSection(".toc", + if (!TOC.empty()) { + const MCSectionELF *Section; + + if (isPPC64) + Section = OutStreamer.getContext().getELFSection(".toc", + ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC, + SectionKind::getReadOnly()); + else + Section = OutStreamer.getContext().getELFSection(".got2", ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC, SectionKind::getReadOnly()); OutStreamer.SwitchSection(Section); @@ -778,7 +904,10 @@ bool PPCLinuxAsmPrinter::doFinalization(Module &M) { E = TOC.end(); I != E; ++I) { OutStreamer.EmitLabel(I->second); MCSymbol *S = OutContext.GetOrCreateSymbol(I->first->getName()); - TS.emitTCEntry(*S); + if (isPPC64) + TS.emitTCEntry(*S); + else + OutStreamer.EmitSymbolValue(S, 4); } } @@ -804,6 +933,68 @@ bool PPCLinuxAsmPrinter::doFinalization(Module &M) { return AsmPrinter::doFinalization(M); } +/// EmitFunctionBodyStart - Emit a global entry point prefix for ELFv2. +void PPCLinuxAsmPrinter::EmitFunctionBodyStart() { + // In the ELFv2 ABI, in functions that use the TOC register, we need to + // provide two entry points. The ABI guarantees that when calling the + // local entry point, r2 is set up by the caller to contain the TOC base + // for this function, and when calling the global entry point, r12 is set + // up by the caller to hold the address of the global entry point. We + // thus emit a prefix sequence along the following lines: + // + // func: + // # global entry point + // addis r2,r12,(.TOC.-func)@ha + // addi r2,r2,(.TOC.-func)@l + // .localentry func, .-func + // # local entry point, followed by function body + // + // This ensures we have r2 set up correctly while executing the function + // body, no matter which entry point is called. + if (Subtarget.isELFv2ABI() + // Only do all that if the function uses r2 in the first place. + && !MF->getRegInfo().use_empty(PPC::X2)) { + + MCSymbol *GlobalEntryLabel = OutContext.CreateTempSymbol(); + OutStreamer.EmitLabel(GlobalEntryLabel); + const MCSymbolRefExpr *GlobalEntryLabelExp = + MCSymbolRefExpr::Create(GlobalEntryLabel, OutContext); + + MCSymbol *TOCSymbol = OutContext.GetOrCreateSymbol(StringRef(".TOC.")); + const MCExpr *TOCDeltaExpr = + MCBinaryExpr::CreateSub(MCSymbolRefExpr::Create(TOCSymbol, OutContext), + GlobalEntryLabelExp, OutContext); + + const MCExpr *TOCDeltaHi = + PPCMCExpr::CreateHa(TOCDeltaExpr, false, OutContext); + EmitToStreamer(OutStreamer, MCInstBuilder(PPC::ADDIS) + .addReg(PPC::X2) + .addReg(PPC::X12) + .addExpr(TOCDeltaHi)); + + const MCExpr *TOCDeltaLo = + PPCMCExpr::CreateLo(TOCDeltaExpr, false, OutContext); + EmitToStreamer(OutStreamer, MCInstBuilder(PPC::ADDI) + .addReg(PPC::X2) + .addReg(PPC::X2) + .addExpr(TOCDeltaLo)); + + MCSymbol *LocalEntryLabel = OutContext.CreateTempSymbol(); + OutStreamer.EmitLabel(LocalEntryLabel); + const MCSymbolRefExpr *LocalEntryLabelExp = + MCSymbolRefExpr::Create(LocalEntryLabel, OutContext); + const MCExpr *LocalOffsetExp = + MCBinaryExpr::CreateSub(LocalEntryLabelExp, + GlobalEntryLabelExp, OutContext); + + PPCTargetStreamer *TS = + static_cast<PPCTargetStreamer *>(OutStreamer.getTargetStreamer()); + + if (TS) + TS->emitLocalEntry(CurrentFnSym, LocalOffsetExp); + } +} + /// EmitFunctionBodyEnd - Print the traceback table before the .size /// directive. /// @@ -854,13 +1045,12 @@ void PPCDarwinAsmPrinter::EmitStartOfAsmFile(Module &M) { if (Subtarget.isPPC64() && Directive < PPC::DIR_64) Directive = PPC::DIR_64; assert(Directive <= PPC::DIR_64 && "Directive out of range."); - - // FIXME: This is a total hack, finish mc'izing the PPC backend. - if (OutStreamer.hasRawTextSupport()) { - assert(Directive < array_lengthof(CPUDirectives) && - "CPUDirectives[] might not be up-to-date!"); - OutStreamer.EmitRawText("\t.machine " + Twine(CPUDirectives[Directive])); - } + + assert(Directive < array_lengthof(CPUDirectives) && + "CPUDirectives[] might not be up-to-date!"); + PPCTargetStreamer &TStreamer = + *static_cast<PPCTargetStreamer *>(OutStreamer.getTargetStreamer()); + TStreamer.emitMachine(CPUDirectives[Directive]); // Prime text sections so they are adjacent. This reduces the likelihood a // large data or debug section causes a branch to exceed 16M limit. @@ -870,14 +1060,14 @@ void PPCDarwinAsmPrinter::EmitStartOfAsmFile(Module &M) { if (TM.getRelocationModel() == Reloc::PIC_) { OutStreamer.SwitchSection( OutContext.getMachOSection("__TEXT", "__picsymbolstub1", - MCSectionMachO::S_SYMBOL_STUBS | - MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, + MachO::S_SYMBOL_STUBS | + MachO::S_ATTR_PURE_INSTRUCTIONS, 32, SectionKind::getText())); } else if (TM.getRelocationModel() == Reloc::DynamicNoPIC) { OutStreamer.SwitchSection( OutContext.getMachOSection("__TEXT","__symbol_stub1", - MCSectionMachO::S_SYMBOL_STUBS | - MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, + MachO::S_SYMBOL_STUBS | + MachO::S_ATTR_PURE_INSTRUCTIONS, 16, SectionKind::getText())); } OutStreamer.SwitchSection(getObjFileLowering().getTextSection()); @@ -909,8 +1099,8 @@ EmitFunctionStubs(const MachineModuleInfoMachO::SymbolListTy &Stubs) { if (TM.getRelocationModel() == Reloc::PIC_) { const MCSection *StubSection = OutContext.getMachOSection("__TEXT", "__picsymbolstub1", - MCSectionMachO::S_SYMBOL_STUBS | - MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, + MachO::S_SYMBOL_STUBS | + MachO::S_ATTR_PURE_INSTRUCTIONS, 32, SectionKind::getText()); for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { OutStreamer.SwitchSection(StubSection); @@ -930,32 +1120,32 @@ EmitFunctionStubs(const MachineModuleInfoMachO::SymbolListTy &Stubs) { MCBinaryExpr::CreateSub(LazyPtrExpr, Anon, OutContext); // mflr r0 - OutStreamer.EmitInstruction(MCInstBuilder(PPC::MFLR).addReg(PPC::R0)); + EmitToStreamer(OutStreamer, MCInstBuilder(PPC::MFLR).addReg(PPC::R0)); // bcl 20, 31, AnonSymbol - OutStreamer.EmitInstruction(MCInstBuilder(PPC::BCLalways).addExpr(Anon)); + EmitToStreamer(OutStreamer, MCInstBuilder(PPC::BCLalways).addExpr(Anon)); OutStreamer.EmitLabel(AnonSymbol); // mflr r11 - OutStreamer.EmitInstruction(MCInstBuilder(PPC::MFLR).addReg(PPC::R11)); + EmitToStreamer(OutStreamer, MCInstBuilder(PPC::MFLR).addReg(PPC::R11)); // addis r11, r11, ha16(LazyPtr - AnonSymbol) const MCExpr *SubHa16 = PPCMCExpr::CreateHa(Sub, isDarwin, OutContext); - OutStreamer.EmitInstruction(MCInstBuilder(PPC::ADDIS) + EmitToStreamer(OutStreamer, MCInstBuilder(PPC::ADDIS) .addReg(PPC::R11) .addReg(PPC::R11) .addExpr(SubHa16)); // mtlr r0 - OutStreamer.EmitInstruction(MCInstBuilder(PPC::MTLR).addReg(PPC::R0)); + EmitToStreamer(OutStreamer, MCInstBuilder(PPC::MTLR).addReg(PPC::R0)); // ldu r12, lo16(LazyPtr - AnonSymbol)(r11) // lwzu r12, lo16(LazyPtr - AnonSymbol)(r11) const MCExpr *SubLo16 = PPCMCExpr::CreateLo(Sub, isDarwin, OutContext); - OutStreamer.EmitInstruction(MCInstBuilder(isPPC64 ? PPC::LDU : PPC::LWZU) + EmitToStreamer(OutStreamer, MCInstBuilder(isPPC64 ? PPC::LDU : PPC::LWZU) .addReg(PPC::R12) .addExpr(SubLo16).addExpr(SubLo16) .addReg(PPC::R11)); // mtctr r12 - OutStreamer.EmitInstruction(MCInstBuilder(PPC::MTCTR).addReg(PPC::R12)); + EmitToStreamer(OutStreamer, MCInstBuilder(PPC::MTCTR).addReg(PPC::R12)); // bctr - OutStreamer.EmitInstruction(MCInstBuilder(PPC::BCTR)); + EmitToStreamer(OutStreamer, MCInstBuilder(PPC::BCTR)); OutStreamer.SwitchSection(LSPSection); OutStreamer.EmitLabel(LazyPtr); @@ -977,8 +1167,8 @@ EmitFunctionStubs(const MachineModuleInfoMachO::SymbolListTy &Stubs) { const MCSection *StubSection = OutContext.getMachOSection("__TEXT","__symbol_stub1", - MCSectionMachO::S_SYMBOL_STUBS | - MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, + MachO::S_SYMBOL_STUBS | + MachO::S_ATTR_PURE_INSTRUCTIONS, 16, SectionKind::getText()); for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { MCSymbol *Stub = Stubs[i].first; @@ -994,7 +1184,7 @@ EmitFunctionStubs(const MachineModuleInfoMachO::SymbolListTy &Stubs) { // lis r11, ha16(LazyPtr) const MCExpr *LazyPtrHa16 = PPCMCExpr::CreateHa(LazyPtrExpr, isDarwin, OutContext); - OutStreamer.EmitInstruction(MCInstBuilder(PPC::LIS) + EmitToStreamer(OutStreamer, MCInstBuilder(PPC::LIS) .addReg(PPC::R11) .addExpr(LazyPtrHa16)); @@ -1002,15 +1192,15 @@ EmitFunctionStubs(const MachineModuleInfoMachO::SymbolListTy &Stubs) { // lwzu r12, lo16(LazyPtr)(r11) const MCExpr *LazyPtrLo16 = PPCMCExpr::CreateLo(LazyPtrExpr, isDarwin, OutContext); - OutStreamer.EmitInstruction(MCInstBuilder(isPPC64 ? PPC::LDU : PPC::LWZU) + EmitToStreamer(OutStreamer, MCInstBuilder(isPPC64 ? PPC::LDU : PPC::LWZU) .addReg(PPC::R12) .addExpr(LazyPtrLo16).addExpr(LazyPtrLo16) .addReg(PPC::R11)); // mtctr r12 - OutStreamer.EmitInstruction(MCInstBuilder(PPC::MTCTR).addReg(PPC::R12)); + EmitToStreamer(OutStreamer, MCInstBuilder(PPC::MTCTR).addReg(PPC::R12)); // bctr - OutStreamer.EmitInstruction(MCInstBuilder(PPC::BCTR)); + EmitToStreamer(OutStreamer, MCInstBuilder(PPC::BCTR)); OutStreamer.SwitchSection(LSPSection); OutStreamer.EmitLabel(LazyPtr); @@ -1051,7 +1241,7 @@ bool PPCDarwinAsmPrinter::doFinalization(Module &M) { for (std::vector<const Function*>::const_iterator I = Personalities.begin(), E = Personalities.end(); I != E; ++I) { if (*I) { - MCSymbol *NLPSym = GetSymbolWithGlobalValueBase(*I, "$non_lazy_ptr"); + MCSymbol *NLPSym = getSymbolWithGlobalValueBase(*I, "$non_lazy_ptr"); MachineModuleInfoImpl::StubValueTy &StubSym = MMIMacho.getGVStubEntry(NLPSym); StubSym = MachineModuleInfoImpl::StubValueTy(getSymbol(*I), true); @@ -1140,4 +1330,5 @@ static AsmPrinter *createPPCAsmPrinterPass(TargetMachine &tm, extern "C" void LLVMInitializePowerPCAsmPrinter() { TargetRegistry::RegisterAsmPrinter(ThePPC32Target, createPPCAsmPrinterPass); TargetRegistry::RegisterAsmPrinter(ThePPC64Target, createPPCAsmPrinterPass); + TargetRegistry::RegisterAsmPrinter(ThePPC64LETarget, createPPCAsmPrinterPass); } |