#include "llvm/Target/TargetRegistry.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Support/CommandLine.h"
#include <cctype>
using namespace llvm;
-STATISTIC(EmittedInsts, "Number of machine instrs printed");
-
static cl::opt<bool>
EnableMCInst("enable-arm-mcinst-printer", cl::Hidden,
cl::desc("enable experimental asmprinter gunk in the arm backend"));
public:
explicit ARMAsmPrinter(formatted_raw_ostream &O, TargetMachine &TM,
- const MCAsmInfo *T, bool V)
- : AsmPrinter(O, TM, T, V), AFI(NULL), MCP(NULL) {
+ MCContext &Ctx, MCStreamer &Streamer,
+ const MCAsmInfo *T)
+ : AsmPrinter(O, TM, Ctx, Streamer, T), AFI(NULL), MCP(NULL) {
Subtarget = &TM.getSubtarget<ARMSubtarget>();
}
unsigned AsmVariant,
const char *ExtraCode);
- void PrintGlobalVariable(const GlobalVariable* GVar);
void printInstruction(const MachineInstr *MI); // autogenerated.
static const char *getRegisterName(unsigned RegNo);
- void printMachineInstruction(const MachineInstr *MI);
+ virtual void EmitInstruction(const MachineInstr *MI);
bool runOnMachineFunction(MachineFunction &F);
+
+ virtual void EmitConstantPool() {} // we emit constant pools customly!
+ virtual void EmitFunctionEntryLabel();
void EmitStartOfAsmFile(Module &M);
void EmitEndOfAsmFile(Module &M);
+ MCSymbol *GetARMSetPICJumpTableLabel2(unsigned uid, unsigned uid2,
+ const MachineBasicBlock *MBB) const;
+ MCSymbol *GetARMJTIPICJumpTableLabel2(unsigned uid, unsigned uid2) const;
+
/// EmitMachineConstantPoolValue - Print a machine constantpool value to
/// the .s file.
virtual void EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) {
- printDataDirective(MCPV->getType());
+ switch (TM.getTargetData()->getTypeAllocSize(MCPV->getType())) {
+ case 1: O << MAI->getData8bitsDirective(0); break;
+ case 2: O << MAI->getData16bitsDirective(0); break;
+ case 4: O << MAI->getData32bitsDirective(0); break;
+ default: assert(0 && "Unknown CPV size");
+ }
ARMConstantPoolValue *ACPV = static_cast<ARMConstantPoolValue*>(MCPV);
SmallString<128> TmpNameStr;
#include "ARMGenAsmWriter.inc"
-/// runOnMachineFunction - This uses the printInstruction()
-/// method to print assembly for each instruction.
-///
-bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
- this->MF = &MF;
-
- AFI = MF.getInfo<ARMFunctionInfo>();
- MCP = MF.getConstantPool();
-
- SetupMachineFunction(MF);
- O << "\n";
-
- // NOTE: we don't print out constant pools here, they are handled as
- // instructions.
-
- O << '\n';
-
- // Print out labels for the function.
- const Function *F = MF.getFunction();
- OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(F, Mang, TM));
-
- switch (F->getLinkage()) {
- default: llvm_unreachable("Unknown linkage type!");
- case Function::PrivateLinkage:
- case Function::InternalLinkage:
- break;
- case Function::ExternalLinkage:
- O << "\t.globl\t" << *CurrentFnSym << "\n";
- break;
- case Function::LinkerPrivateLinkage:
- case Function::WeakAnyLinkage:
- case Function::WeakODRLinkage:
- case Function::LinkOnceAnyLinkage:
- case Function::LinkOnceODRLinkage:
- if (Subtarget->isTargetDarwin()) {
- O << "\t.globl\t" << *CurrentFnSym << "\n";
- O << "\t.weak_definition\t" << *CurrentFnSym << "\n";
- } else {
- O << MAI->getWeakRefDirective() << *CurrentFnSym << "\n";
- }
- break;
- }
-
- printVisibility(CurrentFnSym, F->getVisibility());
-
- unsigned FnAlign = 1 << MF.getAlignment(); // MF alignment is log2.
+void ARMAsmPrinter::EmitFunctionEntryLabel() {
if (AFI->isThumbFunction()) {
- EmitAlignment(FnAlign, F, AFI->getAlign());
O << "\t.code\t16\n";
O << "\t.thumb_func";
if (Subtarget->isTargetDarwin())
- O << "\t" << *CurrentFnSym;
- O << "\n";
- } else {
- EmitAlignment(FnAlign, F);
- }
-
- O << *CurrentFnSym << ":\n";
- // Emit pre-function debug information.
- DW->BeginFunction(&MF);
-
- if (Subtarget->isTargetDarwin()) {
- // If the function is empty, then we need to emit *something*. Otherwise,
- // the function's label might be associated with something that it wasn't
- // meant to be associated with. We emit a noop in this situation.
- MachineFunction::iterator I = MF.begin();
-
- if (++I == MF.end() && MF.front().empty())
- O << "\tnop\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())
- EmitBasicBlockStart(I);
-
- // Print the assembly for the instruction.
- for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
- II != E; ++II)
- printMachineInstruction(II);
+ O << '\t' << *CurrentFnSym;
+ O << '\n';
}
+
+ OutStreamer.EmitLabel(CurrentFnSym);
+}
- if (MAI->hasDotTypeDotSizeDirective())
- O << "\t.size " << *CurrentFnSym << ", .-" << *CurrentFnSym << "\n";
-
- // Emit post-function debug information.
- DW->EndFunction(&MF);
+/// runOnMachineFunction - This uses the printInstruction()
+/// method to print assembly for each instruction.
+///
+bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
+ AFI = MF.getInfo<ARMFunctionInfo>();
+ MCP = MF.getConstantPool();
- return false;
+ return AsmPrinter::runOnMachineFunction(MF);
}
void ARMAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
break;
}
case MachineOperand::MO_MachineBasicBlock:
- O << *GetMBBSymbol(MO.getMBB()->getNumber());
+ O << *MO.getMBB()->getSymbol(OutContext);
return;
case MachineOperand::MO_GlobalAddress: {
bool isCallOp = Modifier && !strcmp(Modifier, "call");
break;
}
case MachineOperand::MO_ConstantPoolIndex:
- O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
- << '_' << MO.getIndex();
+ O << *GetCPISymbol(MO.getIndex());
break;
case MachineOperand::MO_JumpTableIndex:
- O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
- << '_' << MO.getIndex();
+ O << *GetJTISymbol(MO.getIndex());
break;
}
}
// data itself.
if (!strcmp(Modifier, "label")) {
unsigned ID = MI->getOperand(OpNum).getImm();
- O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
- << '_' << ID << ":\n";
+ O << *GetCPISymbol(ID) << ":\n";
} else {
assert(!strcmp(Modifier, "cpentry") && "Unknown modifier for CPE");
unsigned CPI = MI->getOperand(OpNum).getIndex();
}
}
+MCSymbol *ARMAsmPrinter::
+GetARMSetPICJumpTableLabel2(unsigned uid, unsigned uid2,
+ const MachineBasicBlock *MBB) const {
+ SmallString<60> Name;
+ raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix()
+ << getFunctionNumber() << '_' << uid << '_' << uid2
+ << "_set_" << MBB->getNumber();
+ return OutContext.GetOrCreateSymbol(Name.str());
+}
+
+MCSymbol *ARMAsmPrinter::
+GetARMJTIPICJumpTableLabel2(unsigned uid, unsigned uid2) const {
+ SmallString<60> Name;
+ raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() << "JTI"
+ << getFunctionNumber() << '_' << uid << '_' << uid2;
+ return OutContext.GetOrCreateSymbol(Name.str());
+}
+
void ARMAsmPrinter::printJTBlockOperand(const MachineInstr *MI, int OpNum) {
assert(!Subtarget->isThumb2() && "Thumb2 should use double-jump jumptables!");
const MachineOperand &MO1 = MI->getOperand(OpNum);
const MachineOperand &MO2 = MI->getOperand(OpNum+1); // Unique Id
+
unsigned JTI = MO1.getIndex();
- O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
- << '_' << JTI << '_' << MO2.getImm() << ":\n";
+ MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel2(JTI, MO2.getImm());
+ OutStreamer.EmitLabel(JTISymbol);
const char *JTEntryDirective = MAI->getData32bitsDirective();
- const MachineFunction *MF = MI->getParent()->getParent();
const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
- bool UseSet= MAI->getSetDirective() && TM.getRelocationModel() == Reloc::PIC_;
+ bool UseSet= MAI->hasSetDirective() && TM.getRelocationModel() == Reloc::PIC_;
SmallPtrSet<MachineBasicBlock*, 8> JTSets;
for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) {
MachineBasicBlock *MBB = JTBBs[i];
bool isNew = JTSets.insert(MBB);
- if (UseSet && isNew)
- printPICJumpTableSetLabel(JTI, MO2.getImm(), MBB);
+ if (UseSet && isNew) {
+ O << "\t.set\t"
+ << *GetARMSetPICJumpTableLabel2(JTI, MO2.getImm(), MBB) << ','
+ << *MBB->getSymbol(OutContext) << '-' << *JTISymbol << '\n';
+ }
O << JTEntryDirective << ' ';
if (UseSet)
- O << MAI->getPrivateGlobalPrefix() << getFunctionNumber()
- << '_' << JTI << '_' << MO2.getImm()
- << "_set_" << MBB->getNumber();
- else if (TM.getRelocationModel() == Reloc::PIC_) {
- O << *GetMBBSymbol(MBB->getNumber())
- << '-' << MAI->getPrivateGlobalPrefix() << "JTI"
- << getFunctionNumber() << '_' << JTI << '_' << MO2.getImm();
- } else {
- O << *GetMBBSymbol(MBB->getNumber());
- }
+ O << *GetARMSetPICJumpTableLabel2(JTI, MO2.getImm(), MBB);
+ else if (TM.getRelocationModel() == Reloc::PIC_)
+ O << *MBB->getSymbol(OutContext) << '-' << *JTISymbol;
+ else
+ O << *MBB->getSymbol(OutContext);
+
if (i != e-1)
O << '\n';
}
const MachineOperand &MO1 = MI->getOperand(OpNum);
const MachineOperand &MO2 = MI->getOperand(OpNum+1); // Unique Id
unsigned JTI = MO1.getIndex();
- O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
- << '_' << JTI << '_' << MO2.getImm() << ":\n";
+
+ MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel2(JTI, MO2.getImm());
+ OutStreamer.EmitLabel(JTISymbol);
- const MachineFunction *MF = MI->getParent()->getParent();
const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
O << MAI->getData8bitsDirective();
else if (HalfWordOffset)
O << MAI->getData16bitsDirective();
- if (ByteOffset || HalfWordOffset) {
- O << '(' << *GetMBBSymbol(MBB->getNumber());
- O << "-" << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
- << '_' << JTI << '_' << MO2.getImm() << ")/2";
- } else {
- O << "\tb.w " << *GetMBBSymbol(MBB->getNumber());
- }
+
+ if (ByteOffset || HalfWordOffset)
+ O << '(' << *MBB->getSymbol(OutContext) << "-" << *JTISymbol << ")/2";
+ else
+ O << "\tb.w " << *MBB->getSymbol(OutContext);
+
if (i != e-1)
O << '\n';
}
return false;
}
-void ARMAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
- ++EmittedInsts;
-
- // Call the autogenerated instruction printer routines.
- processDebugLoc(MI, true);
-
+void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) {
if (EnableMCInst) {
printInstructionThroughMCStreamer(MI);
} else {
EmitAlignment(2);
printInstruction(MI);
+ O << '\n';
}
-
- if (VerboseAsm)
- EmitComments(*MI);
- O << '\n';
- processDebugLoc(MI, false);
}
void ARMAsmPrinter::EmitStartOfAsmFile(Module &M) {
}
}
-void ARMAsmPrinter::PrintGlobalVariable(const GlobalVariable* GVar) {
- const TargetData *TD = TM.getTargetData();
-
- MCSymbol *GVarSym = GetGlobalValueSymbol(GVar);
-
- Constant *C = GVar->getInitializer();
- const Type *Type = C->getType();
- unsigned Size = TD->getTypeAllocSize(Type);
- unsigned Align = TD->getPreferredAlignmentLog(GVar);
- bool isDarwin = Subtarget->isTargetDarwin();
-
- printVisibility(GVarSym, GVar->getVisibility());
-
- if (Subtarget->isTargetELF())
- O << "\t.type " << *GVarSym << ",%object\n";
-
- SectionKind GVKind = TargetLoweringObjectFile::getKindForGlobal(GVar, TM);
-
- // Handle normal common symbols.
- if (GVKind.isCommon()) {
- if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
-
- O << ".comm " << *GVarSym << ',' << Size;
- if (MAI->getCOMMDirectiveTakesAlignment())
- O << ',' << (MAI->getAlignmentIsInBytes() ? (1 << Align) : Align);
-
- if (VerboseAsm) {
- O << "\t\t" << MAI->getCommentString() << " '";
- WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent());
- O << '\'';
- }
- O << '\n';
- return;
- }
-
- if (GVKind.isBSSLocal()) {
- if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
-
- if (const char *LCOMM = MAI->getLCOMMDirective()) {
- O << LCOMM << *GVarSym << "," << Size;
- if (MAI->getLCOMMDirectiveTakesAlignment())
- O << ',' << Align;
- } else {
- O << "\t.local\t" << *GVarSym << '\n';
- O << MAI->getCOMMDirective() << *GVarSym << "," << Size;
- if (MAI->getCOMMDirectiveTakesAlignment())
- O << "," << (MAI->getAlignmentIsInBytes() ? (1 << Align) : Align);
- }
- if (VerboseAsm) {
- O.PadToColumn(MAI->getCommentColumn());
- O << MAI->getCommentString() << ' ';
- WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent());
- }
- O << "\n";
- return;
- }
-
- const MCSection *TheSection =
- getObjFileLowering().SectionForGlobal(GVar, GVKind, Mang, TM);
-
- // Handle the zerofill directive on darwin, which is a special form of BSS
- // emission.
- if (GVKind.isBSSExtern() && MAI->hasMachoZeroFillDirective()) {
- // .globl _foo
- OutStreamer.EmitSymbolAttribute(GVarSym, MCStreamer::Global);
- // .zerofill __DATA, __common, _foo, 400, 5
- OutStreamer.EmitZerofill(TheSection, GVarSym, Size, 1 << Align);
- return;
- }
-
- OutStreamer.SwitchSection(TheSection);
-
- switch (GVar->getLinkage()) {
- case GlobalValue::CommonLinkage:
- case GlobalValue::LinkOnceAnyLinkage:
- case GlobalValue::LinkOnceODRLinkage:
- case GlobalValue::WeakAnyLinkage:
- case GlobalValue::WeakODRLinkage:
- case GlobalValue::LinkerPrivateLinkage:
- if (isDarwin) {
- O << "\t.globl " << *GVarSym
- << "\n\t.weak_definition " << *GVarSym << "\n";
- } else {
- O << "\t.weak " << *GVarSym << "\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:
- O << "\t.globl " << *GVarSym << "\n";
- break;
- case GlobalValue::PrivateLinkage:
- case GlobalValue::InternalLinkage:
- break;
- default:
- llvm_unreachable("Unknown linkage type!");
- }
-
- EmitAlignment(Align, GVar);
- O << *GVarSym << ":";
- if (VerboseAsm) {
- O.PadToColumn(MAI->getCommentColumn());
- O << MAI->getCommentString() << ' ';
- WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent());
- }
- O << "\n";
- if (MAI->hasDotTypeDotSizeDirective())
- O << "\t.size " << *GVarSym << ", " << Size << "\n";
-
- EmitGlobalConstant(C);
- O << '\n';
-}
-
void ARMAsmPrinter::EmitEndOfAsmFile(Module &M) {
if (Subtarget->isTargetDarwin()) {
// implementation of multiple entry points). If this doesn't occur, the
// linker can safely perform dead code stripping. Since LLVM never
// generates code that does this, it is always safe to set.
- OutStreamer.EmitAssemblerFlag(MCStreamer::SubsectionsViaSymbols);
+ OutStreamer.EmitAssemblerFlag(MCAF_SubsectionsViaSymbols);
}
}
case ARM::t2MOVi32imm:
assert(0 && "Should be lowered by thumb2it pass");
default: break;
- case TargetInstrInfo::DBG_LABEL:
- case TargetInstrInfo::EH_LABEL:
- case TargetInstrInfo::GC_LABEL:
- printLabel(MI);
- return;
- case TargetInstrInfo::KILL:
- printKill(MI);
- return;
- case TargetInstrInfo::INLINEASM:
- printInlineAsm(MI);
- return;
- case TargetInstrInfo::IMPLICIT_DEF:
- printImplicitDef(MI);
- return;
case ARM::PICADD: { // FIXME: Remove asm string from td file.
// This is a pseudo op for a label + instruction sequence, which looks like:
// LPC0:
unsigned CPIdx = (unsigned)MI->getOperand(1).getIndex();
EmitAlignment(2);
-
- const char *Prefix = MAI->getPrivateGlobalPrefix();
- MCSymbol *Label = OutContext.GetOrCreateSymbol(Twine(Prefix)+"CPI"+
- Twine(getFunctionNumber())+
- "_"+ Twine(LabelId));
- OutStreamer.EmitLabel(Label);
+ OutStreamer.EmitLabel(GetCPISymbol(LabelId));
const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPIdx];
if (MCPE.isMachineConstantPoolEntry())