diff --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp index a3cac213544c..c0b18a128a1c 100644 --- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -55,13 +55,6 @@ #include "InstPrinter/PPCInstPrinter.h" using namespace llvm; -// This option tells the asmprinter to use the new (experimental) MCInstPrinter -// path. -static cl::opt UseInstPrinter("enable-ppc-inst-printer", - cl::ReallyHidden - , cl::init(true) - ); - namespace { class PPCAsmPrinter : public AsmPrinter { protected: @@ -77,74 +70,10 @@ namespace { return "PowerPC Assembly Printer"; } - unsigned enumRegToMachineReg(unsigned enumReg) { - switch (enumReg) { - default: llvm_unreachable("Unhandled register!"); - case PPC::CR0: return 0; - case PPC::CR1: return 1; - case PPC::CR2: return 2; - case PPC::CR3: return 3; - case PPC::CR4: return 4; - case PPC::CR5: return 5; - case PPC::CR6: return 6; - case PPC::CR7: return 7; - } - llvm_unreachable(0); - } - - /// printInstruction - This method is automatically generated by tablegen - /// from the instruction set description. This method returns true if the - /// machine instruction was sufficiently described to print it, otherwise it - /// returns false. - void printInstruction(const MachineInstr *MI, raw_ostream &O); - static const char *getRegisterName(unsigned RegNo); - virtual void EmitInstruction(const MachineInstr *MI); - void printOp(const MachineOperand &MO, raw_ostream &O); - /// stripRegisterPrefix - This method strips the character prefix from a - /// register name so that only the number is left. Used by for linux asm. - const char *stripRegisterPrefix(const char *RegName) { - switch (RegName[0]) { - case 'r': - case 'f': - case 'v': return RegName + 1; - case 'c': if (RegName[1] == 'r') return RegName + 2; - } - - return RegName; - } - - /// printRegister - Print register according to target requirements. - /// - void printRegister(const MachineOperand &MO, bool R0AsZero, raw_ostream &O){ - unsigned RegNo = MO.getReg(); - assert(TargetRegisterInfo::isPhysicalRegister(RegNo) && "Not physreg??"); - - // If we should use 0 for R0. - if (R0AsZero && RegNo == PPC::R0) { - O << "0"; - return; - } - - const char *RegName = getRegisterName(RegNo); - // Linux assembler (Others?) does not take register mnemonics. - // FIXME - What about special registers used in mfspr/mtspr? - if (!Subtarget.isDarwin()) RegName = stripRegisterPrefix(RegName); - O << RegName; - } - - void printOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) { - const MachineOperand &MO = MI->getOperand(OpNo); - if (MO.isReg()) { - printRegister(MO, false, O); - } else if (MO.isImm()) { - O << MO.getImm(); - } else { - printOp(MO, O); - } - } + void printOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O); bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, unsigned AsmVariant, const char *ExtraCode, @@ -153,192 +82,9 @@ namespace { unsigned AsmVariant, const char *ExtraCode, raw_ostream &O); - - void printS5ImmOperand(const MachineInstr *MI, unsigned OpNo, - raw_ostream &O) { - char value = MI->getOperand(OpNo).getImm(); - value = (value << (32-5)) >> (32-5); - O << (int)value; - } - void printU5ImmOperand(const MachineInstr *MI, unsigned OpNo, - raw_ostream &O) { - unsigned char value = MI->getOperand(OpNo).getImm(); - assert(value <= 31 && "Invalid u5imm argument!"); - O << (unsigned int)value; - } - void printU6ImmOperand(const MachineInstr *MI, unsigned OpNo, - raw_ostream &O) { - unsigned char value = MI->getOperand(OpNo).getImm(); - assert(value <= 63 && "Invalid u6imm argument!"); - O << (unsigned int)value; - } - void printS16ImmOperand(const MachineInstr *MI, unsigned OpNo, - raw_ostream &O) { - O << (short)MI->getOperand(OpNo).getImm(); - } - void printU16ImmOperand(const MachineInstr *MI, unsigned OpNo, - raw_ostream &O) { - O << (unsigned short)MI->getOperand(OpNo).getImm(); - } - void printS16X4ImmOperand(const MachineInstr *MI, unsigned OpNo, - raw_ostream &O) { - if (MI->getOperand(OpNo).isImm()) { - O << (short)(MI->getOperand(OpNo).getImm()*4); - } else { - O << "lo16("; - printOp(MI->getOperand(OpNo), O); - if (TM.getRelocationModel() == Reloc::PIC_) - O << "-\"L" << getFunctionNumber() << "$pb\")"; - else - O << ')'; - } - } - void printBranchOperand(const MachineInstr *MI, unsigned OpNo, - raw_ostream &O) { - // Branches can take an immediate operand. This is used by the branch - // selection pass to print $+8, an eight byte displacement from the PC. - if (MI->getOperand(OpNo).isImm()) { - O << "$+" << MI->getOperand(OpNo).getImm()*4; - } else { - printOp(MI->getOperand(OpNo), O); - } - } - void printCallOperand(const MachineInstr *MI, unsigned OpNo, - raw_ostream &O) { - const MachineOperand &MO = MI->getOperand(OpNo); - if (TM.getRelocationModel() != Reloc::Static) { - if (MO.isGlobal()) { - const GlobalValue *GV = MO.getGlobal(); - if (GV->isDeclaration() || GV->isWeakForLinker()) { - // Dynamically-resolved functions need a stub for the function. - MCSymbol *Sym = GetSymbolWithGlobalValueBase(GV, "$stub"); - MachineModuleInfoImpl::StubValueTy &StubSym = - MMI->getObjFileInfo().getFnStubEntry(Sym); - if (StubSym.getPointer() == 0) - StubSym = MachineModuleInfoImpl:: - StubValueTy(Mang->getSymbol(GV), !GV->hasInternalLinkage()); - O << *Sym; - return; - } - } - if (MO.isSymbol()) { - SmallString<128> TempNameStr; - TempNameStr += StringRef(MO.getSymbolName()); - TempNameStr += StringRef("$stub"); - - MCSymbol *Sym = GetExternalSymbolSymbol(TempNameStr.str()); - MachineModuleInfoImpl::StubValueTy &StubSym = - MMI->getObjFileInfo().getFnStubEntry(Sym); - if (StubSym.getPointer() == 0) - StubSym = MachineModuleInfoImpl:: - StubValueTy(GetExternalSymbolSymbol(MO.getSymbolName()), true); - O << *Sym; - return; - } - } - - printOp(MI->getOperand(OpNo), O); - } - void printAbsAddrOperand(const MachineInstr *MI, unsigned OpNo, - raw_ostream &O) { - O << (int)MI->getOperand(OpNo).getImm()*4; - } - void printPICLabel(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) { - O << "\"L" << getFunctionNumber() << "$pb\"\n"; - O << "\"L" << getFunctionNumber() << "$pb\":"; - } - void printSymbolHi(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) { - if (MI->getOperand(OpNo).isImm()) { - printS16ImmOperand(MI, OpNo, O); - } else { - if (Subtarget.isDarwin()) O << "ha16("; - printOp(MI->getOperand(OpNo), O); - if (TM.getRelocationModel() == Reloc::PIC_) - O << "-L" << getFunctionNumber() << "$pb"; - if (Subtarget.isDarwin()) - O << ')'; - else - O << "@ha"; - } - } - void printSymbolLo(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) { - if (MI->getOperand(OpNo).isImm()) { - printS16ImmOperand(MI, OpNo, O); - } else { - if (Subtarget.isDarwin()) O << "lo16("; - printOp(MI->getOperand(OpNo), O); - if (TM.getRelocationModel() == Reloc::PIC_) - O << "-L" << getFunctionNumber() << "$pb"; - if (Subtarget.isDarwin()) - O << ')'; - else - O << "@l"; - } - } - void printcrbitm(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) { - unsigned CCReg = MI->getOperand(OpNo).getReg(); - unsigned RegNo = enumRegToMachineReg(CCReg); - O << (0x80 >> RegNo); - } - // The new addressing mode printers. - void printMemRegImm(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) { - printSymbolLo(MI, OpNo, O); - O << '('; - if (MI->getOperand(OpNo+1).isReg() && - MI->getOperand(OpNo+1).getReg() == PPC::R0) - O << "0"; - else - printOperand(MI, OpNo+1, O); - O << ')'; - } - void printMemRegImmShifted(const MachineInstr *MI, unsigned OpNo, - raw_ostream &O) { - if (MI->getOperand(OpNo).isImm()) - printS16X4ImmOperand(MI, OpNo, O); - else - printSymbolLo(MI, OpNo, O); - O << '('; - if (MI->getOperand(OpNo+1).isReg() && - MI->getOperand(OpNo+1).getReg() == PPC::R0) - O << "0"; - else - printOperand(MI, OpNo+1, O); - O << ')'; - } - - void printMemRegReg(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) { - // When used as the base register, r0 reads constant zero rather than - // the value contained in the register. For this reason, the darwin - // assembler requires that we print r0 as 0 (no r) when used as the base. - const MachineOperand &MO = MI->getOperand(OpNo); - printRegister(MO, true, O); - O << ", "; - printOperand(MI, OpNo+1, O); - } - - void printTOCEntryLabel(const MachineInstr *MI, unsigned OpNo, - raw_ostream &O) { - const MachineOperand &MO = MI->getOperand(OpNo); - assert(MO.isGlobal()); - MCSymbol *Sym = Mang->getSymbol(MO.getGlobal()); - - // Map symbol -> label of TOC entry. - MCSymbol *&TOCEntry = TOC[Sym]; - if (TOCEntry == 0) - TOCEntry = OutContext. - GetOrCreateSymbol(StringRef(MAI->getPrivateGlobalPrefix()) + - "C" + Twine(LabelID++)); - - O << *TOCEntry << "@toc"; - } - - void printPredicateOperand(const MachineInstr *MI, unsigned OpNo, - raw_ostream &O, const char *Modifier); - MachineLocation getDebugValueLocation(const MachineInstr *MI) const { - MachineLocation Location; - assert (MI->getNumOperands() == 4 && "Invalid no. of machine operands!"); + assert(MI->getNumOperands() == 4 && "Invalid no. of machine operands!"); // Frame address. Currently handles register +- offset only. if (MI->getOperand(0).isReg() && MI->getOperand(2).isImm()) Location.set(MI->getOperand(0).getReg(), MI->getOperand(2).getImm()); @@ -382,13 +128,35 @@ namespace { }; } // end of anonymous namespace -// Include the auto-generated portion of the assembly writer -#include "PPCGenAsmWriter.inc" +/// stripRegisterPrefix - This method strips the character prefix from a +/// register name so that only the number is left. Used by for linux asm. +static const char *stripRegisterPrefix(const char *RegName) { + switch (RegName[0]) { + case 'r': + case 'f': + case 'v': return RegName + 1; + case 'c': if (RegName[1] == 'r') return RegName + 2; + } + + return RegName; +} -void PPCAsmPrinter::printOp(const MachineOperand &MO, raw_ostream &O) { +void PPCAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo, + raw_ostream &O) { + const MachineOperand &MO = MI->getOperand(OpNo); + switch (MO.getType()) { + case MachineOperand::MO_Register: { + const char *RegName = PPCInstPrinter::getRegisterName(MO.getReg()); + // Linux assembler (Others?) does not take register mnemonics. + // FIXME - What about special registers used in mfspr/mtspr? + if (!Subtarget.isDarwin()) RegName = stripRegisterPrefix(RegName); + O << RegName; + return; + } case MachineOperand::MO_Immediate: - llvm_unreachable("printOp() does not handle immediate values"); + O << MO.getImm(); + return; case MachineOperand::MO_MachineBasicBlock: O << *MO.getMBB()->getSymbol(); @@ -481,9 +249,7 @@ bool PPCAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, switch (ExtraCode[0]) { default: return true; // Unknown modifier. case 'c': // Don't print "$" before a global var name or constant. - // PPC never has a prefix. - printOperand(MI, OpNo, O); - return false; + break; // PPC never has a prefix. case 'L': // Write second word of DImode reference. // Verify that this operand has two consecutive registers. if (!MI->getOperand(OpNo).isReg() || @@ -515,183 +281,84 @@ bool PPCAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) { if (ExtraCode && ExtraCode[0]) return true; // Unknown modifier. - assert (MI->getOperand(OpNo).isReg()); + assert(MI->getOperand(OpNo).isReg()); O << "0("; printOperand(MI, OpNo, O); O << ")"; return false; } -void PPCAsmPrinter::printPredicateOperand(const MachineInstr *MI, unsigned OpNo, - raw_ostream &O, const char *Modifier){ - assert(Modifier && "Must specify 'cc' or 'reg' as predicate op modifier!"); - unsigned Code = MI->getOperand(OpNo).getImm(); - if (!strcmp(Modifier, "cc")) { - switch ((PPC::Predicate)Code) { - case PPC::PRED_ALWAYS: return; // Don't print anything for always. - case PPC::PRED_LT: O << "lt"; return; - case PPC::PRED_LE: O << "le"; return; - case PPC::PRED_EQ: O << "eq"; return; - case PPC::PRED_GE: O << "ge"; return; - case PPC::PRED_GT: O << "gt"; return; - case PPC::PRED_NE: O << "ne"; return; - case PPC::PRED_UN: O << "un"; return; - case PPC::PRED_NU: O << "nu"; return; - } - - } else { - assert(!strcmp(Modifier, "reg") && - "Need to specify 'cc' or 'reg' as predicate op modifier!"); - // Don't print the register for 'always'. - if (Code == PPC::PRED_ALWAYS) return; - printOperand(MI, OpNo+1, O); - } -} /// EmitInstruction -- Print out a single PowerPC MI in Darwin syntax to /// the current output stream. /// void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) { - if (UseInstPrinter) { - MCInst TmpInst; + MCInst TmpInst; + + // Lower multi-instruction pseudo operations. + switch (MI->getOpcode()) { + default: break; + case PPC::MovePCtoLR: + case PPC::MovePCtoLR8: { + // Transform %LR = MovePCtoLR + // Into this, where the label is the PIC base: + // bl L1$pb + // L1$pb: + MCSymbol *PICBase = MF->getPICBaseSymbol(); - // Lower multi-instruction pseudo operations. - switch (MI->getOpcode()) { - default: break; - case PPC::MovePCtoLR: - case PPC::MovePCtoLR8: { - // Transform %LR = MovePCtoLR - // Into this, where the label is the PIC base: - // bl L1$pb - // L1$pb: - MCSymbol *PICBase = MF->getPICBaseSymbol(); - - // Emit the 'bl'. - TmpInst.setOpcode(PPC::BL_Darwin); // Darwin vs SVR4 doesn't matter here. - - - // FIXME: We would like an efficient form for this, so we don't have to do - // a lot of extra uniquing. - TmpInst.addOperand(MCOperand::CreateExpr(MCSymbolRefExpr:: - Create(PICBase, OutContext))); - OutStreamer.EmitInstruction(TmpInst); - - // Emit the label. - OutStreamer.EmitLabel(PICBase); - return; - } - case PPC::LDtoc: { - // Transform %X3 = LDtoc , %X2 - LowerPPCMachineInstrToMCInst(MI, TmpInst, *this); - - // Change the opcode to LD, and the global address operand to be a - // reference to the TOC entry we will synthesize later. - TmpInst.setOpcode(PPC::LD); - const MachineOperand &MO = MI->getOperand(1); - assert(MO.isGlobal()); - - // Map symbol -> label of TOC entry. - MCSymbol *&TOCEntry = TOC[Mang->getSymbol(MO.getGlobal())]; - if (TOCEntry == 0) { - TOCEntry = OutContext. - GetOrCreateSymbol(StringRef(MAI->getPrivateGlobalPrefix()) + - "C" + Twine(LabelID++)); - } - - const MCExpr *Exp = - MCSymbolRefExpr::Create(TOCEntry, MCSymbolRefExpr::VK_PPC_TOC, - OutContext); - TmpInst.getOperand(1) = MCOperand::CreateExpr(Exp); - OutStreamer.EmitInstruction(TmpInst); - return; - } - - case PPC::MFCRpseud: - // Transform: %R3 = MFCRpseud %CR7 - // Into: %R3 = MFCR ;; cr7 - OutStreamer.AddComment(getRegisterName(MI->getOperand(1).getReg())); - TmpInst.setOpcode(PPC::MFCR); - TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg())); - OutStreamer.EmitInstruction(TmpInst); - return; - } - + // Emit the 'bl'. + TmpInst.setOpcode(PPC::BL_Darwin); // Darwin vs SVR4 doesn't matter here. + + + // FIXME: We would like an efficient form for this, so we don't have to do + // a lot of extra uniquing. + TmpInst.addOperand(MCOperand::CreateExpr(MCSymbolRefExpr:: + Create(PICBase, OutContext))); + OutStreamer.EmitInstruction(TmpInst); + + // Emit the label. + OutStreamer.EmitLabel(PICBase); + return; + } + case PPC::LDtoc: { + // Transform %X3 = LDtoc , %X2 LowerPPCMachineInstrToMCInst(MI, TmpInst, *this); + + // Change the opcode to LD, and the global address operand to be a + // reference to the TOC entry we will synthesize later. + TmpInst.setOpcode(PPC::LD); + const MachineOperand &MO = MI->getOperand(1); + assert(MO.isGlobal()); + + // Map symbol -> label of TOC entry. + MCSymbol *&TOCEntry = TOC[Mang->getSymbol(MO.getGlobal())]; + if (TOCEntry == 0) { + TOCEntry = OutContext. + GetOrCreateSymbol(StringRef(MAI->getPrivateGlobalPrefix()) + + "C" + Twine(LabelID++)); + } + + const MCExpr *Exp = + MCSymbolRefExpr::Create(TOCEntry, MCSymbolRefExpr::VK_PPC_TOC, + OutContext); + TmpInst.getOperand(1) = MCOperand::CreateExpr(Exp); OutStreamer.EmitInstruction(TmpInst); return; } - - - SmallString<128> Str; - raw_svector_ostream O(Str); - - if (MI->getOpcode() == TargetOpcode::DBG_VALUE) { - unsigned NOps = MI->getNumOperands(); - assert(NOps==4); - O << '\t' << MAI->getCommentString() << "DEBUG_VALUE: "; - // cast away const; DIetc do not take const operands for some reason. - DIVariable V(const_cast(MI->getOperand(NOps-1).getMetadata())); - O << V.getName(); - O << " <- "; - // Frame address. Currently handles register +- offset only. - assert(MI->getOperand(0).isReg() && MI->getOperand(1).isImm()); - O << '['; printOperand(MI, 0, O); O << '+'; printOperand(MI, 1, O); - O << ']'; - O << "+"; - printOperand(MI, NOps-2, O); - OutStreamer.EmitRawText(O.str()); + + case PPC::MFCRpseud: + // Transform: %R3 = MFCRpseud %CR7 + // Into: %R3 = MFCR ;; cr7 + OutStreamer.AddComment(PPCInstPrinter:: + getRegisterName(MI->getOperand(1).getReg())); + TmpInst.setOpcode(PPC::MFCR); + TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg())); + OutStreamer.EmitInstruction(TmpInst); return; } - // Check for slwi/srwi mnemonics. - if (MI->getOpcode() == PPC::RLWINM) { - unsigned char SH = MI->getOperand(2).getImm(); - unsigned char MB = MI->getOperand(3).getImm(); - unsigned char ME = MI->getOperand(4).getImm(); - bool useSubstituteMnemonic = false; - if (SH <= 31 && MB == 0 && ME == (31-SH)) { - O << "\tslwi "; useSubstituteMnemonic = true; - } - if (SH <= 31 && MB == (32-SH) && ME == 31) { - O << "\tsrwi "; useSubstituteMnemonic = true; - SH = 32-SH; - } - if (useSubstituteMnemonic) { - printOperand(MI, 0, O); - O << ", "; - printOperand(MI, 1, O); - O << ", " << (unsigned int)SH; - OutStreamer.EmitRawText(O.str()); - return; - } - } - - if ((MI->getOpcode() == PPC::OR || MI->getOpcode() == PPC::OR8) && - MI->getOperand(1).getReg() == MI->getOperand(2).getReg()) { - O << "\tmr "; - printOperand(MI, 0, O); - O << ", "; - printOperand(MI, 1, O); - OutStreamer.EmitRawText(O.str()); - return; - } - - if (MI->getOpcode() == PPC::RLDICR) { - unsigned char SH = MI->getOperand(2).getImm(); - unsigned char ME = MI->getOperand(3).getImm(); - // rldicr RA, RS, SH, 63-SH == sldi RA, RS, SH - if (63-SH == ME) { - O << "\tsldi "; - printOperand(MI, 0, O); - O << ", "; - printOperand(MI, 1, O); - O << ", " << (unsigned int)SH; - OutStreamer.EmitRawText(O.str()); - return; - } - } - printInstruction(MI, O); - OutStreamer.EmitRawText(O.str()); + LowerPPCMachineInstrToMCInst(MI, TmpInst, *this); + OutStreamer.EmitInstruction(TmpInst); } void PPCLinuxAsmPrinter::EmitFunctionEntryLabel() {