X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FSparc%2FSparcAsmPrinter.cpp;h=0439f9d8ea819b57422cd5942456245559438710;hb=bcc0fa6a6430e8bba856f5d64fdd4f48b7b8d54d;hp=c98be39621e71b9e82231e251fe518016349c3d7;hpb=b56c57bcbb8b87dca05a18c284155fa75285470b;p=oota-llvm.git diff --git a/lib/Target/Sparc/SparcAsmPrinter.cpp b/lib/Target/Sparc/SparcAsmPrinter.cpp index c98be39621e..0439f9d8ea8 100644 --- a/lib/Target/Sparc/SparcAsmPrinter.cpp +++ b/lib/Target/Sparc/SparcAsmPrinter.cpp @@ -12,10 +12,8 @@ // //===----------------------------------------------------------------------===// -#define DEBUG_TYPE "asm-printer" #include "Sparc.h" #include "InstPrinter/SparcInstPrinter.h" -#include "MCTargetDesc/SparcBaseInfo.h" #include "MCTargetDesc/SparcMCExpr.h" #include "SparcInstrInfo.h" #include "SparcTargetMachine.h" @@ -23,7 +21,9 @@ #include "llvm/ADT/SmallString.h" #include "llvm/CodeGen/AsmPrinter.h" #include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineModuleInfoImpls.h" #include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" #include "llvm/IR/Mangler.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" @@ -34,26 +34,31 @@ #include "llvm/Support/raw_ostream.h" using namespace llvm; +#define DEBUG_TYPE "asm-printer" + namespace { class SparcAsmPrinter : public AsmPrinter { SparcTargetStreamer &getTargetStreamer() { - return static_cast(OutStreamer.getTargetStreamer()); + return static_cast( + *OutStreamer.getTargetStreamer()); } public: - explicit SparcAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) - : AsmPrinter(TM, Streamer) {} + explicit SparcAsmPrinter(TargetMachine &TM, + std::unique_ptr Streamer) + : AsmPrinter(TM, std::move(Streamer)) {} - virtual const char *getPassName() const { + const char *getPassName() const override { return "Sparc Assembly Printer"; } void printOperand(const MachineInstr *MI, int opNum, raw_ostream &OS); void printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &OS, - const char *Modifier = 0); + const char *Modifier = nullptr); void printCCOperand(const MachineInstr *MI, int opNum, raw_ostream &OS); - virtual void EmitFunctionBodyStart(); - virtual void EmitInstruction(const MachineInstr *MI); + void EmitFunctionBodyStart() override; + void EmitInstruction(const MachineInstr *MI) override; + void EmitEndOfAsmFile(Module &M) override; static const char *getRegisterName(unsigned RegNo) { return SparcInstPrinter::getRegisterName(RegNo); @@ -61,25 +66,28 @@ namespace { 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; - virtual bool isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) - const; + void LowerGETPCXAndEmitMCInsts(const MachineInstr *MI, + const MCSubtargetInfo &STI); }; } // end of anonymous namespace -static MCOperand createPCXCallOP(MCSymbol *Label, - MCContext &OutContext) -{ - const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::Create(Label, +static MCOperand createSparcMCOperand(SparcMCExpr::VariantKind Kind, + MCSymbol *Sym, MCContext &OutContext) { + const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::Create(Sym, OutContext); - const SparcMCExpr *expr = SparcMCExpr::Create(SparcMCExpr::VK_Sparc_None, - MCSym, OutContext); + const SparcMCExpr *expr = SparcMCExpr::Create(Kind, MCSym, OutContext); return MCOperand::CreateExpr(expr); + +} +static MCOperand createPCXCallOP(MCSymbol *Label, + MCContext &OutContext) { + return createSparcMCOperand(SparcMCExpr::VK_Sparc_None, Label, OutContext); } static MCOperand createPCXRelExprOp(SparcMCExpr::VariantKind Kind, @@ -101,61 +109,127 @@ static MCOperand createPCXRelExprOp(SparcMCExpr::VariantKind Kind, } static void EmitCall(MCStreamer &OutStreamer, - MCOperand &Callee) + MCOperand &Callee, + const MCSubtargetInfo &STI) { MCInst CallInst; CallInst.setOpcode(SP::CALL); CallInst.addOperand(Callee); - OutStreamer.EmitInstruction(CallInst); + OutStreamer.EmitInstruction(CallInst, STI); } static void EmitSETHI(MCStreamer &OutStreamer, - MCOperand &Imm, MCOperand &RD) + MCOperand &Imm, MCOperand &RD, + const MCSubtargetInfo &STI) { MCInst SETHIInst; SETHIInst.setOpcode(SP::SETHIi); SETHIInst.addOperand(RD); SETHIInst.addOperand(Imm); - OutStreamer.EmitInstruction(SETHIInst); + OutStreamer.EmitInstruction(SETHIInst, STI); } -static void EmitOR(MCStreamer &OutStreamer, MCOperand &RS1, - MCOperand &Imm, MCOperand &RD) +static void EmitBinary(MCStreamer &OutStreamer, unsigned Opcode, + MCOperand &RS1, MCOperand &Src2, MCOperand &RD, + const MCSubtargetInfo &STI) { - MCInst ORInst; - ORInst.setOpcode(SP::ORri); - ORInst.addOperand(RD); - ORInst.addOperand(RS1); - ORInst.addOperand(Imm); - OutStreamer.EmitInstruction(ORInst); + MCInst Inst; + Inst.setOpcode(Opcode); + Inst.addOperand(RD); + Inst.addOperand(RS1); + Inst.addOperand(Src2); + OutStreamer.EmitInstruction(Inst, STI); +} + +static void EmitOR(MCStreamer &OutStreamer, + MCOperand &RS1, MCOperand &Imm, MCOperand &RD, + const MCSubtargetInfo &STI) { + EmitBinary(OutStreamer, SP::ORri, RS1, Imm, RD, STI); } static void EmitADD(MCStreamer &OutStreamer, - MCOperand &RS1, MCOperand &RS2, MCOperand &RD) -{ - MCInst ADDInst; - ADDInst.setOpcode(SP::ADDrr); - ADDInst.addOperand(RD); - ADDInst.addOperand(RS1); - ADDInst.addOperand(RS2); - OutStreamer.EmitInstruction(ADDInst); + MCOperand &RS1, MCOperand &RS2, MCOperand &RD, + const MCSubtargetInfo &STI) { + EmitBinary(OutStreamer, SP::ADDrr, RS1, RS2, RD, STI); } -static void LowerGETPCXAndEmitMCInsts(const MachineInstr *MI, - MCStreamer &OutStreamer, - MCContext &OutContext) +static void EmitSHL(MCStreamer &OutStreamer, + MCOperand &RS1, MCOperand &Imm, MCOperand &RD, + const MCSubtargetInfo &STI) { + EmitBinary(OutStreamer, SP::SLLri, RS1, Imm, RD, STI); +} + + +static void EmitHiLo(MCStreamer &OutStreamer, MCSymbol *GOTSym, + SparcMCExpr::VariantKind HiKind, + SparcMCExpr::VariantKind LoKind, + MCOperand &RD, + MCContext &OutContext, + const MCSubtargetInfo &STI) { + + MCOperand hi = createSparcMCOperand(HiKind, GOTSym, OutContext); + MCOperand lo = createSparcMCOperand(LoKind, GOTSym, OutContext); + EmitSETHI(OutStreamer, hi, RD, STI); + EmitOR(OutStreamer, RD, lo, RD, STI); +} + +void SparcAsmPrinter::LowerGETPCXAndEmitMCInsts(const MachineInstr *MI, + const MCSubtargetInfo &STI) { - const MachineOperand &MO = MI->getOperand(0); - MCSymbol *StartLabel = OutContext.CreateTempSymbol(); - MCSymbol *EndLabel = OutContext.CreateTempSymbol(); - MCSymbol *SethiLabel = OutContext.CreateTempSymbol(); MCSymbol *GOTLabel = OutContext.GetOrCreateSymbol(Twine("_GLOBAL_OFFSET_TABLE_")); + const MachineOperand &MO = MI->getOperand(0); assert(MO.getReg() != SP::O7 && "%o7 is assigned as destination for getpcx!"); MCOperand MCRegOP = MCOperand::CreateReg(MO.getReg()); + + + if (TM.getRelocationModel() != Reloc::PIC_) { + // Just load the address of GOT to MCRegOP. + switch(TM.getCodeModel()) { + default: + llvm_unreachable("Unsupported absolute code model"); + case CodeModel::Small: + EmitHiLo(OutStreamer, GOTLabel, + SparcMCExpr::VK_Sparc_HI, SparcMCExpr::VK_Sparc_LO, + MCRegOP, OutContext, STI); + break; + case CodeModel::Medium: { + EmitHiLo(OutStreamer, GOTLabel, + SparcMCExpr::VK_Sparc_H44, SparcMCExpr::VK_Sparc_M44, + MCRegOP, OutContext, STI); + MCOperand imm = MCOperand::CreateExpr(MCConstantExpr::Create(12, + OutContext)); + EmitSHL(OutStreamer, MCRegOP, imm, MCRegOP, STI); + MCOperand lo = createSparcMCOperand(SparcMCExpr::VK_Sparc_L44, + GOTLabel, OutContext); + EmitOR(OutStreamer, MCRegOP, lo, MCRegOP, STI); + break; + } + case CodeModel::Large: { + EmitHiLo(OutStreamer, GOTLabel, + SparcMCExpr::VK_Sparc_HH, SparcMCExpr::VK_Sparc_HM, + MCRegOP, OutContext, STI); + MCOperand imm = MCOperand::CreateExpr(MCConstantExpr::Create(32, + OutContext)); + EmitSHL(OutStreamer, MCRegOP, imm, MCRegOP, STI); + // Use register %o7 to load the lower 32 bits. + MCOperand RegO7 = MCOperand::CreateReg(SP::O7); + EmitHiLo(OutStreamer, GOTLabel, + SparcMCExpr::VK_Sparc_HI, SparcMCExpr::VK_Sparc_LO, + RegO7, OutContext, STI); + EmitADD(OutStreamer, MCRegOP, RegO7, MCRegOP, STI); + } + } + return; + } + + MCSymbol *StartLabel = OutContext.CreateTempSymbol(); + MCSymbol *EndLabel = OutContext.CreateTempSymbol(); + MCSymbol *SethiLabel = OutContext.CreateTempSymbol(); + MCOperand RegO7 = MCOperand::CreateReg(SP::O7); // : @@ -168,23 +242,22 @@ static void LowerGETPCXAndEmitMCInsts(const MachineInstr *MI, OutStreamer.EmitLabel(StartLabel); MCOperand Callee = createPCXCallOP(EndLabel, OutContext); - EmitCall(OutStreamer, Callee); + EmitCall(OutStreamer, Callee, STI); OutStreamer.EmitLabel(SethiLabel); - MCOperand hiImm = createPCXRelExprOp(SparcMCExpr::VK_Sparc_HI, + MCOperand hiImm = createPCXRelExprOp(SparcMCExpr::VK_Sparc_PC22, GOTLabel, StartLabel, SethiLabel, OutContext); - EmitSETHI(OutStreamer, hiImm, MCRegOP); + EmitSETHI(OutStreamer, hiImm, MCRegOP, STI); OutStreamer.EmitLabel(EndLabel); - MCOperand loImm = createPCXRelExprOp(SparcMCExpr::VK_Sparc_LO, + MCOperand loImm = createPCXRelExprOp(SparcMCExpr::VK_Sparc_PC10, GOTLabel, StartLabel, EndLabel, OutContext); - EmitOR(OutStreamer, MCRegOP, loImm, MCRegOP); - EmitADD(OutStreamer, MCRegOP, RegO7, MCRegOP); + EmitOR(OutStreamer, MCRegOP, loImm, MCRegOP, STI); + EmitADD(OutStreamer, MCRegOP, RegO7, MCRegOP, STI); } void SparcAsmPrinter::EmitInstruction(const MachineInstr *MI) { - MCInst TmpInst; switch (MI->getOpcode()) { default: break; @@ -192,15 +265,20 @@ void SparcAsmPrinter::EmitInstruction(const MachineInstr *MI) // FIXME: Debug Value. return; case SP::GETPCX: - LowerGETPCXAndEmitMCInsts(MI, OutStreamer, OutContext); + LowerGETPCXAndEmitMCInsts(MI, getSubtargetInfo()); return; } - LowerSparcMachineInstrToMCInst(MI, TmpInst, *this); - OutStreamer.EmitInstruction(TmpInst); + MachineBasicBlock::const_instr_iterator I = MI; + MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end(); + do { + MCInst TmpInst; + LowerSparcMachineInstrToMCInst(I, TmpInst, *this); + EmitToStreamer(OutStreamer, TmpInst); + } while ((++I != E) && I->isInsideBundle()); // Delay slot check. } void SparcAsmPrinter::EmitFunctionBodyStart() { - if (!TM.getSubtarget().is64Bit()) + if (!MF->getSubtarget().is64Bit()) return; const MachineRegisterInfo &MRI = MF->getRegInfo(); @@ -221,82 +299,59 @@ void SparcAsmPrinter::printOperand(const MachineInstr *MI, int opNum, raw_ostream &O) { const DataLayout *DL = TM.getDataLayout(); const MachineOperand &MO = MI->getOperand (opNum); - unsigned TF = MO.getTargetFlags(); + SparcMCExpr::VariantKind TF = (SparcMCExpr::VariantKind) MO.getTargetFlags(); + #ifndef NDEBUG // Verify the target flags. if (MO.isGlobal() || MO.isSymbol() || MO.isCPI()) { if (MI->getOpcode() == SP::CALL) - assert(TF == SPII::MO_NO_FLAG && + assert(TF == SparcMCExpr::VK_Sparc_None && "Cannot handle target flags on call address"); else if (MI->getOpcode() == SP::SETHIi || MI->getOpcode() == SP::SETHIXi) - assert((TF == SPII::MO_HI || TF == SPII::MO_H44 || TF == SPII::MO_HH - || TF == SPII::MO_TLS_GD_HI22 - || TF == SPII::MO_TLS_LDM_HI22 - || TF == SPII::MO_TLS_LDO_HIX22 - || TF == SPII::MO_TLS_IE_HI22 - || TF == SPII::MO_TLS_LE_HIX22) && + assert((TF == SparcMCExpr::VK_Sparc_HI + || TF == SparcMCExpr::VK_Sparc_H44 + || TF == SparcMCExpr::VK_Sparc_HH + || TF == SparcMCExpr::VK_Sparc_TLS_GD_HI22 + || TF == SparcMCExpr::VK_Sparc_TLS_LDM_HI22 + || TF == SparcMCExpr::VK_Sparc_TLS_LDO_HIX22 + || TF == SparcMCExpr::VK_Sparc_TLS_IE_HI22 + || TF == SparcMCExpr::VK_Sparc_TLS_LE_HIX22) && "Invalid target flags for address operand on sethi"); else if (MI->getOpcode() == SP::TLS_CALL) - assert((TF == SPII::MO_NO_FLAG - || TF == SPII::MO_TLS_GD_CALL - || TF == SPII::MO_TLS_LDM_CALL) && + assert((TF == SparcMCExpr::VK_Sparc_None + || TF == SparcMCExpr::VK_Sparc_TLS_GD_CALL + || TF == SparcMCExpr::VK_Sparc_TLS_LDM_CALL) && "Cannot handle target flags on tls call address"); else if (MI->getOpcode() == SP::TLS_ADDrr) - assert((TF == SPII::MO_TLS_GD_ADD || TF == SPII::MO_TLS_LDM_ADD - || TF == SPII::MO_TLS_LDO_ADD || TF == SPII::MO_TLS_IE_ADD) && + assert((TF == SparcMCExpr::VK_Sparc_TLS_GD_ADD + || TF == SparcMCExpr::VK_Sparc_TLS_LDM_ADD + || TF == SparcMCExpr::VK_Sparc_TLS_LDO_ADD + || TF == SparcMCExpr::VK_Sparc_TLS_IE_ADD) && "Cannot handle target flags on add for TLS"); else if (MI->getOpcode() == SP::TLS_LDrr) - assert(TF == SPII::MO_TLS_IE_LD && + assert(TF == SparcMCExpr::VK_Sparc_TLS_IE_LD && "Cannot handle target flags on ld for TLS"); else if (MI->getOpcode() == SP::TLS_LDXrr) - assert(TF == SPII::MO_TLS_IE_LDX && + assert(TF == SparcMCExpr::VK_Sparc_TLS_IE_LDX && "Cannot handle target flags on ldx for TLS"); else if (MI->getOpcode() == SP::XORri || MI->getOpcode() == SP::XORXri) - assert((TF == SPII::MO_TLS_LDO_LOX10 || TF == SPII::MO_TLS_LE_LOX10) && + assert((TF == SparcMCExpr::VK_Sparc_TLS_LDO_LOX10 + || TF == SparcMCExpr::VK_Sparc_TLS_LE_LOX10) && "Cannot handle target flags on xor for TLS"); else - assert((TF == SPII::MO_LO || TF == SPII::MO_M44 || TF == SPII::MO_L44 - || TF == SPII::MO_HM - || TF == SPII::MO_TLS_GD_LO10 - || TF == SPII::MO_TLS_LDM_LO10 - || TF == SPII::MO_TLS_IE_LO10 ) && + assert((TF == SparcMCExpr::VK_Sparc_LO + || TF == SparcMCExpr::VK_Sparc_M44 + || TF == SparcMCExpr::VK_Sparc_L44 + || TF == SparcMCExpr::VK_Sparc_HM + || TF == SparcMCExpr::VK_Sparc_TLS_GD_LO10 + || TF == SparcMCExpr::VK_Sparc_TLS_LDM_LO10 + || TF == SparcMCExpr::VK_Sparc_TLS_IE_LO10 ) && "Invalid target flags for small address operand"); } #endif - bool CloseParen = true; - switch (TF) { - default: - llvm_unreachable("Unknown target flags on operand"); - case SPII::MO_NO_FLAG: - CloseParen = false; - break; - case SPII::MO_LO: O << "%lo("; break; - case SPII::MO_HI: O << "%hi("; break; - case SPII::MO_H44: O << "%h44("; break; - case SPII::MO_M44: O << "%m44("; break; - case SPII::MO_L44: O << "%l44("; break; - case SPII::MO_HH: O << "%hh("; break; - case SPII::MO_HM: O << "%hm("; break; - case SPII::MO_TLS_GD_HI22: O << "%tgd_hi22("; break; - case SPII::MO_TLS_GD_LO10: O << "%tgd_lo10("; break; - case SPII::MO_TLS_GD_ADD: O << "%tgd_add("; break; - case SPII::MO_TLS_GD_CALL: O << "%tgd_call("; break; - case SPII::MO_TLS_LDM_HI22: O << "%tldm_hi22("; break; - case SPII::MO_TLS_LDM_LO10: O << "%tldm_lo10("; break; - case SPII::MO_TLS_LDM_ADD: O << "%tldm_add("; break; - case SPII::MO_TLS_LDM_CALL: O << "%tldm_call("; break; - case SPII::MO_TLS_LDO_HIX22: O << "%tldo_hix22("; break; - case SPII::MO_TLS_LDO_LOX10: O << "%tldo_lox10("; break; - case SPII::MO_TLS_LDO_ADD: O << "%tldo_add("; break; - case SPII::MO_TLS_IE_HI22: O << "%tie_hi22("; break; - case SPII::MO_TLS_IE_LO10: O << "%tie_lo10("; break; - case SPII::MO_TLS_IE_LD: O << "%tie_ld("; break; - case SPII::MO_TLS_IE_LDX: O << "%tie_ldx("; break; - case SPII::MO_TLS_IE_ADD: O << "%tie_add("; break; - case SPII::MO_TLS_LE_HIX22: O << "%tle_hix22("; break; - case SPII::MO_TLS_LE_LOX10: O << "%tle_lox10("; break; - } + + bool CloseParen = SparcMCExpr::printVariantKind(O, TF); switch (MO.getType()) { case MachineOperand::MO_Register: @@ -387,35 +442,21 @@ bool SparcAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, return false; } -/// isBlockOnlyReachableByFallthough - Return true if the basic block has -/// exactly one predecessor and the control transfer mechanism between -/// the predecessor and this block is a fall-through. -/// -/// This overrides AsmPrinter's implementation to handle delay slots. -bool SparcAsmPrinter:: -isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const { - // If this is a landing pad, it isn't a fall through. If it has no preds, - // then nothing falls through to it. - if (MBB->isLandingPad() || MBB->pred_empty()) - return false; - - // If there isn't exactly one predecessor, it can't be a fall through. - MachineBasicBlock::const_pred_iterator PI = MBB->pred_begin(), PI2 = PI; - ++PI2; - if (PI2 != MBB->pred_end()) - return false; - - // The predecessor has to be immediately before this block. - const MachineBasicBlock *Pred = *PI; - - if (!Pred->isLayoutSuccessor(MBB)) - return false; - - // Check if the last terminator is an unconditional branch. - MachineBasicBlock::const_iterator I = Pred->end(); - while (I != Pred->begin() && !(--I)->isTerminator()) - ; // Noop - return I == Pred->end() || !I->isBarrier(); +void SparcAsmPrinter::EmitEndOfAsmFile(Module &M) { + const TargetLoweringObjectFileELF &TLOFELF = + static_cast(getObjFileLowering()); + MachineModuleInfoELF &MMIELF = MMI->getObjFileInfo(); + + // Generate stubs for global variables. + MachineModuleInfoELF::SymbolListTy Stubs = MMIELF.GetGVStubList(); + if (!Stubs.empty()) { + OutStreamer.SwitchSection(TLOFELF.getDataSection()); + unsigned PtrSize = TM.getDataLayout()->getPointerSize(0); + for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { + OutStreamer.EmitLabel(Stubs[i].first); + OutStreamer.EmitSymbolValue(Stubs[i].second.getPointer(), PtrSize); + } + } } // Force static initialization.