X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FARM%2FARMAsmPrinter.cpp;h=e850ef1983b0fa004fe5604ef7a0a09aa45f3003;hb=c215b3ef5d9627f5fb6fe9034e46bc29ae592916;hp=a6ceb85cb3c9a5b020ca520956e9be180a8ceafc;hpb=a8e2989ece6dc46df59b0768184028257f913843;p=oota-llvm.git diff --git a/lib/Target/ARM/ARMAsmPrinter.cpp b/lib/Target/ARM/ARMAsmPrinter.cpp index a6ceb85cb3c..e850ef1983b 100644 --- a/lib/Target/ARM/ARMAsmPrinter.cpp +++ b/lib/Target/ARM/ARMAsmPrinter.cpp @@ -2,8 +2,7 @@ // // The LLVM Compiler Infrastructure // -// This file was developed by the "Instituto Nokia de Tecnologia" and -// is distributed under the University of Illinois Open Source +// This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// @@ -23,20 +22,19 @@ #include "llvm/Module.h" #include "llvm/CodeGen/AsmPrinter.h" #include "llvm/CodeGen/DwarfWriter.h" -#include "llvm/CodeGen/MachineDebugInfo.h" +#include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineJumpTableInfo.h" #include "llvm/Target/TargetAsmInfo.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" #include "llvm/ADT/Statistic.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/Mangler.h" #include "llvm/Support/MathExtras.h" #include -#include -#include using namespace llvm; STATISTIC(EmittedInsts, "Number of machine instrs printed"); @@ -83,6 +81,7 @@ namespace { void printOperand(const MachineInstr *MI, int opNum, const char *Modifier = 0); void printSOImmOperand(const MachineInstr *MI, int opNum); + void printSOImm2PartOperand(const MachineInstr *MI, int opNum); void printSORegOperand(const MachineInstr *MI, int opNum); void printAddrMode2Operand(const MachineInstr *MI, int OpNo); void printAddrMode2OffsetOperand(const MachineInstr *MI, int OpNo); @@ -97,11 +96,12 @@ namespace { void printThumbAddrModeRROperand(const MachineInstr *MI, int OpNo); void printThumbAddrModeRI5Operand(const MachineInstr *MI, int OpNo, unsigned Scale); - void printThumbAddrModeRI5_1Operand(const MachineInstr *MI, int OpNo); - void printThumbAddrModeRI5_2Operand(const MachineInstr *MI, int OpNo); - void printThumbAddrModeRI5_4Operand(const MachineInstr *MI, int OpNo); + void printThumbAddrModeS1Operand(const MachineInstr *MI, int OpNo); + void printThumbAddrModeS2Operand(const MachineInstr *MI, int OpNo); + void printThumbAddrModeS4Operand(const MachineInstr *MI, int OpNo); void printThumbAddrModeSPOperand(const MachineInstr *MI, int OpNo); - void printCCOperand(const MachineInstr *MI, int opNum); + void printPredicateOperand(const MachineInstr *MI, int opNum); + void printSBitModifierOperand(const MachineInstr *MI, int opNum); void printPCLabel(const MachineInstr *MI, int opNum); void printRegisterList(const MachineInstr *MI, int opNum); void printCPInstOperand(const MachineInstr *MI, int opNum, @@ -121,22 +121,39 @@ namespace { printDataDirective(MCPV->getType()); ARMConstantPoolValue *ACPV = (ARMConstantPoolValue*)MCPV; - std::string Name = Mang->getValueName(ACPV->getGV()); + GlobalValue *GV = ACPV->getGV(); + std::string Name = GV ? Mang->getValueName(GV) : TAI->getGlobalPrefix(); + if (!GV) + Name += ACPV->getSymbol(); if (ACPV->isNonLazyPointer()) { GVNonLazyPtrs.insert(Name); - O << TAI->getPrivateGlobalPrefix() << Name << "$non_lazy_ptr"; + printSuffixedName(Name, "$non_lazy_ptr"); + } else if (ACPV->isStub()) { + FnStubs.insert(Name); + printSuffixedName(Name, "$stub"); } else O << Name; - if (ACPV->getPCAdjustment() != 0) + if (ACPV->hasModifier()) O << "(" << ACPV->getModifier() << ")"; + if (ACPV->getPCAdjustment() != 0) { O << "-(" << TAI->getPrivateGlobalPrefix() << "PC" << utostr(ACPV->getLabelId()) - << "+" << (unsigned)ACPV->getPCAdjustment() << ")"; + << "+" << (unsigned)ACPV->getPCAdjustment(); + if (ACPV->mustAddCurrentAddress()) + O << "-."; + O << ")"; + } O << "\n"; + + // If the constant pool value is a extern weak symbol, remember to emit + // the weak reference. + if (GV && GV->hasExternalWeakLinkage()) + ExtWeakSymbols.insert(GV); } void getAnalysisUsage(AnalysisUsage &AU) const { + AsmPrinter::getAnalysisUsage(AU); AU.setPreservesAll(); - AU.addRequired(); + AU.addRequired(); } }; } // end of anonymous namespace @@ -159,9 +176,7 @@ FunctionPass *llvm::createARMCodePrinterPass(std::ostream &o, bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) { AFI = MF.getInfo(); - if (Subtarget->isDarwin()) { - DW.SetDebugInfo(&getAnalysis()); - } + DW.SetModuleInfo(&getAnalysis()); SetupMachineFunction(MF); O << "\n"; @@ -183,7 +198,7 @@ bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) { break; case Function::WeakLinkage: case Function::LinkOnceLinkage: - if (Subtarget->isDarwin()) { + if (Subtarget->isTargetDarwin()) { SwitchToTextSection( ".section __TEXT,__textcoal_nt,coalesced,pure_instructions", F); O << "\t.globl\t" << CurrentFnName << "\n"; @@ -194,18 +209,38 @@ bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) { break; } + const char *VisibilityDirective = NULL; + if (F->hasHiddenVisibility()) + VisibilityDirective = TAI->getHiddenDirective(); + else if (F->hasProtectedVisibility()) + VisibilityDirective = TAI->getProtectedDirective(); + + if (VisibilityDirective) + O << VisibilityDirective << CurrentFnName << "\n"; + if (AFI->isThumbFunction()) { - EmitAlignment(1, F); + EmitAlignment(1, F, AFI->getAlign()); O << "\t.code\t16\n"; - O << "\t.thumb_func\t" << CurrentFnName << "\n"; + O << "\t.thumb_func"; + if (Subtarget->isTargetDarwin()) + O << "\t" << CurrentFnName; + O << "\n"; InCPMode = false; } else EmitAlignment(2, F); O << CurrentFnName << ":\n"; - if (Subtarget->isDarwin()) { - // Emit pre-function debug information. - DW.BeginFunction(&MF); + // 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. @@ -213,7 +248,7 @@ bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) { I != E; ++I) { // Print a label for the basic block. if (I != MF.begin()) { - printBasicBlockLabel(I, true); + printBasicBlockLabel(I, true, true); O << '\n'; } for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end(); @@ -226,10 +261,8 @@ bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) { if (TAI->hasDotTypeDotSizeDirective()) O << "\t.size " << CurrentFnName << ", .-" << CurrentFnName << "\n"; - if (Subtarget->isDarwin()) { - // Emit post-function debug information. - DW.EndFunction(); - } + // Emit post-function debug information. + DW.EndFunction(); return false; } @@ -239,8 +272,8 @@ void ARMAsmPrinter::printOperand(const MachineInstr *MI, int opNum, const MachineOperand &MO = MI->getOperand(opNum); switch (MO.getType()) { case MachineOperand::MO_Register: - if (MRegisterInfo::isPhysicalRegister(MO.getReg())) - O << TM.getRegisterInfo()->get(MO.getReg()).Name; + if (TargetRegisterInfo::isPhysicalRegister(MO.getReg())) + O << TM.getRegisterInfo()->get(MO.getReg()).AsmName; else assert(0 && "not implemented"); break; @@ -248,25 +281,33 @@ void ARMAsmPrinter::printOperand(const MachineInstr *MI, int opNum, if (!Modifier || strcmp(Modifier, "no_hash") != 0) O << "#"; - O << (int)MO.getImmedValue(); + O << (int)MO.getImm(); break; } case MachineOperand::MO_MachineBasicBlock: - printBasicBlockLabel(MO.getMachineBasicBlock()); + printBasicBlockLabel(MO.getMBB()); return; case MachineOperand::MO_GlobalAddress: { bool isCallOp = Modifier && !strcmp(Modifier, "call"); GlobalValue *GV = MO.getGlobal(); std::string Name = Mang->getValueName(GV); - bool isExt = (GV->isExternal() || GV->hasWeakLinkage() || + bool isExt = (GV->isDeclaration() || GV->hasWeakLinkage() || GV->hasLinkOnceLinkage()); - if (isExt && isCallOp && Subtarget->isDarwin() && + if (isExt && isCallOp && Subtarget->isTargetDarwin() && TM.getRelocationModel() != Reloc::Static) { - O << TAI->getPrivateGlobalPrefix() << Name << "$stub"; + printSuffixedName(Name, "$stub"); FnStubs.insert(Name); } else O << Name; - + + if (MO.getOffset() > 0) + O << '+' << MO.getOffset(); + else if (MO.getOffset() < 0) + O << MO.getOffset(); + + if (isCallOp && Subtarget->isTargetELF() && + TM.getRelocationModel() == Reloc::PIC_) + O << "(PLT)"; if (GV->hasExternalWeakLinkage()) ExtWeakSymbols.insert(GV); break; @@ -275,35 +316,34 @@ void ARMAsmPrinter::printOperand(const MachineInstr *MI, int opNum, bool isCallOp = Modifier && !strcmp(Modifier, "call"); std::string Name(TAI->getGlobalPrefix()); Name += MO.getSymbolName(); - if (isCallOp && Subtarget->isDarwin() && + if (isCallOp && Subtarget->isTargetDarwin() && TM.getRelocationModel() != Reloc::Static) { - O << TAI->getPrivateGlobalPrefix() << Name << "$stub"; + printSuffixedName(Name, "$stub"); FnStubs.insert(Name); } else O << Name; + if (isCallOp && Subtarget->isTargetELF() && + TM.getRelocationModel() == Reloc::PIC_) + O << "(PLT)"; break; } case MachineOperand::MO_ConstantPoolIndex: O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() - << '_' << MO.getConstantPoolIndex(); + << '_' << MO.getIndex(); break; case MachineOperand::MO_JumpTableIndex: O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() - << '_' << MO.getJumpTableIndex(); + << '_' << MO.getIndex(); break; default: O << ""; abort (); break; } } -/// printSOImmOperand - SOImm is 4-bit rotate amount in bits 8-11 with 8-bit -/// immediate in bits 0-7. -void ARMAsmPrinter::printSOImmOperand(const MachineInstr *MI, int OpNum) { - const MachineOperand &MO = MI->getOperand(OpNum); - assert(MO.isImmediate() && (MO.getImmedValue() < (1 << 12)) && - "Not a valid so_imm value!"); - unsigned Imm = ARM_AM::getSOImmValImm(MO.getImmedValue()); - unsigned Rot = ARM_AM::getSOImmValRot(MO.getImmedValue()); +static void printSOImm(std::ostream &O, int64_t V, const TargetAsmInfo *TAI) { + assert(V < (1 << 12) && "Not a valid so_imm value!"); + unsigned Imm = ARM_AM::getSOImmValImm(V); + unsigned Rot = ARM_AM::getSOImmValRot(V); // Print low-level immediate formation info, per // A5.1.3: "Data-processing operands - Immediate". @@ -316,6 +356,32 @@ void ARMAsmPrinter::printSOImmOperand(const MachineInstr *MI, int OpNum) { } } +/// printSOImmOperand - SOImm is 4-bit rotate amount in bits 8-11 with 8-bit +/// immediate in bits 0-7. +void ARMAsmPrinter::printSOImmOperand(const MachineInstr *MI, int OpNum) { + const MachineOperand &MO = MI->getOperand(OpNum); + assert(MO.isImmediate() && "Not a valid so_imm value!"); + printSOImm(O, MO.getImm(), TAI); +} + +/// printSOImm2PartOperand - SOImm is broken into two pieces using a mov +/// followed by a or to materialize. +void ARMAsmPrinter::printSOImm2PartOperand(const MachineInstr *MI, int OpNum) { + const MachineOperand &MO = MI->getOperand(OpNum); + assert(MO.isImmediate() && "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), TAI); + O << "\n\torr"; + printPredicateOperand(MI, 2); + O << " "; + printOperand(MI, 0); + O << ", "; + printOperand(MI, 0); + O << ", "; + printSOImm(O, ARM_AM::getSOImmVal(V2), TAI); +} + // so_reg is a 4-operand unit corresponding to register forms of the A5.1 // "Addressing Mode 1 - Data-processing operands" forms. This includes: // REG 0 0 - e.g. R5 @@ -326,17 +392,17 @@ void ARMAsmPrinter::printSORegOperand(const MachineInstr *MI, int Op) { const MachineOperand &MO2 = MI->getOperand(Op+1); const MachineOperand &MO3 = MI->getOperand(Op+2); - assert(MRegisterInfo::isPhysicalRegister(MO1.getReg())); - O << TM.getRegisterInfo()->get(MO1.getReg()).Name; + assert(TargetRegisterInfo::isPhysicalRegister(MO1.getReg())); + O << TM.getRegisterInfo()->get(MO1.getReg()).AsmName; // Print the shift opc. O << ", " - << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO3.getImmedValue())) + << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO3.getImm())) << " "; if (MO2.getReg()) { - assert(MRegisterInfo::isPhysicalRegister(MO2.getReg())); - O << TM.getRegisterInfo()->get(MO2.getReg()).Name; + assert(TargetRegisterInfo::isPhysicalRegister(MO2.getReg())); + O << TM.getRegisterInfo()->get(MO2.getReg()).AsmName; assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0); } else { O << "#" << ARM_AM::getSORegOffset(MO3.getImm()); @@ -353,7 +419,7 @@ void ARMAsmPrinter::printAddrMode2Operand(const MachineInstr *MI, int Op) { return; } - O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).Name; + O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName; if (!MO2.getReg()) { if (ARM_AM::getAM2Offset(MO3.getImm())) // Don't print +0. @@ -366,11 +432,11 @@ void ARMAsmPrinter::printAddrMode2Operand(const MachineInstr *MI, int Op) { O << ", " << (char)ARM_AM::getAM2Op(MO3.getImm()) - << TM.getRegisterInfo()->get(MO2.getReg()).Name; + << TM.getRegisterInfo()->get(MO2.getReg()).AsmName; if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm())) O << ", " - << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO3.getImmedValue())) + << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO3.getImm())) << " #" << ShImm; O << "]"; } @@ -380,19 +446,20 @@ void ARMAsmPrinter::printAddrMode2OffsetOperand(const MachineInstr *MI, int Op){ const MachineOperand &MO2 = MI->getOperand(Op+1); if (!MO1.getReg()) { - if (ARM_AM::getAM2Offset(MO2.getImm())) // Don't print +0. - O << "#" - << (char)ARM_AM::getAM2Op(MO2.getImm()) - << ARM_AM::getAM2Offset(MO2.getImm()); + unsigned ImmOffs = ARM_AM::getAM2Offset(MO2.getImm()); + assert(ImmOffs && "Malformed indexed load / store!"); + O << "#" + << (char)ARM_AM::getAM2Op(MO2.getImm()) + << ImmOffs; return; } O << (char)ARM_AM::getAM2Op(MO2.getImm()) - << TM.getRegisterInfo()->get(MO1.getReg()).Name; + << TM.getRegisterInfo()->get(MO1.getReg()).AsmName; if (unsigned ShImm = ARM_AM::getAM2Offset(MO2.getImm())) O << ", " - << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO2.getImmedValue())) + << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO2.getImm())) << " #" << ShImm; } @@ -401,13 +468,13 @@ void ARMAsmPrinter::printAddrMode3Operand(const MachineInstr *MI, int Op) { const MachineOperand &MO2 = MI->getOperand(Op+1); const MachineOperand &MO3 = MI->getOperand(Op+2); - assert(MRegisterInfo::isPhysicalRegister(MO1.getReg())); - O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).Name; + assert(TargetRegisterInfo::isPhysicalRegister(MO1.getReg())); + O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName; if (MO2.getReg()) { O << ", " << (char)ARM_AM::getAM3Op(MO3.getImm()) - << TM.getRegisterInfo()->get(MO2.getReg()).Name + << TM.getRegisterInfo()->get(MO2.getReg()).AsmName << "]"; return; } @@ -425,13 +492,14 @@ void ARMAsmPrinter::printAddrMode3OffsetOperand(const MachineInstr *MI, int Op){ if (MO1.getReg()) { O << (char)ARM_AM::getAM3Op(MO2.getImm()) - << TM.getRegisterInfo()->get(MO1.getReg()).Name; + << TM.getRegisterInfo()->get(MO1.getReg()).AsmName; return; } unsigned ImmOffs = ARM_AM::getAM3Offset(MO2.getImm()); + assert(ImmOffs && "Malformed indexed load / store!"); O << "#" - << (char)ARM_AM::getAM3Op(MO2.getImm()) + << (char)ARM_AM::getAM3Op(MO2.getImm()) << ImmOffs; } @@ -464,7 +532,7 @@ void ARMAsmPrinter::printAddrMode5Operand(const MachineInstr *MI, int Op, return; } - assert(MRegisterInfo::isPhysicalRegister(MO1.getReg())); + assert(TargetRegisterInfo::isPhysicalRegister(MO1.getReg())); if (Modifier && strcmp(Modifier, "submode") == 0) { ARM_AM::AMSubMode Mode = ARM_AM::getAM5SubMode(MO2.getImm()); @@ -477,13 +545,13 @@ 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()).Name; + O << TM.getRegisterInfo()->get(MO1.getReg()).AsmName; if (ARM_AM::getAM5WBFlag(MO2.getImm())) O << "!"; return; } - O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).Name; + O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName; if (unsigned ImmOffs = ARM_AM::getAM5Offset(MO2.getImm())) { O << ", #" @@ -501,16 +569,16 @@ void ARMAsmPrinter::printAddrModePCOperand(const MachineInstr *MI, int Op, } const MachineOperand &MO1 = MI->getOperand(Op); - assert(MRegisterInfo::isPhysicalRegister(MO1.getReg())); - O << "[pc, +" << TM.getRegisterInfo()->get(MO1.getReg()).Name << "]"; + assert(TargetRegisterInfo::isPhysicalRegister(MO1.getReg())); + O << "[pc, +" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName << "]"; } 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()).Name; - O << ", " << TM.getRegisterInfo()->get(MO2.getReg()).Name << "]"; + O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName; + O << ", " << TM.getRegisterInfo()->get(MO2.getReg()).AsmName << "]"; } void @@ -518,14 +586,17 @@ ARMAsmPrinter::printThumbAddrModeRI5Operand(const MachineInstr *MI, int Op, unsigned Scale) { const MachineOperand &MO1 = MI->getOperand(Op); const MachineOperand &MO2 = MI->getOperand(Op+1); + const MachineOperand &MO3 = MI->getOperand(Op+2); if (!MO1.isRegister()) { // FIXME: This is for CP entries, but isn't right. printOperand(MI, Op); return; } - O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).Name; - if (unsigned ImmOffs = MO2.getImm()) { + O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName; + if (MO3.getReg()) + O << ", " << TM.getRegisterInfo()->get(MO3.getReg()).AsmName; + else if (unsigned ImmOffs = MO2.getImm()) { O << ", #" << ImmOffs; if (Scale > 1) O << " * " << Scale; @@ -534,34 +605,43 @@ ARMAsmPrinter::printThumbAddrModeRI5Operand(const MachineInstr *MI, int Op, } void -ARMAsmPrinter::printThumbAddrModeRI5_1Operand(const MachineInstr *MI, int Op) { +ARMAsmPrinter::printThumbAddrModeS1Operand(const MachineInstr *MI, int Op) { printThumbAddrModeRI5Operand(MI, Op, 1); } void -ARMAsmPrinter::printThumbAddrModeRI5_2Operand(const MachineInstr *MI, int Op) { +ARMAsmPrinter::printThumbAddrModeS2Operand(const MachineInstr *MI, int Op) { printThumbAddrModeRI5Operand(MI, Op, 2); } void -ARMAsmPrinter::printThumbAddrModeRI5_4Operand(const MachineInstr *MI, int Op) { +ARMAsmPrinter::printThumbAddrModeS4Operand(const MachineInstr *MI, int Op) { printThumbAddrModeRI5Operand(MI, Op, 4); } 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()).Name; + O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName; if (unsigned ImmOffs = MO2.getImm()) O << ", #" << ImmOffs << " * 4"; O << "]"; } -void ARMAsmPrinter::printCCOperand(const MachineInstr *MI, int opNum) { - int CC = (int)MI->getOperand(opNum).getImmedValue(); - O << ARMCondCodeToString((ARMCC::CondCodes)CC); +void ARMAsmPrinter::printPredicateOperand(const MachineInstr *MI, int opNum) { + ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(opNum).getImm(); + if (CC != ARMCC::AL) + O << ARMCondCodeToString(CC); +} + +void ARMAsmPrinter::printSBitModifierOperand(const MachineInstr *MI, int opNum){ + unsigned Reg = MI->getOperand(opNum).getReg(); + if (Reg) { + assert(Reg == ARM::CPSR && "Expect ARM CPSR register!"); + O << 's'; + } } void ARMAsmPrinter::printPCLabel(const MachineInstr *MI, int opNum) { - int Id = (int)MI->getOperand(opNum).getImmedValue(); + int Id = (int)MI->getOperand(opNum).getImm(); O << TAI->getPrivateGlobalPrefix() << "PC" << Id; } @@ -585,24 +665,29 @@ void ARMAsmPrinter::printCPInstOperand(const MachineInstr *MI, int OpNo, << '_' << ID << ":\n"; } else { assert(!strcmp(Modifier, "cpentry") && "Unknown modifier for CPE"); - unsigned CPI = MI->getOperand(OpNo).getConstantPoolIndex(); + unsigned CPI = MI->getOperand(OpNo).getIndex(); const MachineConstantPoolEntry &MCPE = // Chasing pointers is fun? MI->getParent()->getParent()->getConstantPool()->getConstants()[CPI]; if (MCPE.isMachineConstantPoolEntry()) EmitMachineConstantPoolValue(MCPE.Val.MachineCPVal); - else + else { EmitGlobalConstant(MCPE.Val.ConstVal); + // remember to emit the weak reference + if (const GlobalValue *GV = dyn_cast(MCPE.Val.ConstVal)) + if (GV->hasExternalWeakLinkage()) + ExtWeakSymbols.insert(GV); + } } } void ARMAsmPrinter::printJTBlockOperand(const MachineInstr *MI, int OpNo) { const MachineOperand &MO1 = MI->getOperand(OpNo); const MachineOperand &MO2 = MI->getOperand(OpNo+1); // Unique Id - unsigned JTI = MO1.getJumpTableIndex(); + unsigned JTI = MO1.getIndex(); O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() - << '_' << JTI << '_' << MO2.getImmedValue() << ":\n"; + << '_' << JTI << '_' << MO2.getImm() << ":\n"; const char *JTEntryDirective = TAI->getJumpTableDirective(); if (!JTEntryDirective) @@ -617,22 +702,23 @@ void ARMAsmPrinter::printJTBlockOperand(const MachineInstr *MI, int OpNo) { for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) { MachineBasicBlock *MBB = JTBBs[i]; if (UseSet && JTSets.insert(MBB).second) - printSetLabel(JTI, MO2.getImmedValue(), MBB); + printPICJumpTableSetLabel(JTI, MO2.getImm(), MBB); O << JTEntryDirective << ' '; if (UseSet) O << TAI->getPrivateGlobalPrefix() << getFunctionNumber() - << '_' << JTI << '_' << MO2.getImmedValue() + << '_' << JTI << '_' << MO2.getImm() << "_set_" << MBB->getNumber(); else if (TM.getRelocationModel() == Reloc::PIC_) { - printBasicBlockLabel(MBB, false, false); + 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.getImmedValue(); + << getFunctionNumber() << '_' << JTI << '_' << MO2.getImm(); } else - printBasicBlockLabel(MBB, false, false); - O << '\n'; + printBasicBlockLabel(MBB, false, false, false); + if (i != e-1) + O << '\n'; } } @@ -645,6 +731,10 @@ bool ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, switch (ExtraCode[0]) { default: return true; // Unknown modifier. + case 'c': // Don't print "$" before a global var name or constant. + case 'P': // Print a VFP double precision register. + printOperand(MI, OpNo); + return false; case 'Q': if (TM.getTargetData()->isLittleEndian()) break; @@ -670,30 +760,60 @@ bool ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, void ARMAsmPrinter::printMachineInstruction(const MachineInstr *MI) { ++EmittedInsts; - if (MI->getOpcode() == ARM::CONSTPOOL_ENTRY) { + int Opc = MI->getOpcode(); + switch (Opc) { + case ARM::CONSTPOOL_ENTRY: if (!InCPMode && AFI->isThumbFunction()) { EmitAlignment(2); InCPMode = true; } - } else { - if (InCPMode && AFI->isThumbFunction()) { - EmitAlignment(1); + break; + default: { + if (InCPMode && AFI->isThumbFunction()) InCPMode = false; + switch (Opc) { + case ARM::PICADD: + case ARM::PICLD: + case ARM::PICLDZH: + case ARM::PICLDZB: + case ARM::PICLDH: + case ARM::PICLDB: + case ARM::PICLDSH: + case ARM::PICLDSB: + case ARM::PICSTR: + case ARM::PICSTRH: + case ARM::PICSTRB: + case ARM::tPICADD: + break; + default: + break; } - O << "\t"; - } + }} // Call the autogenerated instruction printer routines. printInstruction(MI); } bool ARMAsmPrinter::doInitialization(Module &M) { - if (Subtarget->isDarwin()) { - // Emit initial debug information. - DW.BeginModule(&M); - } + // Emit initial debug information. + DW.BeginModule(&M); - return AsmPrinter::doInitialization(M); + bool Result = AsmPrinter::doInitialization(M); + + // Darwin wants symbols to be quoted if they have complex names. + if (Subtarget->isTargetDarwin()) + Mang->setUseQuotes(true); + + 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, std::ostream &OS) { + for (const char *Name = V->getNameStart(), *E = Name+V->getNameLen(); + Name != E; ++Name) + if (isprint(*Name)) + OS << *Name; } bool ARMAsmPrinter::doFinalization(Module &M) { @@ -704,30 +824,56 @@ bool ARMAsmPrinter::doFinalization(Module &M) { if (!I->hasInitializer()) // External global require no code continue; - if (EmitSpecialLLVMGlobal(I)) + if (EmitSpecialLLVMGlobal(I)) { + if (Subtarget->isTargetDarwin() && + TM.getRelocationModel() == Reloc::Static) { + if (I->getName() == "llvm.global_ctors") + O << ".reference .constructors_used\n"; + else if (I->getName() == "llvm.global_dtors") + O << ".reference .destructors_used\n"; + } continue; + } std::string name = Mang->getValueName(I); Constant *C = I->getInitializer(); - unsigned Size = TD->getTypeSize(C->getType()); + const Type *Type = C->getType(); + unsigned Size = TD->getABITypeSize(Type); unsigned Align = TD->getPreferredAlignmentLog(I); - if (C->isNullValue() && - !I->hasSection() && - (I->hasInternalLinkage() || I->hasWeakLinkage() || - I->hasLinkOnceLinkage() || - (Subtarget->isDarwin() && I->hasExternalLinkage()))) { - if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it. + const char *VisibilityDirective = NULL; + if (I->hasHiddenVisibility()) + VisibilityDirective = TAI->getHiddenDirective(); + else if (I->hasProtectedVisibility()) + VisibilityDirective = TAI->getProtectedDirective(); + + if (VisibilityDirective) + O << VisibilityDirective << name << "\n"; + + if (Subtarget->isTargetELF()) + O << "\t.type " << name << ",%object\n"; + + if (C->isNullValue() && !I->hasSection() && !I->isThreadLocal()) { if (I->hasExternalLinkage()) { + if (const char *Directive = TAI->getZeroFillDirective()) { O << "\t.globl\t" << name << "\n"; - O << "\t.zerofill __DATA__, __common, " << name << ", " - << Size << ", " << Align; - } else { - SwitchToDataSection(TAI->getDataSection(), I); + O << Directive << "__DATA, __common, " << name << ", " + << Size << ", " << Align << "\n"; + continue; + } + } + + if (I->hasInternalLinkage() || I->hasWeakLinkage() || + I->hasLinkOnceLinkage()) { + if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it. + if (!NoZerosInBSS && TAI->getBSSSection()) + SwitchToDataSection(TAI->getBSSSection(), I); + else + SwitchToDataSection(TAI->getDataSection(), I); if (TAI->getLCOMMDirective() != NULL) { if (I->hasInternalLinkage()) { O << TAI->getLCOMMDirective() << name << "," << Size; - if (Subtarget->isDarwin()) + if (Subtarget->isTargetDarwin()) O << "," << Align; } else O << TAI->getCOMMDirective() << name << "," << Size; @@ -738,59 +884,99 @@ bool ARMAsmPrinter::doFinalization(Module &M) { if (TAI->getCOMMDirectiveTakesAlignment()) O << "," << (TAI->getAlignmentIsInBytes() ? (1 << Align) : Align); } + O << "\t\t" << TAI->getCommentString() << " "; + PrintUnmangledNameSafely(I, O); + O << "\n"; + continue; } - O << "\t\t" << TAI->getCommentString() << " " << I->getName() << "\n"; - continue; - } else { - switch (I->getLinkage()) { - default: - assert(0 && "Unknown linkage type!"); - break; - case GlobalValue::LinkOnceLinkage: - case GlobalValue::WeakLinkage: - if (Subtarget->isDarwin()) { - O << "\t.globl " << name << "\n" - << "\t.weak_definition " << name << "\n"; - SwitchToDataSection("\t.section __DATA,__const_coal,coalesced", I); - } else { - O << "\t.section\t.llvm.linkonce.d." << name << ",\"aw\",@progbits\n" - << "\t.weak " << name << "\n"; - } - break; - case GlobalValue::ExternalLinkage: - O << "\t.globl " << name << "\n"; - // FALL THROUGH - case GlobalValue::InternalLinkage: - if (I->isConstant()) { - const ConstantArray *CVA = dyn_cast(C); - if (TAI->getCStringSection() && CVA && CVA->isCString()) { - SwitchToDataSection(TAI->getCStringSection(), I); - break; - } - } + } - if (I->hasSection() && - (I->getSection() == ".ctors" || - I->getSection() == ".dtors")) { - assert(!Subtarget->isDarwin()); - std::string SectionName = ".section " + I->getSection(); - SectionName += ",\"aw\",@progbits"; - SwitchToDataSection(SectionName.c_str()); - } else { - SwitchToDataSection(TAI->getDataSection(), I); + switch (I->getLinkage()) { + case GlobalValue::LinkOnceLinkage: + case GlobalValue::WeakLinkage: + if (Subtarget->isTargetDarwin()) { + O << "\t.globl " << name << "\n" + << "\t.weak_definition " << name << "\n"; + SwitchToDataSection("\t.section __DATA,__datacoal_nt,coalesced", I); + } else { + std::string SectionName("\t.section\t.llvm.linkonce.d." + + name + + ",\"aw\",%progbits"); + SwitchToDataSection(SectionName.c_str(), I); + 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"; + // FALL THROUGH + case GlobalValue::InternalLinkage: { + if (I->isConstant()) { + const ConstantArray *CVA = dyn_cast(C); + if (TAI->getCStringSection() && CVA && CVA->isCString()) { + SwitchToDataSection(TAI->getCStringSection(), I); + break; + } + } + // FIXME: special handling for ".ctors" & ".dtors" sections + if (I->hasSection() && + (I->getSection() == ".ctors" || + I->getSection() == ".dtors")) { + assert(!Subtarget->isTargetDarwin()); + std::string SectionName = ".section " + I->getSection(); + SectionName += ",\"aw\",%progbits"; + SwitchToDataSection(SectionName.c_str()); + } else if (I->hasSection() && Subtarget->isTargetDarwin()) { + // Honor all section names on Darwin; ObjC uses this + std::string SectionName = ".section " + I->getSection(); + SwitchToDataSection(SectionName.c_str()); + } else { + if (C->isNullValue() && !NoZerosInBSS && TAI->getBSSSection()) + SwitchToDataSection(I->isThreadLocal() ? TAI->getTLSBSSSection() : + TAI->getBSSSection(), I); + else if (!I->isConstant()) + SwitchToDataSection(I->isThreadLocal() ? TAI->getTLSDataSection() : + TAI->getDataSection(), I); + else if (I->isThreadLocal()) + SwitchToDataSection(TAI->getTLSDataSection()); + else { + // Read-only data. + bool HasReloc = C->ContainsRelocations(); + if (HasReloc && + Subtarget->isTargetDarwin() && + TM.getRelocationModel() != Reloc::Static) + SwitchToDataSection("\t.const_data\n"); + else if (!HasReloc && Size == 4 && + TAI->getFourByteConstantSection()) + SwitchToDataSection(TAI->getFourByteConstantSection(), I); + else if (!HasReloc && Size == 8 && + TAI->getEightByteConstantSection()) + SwitchToDataSection(TAI->getEightByteConstantSection(), I); + else if (!HasReloc && Size == 16 && + TAI->getSixteenByteConstantSection()) + SwitchToDataSection(TAI->getSixteenByteConstantSection(), I); + else if (TAI->getReadOnlySection()) + SwitchToDataSection(TAI->getReadOnlySection(), I); + else + SwitchToDataSection(TAI->getDataSection(), I); } - - break; } + + break; + } + default: + assert(0 && "Unknown linkage type!"); + break; } EmitAlignment(Align, I); - if (TAI->hasDotTypeDotSizeDirective()) { - O << "\t.type " << name << ", %object\n"; + O << name << ":\t\t\t\t" << TAI->getCommentString() << " "; + PrintUnmangledNameSafely(I, O); + O << "\n"; + if (TAI->hasDotTypeDotSizeDirective()) O << "\t.size " << name << ", " << Size << "\n"; - } - O << name << ":\n"; - // If the initializer is a extern weak symbol, remember to emit the weak // reference! if (const GlobalValue *GV = dyn_cast(C)) @@ -801,7 +987,9 @@ bool ARMAsmPrinter::doFinalization(Module &M) { O << '\n'; } - if (Subtarget->isDarwin()) { + if (Subtarget->isTargetDarwin()) { + SwitchToDataSection(""); + // Output stubs for dynamically-linked functions unsigned j = 1; for (std::set::iterator i = FnStubs.begin(), e = FnStubs.end(); @@ -816,32 +1004,45 @@ bool ARMAsmPrinter::doFinalization(Module &M) { EmitAlignment(2); O << "\t.code\t32\n"; - O << "L" << *i << "$stub:\n"; + std::string p = *i; + printSuffixedName(p, "$stub"); + O << ":\n"; O << "\t.indirect_symbol " << *i << "\n"; - O << "\tldr ip, L" << *i << "$slp\n"; + O << "\tldr ip, "; + printSuffixedName(p, "$slp"); + O << "\n"; if (TM.getRelocationModel() == Reloc::PIC_) { - O << "L" << *i << "$scv:\n"; + printSuffixedName(p, "$scv"); + O << ":\n"; O << "\tadd ip, pc, ip\n"; } O << "\tldr pc, [ip, #0]\n"; - O << "L" << *i << "$slp:\n"; - if (TM.getRelocationModel() == Reloc::PIC_) - O << "\t.long\tL" << *i << "$lazy_ptr-(L" << *i << "$scv+8)\n"; - else - O << "\t.long\tL" << *i << "$lazy_ptr\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); - O << "L" << *i << "$lazy_ptr:\n"; + printSuffixedName(p, "$lazy_ptr"); + O << ":\n"; O << "\t.indirect_symbol " << *i << "\n"; O << "\t.long\tdyld_stub_binding_helper\n"; } O << "\n"; // Output non-lazy-pointers for external and common global variables. - if (GVNonLazyPtrs.begin() != GVNonLazyPtrs.end()) + if (!GVNonLazyPtrs.empty()) SwitchToDataSection(".non_lazy_symbol_pointer", 0); for (std::set::iterator i = GVNonLazyPtrs.begin(), e = GVNonLazyPtrs.end(); i != e; ++i) { - O << "L" << *i << "$non_lazy_ptr:\n"; + std::string p = *i; + printSuffixedName(p, "$non_lazy_ptr"); + O << ":\n"; O << "\t.indirect_symbol " << *i << "\n"; O << "\t.long\t0\n"; } @@ -855,8 +1056,10 @@ bool ARMAsmPrinter::doFinalization(Module &M) { // linker can safely perform dead code stripping. Since LLVM never // generates code that does this, it is always safe to set. O << "\t.subsections_via_symbols\n"; + } else { + // Emit final debug information for ELF. + DW.EndModule(); } - AsmPrinter::doFinalization(M); - return false; // success + return AsmPrinter::doFinalization(M); }