#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCSymbol.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/Support/Mangler.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/MathExtras.h"
#include <cctype>
-
using namespace llvm;
STATISTIC(EmittedInsts, "Number of machine instrs printed");
namespace {
- class VISIBILITY_HIDDEN MipsAsmPrinter : public AsmPrinter {
+ class MipsAsmPrinter : public AsmPrinter {
const MipsSubtarget *Subtarget;
public:
explicit MipsAsmPrinter(formatted_raw_ostream &O, TargetMachine &TM,
const char *Modifier = 0);
void printFCCOperand(const MachineInstr *MI, int opNum,
const char *Modifier = 0);
- void PrintGlobalVariable(const GlobalVariable *GVar);
void printSavedRegsBitmask(MachineFunction &MF);
void printHex32(unsigned int Value);
const char *emitCurrentABIString();
- void emitFunctionStart(MachineFunction &MF);
void emitFunctionEnd(MachineFunction &MF);
void emitFrameDirective(MachineFunction &MF);
void printInstruction(const MachineInstr *MI); // autogenerated.
+ static const char *getRegisterName(unsigned RegNo);
+
bool runOnMachineFunction(MachineFunction &F);
- bool doInitialization(Module &M);
+ virtual void EmitFunctionEntryLabel();
+ void EmitStartOfAsmFile(Module &M);
};
} // end of anonymous namespace
unsigned stackSize = MF.getFrameInfo()->getStackSize();
- O << "\t.frame\t" << '$' << LowercaseString(RI.get(stackReg).AsmName)
+ O << "\t.frame\t" << '$' << LowercaseString(getRegisterName(stackReg))
<< ',' << stackSize << ','
- << '$' << LowercaseString(RI.get(returnReg).AsmName)
+ << '$' << LowercaseString(getRegisterName(returnReg))
<< '\n';
}
return NULL;
}
-/// Emit the directives used by GAS on the start of functions
-void MipsAsmPrinter::emitFunctionStart(MachineFunction &MF) {
- // Print out the label for the function.
- const Function *F = MF.getFunction();
- OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(F, Mang, TM));
-
- // 2 bits aligned
- EmitAlignment(MF.getAlignment(), F);
-
- O << "\t.globl\t" << CurrentFnName << '\n';
- O << "\t.ent\t" << CurrentFnName << '\n';
-
- printVisibility(CurrentFnName, F->getVisibility());
-
- if ((MAI->hasDotTypeDotSizeDirective()) && Subtarget->isLinux())
- O << "\t.type\t" << CurrentFnName << ", @function\n";
-
- O << CurrentFnName << ":\n";
-
- emitFrameDirective(MF);
- printSavedRegsBitmask(MF);
-
- O << '\n';
-}
-
/// Emit the directives used by GAS on the end of functions
void MipsAsmPrinter::emitFunctionEnd(MachineFunction &MF) {
// There are instruction for this macros, but they must
O << "\t.set\tmacro\n";
O << "\t.set\treorder\n";
- O << "\t.end\t" << CurrentFnName << '\n';
+ O << "\t.end\t" << *CurrentFnSym << '\n';
if (MAI->hasDotTypeDotSizeDirective() && !Subtarget->isLinux())
- O << "\t.size\t" << CurrentFnName << ", .-" << CurrentFnName << '\n';
+ O << "\t.size\t" << *CurrentFnSym << ", .-" << *CurrentFnSym << '\n';
+}
+
+void MipsAsmPrinter::EmitFunctionEntryLabel() {
+ O << "\t.ent\t" << *CurrentFnSym << '\n';
+ OutStreamer.EmitLabel(CurrentFnSym);
}
/// runOnMachineFunction - This uses the printMachineInstruction()
/// method to print assembly for each instruction.
bool MipsAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
- this->MF = &MF;
-
SetupMachineFunction(MF);
-
- // Print out constants referenced by the function
- EmitConstantPool(MF.getConstantPool());
-
- // Print out jump tables referenced by the function
- EmitJumpTableInfo(MF.getJumpTableInfo(), MF);
-
- O << "\n\n";
-
- // Emit the function start directives
- emitFunctionStart(MF);
-
+
+ EmitFunctionHeader();
+
+ emitFrameDirective(MF);
+ printSavedRegsBitmask(MF);
+
+ O << '\n';
+
// Print out code for the function.
for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
I != E; ++I) {
// Print a label for the basic block.
- if (I != MF.begin()) {
- printBasicBlockLabel(I, true, true);
- O << '\n';
- }
+ if (I != MF.begin())
+ EmitBasicBlockStart(I);
for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
II != E; ++II) {
- processDebugLoc(II->getDebugLoc());
+ processDebugLoc(II, true);
// Print the assembly for the instruction.
printInstruction(II);
- if (VerboseAsm && !II->getDebugLoc().isUnknown())
+ if (VerboseAsm)
EmitComments(*II);
O << '\n';
-
+
+ processDebugLoc(II, false);
++EmittedInsts;
}
// Emit function end directives
emitFunctionEnd(MF);
-
+
+ // Print out jump tables referenced by the function
+ EmitJumpTableInfo();
+
// We didn't modify anything.
return false;
}
void MipsAsmPrinter::printOperand(const MachineInstr *MI, int opNum) {
const MachineOperand &MO = MI->getOperand(opNum);
- const TargetRegisterInfo &RI = *TM.getRegisterInfo();
bool closeP = false;
if (MO.getTargetFlags())
break;
}
- switch (MO.getType())
- {
+ switch (MO.getType()) {
case MachineOperand::MO_Register:
- if (TargetRegisterInfo::isPhysicalRegister(MO.getReg()))
- O << '$' << LowercaseString (RI.get(MO.getReg()).AsmName);
- else
- O << '$' << MO.getReg();
+ O << '$' << LowercaseString(getRegisterName(MO.getReg()));
break;
case MachineOperand::MO_Immediate:
break;
case MachineOperand::MO_MachineBasicBlock:
- printBasicBlockLabel(MO.getMBB());
+ O << *MO.getMBB()->getSymbol(OutContext);
return;
case MachineOperand::MO_GlobalAddress:
- O << Mang->getMangledName(MO.getGlobal());
+ O << *GetGlobalValueSymbol(MO.getGlobal());
break;
case MachineOperand::MO_ExternalSymbol:
- O << MO.getSymbolName();
+ O << *GetExternalSymbolSymbol(MO.getSymbolName());
break;
case MachineOperand::MO_JumpTableIndex:
O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
- << '_' << MO.getIndex();
+ << '_' << MO.getIndex();
break;
case MachineOperand::MO_ConstantPoolIndex:
O << MAI->getPrivateGlobalPrefix() << "CPI"
<< getFunctionNumber() << "_" << MO.getIndex();
+ if (MO.getOffset())
+ O << "+" << MO.getOffset();
break;
default:
O << Mips::MipsFCCToString((Mips::CondCode)MO.getImm());
}
-bool MipsAsmPrinter::doInitialization(Module &M) {
+void MipsAsmPrinter::EmitStartOfAsmFile(Module &M) {
// FIXME: Use SwitchSection.
// Tell the assembler which ABI we are using
// return to previous section
O << "\t.previous" << '\n';
-
- return AsmPrinter::doInitialization(M);
-}
-
-void MipsAsmPrinter::PrintGlobalVariable(const GlobalVariable *GVar) {
- const TargetData *TD = TM.getTargetData();
-
- if (!GVar->hasInitializer())
- return; // External global require no code
-
- // Check to see if this is a special global used by LLVM, if so, emit it.
- if (EmitSpecialLLVMGlobal(GVar))
- return;
-
- O << "\n\n";
- std::string name = Mang->getMangledName(GVar);
- Constant *C = GVar->getInitializer();
- const Type *CTy = C->getType();
- unsigned Size = TD->getTypeAllocSize(CTy);
- const ConstantArray *CVA = dyn_cast<ConstantArray>(C);
- bool printSizeAndType = true;
-
- // A data structure or array is aligned in memory to the largest
- // alignment boundary required by any data type inside it (this matches
- // the Preferred Type Alignment). For integral types, the alignment is
- // the type size.
- unsigned Align;
- if (CTy->getTypeID() == Type::IntegerTyID ||
- CTy->getTypeID() == Type::VoidTyID) {
- assert(!(Size & (Size-1)) && "Alignment is not a power of two!");
- Align = Log2_32(Size);
- } else
- Align = TD->getPreferredTypeAlignmentShift(CTy);
-
- printVisibility(name, GVar->getVisibility());
-
- OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(GVar, Mang,
- TM));
-
- if (C->isNullValue() && !GVar->hasSection()) {
- if (!GVar->isThreadLocal() &&
- (GVar->hasLocalLinkage() || GVar->isWeakForLinker())) {
- if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
-
- if (GVar->hasLocalLinkage())
- O << "\t.local\t" << name << '\n';
-
- O << MAI->getCOMMDirective() << name << ',' << Size;
- if (MAI->getCOMMDirectiveTakesAlignment())
- O << ',' << (1 << Align);
-
- O << '\n';
- return;
- }
- }
- switch (GVar->getLinkage()) {
- case GlobalValue::LinkOnceAnyLinkage:
- case GlobalValue::LinkOnceODRLinkage:
- case GlobalValue::CommonLinkage:
- case GlobalValue::WeakAnyLinkage:
- case GlobalValue::WeakODRLinkage:
- // FIXME: Verify correct for weak.
- // Nonnull linkonce -> weak
- O << "\t.weak " << name << '\n';
- break;
- case GlobalValue::AppendingLinkage:
- // FIXME: appending linkage variables should go into a section of their name
- // or something. For now, just emit them as external.
- case GlobalValue::ExternalLinkage:
- // If external or appending, declare as a global symbol
- O << MAI->getGlobalDirective() << name << '\n';
- // Fall Through
- case GlobalValue::PrivateLinkage:
- case GlobalValue::LinkerPrivateLinkage:
- case GlobalValue::InternalLinkage:
- if (CVA && CVA->isCString())
- printSizeAndType = false;
- break;
- case GlobalValue::GhostLinkage:
- llvm_unreachable("Should not have any unmaterialized functions!");
- case GlobalValue::DLLImportLinkage:
- llvm_unreachable("DLLImport linkage is not supported by this target!");
- case GlobalValue::DLLExportLinkage:
- llvm_unreachable("DLLExport linkage is not supported by this target!");
- default:
- llvm_unreachable("Unknown linkage type!");
- }
-
- EmitAlignment(Align, GVar);
-
- if (MAI->hasDotTypeDotSizeDirective() && printSizeAndType) {
- O << "\t.type " << name << ",@object\n";
- O << "\t.size " << name << ',' << Size << '\n';
- }
-
- O << name << ":\n";
- EmitGlobalConstant(C);
}
-
// Force static initialization.
extern "C" void LLVMInitializeMipsAsmPrinter() {
RegisterAsmPrinter<MipsAsmPrinter> X(TheMipsTarget);