X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FARM%2FAsmPrinter%2FARMAsmPrinter.cpp;h=7e22b62a2607a9de72e11860a76c84443fd40253;hb=d1ff72b8a797304f146e4293db8c814231ea8cb3;hp=7e89b9f5e92ea65a5d068bb9417c217f9dd3db94;hpb=a70e644820db9c58f201bd27ed3c28f81261a0d9;p=oota-llvm.git diff --git a/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp b/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp index 7e89b9f5e92..7e22b62a260 100644 --- a/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp +++ b/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp @@ -23,6 +23,7 @@ #include "ARMTargetMachine.h" #include "llvm/Constants.h" #include "llvm/Module.h" +#include "llvm/Type.h" #include "llvm/Assembly/Writer.h" #include "llvm/CodeGen/AsmPrinter.h" #include "llvm/CodeGen/DwarfWriter.h" @@ -42,18 +43,15 @@ #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 "llvm/Support/ErrorHandling.h" #include "llvm/Support/FormattedStream.h" -#include "llvm/Support/Mangler.h" #include "llvm/Support/MathExtras.h" #include using namespace llvm; -STATISTIC(EmittedInsts, "Number of machine instrs printed"); - static cl::opt EnableMCInst("enable-arm-mcinst-printer", cl::Hidden, cl::desc("enable experimental asmprinter gunk in the arm backend")); @@ -75,8 +73,9 @@ namespace { 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(); } @@ -109,6 +108,7 @@ namespace { const char *Modifier = 0); void printBitfieldInvMaskImmOperand (const MachineInstr *MI, int OpNum); + void printThumbS4ImmOperand(const MachineInstr *MI, int OpNum); void printThumbITMask(const MachineInstr *MI, int OpNum); void printThumbAddrModeRROperand(const MachineInstr *MI, int OpNum); void printThumbAddrModeRI5Operand(const MachineInstr *MI, int OpNum, @@ -135,6 +135,21 @@ namespace { void printJT2BlockOperand(const MachineInstr *MI, int OpNum); void printTBAddrMode(const MachineInstr *MI, int OpNum); void printNoHashImmediate(const MachineInstr *MI, int OpNum); + void printVFPf32ImmOperand(const MachineInstr *MI, int OpNum); + void printVFPf64ImmOperand(const MachineInstr *MI, int OpNum); + + void printHex8ImmOperand(const MachineInstr *MI, int OpNum) { + O << "#0x" << utohexstr(MI->getOperand(OpNum).getImm() & 0xff); + } + void printHex16ImmOperand(const MachineInstr *MI, int OpNum) { + O << "#0x" << utohexstr(MI->getOperand(OpNum).getImm() & 0xffff); + } + void printHex32ImmOperand(const MachineInstr *MI, int OpNum) { + O << "#0x" << utohexstr(MI->getOperand(OpNum).getImm() & 0xffffffff); + } + void printHex64ImmOperand(const MachineInstr *MI, int OpNum) { + O << "#0x" << utohexstr(MI->getOperand(OpNum).getImm()); + } virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNum, unsigned AsmVariant, const char *ExtraCode); @@ -142,64 +157,74 @@ namespace { 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(MCPV); - GlobalValue *GV = ACPV->getGV(); - std::string Name; + SmallString<128> TmpNameStr; if (ACPV->isLSDA()) { - SmallString<16> LSDAName; - raw_svector_ostream(LSDAName) << MAI->getPrivateGlobalPrefix() << + raw_svector_ostream(TmpNameStr) << MAI->getPrivateGlobalPrefix() << "_LSDA_" << getFunctionNumber(); - Name = LSDAName.str(); - } else if (GV) { + O << TmpNameStr.str(); + } else if (ACPV->isBlockAddress()) { + O << GetBlockAddressSymbol(ACPV->getBlockAddress())->getName(); + } else if (ACPV->isGlobalValue()) { + GlobalValue *GV = ACPV->getGV(); bool isIndirect = Subtarget->isTargetDarwin() && Subtarget->GVIsIndirectSymbol(GV, TM.getRelocationModel()); if (!isIndirect) - Name = Mang->getMangledName(GV); + O << *GetGlobalValueSymbol(GV); else { // FIXME: Remove this when Darwin transition to @GOT like syntax. - Name = Mang->getMangledName(GV, "$non_lazy_ptr", true); - MCSymbol *Sym = OutContext.GetOrCreateSymbol(Name.c_str()); + MCSymbol *Sym = GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr"); + O << *Sym; MachineModuleInfoMachO &MMIMachO = MMI->getObjFileInfo(); const MCSymbol *&StubSym = GV->hasHiddenVisibility() ? MMIMachO.getHiddenGVStubEntry(Sym) : MMIMachO.getGVStubEntry(Sym); - if (StubSym == 0) { - SmallString<128> NameStr; - Mang->getNameWithPrefix(NameStr, GV, false); - StubSym = OutContext.GetOrCreateSymbol(NameStr.str()); - } + if (StubSym == 0) + StubSym = GetGlobalValueSymbol(GV); } - } else - Name = Mang->makeNameProper(ACPV->getSymbol()); - O << Name; + } else { + assert(ACPV->isExtSymbol() && "unrecognized constant pool value"); + O << *GetExternalSymbolSymbol(ACPV->getSymbol()); + } if (ACPV->hasModifier()) O << "(" << ACPV->getModifier() << ")"; if (ACPV->getPCAdjustment() != 0) { O << "-(" << MAI->getPrivateGlobalPrefix() << "PC" - << ACPV->getLabelId() + << getFunctionNumber() << "_" << ACPV->getLabelId() << "+" << (unsigned)ACPV->getPCAdjustment(); if (ACPV->mustAddCurrentAddress()) O << "-."; - O << ")"; + O << ')'; } - O << "\n"; + O << '\n'; } void getAnalysisUsage(AnalysisUsage &AU) const { @@ -213,102 +238,33 @@ namespace { #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(); - 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" << CurrentFnName << "\n"; - break; - case Function::LinkerPrivateLinkage: - case Function::WeakAnyLinkage: - case Function::WeakODRLinkage: - case Function::LinkOnceAnyLinkage: - case Function::LinkOnceODRLinkage: - if (Subtarget->isTargetDarwin()) { - O << "\t.globl\t" << CurrentFnName << "\n"; - O << "\t.weak_definition\t" << CurrentFnName << "\n"; - } else { - O << MAI->getWeakRefDirective() << CurrentFnName << "\n"; - } - break; - } - - printVisibility(CurrentFnName, 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" << CurrentFnName; - O << "\n"; - } else { - EmitAlignment(FnAlign, F); - } - - O << CurrentFnName << ":\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 " << CurrentFnName << ", .-" << CurrentFnName << "\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(); + MCP = MF.getConstantPool(); - return false; + return AsmPrinter::runOnMachineFunction(MF); } void ARMAsmPrinter::printOperand(const MachineInstr *MI, int OpNum, const char *Modifier) { const MachineOperand &MO = MI->getOperand(OpNum); + unsigned TF = MO.getTargetFlags(); + switch (MO.getType()) { default: assert(0 && ""); @@ -327,6 +283,7 @@ void ARMAsmPrinter::printOperand(const MachineInstr *MI, int OpNum, &ARM::DPR_VFP2RegClass); O << getRegisterName(DReg) << '[' << (RegNum & 1) << ']'; } else { + assert(!MO.getSubReg() && "Subregs should be eliminated!"); O << getRegisterName(Reg); } break; @@ -334,22 +291,29 @@ void ARMAsmPrinter::printOperand(const MachineInstr *MI, int OpNum, case MachineOperand::MO_Immediate: { int64_t Imm = MO.getImm(); O << '#'; - if (Modifier) { - if (strcmp(Modifier, "lo16") == 0) - O << ":lower16:"; - else if (strcmp(Modifier, "hi16") == 0) - O << ":upper16:"; - } + if ((Modifier && strcmp(Modifier, "lo16") == 0) || + (TF & ARMII::MO_LO16)) + O << ":lower16:"; + else if ((Modifier && strcmp(Modifier, "hi16") == 0) || + (TF & ARMII::MO_HI16)) + O << ":upper16:"; O << Imm; break; } case MachineOperand::MO_MachineBasicBlock: - GetMBBSymbol(MO.getMBB()->getNumber())->print(O, MAI); + O << *MO.getMBB()->getSymbol(OutContext); return; case MachineOperand::MO_GlobalAddress: { bool isCallOp = Modifier && !strcmp(Modifier, "call"); GlobalValue *GV = MO.getGlobal(); - O << Mang->getMangledName(GV); + + if ((Modifier && strcmp(Modifier, "lo16") == 0) || + (TF & ARMII::MO_LO16)) + O << ":lower16:"; + else if ((Modifier && strcmp(Modifier, "hi16") == 0) || + (TF & ARMII::MO_HI16)) + O << ":upper16:"; + O << *GetGlobalValueSymbol(GV); printOffset(MO.getOffset()); @@ -360,21 +324,18 @@ void ARMAsmPrinter::printOperand(const MachineInstr *MI, int OpNum, } case MachineOperand::MO_ExternalSymbol: { bool isCallOp = Modifier && !strcmp(Modifier, "call"); - std::string Name = Mang->makeNameProper(MO.getSymbolName()); - - O << Name; + O << *GetExternalSymbolSymbol(MO.getSymbolName()); + if (isCallOp && Subtarget->isTargetELF() && TM.getRelocationModel() == Reloc::PIC_) O << "(PLT)"; 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; } } @@ -393,9 +354,11 @@ static void printSOImm(formatted_raw_ostream &O, int64_t V, bool VerboseAsm, if (Rot) { O << "#" << Imm << ", " << Rot; // Pretty printed version. - if (VerboseAsm) - O << ' ' << MAI->getCommentString() - << ' ' << (int)ARM_AM::rotr32(Imm, Rot); + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() << ' '; + O << (int)ARM_AM::rotr32(Imm, Rot); + } } else { O << "#" << Imm; } @@ -419,7 +382,7 @@ void ARMAsmPrinter::printSOImm2PartOperand(const MachineInstr *MI, int OpNum) { printSOImm(O, V1, VerboseAsm, MAI); O << "\n\torr"; printPredicateOperand(MI, 2); - O << " "; + O << "\t"; printOperand(MI, 0); O << ", "; printOperand(MI, 0); @@ -586,12 +549,7 @@ void ARMAsmPrinter::printAddrMode5Operand(const MachineInstr *MI, int Op, if (Modifier && strcmp(Modifier, "submode") == 0) { ARM_AM::AMSubMode Mode = ARM_AM::getAM5SubMode(MO2.getImm()); - if (MO1.getReg() == ARM::SP) { - bool isFLDM = (MI->getOpcode() == ARM::FLDMD || - MI->getOpcode() == ARM::FLDMS); - O << ARM_AM::getAMSubModeAltStr(Mode, isFLDM); - } else - O << ARM_AM::getAMSubModeStr(Mode); + O << ARM_AM::getAMSubModeStr(Mode); return; } else if (Modifier && strcmp(Modifier, "base") == 0) { // Used for FSTM{D|S} and LSTM{D|S} operations. @@ -615,9 +573,14 @@ void ARMAsmPrinter::printAddrMode6Operand(const MachineInstr *MI, int Op) { const MachineOperand &MO1 = MI->getOperand(Op); const MachineOperand &MO2 = MI->getOperand(Op+1); const MachineOperand &MO3 = MI->getOperand(Op+2); + const MachineOperand &MO4 = MI->getOperand(Op+3); - // FIXME: No support yet for specifying alignment. - O << "[" << getRegisterName(MO1.getReg()) << "]"; + O << "[" << getRegisterName(MO1.getReg()); + if (MO4.getImm()) { + // FIXME: Both darwin as and GNU as violate ARM docs here. + O << ", :" << MO4.getImm(); + } + O << "]"; if (ARM_AM::getAM6WBFlag(MO3.getImm())) { if (MO2.getReg() == 0) @@ -651,6 +614,10 @@ ARMAsmPrinter::printBitfieldInvMaskImmOperand(const MachineInstr *MI, int Op) { //===--------------------------------------------------------------------===// +void ARMAsmPrinter::printThumbS4ImmOperand(const MachineInstr *MI, int Op) { + O << "#" << MI->getOperand(Op).getImm() * 4; +} + void ARMAsmPrinter::printThumbITMask(const MachineInstr *MI, int Op) { // (3 - the number of trailing zeros) is the number of then / else. @@ -689,11 +656,8 @@ ARMAsmPrinter::printThumbAddrModeRI5Operand(const MachineInstr *MI, int Op, O << "[" << getRegisterName(MO1.getReg()); if (MO3.getReg()) O << ", " << getRegisterName(MO3.getReg()); - else if (unsigned ImmOffs = MO2.getImm()) { - O << ", #" << ImmOffs; - if (Scale > 1) - O << " * " << Scale; - } + else if (unsigned ImmOffs = MO2.getImm()) + O << ", #+" << ImmOffs * Scale; O << "]"; } @@ -715,7 +679,7 @@ void ARMAsmPrinter::printThumbAddrModeSPOperand(const MachineInstr *MI,int Op) { const MachineOperand &MO2 = MI->getOperand(Op+1); O << "[" << getRegisterName(MO1.getReg()); if (unsigned ImmOffs = MO2.getImm()) - O << ", #" << ImmOffs << " * 4"; + O << ", #+" << ImmOffs*4; O << "]"; } @@ -781,9 +745,9 @@ void ARMAsmPrinter::printT2AddrModeImm8s4Operand(const MachineInstr *MI, int32_t OffImm = (int32_t)MO2.getImm() / 4; // Don't print +0. if (OffImm < 0) - O << ", #-" << -OffImm << " * 4"; + O << ", #-" << -OffImm * 4; else if (OffImm > 0) - O << ", #+" << OffImm << " * 4"; + O << ", #+" << OffImm * 4; O << "]"; } @@ -836,7 +800,8 @@ void ARMAsmPrinter::printSBitModifierOperand(const MachineInstr *MI, int OpNum){ void ARMAsmPrinter::printPCLabel(const MachineInstr *MI, int OpNum) { int Id = (int)MI->getOperand(OpNum).getImm(); - O << MAI->getPrivateGlobalPrefix() << "PC" << Id; + O << MAI->getPrivateGlobalPrefix() + << "PC" << getFunctionNumber() << "_" << Id; } void ARMAsmPrinter::printRegisterList(const MachineInstr *MI, int OpNum) { @@ -858,8 +823,7 @@ void ARMAsmPrinter::printCPInstOperand(const MachineInstr *MI, int OpNum, // 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(); @@ -874,42 +838,59 @@ void ARMAsmPrinter::printCPInstOperand(const MachineInstr *MI, int OpNum, } } +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 &JT = MJTI->getJumpTables(); const std::vector &JTBBs = JT[JTI].MBBs; - bool UseSet= MAI->getSetDirective() && TM.getRelocationModel() == Reloc::PIC_; + bool UseSet= MAI->hasSetDirective() && TM.getRelocationModel() == Reloc::PIC_; SmallPtrSet 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_) { - GetMBBSymbol(MBB->getNumber())->print(O, MAI); - O << '-' << MAI->getPrivateGlobalPrefix() << "JTI" - << getFunctionNumber() << '_' << JTI << '_' << MO2.getImm(); - } else { - GetMBBSymbol(MBB->getNumber())->print(O, MAI); - } + 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'; } @@ -919,10 +900,10 @@ void ARMAsmPrinter::printJT2BlockOperand(const MachineInstr *MI, int OpNum) { 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 &JT = MJTI->getJumpTables(); const std::vector &JTBBs = JT[JTI].MBBs; @@ -938,15 +919,12 @@ void ARMAsmPrinter::printJT2BlockOperand(const MachineInstr *MI, int OpNum) { O << MAI->getData8bitsDirective(); else if (HalfWordOffset) O << MAI->getData16bitsDirective(); - if (ByteOffset || HalfWordOffset) { - O << '('; - GetMBBSymbol(MBB->getNumber())->print(O, MAI); - O << "-" << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() - << '_' << JTI << '_' << MO2.getImm() << ")/2"; - } else { - O << "\tb.w "; - GetMBBSymbol(MBB->getNumber())->print(O, MAI); - } + + if (ByteOffset || HalfWordOffset) + O << '(' << *MBB->getSymbol(OutContext) << "-" << *JTISymbol << ")/2"; + else + O << "\tb.w " << *MBB->getSymbol(OutContext); + if (i != e-1) O << '\n'; } @@ -970,6 +948,26 @@ void ARMAsmPrinter::printNoHashImmediate(const MachineInstr *MI, int OpNum) { O << MI->getOperand(OpNum).getImm(); } +void ARMAsmPrinter::printVFPf32ImmOperand(const MachineInstr *MI, int OpNum) { + const ConstantFP *FP = MI->getOperand(OpNum).getFPImm(); + O << '#' << FP->getValueAPF().convertToFloat(); + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() << ' '; + WriteAsOperand(O, FP, /*PrintType=*/false); + } +} + +void ARMAsmPrinter::printVFPf64ImmOperand(const MachineInstr *MI, int OpNum) { + const ConstantFP *FP = MI->getOperand(OpNum).getFPImm(); + O << '#' << FP->getValueAPF().convertToDouble(); + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() << ' '; + WriteAsOperand(O, FP, /*PrintType=*/false); + } +} + bool ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum, unsigned AsmVariant, const char *ExtraCode){ // Does this asm operand have a single letter operand modifier? @@ -990,6 +988,7 @@ bool ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum, printNoHashImmediate(MI, OpNum); return false; case 'P': // Print a VFP double precision register. + case 'q': // Print a NEON quad precision register. printOperand(MI, OpNum); return false; case 'Q': @@ -1026,12 +1025,7 @@ bool ARMAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, 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 { @@ -1040,12 +1034,8 @@ void ARMAsmPrinter::printMachineInstruction(const MachineInstr *MI) { EmitAlignment(2); printInstruction(MI); + O << '\n'; } - - if (VerboseAsm && !MI->getDebugLoc().isUnknown()) - EmitComments(*MI); - O << '\n'; - processDebugLoc(MI, false); } void ARMAsmPrinter::EmitStartOfAsmFile(Module &M) { @@ -1079,9 +1069,8 @@ void ARMAsmPrinter::EmitStartOfAsmFile(Module &M) { } } - // Use unified assembler syntax mode for Thumb. - if (Subtarget->isThumb()) - O << "\t.syntax unified\n"; + // Use unified assembler syntax. + O << "\t.syntax unified\n"; // Emit ARM Build Attributes if (Subtarget->isTargetELF()) { @@ -1117,143 +1106,6 @@ void ARMAsmPrinter::EmitStartOfAsmFile(Module &M) { } } -void ARMAsmPrinter::PrintGlobalVariable(const GlobalVariable* GVar) { - const TargetData *TD = TM.getTargetData(); - - if (!GVar->hasInitializer()) // External global require no code - return; - - // Check to see if this is a special global used by LLVM, if so, emit it. - - if (EmitSpecialLLVMGlobal(GVar)) { - if (Subtarget->isTargetDarwin() && - TM.getRelocationModel() == Reloc::Static) { - if (GVar->getName() == "llvm.global_ctors") - O << ".reference .constructors_used\n"; - else if (GVar->getName() == "llvm.global_dtors") - O << ".reference .destructors_used\n"; - } - return; - } - - std::string name = Mang->getMangledName(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(name, GVar->getVisibility()); - - if (Subtarget->isTargetELF()) - O << "\t.type " << name << ",%object\n"; - - const MCSection *TheSection = - getObjFileLowering().SectionForGlobal(GVar, Mang, TM); - OutStreamer.SwitchSection(TheSection); - - // FIXME: get this stuff from section kind flags. - if (C->isNullValue() && !GVar->hasSection() && !GVar->isThreadLocal() && - // Don't put things that should go in the cstring section into "comm". - !TheSection->getKind().isMergeableCString()) { - if (GVar->hasExternalLinkage()) { - if (const char *Directive = MAI->getZeroFillDirective()) { - O << "\t.globl\t" << name << "\n"; - O << Directive << "__DATA, __common, " << name << ", " - << Size << ", " << Align << "\n"; - return; - } - } - - if (GVar->hasLocalLinkage() || GVar->isWeakForLinker()) { - if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it. - - if (isDarwin) { - if (GVar->hasLocalLinkage()) { - O << MAI->getLCOMMDirective() << name << "," << Size - << ',' << Align; - } else if (GVar->hasCommonLinkage()) { - O << MAI->getCOMMDirective() << name << "," << Size - << ',' << Align; - } else { - OutStreamer.SwitchSection(TheSection); - O << "\t.globl " << name << '\n' - << MAI->getWeakDefDirective() << name << '\n'; - EmitAlignment(Align, GVar); - O << name << ":"; - if (VerboseAsm) { - O << "\t\t\t\t" << MAI->getCommentString() << ' '; - WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent()); - } - O << '\n'; - EmitGlobalConstant(C); - return; - } - } else if (MAI->getLCOMMDirective() != NULL) { - if (GVar->hasLocalLinkage()) { - O << MAI->getLCOMMDirective() << name << "," << Size; - } else { - O << MAI->getCOMMDirective() << name << "," << Size; - if (MAI->getCOMMDirectiveTakesAlignment()) - O << ',' << (MAI->getAlignmentIsInBytes() ? (1 << Align) : Align); - } - } else { - if (GVar->hasLocalLinkage()) - O << "\t.local\t" << name << "\n"; - O << MAI->getCOMMDirective() << name << "," << 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 << "\n"; - return; - } - } - - 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 " << name << "\n" - << "\t.weak_definition " << name << "\n"; - } else { - 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: - O << "\t.globl " << name << "\n"; - break; - case GlobalValue::PrivateLinkage: - case GlobalValue::InternalLinkage: - break; - default: - llvm_unreachable("Unknown linkage type!"); - } - - EmitAlignment(Align, GVar); - O << name << ":"; - if (VerboseAsm) { - O << "\t\t\t\t" << MAI->getCommentString() << " "; - WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent()); - } - O << "\n"; - if (MAI->hasDotTypeDotSizeDirective()) - O << "\t.size " << name << ", " << Size << "\n"; - - EmitGlobalConstant(C); - O << '\n'; -} - void ARMAsmPrinter::EmitEndOfAsmFile(Module &M) { if (Subtarget->isTargetDarwin()) { @@ -1273,10 +1125,8 @@ void ARMAsmPrinter::EmitEndOfAsmFile(Module &M) { OutStreamer.SwitchSection(TLOFMacho.getNonLazySymbolPointerSection()); EmitAlignment(2); for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { - Stubs[i].first->print(O, MAI); - O << ":\n\t.indirect_symbol "; - Stubs[i].second->print(O, MAI); - O << "\n\t.long\t0\n"; + O << *Stubs[i].first << ":\n\t.indirect_symbol "; + O << *Stubs[i].second << "\n\t.long\t0\n"; } } @@ -1284,12 +1134,8 @@ void ARMAsmPrinter::EmitEndOfAsmFile(Module &M) { if (!Stubs.empty()) { OutStreamer.SwitchSection(getObjFileLowering().getDataSection()); EmitAlignment(2); - for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { - Stubs[i].first->print(O, MAI); - O << ":\n\t.long "; - Stubs[i].second->print(O, MAI); - O << "\n"; - } + for (unsigned i = 0, e = Stubs.size(); i != e; ++i) + O << *Stubs[i].first << ":\n\t.long " << *Stubs[i].second << "\n"; } // Funny Darwin hack: This flag tells the linker that no global symbols @@ -1297,37 +1143,18 @@ void ARMAsmPrinter::EmitEndOfAsmFile(Module &M) { // 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); } } -// Force static initialization. -extern "C" void LLVMInitializeARMAsmPrinter() { - RegisterAsmPrinter X(TheARMTarget); - RegisterAsmPrinter Y(TheThumbTarget); -} - - //===----------------------------------------------------------------------===// void ARMAsmPrinter::printInstructionThroughMCStreamer(const MachineInstr *MI) { - ARMMCInstLower MCInstLowering(OutContext, *Mang, getFunctionNumber(), *MAI); + ARMMCInstLower MCInstLowering(OutContext, *Mang, *this); switch (MI->getOpcode()) { + 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: - return; - case TargetInstrInfo::INLINEASM: - O << '\t'; - 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: @@ -1336,10 +1163,11 @@ void ARMAsmPrinter::printInstructionThroughMCStreamer(const MachineInstr *MI) { // Emit the label. // FIXME: MOVE TO SHARED PLACE. - SmallString<60> Name; unsigned Id = (unsigned)MI->getOperand(2).getImm(); - raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() << "PC" << Id; - OutStreamer.EmitLabel(OutContext.GetOrCreateSymbol(Name.str())); + const char *Prefix = MAI->getPrivateGlobalPrefix(); + MCSymbol *Label =OutContext.GetOrCreateSymbol(Twine(Prefix) + + "PC" + Twine(getFunctionNumber()) + "_" + Twine(Id)); + OutStreamer.EmitLabel(Label); // Form and emit tha dd. @@ -1360,9 +1188,7 @@ void ARMAsmPrinter::printInstructionThroughMCStreamer(const MachineInstr *MI) { unsigned CPIdx = (unsigned)MI->getOperand(1).getIndex(); EmitAlignment(2); - - O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() - << '_' << LabelId << ":\n"; + OutStreamer.EmitLabel(GetCPISymbol(LabelId)); const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPIdx]; if (MCPE.isMachineConstantPoolEntry()) @@ -1372,6 +1198,79 @@ void ARMAsmPrinter::printInstructionThroughMCStreamer(const MachineInstr *MI) { return; } + case ARM::MOVi2pieces: { // FIXME: Remove asmstring from td file. + // This is a hack that lowers as a two instruction sequence. + unsigned DstReg = MI->getOperand(0).getReg(); + unsigned ImmVal = (unsigned)MI->getOperand(1).getImm(); + + unsigned SOImmValV1 = ARM_AM::getSOImmTwoPartFirst(ImmVal); + unsigned SOImmValV2 = ARM_AM::getSOImmTwoPartSecond(ImmVal); + + { + MCInst TmpInst; + TmpInst.setOpcode(ARM::MOVi); + TmpInst.addOperand(MCOperand::CreateReg(DstReg)); + TmpInst.addOperand(MCOperand::CreateImm(SOImmValV1)); + + // Predicate. + TmpInst.addOperand(MCOperand::CreateImm(MI->getOperand(2).getImm())); + TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(3).getReg())); + + TmpInst.addOperand(MCOperand::CreateReg(0)); // cc_out + printMCInst(&TmpInst); + O << '\n'; + } + + { + MCInst TmpInst; + TmpInst.setOpcode(ARM::ORRri); + TmpInst.addOperand(MCOperand::CreateReg(DstReg)); // dstreg + TmpInst.addOperand(MCOperand::CreateReg(DstReg)); // inreg + TmpInst.addOperand(MCOperand::CreateImm(SOImmValV2)); // so_imm + // Predicate. + TmpInst.addOperand(MCOperand::CreateImm(MI->getOperand(2).getImm())); + TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(3).getReg())); + + TmpInst.addOperand(MCOperand::CreateReg(0)); // cc_out + printMCInst(&TmpInst); + } + return; + } + case ARM::MOVi32imm: { // FIXME: Remove asmstring from td file. + // This is a hack that lowers as a two instruction sequence. + unsigned DstReg = MI->getOperand(0).getReg(); + unsigned ImmVal = (unsigned)MI->getOperand(1).getImm(); + + { + MCInst TmpInst; + TmpInst.setOpcode(ARM::MOVi16); + TmpInst.addOperand(MCOperand::CreateReg(DstReg)); // dstreg + TmpInst.addOperand(MCOperand::CreateImm(ImmVal & 65535)); // lower16(imm) + + // Predicate. + TmpInst.addOperand(MCOperand::CreateImm(MI->getOperand(2).getImm())); + TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(3).getReg())); + + printMCInst(&TmpInst); + O << '\n'; + } + + { + MCInst TmpInst; + TmpInst.setOpcode(ARM::MOVTi16); + TmpInst.addOperand(MCOperand::CreateReg(DstReg)); // dstreg + TmpInst.addOperand(MCOperand::CreateReg(DstReg)); // srcreg + TmpInst.addOperand(MCOperand::CreateImm(ImmVal >> 16)); // upper16(imm) + + // Predicate. + TmpInst.addOperand(MCOperand::CreateImm(MI->getOperand(2).getImm())); + TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(3).getReg())); + + printMCInst(&TmpInst); + } + + return; + } } MCInst TmpInst; @@ -1379,3 +1278,26 @@ void ARMAsmPrinter::printInstructionThroughMCStreamer(const MachineInstr *MI) { printMCInst(&TmpInst); } + +//===----------------------------------------------------------------------===// +// Target Registry Stuff +//===----------------------------------------------------------------------===// + +static MCInstPrinter *createARMMCInstPrinter(const Target &T, + unsigned SyntaxVariant, + const MCAsmInfo &MAI, + raw_ostream &O) { + if (SyntaxVariant == 0) + return new ARMInstPrinter(O, MAI, false); + return 0; +} + +// Force static initialization. +extern "C" void LLVMInitializeARMAsmPrinter() { + RegisterAsmPrinter X(TheARMTarget); + RegisterAsmPrinter Y(TheThumbTarget); + + TargetRegistry::RegisterMCInstPrinter(TheARMTarget, createARMMCInstPrinter); + TargetRegistry::RegisterMCInstPrinter(TheThumbTarget, createARMMCInstPrinter); +} +