MipsAsmPrinter.cpp [plain text]
#define DEBUG_TYPE "mips-asm-printer"
#include "Mips.h"
#include "MipsSubtarget.h"
#include "MipsInstrInfo.h"
#include "MipsTargetMachine.h"
#include "MipsMachineFunction.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/DwarfWriter.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Target/Mangler.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Target/TargetRegistry.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/MathExtras.h"
#include <cctype>
using namespace llvm;
namespace {
class MipsAsmPrinter : public AsmPrinter {
const MipsSubtarget *Subtarget;
public:
explicit MipsAsmPrinter(formatted_raw_ostream &O, TargetMachine &TM,
MCStreamer &Streamer)
: AsmPrinter(O, TM, Streamer) {
Subtarget = &TM.getSubtarget<MipsSubtarget>();
}
virtual const char *getPassName() const {
return "Mips Assembly Printer";
}
bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
unsigned AsmVariant, const char *ExtraCode);
void printOperand(const MachineInstr *MI, int opNum);
void printUnsignedImm(const MachineInstr *MI, int opNum);
void printMemOperand(const MachineInstr *MI, int opNum,
const char *Modifier = 0);
void printFCCOperand(const MachineInstr *MI, int opNum,
const char *Modifier = 0);
void printSavedRegsBitmask();
void printHex32(unsigned int Value);
const char *emitCurrentABIString();
void emitFrameDirective();
void printInstruction(const MachineInstr *MI); void EmitInstruction(const MachineInstr *MI) {
printInstruction(MI);
OutStreamer.AddBlankLine();
}
virtual void EmitFunctionBodyStart();
virtual void EmitFunctionBodyEnd();
static const char *getRegisterName(unsigned RegNo);
virtual void EmitFunctionEntryLabel();
void EmitStartOfAsmFile(Module &M);
};
}
#include "MipsGenAsmWriter.inc"
void MipsAsmPrinter::printSavedRegsBitmask() {
const TargetRegisterInfo &RI = *TM.getRegisterInfo();
const MipsFunctionInfo *MipsFI = MF->getInfo<MipsFunctionInfo>();
unsigned int CPUBitmask = 0;
unsigned int FPUBitmask = 0;
const MachineFrameInfo *MFI = MF->getFrameInfo();
const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo();
for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
unsigned RegNum = MipsRegisterInfo::getRegisterNumbering(CSI[i].getReg());
if (CSI[i].getRegClass() == Mips::CPURegsRegisterClass)
CPUBitmask |= (1 << RegNum);
else
FPUBitmask |= (1 << RegNum);
}
if (RI.hasFP(*MF))
CPUBitmask |= (1 << MipsRegisterInfo::
getRegisterNumbering(RI.getFrameRegister(*MF)));
if (MFI->adjustsStack())
CPUBitmask |= (1 << MipsRegisterInfo::
getRegisterNumbering(RI.getRARegister()));
O << "\t.mask \t"; printHex32(CPUBitmask); O << ','
<< MipsFI->getCPUTopSavedRegOff() << '\n';
O << "\t.fmask\t"; printHex32(FPUBitmask); O << ","
<< MipsFI->getFPUTopSavedRegOff() << '\n';
}
void MipsAsmPrinter::
printHex32(unsigned int Value)
{
O << "0x";
for (int i = 7; i >= 0; i--)
O << utohexstr( (Value & (0xF << (i*4))) >> (i*4) );
}
void MipsAsmPrinter::emitFrameDirective() {
const TargetRegisterInfo &RI = *TM.getRegisterInfo();
unsigned stackReg = RI.getFrameRegister(*MF);
unsigned returnReg = RI.getRARegister();
unsigned stackSize = MF->getFrameInfo()->getStackSize();
O << "\t.frame\t" << '$' << LowercaseString(getRegisterName(stackReg))
<< ',' << stackSize << ','
<< '$' << LowercaseString(getRegisterName(returnReg))
<< '\n';
}
const char *MipsAsmPrinter::emitCurrentABIString() {
switch(Subtarget->getTargetABI()) {
case MipsSubtarget::O32: return "abi32";
case MipsSubtarget::O64: return "abiO64";
case MipsSubtarget::N32: return "abiN32";
case MipsSubtarget::N64: return "abi64";
case MipsSubtarget::EABI: return "eabi32"; default: break;
}
llvm_unreachable("Unknown Mips ABI");
return NULL;
}
void MipsAsmPrinter::EmitFunctionEntryLabel() {
O << "\t.ent\t" << *CurrentFnSym << '\n';
OutStreamer.EmitLabel(CurrentFnSym);
}
void MipsAsmPrinter::EmitFunctionBodyStart() {
emitFrameDirective();
printSavedRegsBitmask();
}
void MipsAsmPrinter::EmitFunctionBodyEnd() {
O << "\t.set\tmacro\n";
O << "\t.set\treorder\n";
O << "\t.end\t" << *CurrentFnSym << '\n';
}
bool MipsAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
unsigned AsmVariant,const char *ExtraCode){
if (ExtraCode && ExtraCode[0])
return true;
printOperand(MI, OpNo);
return false;
}
void MipsAsmPrinter::printOperand(const MachineInstr *MI, int opNum) {
const MachineOperand &MO = MI->getOperand(opNum);
bool closeP = false;
if (MO.getTargetFlags())
closeP = true;
switch(MO.getTargetFlags()) {
case MipsII::MO_GPREL: O << "%gp_rel("; break;
case MipsII::MO_GOT_CALL: O << "%call16("; break;
case MipsII::MO_GOT:
if (MI->getOpcode() == Mips::LW)
O << "%got(";
else
O << "%lo(";
break;
case MipsII::MO_ABS_HILO:
if (MI->getOpcode() == Mips::LUi)
O << "%hi(";
else
O << "%lo(";
break;
}
switch (MO.getType()) {
case MachineOperand::MO_Register:
O << '$' << LowercaseString(getRegisterName(MO.getReg()));
break;
case MachineOperand::MO_Immediate:
O << (short int)MO.getImm();
break;
case MachineOperand::MO_MachineBasicBlock:
O << *MO.getMBB()->getSymbol();
return;
case MachineOperand::MO_GlobalAddress:
O << *Mang->getSymbol(MO.getGlobal());
break;
case MachineOperand::MO_ExternalSymbol:
O << *GetExternalSymbolSymbol(MO.getSymbolName());
break;
case MachineOperand::MO_JumpTableIndex:
O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
<< '_' << MO.getIndex();
break;
case MachineOperand::MO_ConstantPoolIndex:
O << MAI->getPrivateGlobalPrefix() << "CPI"
<< getFunctionNumber() << "_" << MO.getIndex();
if (MO.getOffset())
O << "+" << MO.getOffset();
break;
default:
llvm_unreachable("<unknown operand type>");
}
if (closeP) O << ")";
}
void MipsAsmPrinter::printUnsignedImm(const MachineInstr *MI, int opNum) {
const MachineOperand &MO = MI->getOperand(opNum);
if (MO.getType() == MachineOperand::MO_Immediate)
O << (unsigned short int)MO.getImm();
else
printOperand(MI, opNum);
}
void MipsAsmPrinter::
printMemOperand(const MachineInstr *MI, int opNum, const char *Modifier) {
if (Modifier && !strcmp(Modifier, "stackloc")) {
printOperand(MI, opNum+1);
O << ", ";
printOperand(MI, opNum);
return;
}
printOperand(MI, opNum);
O << "(";
printOperand(MI, opNum+1);
O << ")";
}
void MipsAsmPrinter::
printFCCOperand(const MachineInstr *MI, int opNum, const char *Modifier) {
const MachineOperand& MO = MI->getOperand(opNum);
O << Mips::MipsFCCToString((Mips::CondCode)MO.getImm());
}
void MipsAsmPrinter::EmitStartOfAsmFile(Module &M) {
O << "\t.section .mdebug." << emitCurrentABIString() << '\n';
if (Subtarget->isABI_EABI())
O << "\t.section .gcc_compiled_long" <<
(Subtarget->isGP32bit() ? "32" : "64") << '\n';
O << "\t.previous" << '\n';
}
extern "C" void LLVMInitializeMipsAsmPrinter() {
RegisterAsmPrinter<MipsAsmPrinter> X(TheMipsTarget);
RegisterAsmPrinter<MipsAsmPrinter> Y(TheMipselTarget);
}