1. Fixing error where basic block labels were not being printed out when they need to be for the MBlaze backend because AsmPrinter::isBlockOnlyReachableByFallthrough does not take into account delay slots.

2. Re-adding .mask and .frame directives in printed assembly.
3. Adding .ent and .end directives in printed assembly.
4. Minor cleanups to MBlaze backend.

llvm-svn: 120095
This commit is contained in:
Wesley Peck 2010-11-24 15:39:32 +00:00
parent 8be65a792f
commit 51917b868d
5 changed files with 126 additions and 33 deletions

View File

@ -60,6 +60,15 @@ namespace {
return "MBlaze Assembly Printer";
}
void printSavedRegsBitmask(raw_ostream &O);
void emitFrameDirective();
virtual void EmitFunctionBodyStart();
virtual void EmitFunctionBodyEnd();
virtual void EmitFunctionEntryLabel();
virtual bool isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB)
const;
bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
unsigned AsmVariant, const char *ExtraCode,
raw_ostream &O);
@ -106,6 +115,79 @@ namespace {
//
//===----------------------------------------------------------------------===//
// Print a 32 bit hex number with all numbers.
static void printHex32(unsigned int Value, raw_ostream &O) {
O << "0x";
for (int i = 7; i >= 0; i--)
O << utohexstr((Value & (0xF << (i*4))) >> (i*4));
}
// Create a bitmask with all callee saved registers for CPU or Floating Point
// registers. For CPU registers consider RA, GP and FP for saving if necessary.
void MBlazeAsmPrinter::printSavedRegsBitmask(raw_ostream &O) {
const TargetFrameInfo *TFI = TM.getFrameInfo();
const TargetRegisterInfo &RI = *TM.getRegisterInfo();
const MBlazeFunctionInfo *MBlazeFI = MF->getInfo<MBlazeFunctionInfo>();
// CPU Saved Registers Bitmasks
unsigned int CPUBitmask = 0;
// Set the CPU Bitmasks
const MachineFrameInfo *MFI = MF->getFrameInfo();
const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo();
for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
unsigned Reg = CSI[i].getReg();
unsigned RegNum = MBlazeRegisterInfo::getRegisterNumbering(Reg);
if (MBlaze::GPRRegisterClass->contains(Reg))
CPUBitmask |= (1 << RegNum);
}
// Return Address and Frame registers must also be set in CPUBitmask.
if (TFI->hasFP(*MF))
CPUBitmask |= (1 << MBlazeRegisterInfo::
getRegisterNumbering(RI.getFrameRegister(*MF)));
if (MFI->adjustsStack())
CPUBitmask |= (1 << MBlazeRegisterInfo::
getRegisterNumbering(RI.getRARegister()));
// Print CPUBitmask
O << "\t.mask \t"; printHex32(CPUBitmask, O); O << ','
<< MBlazeFI->getCPUTopSavedRegOff() << '\n';
}
/// Frame Directive
void MBlazeAsmPrinter::emitFrameDirective() {
const TargetRegisterInfo &RI = *TM.getRegisterInfo();
unsigned stkReg = RI.getFrameRegister(*MF);
unsigned retReg = RI.getRARegister();
unsigned stkSze = MF->getFrameInfo()->getStackSize();
OutStreamer.EmitRawText("\t.frame\t" +
Twine(MBlazeInstPrinter::getRegisterName(stkReg)) +
"," + Twine(stkSze) + "," +
Twine(MBlazeInstPrinter::getRegisterName(retReg)));
}
void MBlazeAsmPrinter::EmitFunctionEntryLabel() {
OutStreamer.EmitRawText("\t.ent\t" + Twine(CurrentFnSym->getName()));
AsmPrinter::EmitFunctionEntryLabel();
}
void MBlazeAsmPrinter::EmitFunctionBodyStart() {
emitFrameDirective();
SmallString<128> Str;
raw_svector_ostream OS(Str);
printSavedRegsBitmask(OS);
OutStreamer.EmitRawText(OS.str());
}
void MBlazeAsmPrinter::EmitFunctionBodyEnd() {
OutStreamer.EmitRawText("\t.end\t" + Twine(CurrentFnSym->getName()));
}
//===----------------------------------------------------------------------===//
void MBlazeAsmPrinter::EmitInstruction(const MachineInstr *MI) {
MBlazeMCInstLower MCInstLowering(OutContext, *Mang, *this);
@ -115,14 +197,6 @@ void MBlazeAsmPrinter::EmitInstruction(const MachineInstr *MI) {
OutStreamer.EmitInstruction(TmpInst);
}
// Print a 32 bit hex number with all numbers.
static void printHex32(unsigned int Value, raw_ostream &O) {
O << "0x";
for (int i = 7; i >= 0; i--)
O << utohexstr((Value & (0xF << (i*4))) >> (i*4));
}
// Print out an operand for an inline asm expression.
bool MBlazeAsmPrinter::
PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
@ -210,6 +284,39 @@ printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &O,
printOperand(MI, opNum+1, O);
}
/// 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.
bool MBlazeAsmPrinter::
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;
// If the block is completely empty, then it definitely does fall through.
if (Pred->empty())
return true;
// Check if the last terminator is an unconditional branch.
MachineBasicBlock::const_iterator I = Pred->end();
while (I != Pred->begin() && !(--I)->getDesc().isTerminator())
; // Noop
return I == Pred->end() || !I->getDesc().isBarrier();
}
static MCInstPrinter *createMBlazeMCInstPrinter(const Target &T,
unsigned SyntaxVariant,
const MCAsmInfo &MAI) {

View File

@ -15,13 +15,8 @@
using namespace llvm;
MBlazeMCAsmInfo::MBlazeMCAsmInfo() {
SupportsDebugInformation = true;
AlignmentIsInBytes = false;
Data16bitsDirective = "\t.half\t";
Data32bitsDirective = "\t.word\t";
Data64bitsDirective = 0;
PrivateGlobalPrefix = "$";
CommentString = "#";
ZeroDirective = "\t.space\t";
GPRel32Directive = "\t.gpword\t";
HasSetDirective = false;
}

View File

@ -32,10 +32,8 @@ using namespace llvm;
MCSymbol *MBlazeMCInstLower::
GetGlobalAddressSymbol(const MachineOperand &MO) const {
switch (MO.getTargetFlags()) {
default:
llvm_unreachable("Unknown target flag on GV operand");
case 0: break;
default: llvm_unreachable("Unknown target flag on GV operand");
case 0: break;
}
return Printer.Mang->getSymbol(MO.getGlobal());
@ -44,10 +42,8 @@ GetGlobalAddressSymbol(const MachineOperand &MO) const {
MCSymbol *MBlazeMCInstLower::
GetExternalSymbolSymbol(const MachineOperand &MO) const {
switch (MO.getTargetFlags()) {
default:
assert(0 && "Unknown target flag on GV operand");
case 0: break;
default: llvm_unreachable("Unknown target flag on GV operand");
case 0: break;
}
return Printer.GetExternalSymbolSymbol(MO.getSymbolName());
@ -59,12 +55,9 @@ GetJumpTableSymbol(const MachineOperand &MO) const {
raw_svector_ostream(Name) << Printer.MAI->getPrivateGlobalPrefix() << "JTI"
<< Printer.getFunctionNumber() << '_'
<< MO.getIndex();
switch (MO.getTargetFlags()) {
default:
llvm_unreachable("Unknown target flag on GV operand");
case 0: break;
default: llvm_unreachable("Unknown target flag on GV operand");
case 0: break;
}
// Create a symbol for the name.
@ -129,8 +122,7 @@ void MBlazeMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
MCOperand MCOp;
switch (MO.getType()) {
default:
assert(0 && "unknown operand type");
default: llvm_unreachable("unknown operand type");
case MachineOperand::MO_Register:
// Ignore all implicit register operands.
if (MO.isImplicit()) continue;

View File

@ -242,9 +242,8 @@ unsigned MBlazeRegisterInfo::getEHHandlerRegister() const {
return 0;
}
int MBlazeRegisterInfo::getDwarfRegNum(unsigned RegNum, bool isEH) const {
llvm_unreachable("What is the dwarf register number");
return -1;
int MBlazeRegisterInfo::getDwarfRegNum(unsigned RegNo, bool isEH) const {
return MBlazeGenRegisterInfo::getDwarfRegNumFull(RegNo,0);
}
#include "MBlazeGenRegisterInfo.inc"

View File

@ -43,7 +43,7 @@ static MCStreamer *createMCStreamer(const Target &T, const std::string &TT,
case Triple::MinGW64:
case Triple::Cygwin:
case Triple::Win32:
llvm_unreachable("ARM does not support Windows COFF format");
llvm_unreachable("MBlaze does not support Windows COFF format");
return NULL;
default:
return createELFStreamer(Ctx, TAB, _OS, _Emitter, RelaxAll);