diff options
Diffstat (limited to 'lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp')
-rw-r--r-- | lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp | 691 |
1 files changed, 377 insertions, 314 deletions
diff --git a/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp b/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp index 434a19a..546731b 100644 --- a/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp +++ b/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp @@ -1,5 +1,3 @@ -//===-- ARMAsmPrinter.cpp - ARM LLVM assembly writer ----------------------===// -// // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source @@ -21,23 +19,30 @@ #include "ARMMachineFunctionInfo.h" #include "llvm/Constants.h" #include "llvm/Module.h" -#include "llvm/MDNode.h" +#include "llvm/Assembly/Writer.h" #include "llvm/CodeGen/AsmPrinter.h" #include "llvm/CodeGen/DwarfWriter.h" #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineJumpTableInfo.h" -#include "llvm/Target/TargetAsmInfo.h" +#include "llvm/MC/MCSectionMachO.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/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/Compiler.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Mangler.h" #include "llvm/Support/MathExtras.h" -#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/FormattedStream.h" #include <cctype> using namespace llvm; @@ -45,7 +50,6 @@ STATISTIC(EmittedInsts, "Number of machine instrs printed"); namespace { class VISIBILITY_HIDDEN ARMAsmPrinter : public AsmPrinter { - DwarfWriter *DW; /// Subtarget - Keep a pointer to the ARMSubtarget around so that we can /// make the right decision when printing asm code for different targets. @@ -68,22 +72,18 @@ namespace { /// GVNonLazyPtrs - Keeps the set of GlobalValues that require /// non-lazy-pointers for indirect access. - StringSet<> GVNonLazyPtrs; + StringMap<std::string> GVNonLazyPtrs; /// HiddenGVNonLazyPtrs - Keeps the set of GlobalValues with hidden /// visibility that require non-lazy-pointers for indirect access. - StringSet<> HiddenGVNonLazyPtrs; - - /// FnStubs - Keeps the set of external function GlobalAddresses that the - /// asm printer should generate stubs for. - StringSet<> FnStubs; + StringMap<std::string> HiddenGVNonLazyPtrs; /// True if asm printer is printing a series of CONSTPOOL_ENTRY. bool InCPMode; public: - explicit ARMAsmPrinter(raw_ostream &O, TargetMachine &TM, - const TargetAsmInfo *T, bool V) - : AsmPrinter(O, TM, T, V), DW(0), AFI(NULL), MCP(NULL), + explicit ARMAsmPrinter(formatted_raw_ostream &O, TargetMachine &TM, + const MCAsmInfo *T, bool V) + : AsmPrinter(O, TM, T, V), AFI(NULL), MCP(NULL), InCPMode(false) { Subtarget = &TM.getSubtarget<ARMSubtarget>(); } @@ -110,6 +110,7 @@ namespace { const char *Modifier = 0); void printBitfieldInvMaskImmOperand (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, unsigned Scale); @@ -118,10 +119,10 @@ namespace { void printThumbAddrModeS4Operand(const MachineInstr *MI, int OpNum); void printThumbAddrModeSPOperand(const MachineInstr *MI, int OpNum); - void printT2SOImmOperand(const MachineInstr *MI, int OpNum); void printT2SOOperand(const MachineInstr *MI, int OpNum); void printT2AddrModeImm12Operand(const MachineInstr *MI, int OpNum); void printT2AddrModeImm8Operand(const MachineInstr *MI, int OpNum); + void printT2AddrModeImm8s4Operand(const MachineInstr *MI, int OpNum); void printT2AddrModeImm8OffsetOperand(const MachineInstr *MI, int OpNum); void printT2AddrModeSoRegOperand(const MachineInstr *MI, int OpNum); @@ -132,6 +133,9 @@ namespace { void printCPInstOperand(const MachineInstr *MI, int OpNum, const char *Modifier); void printJTBlockOperand(const MachineInstr *MI, int OpNum); + void printJT2BlockOperand(const MachineInstr *MI, int OpNum); + void printTBAddrMode(const MachineInstr *MI, int OpNum); + void printNoHashImmediate(const MachineInstr *MI, int OpNum); virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNum, unsigned AsmVariant, const char *ExtraCode); @@ -139,12 +143,14 @@ namespace { unsigned AsmVariant, const char *ExtraCode); - void printModuleLevelGV(const GlobalVariable* GVar); - bool printInstruction(const MachineInstr *MI); // autogenerated. + void PrintGlobalVariable(const GlobalVariable* GVar); + void printInstruction(const MachineInstr *MI); // autogenerated. + static const char *getRegisterName(unsigned RegNo); + void printMachineInstruction(const MachineInstr *MI); bool runOnMachineFunction(MachineFunction &F); - bool doInitialization(Module &M); bool doFinalization(Module &M); + void EmitStartOfAsmFile(Module &M); /// EmitMachineConstantPoolValue - Print a machine constantpool value to /// the .s file. @@ -153,24 +159,35 @@ namespace { ARMConstantPoolValue *ACPV = static_cast<ARMConstantPoolValue*>(MCPV); GlobalValue *GV = ACPV->getGV(); - std::string Name = GV ? Mang->getValueName(GV) : TAI->getGlobalPrefix(); - if (!GV) - Name += ACPV->getSymbol(); - if (ACPV->isNonLazyPointer()) { - if (GV->hasHiddenVisibility()) - HiddenGVNonLazyPtrs.insert(Name); - else - GVNonLazyPtrs.insert(Name); - printSuffixedName(Name, "$non_lazy_ptr"); - } else if (ACPV->isStub()) { - FnStubs.insert(Name); - printSuffixedName(Name, "$stub"); + std::string Name; + + if (ACPV->isLSDA()) { + SmallString<16> LSDAName; + raw_svector_ostream(LSDAName) << MAI->getPrivateGlobalPrefix() << + "_LSDA_" << getFunctionNumber(); + Name = LSDAName.str(); + } else if (GV) { + bool isIndirect = Subtarget->isTargetDarwin() && + Subtarget->GVIsIndirectSymbol(GV, TM.getRelocationModel()); + if (!isIndirect) + Name = Mang->getMangledName(GV); + else { + // FIXME: Remove this when Darwin transition to @GOT like syntax. + std::string SymName = Mang->getMangledName(GV); + Name = Mang->getMangledName(GV, "$non_lazy_ptr", true); + if (GV->hasHiddenVisibility()) + HiddenGVNonLazyPtrs[SymName] = Name; + else + GVNonLazyPtrs[SymName] = Name; + } } else - O << Name; + Name = Mang->makeNameProper(ACPV->getSymbol()); + O << Name; + if (ACPV->hasModifier()) O << "(" << ACPV->getModifier() << ")"; if (ACPV->getPCAdjustment() != 0) { - O << "-(" << TAI->getPrivateGlobalPrefix() << "PC" - << utostr(ACPV->getLabelId()) + O << "-(" << MAI->getPrivateGlobalPrefix() << "PC" + << ACPV->getLabelId() << "+" << (unsigned)ACPV->getPCAdjustment(); if (ACPV->mustAddCurrentAddress()) O << "-."; @@ -178,7 +195,7 @@ namespace { } O << "\n"; } - + void getAnalysisUsage(AnalysisUsage &AU) const { AsmPrinter::getAnalysisUsage(AU); AU.setPreservesAll(); @@ -205,38 +222,39 @@ bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) { // NOTE: we don't print out constant pools here, they are handled as // instructions. - O << "\n"; + O << '\n'; + // Print out labels for the function. const Function *F = MF.getFunction(); + OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(F, Mang, TM)); + switch (F->getLinkage()) { - default: assert(0 && "Unknown linkage type!"); + default: llvm_unreachable("Unknown linkage type!"); case Function::PrivateLinkage: case Function::InternalLinkage: - SwitchToTextSection("\t.text", F); break; case Function::ExternalLinkage: - SwitchToTextSection("\t.text", F); 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()) { - SwitchToTextSection( - ".section __TEXT,__textcoal_nt,coalesced,pure_instructions", F); O << "\t.globl\t" << CurrentFnName << "\n"; O << "\t.weak_definition\t" << CurrentFnName << "\n"; } else { - O << TAI->getWeakRefDirective() << CurrentFnName << "\n"; + O << MAI->getWeakRefDirective() << CurrentFnName << "\n"; } break; } printVisibility(CurrentFnName, F->getVisibility()); + unsigned FnAlign = 1 << MF.getAlignment(); // MF alignment is log2. if (AFI->isThumbFunction()) { - EmitAlignment(MF.getAlignment(), F, AFI->getAlign()); + EmitAlignment(FnAlign, F, AFI->getAlign()); O << "\t.code\t16\n"; O << "\t.thumb_func"; if (Subtarget->isTargetDarwin()) @@ -244,7 +262,7 @@ bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) { O << "\n"; InCPMode = false; } else { - EmitAlignment(MF.getAlignment(), F); + EmitAlignment(FnAlign, F); } O << CurrentFnName << ":\n"; @@ -266,8 +284,7 @@ bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) { I != E; ++I) { // Print a label for the basic block. if (I != MF.begin()) { - printBasicBlockLabel(I, true, true, VerboseAsm); - O << '\n'; + EmitBasicBlockStart(I); } for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end(); II != E; ++II) { @@ -276,14 +293,12 @@ bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) { } } - if (TAI->hasDotTypeDotSizeDirective()) + if (MAI->hasDotTypeDotSizeDirective()) O << "\t.size " << CurrentFnName << ", .-" << CurrentFnName << "\n"; // Emit post-function debug information. DW->EndFunction(&MF); - O.flush(); - return false; } @@ -298,37 +313,39 @@ void ARMAsmPrinter::printOperand(const MachineInstr *MI, int OpNum, unsigned DRegLo = TRI->getSubReg(Reg, 5); // arm_dsubreg_0 unsigned DRegHi = TRI->getSubReg(Reg, 6); // arm_dsubreg_1 O << '{' - << TRI->getAsmName(DRegLo) << "-" << TRI->getAsmName(DRegHi) + << getRegisterName(DRegLo) << ',' << getRegisterName(DRegHi) << '}'; + } else if (Modifier && strcmp(Modifier, "lane") == 0) { + unsigned RegNum = ARMRegisterInfo::getRegisterNumbering(Reg); + unsigned DReg = TRI->getMatchingSuperReg(Reg, RegNum & 1 ? 2 : 1, + &ARM::DPR_VFP2RegClass); + O << getRegisterName(DReg) << '[' << (RegNum & 1) << ']'; } else { - O << TRI->getAsmName(Reg); + O << getRegisterName(Reg); } } else - assert(0 && "not implemented"); + llvm_unreachable("not implemented"); break; } case MachineOperand::MO_Immediate: { - if (!Modifier || strcmp(Modifier, "no_hash") != 0) - O << "#"; - - O << MO.getImm(); + int64_t Imm = MO.getImm(); + O << '#'; + if (Modifier) { + if (strcmp(Modifier, "lo16") == 0) + O << ":lower16:"; + else if (strcmp(Modifier, "hi16") == 0) + O << ":upper16:"; + } + O << Imm; break; } case MachineOperand::MO_MachineBasicBlock: - printBasicBlockLabel(MO.getMBB()); + GetMBBSymbol(MO.getMBB()->getNumber())->print(O, MAI); return; case MachineOperand::MO_GlobalAddress: { bool isCallOp = Modifier && !strcmp(Modifier, "call"); GlobalValue *GV = MO.getGlobal(); - std::string Name = Mang->getValueName(GV); - bool isExt = (GV->isDeclaration() || GV->hasWeakLinkage() || - GV->hasLinkOnceLinkage()); - if (isExt && isCallOp && Subtarget->isTargetDarwin() && - TM.getRelocationModel() != Reloc::Static) { - printSuffixedName(Name, "$stub"); - FnStubs.insert(Name); - } else - O << Name; + O << Mang->getMangledName(GV); printOffset(MO.getOffset()); @@ -339,25 +356,20 @@ void ARMAsmPrinter::printOperand(const MachineInstr *MI, int OpNum, } case MachineOperand::MO_ExternalSymbol: { bool isCallOp = Modifier && !strcmp(Modifier, "call"); - std::string Name(TAI->getGlobalPrefix()); - Name += MO.getSymbolName(); - if (isCallOp && Subtarget->isTargetDarwin() && - TM.getRelocationModel() != Reloc::Static) { - printSuffixedName(Name, "$stub"); - FnStubs.insert(Name); - } else - O << Name; + std::string Name = Mang->makeNameProper(MO.getSymbolName()); + + O << Name; if (isCallOp && Subtarget->isTargetELF() && TM.getRelocationModel() == Reloc::PIC_) O << "(PLT)"; break; } case MachineOperand::MO_ConstantPoolIndex: - O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() + O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_' << MO.getIndex(); break; case MachineOperand::MO_JumpTableIndex: - O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() + O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() << '_' << MO.getIndex(); break; default: @@ -365,9 +377,12 @@ void ARMAsmPrinter::printOperand(const MachineInstr *MI, int OpNum, } } -static void printSOImm(raw_ostream &O, int64_t V, bool VerboseAsm, - const TargetAsmInfo *TAI) { - assert(V < (1 << 12) && "Not a valid so_imm value!"); +static void printSOImm(formatted_raw_ostream &O, int64_t V, bool VerboseAsm, + const MCAsmInfo *MAI) { + // Break it up into two parts that make up a shifter immediate. + V = ARM_AM::getSOImmVal(V); + assert(V != -1 && "Not a valid so_imm value!"); + unsigned Imm = ARM_AM::getSOImmValImm(V); unsigned Rot = ARM_AM::getSOImmValRot(V); @@ -377,7 +392,7 @@ static void printSOImm(raw_ostream &O, int64_t V, bool VerboseAsm, O << "#" << Imm << ", " << Rot; // Pretty printed version. if (VerboseAsm) - O << ' ' << TAI->getCommentString() + O << ' ' << MAI->getCommentString() << ' ' << (int)ARM_AM::rotr32(Imm, Rot); } else { O << "#" << Imm; @@ -389,7 +404,7 @@ static void printSOImm(raw_ostream &O, int64_t V, bool VerboseAsm, void ARMAsmPrinter::printSOImmOperand(const MachineInstr *MI, int OpNum) { const MachineOperand &MO = MI->getOperand(OpNum); assert(MO.isImm() && "Not a valid so_imm value!"); - printSOImm(O, MO.getImm(), VerboseAsm, TAI); + printSOImm(O, MO.getImm(), VerboseAsm, MAI); } /// printSOImm2PartOperand - SOImm is broken into two pieces using a 'mov' @@ -399,15 +414,15 @@ void ARMAsmPrinter::printSOImm2PartOperand(const MachineInstr *MI, int OpNum) { assert(MO.isImm() && "Not a valid so_imm value!"); unsigned V1 = ARM_AM::getSOImmTwoPartFirst(MO.getImm()); unsigned V2 = ARM_AM::getSOImmTwoPartSecond(MO.getImm()); - printSOImm(O, ARM_AM::getSOImmVal(V1), VerboseAsm, TAI); + printSOImm(O, V1, VerboseAsm, MAI); O << "\n\torr"; printPredicateOperand(MI, 2); O << " "; - printOperand(MI, 0); + printOperand(MI, 0); O << ", "; - printOperand(MI, 0); + printOperand(MI, 0); O << ", "; - printSOImm(O, ARM_AM::getSOImmVal(V2), VerboseAsm, TAI); + printSOImm(O, V2, VerboseAsm, MAI); } // so_reg is a 4-operand unit corresponding to register forms of the A5.1 @@ -420,8 +435,7 @@ void ARMAsmPrinter::printSORegOperand(const MachineInstr *MI, int Op) { const MachineOperand &MO2 = MI->getOperand(Op+1); const MachineOperand &MO3 = MI->getOperand(Op+2); - assert(TargetRegisterInfo::isPhysicalRegister(MO1.getReg())); - O << TM.getRegisterInfo()->get(MO1.getReg()).AsmName; + O << getRegisterName(MO1.getReg()); // Print the shift opc. O << ", " @@ -429,8 +443,7 @@ void ARMAsmPrinter::printSORegOperand(const MachineInstr *MI, int Op) { << " "; if (MO2.getReg()) { - assert(TargetRegisterInfo::isPhysicalRegister(MO2.getReg())); - O << TM.getRegisterInfo()->get(MO2.getReg()).AsmName; + O << getRegisterName(MO2.getReg()); assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0); } else { O << "#" << ARM_AM::getSORegOffset(MO3.getImm()); @@ -447,7 +460,7 @@ void ARMAsmPrinter::printAddrMode2Operand(const MachineInstr *MI, int Op) { return; } - O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName; + O << "[" << getRegisterName(MO1.getReg()); if (!MO2.getReg()) { if (ARM_AM::getAM2Offset(MO3.getImm())) // Don't print +0. @@ -460,8 +473,8 @@ void ARMAsmPrinter::printAddrMode2Operand(const MachineInstr *MI, int Op) { O << ", " << (char)ARM_AM::getAM2Op(MO3.getImm()) - << TM.getRegisterInfo()->get(MO2.getReg()).AsmName; - + << getRegisterName(MO2.getReg()); + if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm())) O << ", " << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO3.getImm())) @@ -483,8 +496,8 @@ void ARMAsmPrinter::printAddrMode2OffsetOperand(const MachineInstr *MI, int Op){ } O << (char)ARM_AM::getAM2Op(MO2.getImm()) - << TM.getRegisterInfo()->get(MO1.getReg()).AsmName; - + << getRegisterName(MO1.getReg()); + if (unsigned ShImm = ARM_AM::getAM2Offset(MO2.getImm())) O << ", " << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO2.getImm())) @@ -495,18 +508,18 @@ void ARMAsmPrinter::printAddrMode3Operand(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); - + assert(TargetRegisterInfo::isPhysicalRegister(MO1.getReg())); - O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName; + O << "[" << getRegisterName(MO1.getReg()); if (MO2.getReg()) { O << ", " << (char)ARM_AM::getAM3Op(MO3.getImm()) - << TM.getRegisterInfo()->get(MO2.getReg()).AsmName + << getRegisterName(MO2.getReg()) << "]"; return; } - + if (unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm())) O << ", #" << (char)ARM_AM::getAM3Op(MO3.getImm()) @@ -520,7 +533,7 @@ void ARMAsmPrinter::printAddrMode3OffsetOperand(const MachineInstr *MI, int Op){ if (MO1.getReg()) { O << (char)ARM_AM::getAM3Op(MO2.getImm()) - << TM.getRegisterInfo()->get(MO1.getReg()).AsmName; + << getRegisterName(MO1.getReg()); return; } @@ -530,7 +543,7 @@ void ARMAsmPrinter::printAddrMode3OffsetOperand(const MachineInstr *MI, int Op){ << (char)ARM_AM::getAM3Op(MO2.getImm()) << ImmOffs; } - + void ARMAsmPrinter::printAddrMode4Operand(const MachineInstr *MI, int Op, const char *Modifier) { const MachineOperand &MO1 = MI->getOperand(Op); @@ -538,11 +551,18 @@ void ARMAsmPrinter::printAddrMode4Operand(const MachineInstr *MI, int Op, ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MO2.getImm()); if (Modifier && strcmp(Modifier, "submode") == 0) { if (MO1.getReg() == ARM::SP) { + // FIXME bool isLDM = (MI->getOpcode() == ARM::LDM || - MI->getOpcode() == ARM::LDM_RET); + MI->getOpcode() == ARM::LDM_RET || + MI->getOpcode() == ARM::t2LDM || + MI->getOpcode() == ARM::t2LDM_RET); O << ARM_AM::getAMSubModeAltStr(Mode, isLDM); } else O << ARM_AM::getAMSubModeStr(Mode); + } else if (Modifier && strcmp(Modifier, "wide") == 0) { + ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MO2.getImm()); + if (Mode == ARM_AM::ia) + O << ".w"; } else { printOperand(MI, Op); if (ARM_AM::getAM4WBFlag(MO2.getImm())) @@ -559,7 +579,7 @@ void ARMAsmPrinter::printAddrMode5Operand(const MachineInstr *MI, int Op, printOperand(MI, Op); return; } - + assert(TargetRegisterInfo::isPhysicalRegister(MO1.getReg())); if (Modifier && strcmp(Modifier, "submode") == 0) { @@ -573,14 +593,14 @@ void ARMAsmPrinter::printAddrMode5Operand(const MachineInstr *MI, int Op, return; } else if (Modifier && strcmp(Modifier, "base") == 0) { // Used for FSTM{D|S} and LSTM{D|S} operations. - O << TM.getRegisterInfo()->get(MO1.getReg()).AsmName; + O << getRegisterName(MO1.getReg()); if (ARM_AM::getAM5WBFlag(MO2.getImm())) O << "!"; return; } - - O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName; - + + O << "[" << getRegisterName(MO1.getReg()); + if (unsigned ImmOffs = ARM_AM::getAM5Offset(MO2.getImm())) { O << ", #" << (char)ARM_AM::getAM5Op(MO2.getImm()) @@ -595,13 +615,13 @@ void ARMAsmPrinter::printAddrMode6Operand(const MachineInstr *MI, int Op) { const MachineOperand &MO3 = MI->getOperand(Op+2); // FIXME: No support yet for specifying alignment. - O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName << "]"; + O << "[" << getRegisterName(MO1.getReg()) << "]"; if (ARM_AM::getAM6WBFlag(MO3.getImm())) { if (MO2.getReg() == 0) O << "!"; else - O << ", " << TM.getRegisterInfo()->get(MO2.getReg()).AsmName; + O << ", " << getRegisterName(MO2.getReg()); } } @@ -614,7 +634,7 @@ void ARMAsmPrinter::printAddrModePCOperand(const MachineInstr *MI, int Op, const MachineOperand &MO1 = MI->getOperand(Op); assert(TargetRegisterInfo::isPhysicalRegister(MO1.getReg())); - O << "[pc, +" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName << "]"; + O << "[pc, +" << getRegisterName(MO1.getReg()) << "]"; } void @@ -630,11 +650,26 @@ ARMAsmPrinter::printBitfieldInvMaskImmOperand(const MachineInstr *MI, int Op) { //===--------------------------------------------------------------------===// void +ARMAsmPrinter::printThumbITMask(const MachineInstr *MI, int Op) { + // (3 - the number of trailing zeros) is the number of then / else. + unsigned Mask = MI->getOperand(Op).getImm(); + unsigned NumTZ = CountTrailingZeros_32(Mask); + assert(NumTZ <= 3 && "Invalid IT mask!"); + for (unsigned Pos = 3, e = NumTZ; Pos > e; --Pos) { + bool T = (Mask & (1 << Pos)) == 0; + if (T) + O << 't'; + else + O << 'e'; + } +} + +void ARMAsmPrinter::printThumbAddrModeRROperand(const MachineInstr *MI, int Op) { const MachineOperand &MO1 = MI->getOperand(Op); const MachineOperand &MO2 = MI->getOperand(Op+1); - O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName; - O << ", " << TM.getRegisterInfo()->get(MO2.getReg()).AsmName << "]"; + O << "[" << getRegisterName(MO1.getReg()); + O << ", " << getRegisterName(MO2.getReg()) << "]"; } void @@ -649,9 +684,9 @@ ARMAsmPrinter::printThumbAddrModeRI5Operand(const MachineInstr *MI, int Op, return; } - O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName; + O << "[" << getRegisterName(MO1.getReg()); if (MO3.getReg()) - O << ", " << TM.getRegisterInfo()->get(MO3.getReg()).AsmName; + O << ", " << getRegisterName(MO3.getReg()); else if (unsigned ImmOffs = MO2.getImm()) { O << ", #" << ImmOffs; if (Scale > 1) @@ -676,7 +711,7 @@ ARMAsmPrinter::printThumbAddrModeS4Operand(const MachineInstr *MI, int Op) { void ARMAsmPrinter::printThumbAddrModeSPOperand(const MachineInstr *MI,int Op) { const MachineOperand &MO1 = MI->getOperand(Op); const MachineOperand &MO2 = MI->getOperand(Op+1); - O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName; + O << "[" << getRegisterName(MO1.getReg()); if (unsigned ImmOffs = MO2.getImm()) O << ", #" << ImmOffs << " * 4"; O << "]"; @@ -684,20 +719,6 @@ void ARMAsmPrinter::printThumbAddrModeSPOperand(const MachineInstr *MI,int Op) { //===--------------------------------------------------------------------===// -/// printT2SOImmOperand - T2SOImm is: -/// 1. a 4-bit splat control value and 8 bit immediate value -/// 2. a 5-bit rotate amount and a non-zero 8-bit immediate value -/// represented by a normalizedin 7-bit value (msb is always 1) -void ARMAsmPrinter::printT2SOImmOperand(const MachineInstr *MI, int OpNum) { - const MachineOperand &MO = MI->getOperand(OpNum); - assert(MO.isImm() && "Not a valid so_imm value!"); - - unsigned Imm = ARM_AM::getT2SOImmValDecode(MO.getImm()); - // Always print the immediate directly, as the "rotate" form - // is deprecated in some contexts. - O << "#" << Imm; -} - // Constant shifts t2_so_reg is a 2-operand unit corresponding to the Thumb2 // register with shift forms. // REG 0 0 - e.g. R5 @@ -708,7 +729,7 @@ void ARMAsmPrinter::printT2SOOperand(const MachineInstr *MI, int OpNum) { unsigned Reg = MO1.getReg(); assert(TargetRegisterInfo::isPhysicalRegister(Reg)); - O << TM.getRegisterInfo()->getAsmName(Reg); + O << getRegisterName(Reg); // Print the shift opc. O << ", " @@ -724,7 +745,7 @@ void ARMAsmPrinter::printT2AddrModeImm12Operand(const MachineInstr *MI, const MachineOperand &MO1 = MI->getOperand(OpNum); const MachineOperand &MO2 = MI->getOperand(OpNum+1); - O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName; + O << "[" << getRegisterName(MO1.getReg()); unsigned OffImm = MO2.getImm(); if (OffImm) // Don't print +0. @@ -737,7 +758,7 @@ void ARMAsmPrinter::printT2AddrModeImm8Operand(const MachineInstr *MI, const MachineOperand &MO1 = MI->getOperand(OpNum); const MachineOperand &MO2 = MI->getOperand(OpNum+1); - O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName; + O << "[" << getRegisterName(MO1.getReg()); int32_t OffImm = (int32_t)MO2.getImm(); // Don't print +0. @@ -748,6 +769,22 @@ void ARMAsmPrinter::printT2AddrModeImm8Operand(const MachineInstr *MI, O << "]"; } +void ARMAsmPrinter::printT2AddrModeImm8s4Operand(const MachineInstr *MI, + int OpNum) { + const MachineOperand &MO1 = MI->getOperand(OpNum); + const MachineOperand &MO2 = MI->getOperand(OpNum+1); + + O << "[" << getRegisterName(MO1.getReg()); + + int32_t OffImm = (int32_t)MO2.getImm() / 4; + // Don't print +0. + if (OffImm < 0) + O << ", #-" << -OffImm << " * 4"; + else if (OffImm > 0) + O << ", #+" << OffImm << " * 4"; + O << "]"; +} + void ARMAsmPrinter::printT2AddrModeImm8OffsetOperand(const MachineInstr *MI, int OpNum) { const MachineOperand &MO1 = MI->getOperand(OpNum); @@ -765,17 +802,15 @@ void ARMAsmPrinter::printT2AddrModeSoRegOperand(const MachineInstr *MI, const MachineOperand &MO2 = MI->getOperand(OpNum+1); const MachineOperand &MO3 = MI->getOperand(OpNum+2); - O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName; + O << "[" << getRegisterName(MO1.getReg()); - if (MO2.getReg()) { - O << ", +" - << TM.getRegisterInfo()->get(MO2.getReg()).AsmName; + assert(MO2.getReg() && "Invalid so_reg load / store address!"); + O << ", " << getRegisterName(MO2.getReg()); - unsigned ShAmt = MO3.getImm(); - if (ShAmt) { - assert(ShAmt <= 3 && "Not a valid Thumb2 addressing mode!"); - O << ", lsl #" << ShAmt; - } + unsigned ShAmt = MO3.getImm(); + if (ShAmt) { + assert(ShAmt <= 3 && "Not a valid Thumb2 addressing mode!"); + O << ", lsl #" << ShAmt; } O << "]"; } @@ -799,14 +834,17 @@ void ARMAsmPrinter::printSBitModifierOperand(const MachineInstr *MI, int OpNum){ void ARMAsmPrinter::printPCLabel(const MachineInstr *MI, int OpNum) { int Id = (int)MI->getOperand(OpNum).getImm(); - O << TAI->getPrivateGlobalPrefix() << "PC" << Id; + O << MAI->getPrivateGlobalPrefix() << "PC" << Id; } void ARMAsmPrinter::printRegisterList(const MachineInstr *MI, int OpNum) { O << "{"; - for (unsigned i = OpNum, e = MI->getNumOperands(); i != e; ++i) { + // Always skip the first operand, it's the optional (and implicit writeback). + for (unsigned i = OpNum+1, e = MI->getNumOperands(); i != e; ++i) { + if (MI->getOperand(i).isImplicit()) + continue; + if ((int)i != OpNum+1) O << ", "; printOperand(MI, i); - if (i != e-1) O << ", "; } O << "}"; } @@ -818,14 +856,14 @@ void ARMAsmPrinter::printCPInstOperand(const MachineInstr *MI, int OpNum, // data itself. if (!strcmp(Modifier, "label")) { unsigned ID = MI->getOperand(OpNum).getImm(); - O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() + O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_' << ID << ":\n"; } else { assert(!strcmp(Modifier, "cpentry") && "Unknown modifier for CPE"); unsigned CPI = MI->getOperand(OpNum).getIndex(); const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPI]; - + if (MCPE.isMachineConstantPoolEntry()) { EmitMachineConstantPoolValue(MCPE.Val.MachineCPVal); } else { @@ -835,57 +873,119 @@ void ARMAsmPrinter::printCPInstOperand(const MachineInstr *MI, int OpNum, } 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 << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() + O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() << '_' << JTI << '_' << MO2.getImm() << ":\n"; - const char *JTEntryDirective = TAI->getJumpTableDirective(); - if (!JTEntryDirective) - JTEntryDirective = TAI->getData32bitsDirective(); + 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= TAI->getSetDirective() && TM.getRelocationModel() == Reloc::PIC_; - std::set<MachineBasicBlock*> JTSets; + bool UseSet= MAI->getSetDirective() && TM.getRelocationModel() == Reloc::PIC_; + SmallPtrSet<MachineBasicBlock*, 8> JTSets; for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) { MachineBasicBlock *MBB = JTBBs[i]; - if (UseSet && JTSets.insert(MBB).second) + bool isNew = JTSets.insert(MBB); + + if (UseSet && isNew) printPICJumpTableSetLabel(JTI, MO2.getImm(), MBB); O << JTEntryDirective << ' '; if (UseSet) - O << TAI->getPrivateGlobalPrefix() << getFunctionNumber() + O << MAI->getPrivateGlobalPrefix() << getFunctionNumber() << '_' << JTI << '_' << MO2.getImm() << "_set_" << MBB->getNumber(); else if (TM.getRelocationModel() == Reloc::PIC_) { - printBasicBlockLabel(MBB, false, false, false); - // If the arch uses custom Jump Table directives, don't calc relative to JT - if (!TAI->getJumpTableDirective()) - O << '-' << TAI->getPrivateGlobalPrefix() << "JTI" - << getFunctionNumber() << '_' << JTI << '_' << MO2.getImm(); - } else - printBasicBlockLabel(MBB, false, false, false); + GetMBBSymbol(MBB->getNumber())->print(O, MAI); + O << '-' << MAI->getPrivateGlobalPrefix() << "JTI" + << getFunctionNumber() << '_' << JTI << '_' << MO2.getImm(); + } else { + GetMBBSymbol(MBB->getNumber())->print(O, MAI); + } + if (i != e-1) + O << '\n'; + } +} + +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"; + + 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 ByteOffset = false, HalfWordOffset = false; + if (MI->getOpcode() == ARM::t2TBB) + ByteOffset = true; + else if (MI->getOpcode() == ARM::t2TBH) + HalfWordOffset = true; + + for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) { + MachineBasicBlock *MBB = JTBBs[i]; + if (ByteOffset) + 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 (i != e-1) O << '\n'; } + + // Make sure the instruction that follows TBB is 2-byte aligned. + // FIXME: Constant island pass should insert an "ALIGN" instruction instead. + if (ByteOffset && (JTBBs.size() & 1)) { + O << '\n'; + EmitAlignment(1); + } +} + +void ARMAsmPrinter::printTBAddrMode(const MachineInstr *MI, int OpNum) { + O << "[pc, " << getRegisterName(MI->getOperand(OpNum).getReg()); + if (MI->getOpcode() == ARM::t2TBH) + O << ", lsl #1"; + O << ']'; } +void ARMAsmPrinter::printNoHashImmediate(const MachineInstr *MI, int OpNum) { + O << MI->getOperand(OpNum).getImm(); +} bool ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum, unsigned AsmVariant, const char *ExtraCode){ // Does this asm operand have a single letter operand modifier? if (ExtraCode && ExtraCode[0]) { if (ExtraCode[1] != 0) return true; // Unknown modifier. - + switch (ExtraCode[0]) { default: return true; // Unknown modifier. - case 'a': // Don't print "#" before a global var name or constant. - case 'c': // Don't print "$" before a global var name or constant. - printOperand(MI, OpNum, "no_hash"); + case 'a': // Print as a memory address. + if (MI->getOperand(OpNum).isReg()) { + O << "[" << getRegisterName(MI->getOperand(OpNum).getReg()) << "]"; + return false; + } + // Fallthrough + case 'c': // Don't print "#" before an immediate operand. + if (!MI->getOperand(OpNum).isImm()) + return true; + printNoHashImmediate(MI, OpNum); return false; case 'P': // Print a VFP double precision register. printOperand(MI, OpNum); @@ -898,7 +998,7 @@ bool ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum, if (TM.getTargetData()->isBigEndian()) break; // Fallthrough - case 'H': // Write second word of DI / DF reference. + case 'H': // Write second word of DI / DF reference. // Verify that this operand has two consecutive registers. if (!MI->getOperand(OpNum).isReg() || OpNum+1 == MI->getNumOperands() || @@ -907,7 +1007,7 @@ bool ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum, ++OpNum; // Return the high-part. } } - + printOperand(MI, OpNum); return false; } @@ -917,7 +1017,10 @@ bool ARMAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, const char *ExtraCode) { if (ExtraCode && ExtraCode[0]) return true; // Unknown modifier. - printAddrMode2Operand(MI, OpNum); + + const MachineOperand &MO = MI->getOperand(OpNum); + assert(MO.isReg() && "unexpected inline asm memory operand"); + O << "[" << getRegisterName(MO.getReg()) << "]"; return false; } @@ -938,16 +1041,47 @@ void ARMAsmPrinter::printMachineInstruction(const MachineInstr *MI) { }} // Call the autogenerated instruction printer routines. + processDebugLoc(MI, true); printInstruction(MI); + if (VerboseAsm && !MI->getDebugLoc().isUnknown()) + EmitComments(*MI); + O << '\n'; + processDebugLoc(MI, false); } -bool ARMAsmPrinter::doInitialization(Module &M) { - - bool Result = AsmPrinter::doInitialization(M); - DW = getAnalysisIfAvailable<DwarfWriter>(); +void ARMAsmPrinter::EmitStartOfAsmFile(Module &M) { + if (Subtarget->isTargetDarwin()) { + Reloc::Model RelocM = TM.getRelocationModel(); + if (RelocM == Reloc::PIC_ || RelocM == Reloc::DynamicNoPIC) { + // Declare all the text sections up front (before the DWARF sections + // emitted by AsmPrinter::doInitialization) so the assembler will keep + // them together at the beginning of the object file. This helps + // avoid out-of-range branches that are due a fundamental limitation of + // the way symbol offsets are encoded with the current Darwin ARM + // relocations. + TargetLoweringObjectFileMachO &TLOFMacho = + static_cast<TargetLoweringObjectFileMachO &>(getObjFileLowering()); + OutStreamer.SwitchSection(TLOFMacho.getTextSection()); + OutStreamer.SwitchSection(TLOFMacho.getTextCoalSection()); + OutStreamer.SwitchSection(TLOFMacho.getConstTextCoalSection()); + if (RelocM == Reloc::DynamicNoPIC) { + const MCSection *sect = + TLOFMacho.getMachOSection("__TEXT", "__symbol_stub4", + MCSectionMachO::S_SYMBOL_STUBS, + 12, SectionKind::getText()); + OutStreamer.SwitchSection(sect); + } else { + const MCSection *sect = + TLOFMacho.getMachOSection("__TEXT", "__picsymbolstub4", + MCSectionMachO::S_SYMBOL_STUBS, + 16, SectionKind::getText()); + OutStreamer.SwitchSection(sect); + } + } + } - // Thumb-2 instructions are supported only in unified assembler syntax mode. - if (Subtarget->hasThumb2()) + // Use unified assembler syntax mode for Thumb. + if (Subtarget->isThumb()) O << "\t.syntax unified\n"; // Emit ARM Build Attributes @@ -975,22 +1109,16 @@ bool ARMAsmPrinter::doInitialization(Module &M) { O << "\t.eabi_attribute " << ARMBuildAttrs::ABI_align8_needed << ", 1\n" << "\t.eabi_attribute " << ARMBuildAttrs::ABI_align8_preserved << ", 1\n"; + // Hard float. Use both S and D registers and conform to AAPCS-VFP. + if (Subtarget->isAAPCS_ABI() && FloatABIType == FloatABI::Hard) + O << "\t.eabi_attribute " << ARMBuildAttrs::ABI_HardFP_use << ", 3\n" + << "\t.eabi_attribute " << ARMBuildAttrs::ABI_VFP_args << ", 1\n"; + // FIXME: Should we signal R9 usage? } - - return Result; -} - -/// PrintUnmangledNameSafely - Print out the printable characters in the name. -/// Don't print things like \\n or \\0. -static void PrintUnmangledNameSafely(const Value *V, raw_ostream &OS) { - for (const char *Name = V->getNameStart(), *E = Name+V->getNameLen(); - Name != E; ++Name) - if (isprint(*Name)) - OS << *Name; } -void ARMAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) { +void ARMAsmPrinter::PrintGlobalVariable(const GlobalVariable* GVar) { const TargetData *TD = TM.getTargetData(); if (!GVar->hasInitializer()) // External global require no code @@ -1009,10 +1137,8 @@ void ARMAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) { return; } - std::string name = Mang->getValueName(GVar); + std::string name = Mang->getMangledName(GVar); Constant *C = GVar->getInitializer(); - if (isa<MDNode>(C) || isa<MDString>(C)) - return; const Type *Type = C->getType(); unsigned Size = TD->getTypeAllocSize(Type); unsigned Align = TD->getPreferredAlignmentLog(GVar); @@ -1023,14 +1149,16 @@ void ARMAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) { if (Subtarget->isTargetELF()) O << "\t.type " << name << ",%object\n"; - if (C->isNullValue() && !GVar->hasSection() && !GVar->isThreadLocal() && - !(isDarwin && - TAI->SectionKindForGlobal(GVar) == SectionKind::RODataMergeStr)) { - // FIXME: This seems to be pretty darwin-specific + 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()) { - SwitchToSection(TAI->SectionForGlobal(GVar)); - if (const char *Directive = TAI->getZeroFillDirective()) { + if (const char *Directive = MAI->getZeroFillDirective()) { O << "\t.globl\t" << name << "\n"; O << Directive << "__DATA, __common, " << name << ", " << Size << ", " << Align << "\n"; @@ -1043,57 +1171,56 @@ void ARMAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) { if (isDarwin) { if (GVar->hasLocalLinkage()) { - O << TAI->getLCOMMDirective() << name << "," << Size + O << MAI->getLCOMMDirective() << name << "," << Size << ',' << Align; } else if (GVar->hasCommonLinkage()) { - O << TAI->getCOMMDirective() << name << "," << Size + O << MAI->getCOMMDirective() << name << "," << Size << ',' << Align; } else { - SwitchToSection(TAI->SectionForGlobal(GVar)); + OutStreamer.SwitchSection(TheSection); O << "\t.globl " << name << '\n' - << TAI->getWeakDefDirective() << name << '\n'; + << MAI->getWeakDefDirective() << name << '\n'; EmitAlignment(Align, GVar); O << name << ":"; if (VerboseAsm) { - O << "\t\t\t\t" << TAI->getCommentString() << ' '; - PrintUnmangledNameSafely(GVar, O); + O << "\t\t\t\t" << MAI->getCommentString() << ' '; + WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent()); } O << '\n'; EmitGlobalConstant(C); return; } - } else if (TAI->getLCOMMDirective() != NULL) { + } else if (MAI->getLCOMMDirective() != NULL) { if (GVar->hasLocalLinkage()) { - O << TAI->getLCOMMDirective() << name << "," << Size; + O << MAI->getLCOMMDirective() << name << "," << Size; } else { - O << TAI->getCOMMDirective() << name << "," << Size; - if (TAI->getCOMMDirectiveTakesAlignment()) - O << ',' << (TAI->getAlignmentIsInBytes() ? (1 << Align) : Align); + O << MAI->getCOMMDirective() << name << "," << Size; + if (MAI->getCOMMDirectiveTakesAlignment()) + O << ',' << (MAI->getAlignmentIsInBytes() ? (1 << Align) : Align); } } else { - SwitchToSection(TAI->SectionForGlobal(GVar)); if (GVar->hasLocalLinkage()) O << "\t.local\t" << name << "\n"; - O << TAI->getCOMMDirective() << name << "," << Size; - if (TAI->getCOMMDirectiveTakesAlignment()) - O << "," << (TAI->getAlignmentIsInBytes() ? (1 << Align) : Align); + O << MAI->getCOMMDirective() << name << "," << Size; + if (MAI->getCOMMDirectiveTakesAlignment()) + O << "," << (MAI->getAlignmentIsInBytes() ? (1 << Align) : Align); } if (VerboseAsm) { - O << "\t\t" << TAI->getCommentString() << " "; - PrintUnmangledNameSafely(GVar, O); + O << "\t\t" << MAI->getCommentString() << " "; + WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent()); } O << "\n"; return; } } - SwitchToSection(TAI->SectionForGlobal(GVar)); switch (GVar->getLinkage()) { - case GlobalValue::CommonLinkage: - case GlobalValue::LinkOnceAnyLinkage: - case GlobalValue::LinkOnceODRLinkage: - case GlobalValue::WeakAnyLinkage: - case GlobalValue::WeakODRLinkage: + 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"; @@ -1101,28 +1228,27 @@ void ARMAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) { 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: + 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"; - // FALL THROUGH - case GlobalValue::PrivateLinkage: - case GlobalValue::InternalLinkage: break; - default: - assert(0 && "Unknown linkage type!"); + 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" << TAI->getCommentString() << " "; - PrintUnmangledNameSafely(GVar, O); + O << "\t\t\t\t" << MAI->getCommentString() << " "; + WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent()); } O << "\n"; - if (TAI->hasDotTypeDotSizeDirective()) + if (MAI->hasDotTypeDotSizeDirective()) O << "\t.size " << name << ", " << Size << "\n"; EmitGlobalConstant(C); @@ -1131,83 +1257,36 @@ void ARMAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) { bool ARMAsmPrinter::doFinalization(Module &M) { - for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); - I != E; ++I) - printModuleLevelGV(I); - if (Subtarget->isTargetDarwin()) { - SwitchToDataSection(""); - - // Output stubs for dynamically-linked functions - for (StringSet<>::iterator i = FnStubs.begin(), e = FnStubs.end(); - i != e; ++i) { - if (TM.getRelocationModel() == Reloc::PIC_) - SwitchToTextSection(".section __TEXT,__picsymbolstub4,symbol_stubs," - "none,16", 0); - else - SwitchToTextSection(".section __TEXT,__symbol_stub4,symbol_stubs," - "none,12", 0); + // All darwin targets use mach-o. + TargetLoweringObjectFileMachO &TLOFMacho = + static_cast<TargetLoweringObjectFileMachO &>(getObjFileLowering()); - EmitAlignment(2); - O << "\t.code\t32\n"; - - const char *p = i->getKeyData(); - printSuffixedName(p, "$stub"); - O << ":\n"; - O << "\t.indirect_symbol " << p << "\n"; - O << "\tldr ip, "; - printSuffixedName(p, "$slp"); - O << "\n"; - if (TM.getRelocationModel() == Reloc::PIC_) { - printSuffixedName(p, "$scv"); - O << ":\n"; - O << "\tadd ip, pc, ip\n"; - } - O << "\tldr pc, [ip, #0]\n"; - printSuffixedName(p, "$slp"); - O << ":\n"; - O << "\t.long\t"; - printSuffixedName(p, "$lazy_ptr"); - if (TM.getRelocationModel() == Reloc::PIC_) { - O << "-("; - printSuffixedName(p, "$scv"); - O << "+8)\n"; - } else - O << "\n"; - SwitchToDataSection(".lazy_symbol_pointer", 0); - printSuffixedName(p, "$lazy_ptr"); - O << ":\n"; - O << "\t.indirect_symbol " << p << "\n"; - O << "\t.long\tdyld_stub_binding_helper\n"; - } - O << "\n"; + O << '\n'; // Output non-lazy-pointers for external and common global variables. if (!GVNonLazyPtrs.empty()) { - SwitchToDataSection("\t.non_lazy_symbol_pointer", 0); - for (StringSet<>::iterator i = GVNonLazyPtrs.begin(), - e = GVNonLazyPtrs.end(); i != e; ++i) { - const char *p = i->getKeyData(); - printSuffixedName(p, "$non_lazy_ptr"); - O << ":\n"; - O << "\t.indirect_symbol " << p << "\n"; + // Switch with ".non_lazy_symbol_pointer" directive. + OutStreamer.SwitchSection(TLOFMacho.getNonLazySymbolPointerSection()); + EmitAlignment(2); + for (StringMap<std::string>::iterator I = GVNonLazyPtrs.begin(), + E = GVNonLazyPtrs.end(); I != E; ++I) { + O << I->second << ":\n"; + O << "\t.indirect_symbol " << I->getKeyData() << "\n"; O << "\t.long\t0\n"; } } if (!HiddenGVNonLazyPtrs.empty()) { - SwitchToSection(TAI->getDataSection()); - for (StringSet<>::iterator i = HiddenGVNonLazyPtrs.begin(), - e = HiddenGVNonLazyPtrs.end(); i != e; ++i) { - const char *p = i->getKeyData(); - EmitAlignment(2); - printSuffixedName(p, "$non_lazy_ptr"); - O << ":\n"; - O << "\t.long " << p << "\n"; + OutStreamer.SwitchSection(getObjFileLowering().getDataSection()); + EmitAlignment(2); + for (StringMap<std::string>::iterator I = HiddenGVNonLazyPtrs.begin(), + E = HiddenGVNonLazyPtrs.end(); I != E; ++I) { + O << I->second << ":\n"; + O << "\t.long " << I->getKeyData() << "\n"; } } - // Funny Darwin hack: This flag tells the linker that no global symbols // contain code that falls through to other global symbols (e.g. the obvious // implementation of multiple entry points). If this doesn't occur, the @@ -1219,24 +1298,8 @@ bool ARMAsmPrinter::doFinalization(Module &M) { return AsmPrinter::doFinalization(M); } -/// createARMCodePrinterPass - Returns a pass that prints the ARM -/// assembly code for a MachineFunction to the given output stream, -/// using the given target machine description. This should work -/// regardless of whether the function is in SSA form. -/// -FunctionPass *llvm::createARMCodePrinterPass(raw_ostream &o, - ARMBaseTargetMachine &tm, - bool verbose) { - return new ARMAsmPrinter(o, tm, tm.getTargetAsmInfo(), verbose); -} - -namespace { - static struct Register { - Register() { - ARMBaseTargetMachine::registerAsmPrinter(createARMCodePrinterPass); - } - } Registrator; -} - // Force static initialization. -extern "C" void LLVMInitializeARMAsmPrinter() { } +extern "C" void LLVMInitializeARMAsmPrinter() { + RegisterAsmPrinter<ARMAsmPrinter> X(TheARMTarget); + RegisterAsmPrinter<ARMAsmPrinter> Y(TheThumbTarget); +} |