rip out a ton of old instruction printing junk now that the

new instprinting logic is there.

llvm-svn: 119111
This commit is contained in:
Chris Lattner 2010-11-15 03:39:06 +00:00
parent f4a6a14c93
commit 510c66f549
1 changed files with 88 additions and 421 deletions

View File

@ -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<bool> 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<MachineModuleInfoMachO>().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<MachineModuleInfoMachO>().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 <ga:@min1>, %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 <ga:@min1>, %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<MDNode *>(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() {