X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FARM%2FAsmPrinter%2FARMAsmPrinter.cpp;h=7270e37fa2bf6718c8a0bb85dfa05769cfe21c0e;hb=f05522974b3c1b9dc2644831364e19d5132e751b;hp=2bfdcca98d1a496632258485a0727ea4ec92a147;hpb=e4c0c0fab8caadd8159f6bdd6fa03e66d4b4af9c;p=oota-llvm.git diff --git a/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp b/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp index 2bfdcca98d1..7270e37fa2b 100644 --- a/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp +++ b/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp @@ -31,13 +31,15 @@ #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" +#include "llvm/Target/TargetRegistry.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 using namespace llvm; @@ -68,23 +70,47 @@ namespace { /// GVNonLazyPtrs - Keeps the set of GlobalValues that require /// non-lazy-pointers for indirect access. - StringSet<> GVNonLazyPtrs; + StringMap GVNonLazyPtrs; /// HiddenGVNonLazyPtrs - Keeps the set of GlobalValues with hidden /// visibility that require non-lazy-pointers for indirect access. - StringSet<> HiddenGVNonLazyPtrs; - + StringMap HiddenGVNonLazyPtrs; + + struct FnStubInfo { + std::string Stub, LazyPtr, SLP, SCV; + + FnStubInfo() {} + + void Init(const GlobalValue *GV, Mangler *Mang) { + // Already initialized. + if (!Stub.empty()) return; + Stub = Mang->getMangledName(GV, "$stub", true); + LazyPtr = Mang->getMangledName(GV, "$lazy_ptr", true); + SLP = Mang->getMangledName(GV, "$slp", true); + SCV = Mang->getMangledName(GV, "$scv", true); + } + + void Init(const std::string &GV, Mangler *Mang) { + // Already initialized. + if (!Stub.empty()) return; + Stub = Mang->makeNameProper(GV+"$stub", true); + LazyPtr = Mang->makeNameProper(GV+"$lazy_ptr", true); + SLP = Mang->makeNameProper(GV+"$slp", true); + SCV = Mang->makeNameProper(GV+"$scv", true); + } + + }; + /// FnStubs - Keeps the set of external function GlobalAddresses that the /// asm printer should generate stubs for. - StringSet<> FnStubs; + StringMap FnStubs; /// True if asm printer is printing a series of CONSTPOOL_ENTRY. bool InCPMode; public: - explicit ARMAsmPrinter(raw_ostream &O, TargetMachine &TM, - const TargetAsmInfo *T, CodeGenOpt::Level OL, - bool V) - : AsmPrinter(O, TM, T, OL, V), DW(0), AFI(NULL), MCP(NULL), + explicit ARMAsmPrinter(formatted_raw_ostream &O, TargetMachine &TM, + const TargetAsmInfo *T, bool V) + : AsmPrinter(O, TM, T, V), DW(0), AFI(NULL), MCP(NULL), InCPMode(false) { Subtarget = &TM.getSubtarget(); } @@ -93,42 +119,51 @@ namespace { return "ARM Assembly Printer"; } - void printOperand(const MachineInstr *MI, int opNum, + 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 printSOOperand(const MachineInstr *MI, int OpNum); - void printSORegOperand(const MachineInstr *MI, int opNum); - void printT2SOImmOperand(const MachineInstr *MI, int opNum); - void printAddrMode2Operand(const MachineInstr *MI, int OpNo); - void printAddrMode2OffsetOperand(const MachineInstr *MI, int OpNo); - void printAddrMode3Operand(const MachineInstr *MI, int OpNo); - void printAddrMode3OffsetOperand(const MachineInstr *MI, int OpNo); - void printAddrMode4Operand(const MachineInstr *MI, int OpNo, + 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 OpNum); + void printAddrMode2OffsetOperand(const MachineInstr *MI, int OpNum); + void printAddrMode3Operand(const MachineInstr *MI, int OpNum); + void printAddrMode3OffsetOperand(const MachineInstr *MI, int OpNum); + void printAddrMode4Operand(const MachineInstr *MI, int OpNum, const char *Modifier = 0); - void printAddrMode5Operand(const MachineInstr *MI, int OpNo, + void printAddrMode5Operand(const MachineInstr *MI, int OpNum, const char *Modifier = 0); - void printAddrModePCOperand(const MachineInstr *MI, int OpNo, + void printAddrMode6Operand(const MachineInstr *MI, int OpNum); + void printAddrModePCOperand(const MachineInstr *MI, int OpNum, const char *Modifier = 0); - void printBitfieldInvMaskImmOperand (const MachineInstr *MI, int OpNo); - void printThumbAddrModeRROperand(const MachineInstr *MI, int OpNo); - void printThumbAddrModeRI5Operand(const MachineInstr *MI, int OpNo, + 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); - 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 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, + void printThumbAddrModeS1Operand(const MachineInstr *MI, int OpNum); + void printThumbAddrModeS2Operand(const MachineInstr *MI, int OpNum); + void printThumbAddrModeS4Operand(const MachineInstr *MI, int OpNum); + void printThumbAddrModeSPOperand(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); + + 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, const char *Modifier); - void printJTBlockOperand(const MachineInstr *MI, int opNum); + void printJTBlockOperand(const MachineInstr *MI, int OpNum); - virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, + virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNum, unsigned AsmVariant, const char *ExtraCode); - virtual bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, + virtual bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum, unsigned AsmVariant, const char *ExtraCode); @@ -146,20 +181,37 @@ namespace { ARMConstantPoolValue *ACPV = static_cast(MCPV); GlobalValue *GV = ACPV->getGV(); - std::string Name = GV ? Mang->getValueName(GV) : TAI->getGlobalPrefix(); - if (!GV) - Name += ACPV->getSymbol(); + std::string Name; + + if (ACPV->isNonLazyPointer()) { + std::string SymName = Mang->getMangledName(GV); + Name = Mang->getMangledName(GV, "$non_lazy_ptr", true); + if (GV->hasHiddenVisibility()) - HiddenGVNonLazyPtrs.insert(Name); + HiddenGVNonLazyPtrs[SymName] = Name; else - GVNonLazyPtrs.insert(Name); - printSuffixedName(Name, "$non_lazy_ptr"); + GVNonLazyPtrs[SymName] = Name; } else if (ACPV->isStub()) { - FnStubs.insert(Name); - printSuffixedName(Name, "$stub"); - } else - O << Name; + if (GV) { + FnStubInfo &FnInfo = FnStubs[Mang->getMangledName(GV)]; + FnInfo.Init(GV, Mang); + Name = FnInfo.Stub; + } else { + FnStubInfo &FnInfo = FnStubs[Mang->makeNameProper(ACPV->getSymbol())]; + FnInfo.Init(ACPV->getSymbol(), Mang); + Name = FnInfo.Stub; + } + } else { + if (GV) + Name = Mang->getMangledName(GV); + else + Name = Mang->makeNameProper(ACPV->getSymbol()); + } + O << Name; + + + if (ACPV->hasModifier()) O << "(" << ACPV->getModifier() << ")"; if (ACPV->getPCAdjustment() != 0) { O << "-(" << TAI->getPrivateGlobalPrefix() << "PC" @@ -202,7 +254,7 @@ bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) { // Print out labels for the function. const Function *F = MF.getFunction(); 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); @@ -229,15 +281,16 @@ bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) { printVisibility(CurrentFnName, F->getVisibility()); if (AFI->isThumbFunction()) { - EmitAlignment(1, F, AFI->getAlign()); + EmitAlignment(MF.getAlignment(), F, AFI->getAlign()); O << "\t.code\t16\n"; O << "\t.thumb_func"; if (Subtarget->isTargetDarwin()) O << "\t" << CurrentFnName; O << "\n"; InCPMode = false; - } else - EmitAlignment(2, F); + } else { + EmitAlignment(MF.getAlignment(), F); + } O << CurrentFnName << ":\n"; // Emit pre-function debug information. @@ -279,9 +332,9 @@ bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) { return false; } -void ARMAsmPrinter::printOperand(const MachineInstr *MI, int opNum, +void ARMAsmPrinter::printOperand(const MachineInstr *MI, int OpNum, const char *Modifier) { - const MachineOperand &MO = MI->getOperand(opNum); + const MachineOperand &MO = MI->getOperand(OpNum); switch (MO.getType()) { case MachineOperand::MO_Register: { unsigned Reg = MO.getReg(); @@ -290,13 +343,15 @@ 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) + << TRI->getAsmName(DRegLo) << ',' << TRI->getAsmName(DRegHi) << '}'; + } else if (Modifier && strcmp(Modifier, "dregsingle") == 0) { + O << '{' << TRI->getAsmName(Reg) << '}'; } else { O << TRI->getAsmName(Reg); } } else - assert(0 && "not implemented"); + llvm_unreachable("not implemented"); break; } case MachineOperand::MO_Immediate: { @@ -312,15 +367,18 @@ void ARMAsmPrinter::printOperand(const MachineInstr *MI, int opNum, 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()); + std::string Name; + bool isExt = GV->isDeclaration() || GV->isWeakForLinker(); if (isExt && isCallOp && Subtarget->isTargetDarwin() && TM.getRelocationModel() != Reloc::Static) { - printSuffixedName(Name, "$stub"); - FnStubs.insert(Name); - } else - O << Name; + FnStubInfo &FnInfo = FnStubs[Mang->getMangledName(GV)]; + FnInfo.Init(GV, Mang); + Name = FnInfo.Stub; + } else { + Name = Mang->getMangledName(GV); + } + + O << Name; printOffset(MO.getOffset()); @@ -331,14 +389,16 @@ 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(); + std::string Name; if (isCallOp && Subtarget->isTargetDarwin() && TM.getRelocationModel() != Reloc::Static) { - printSuffixedName(Name, "$stub"); - FnStubs.insert(Name); + FnStubInfo &FnInfo = FnStubs[Mang->makeNameProper(MO.getSymbolName())]; + FnInfo.Init(MO.getSymbolName(), Mang); + Name = FnInfo.Stub; } else - O << Name; + Name = Mang->makeNameProper(MO.getSymbolName()); + + O << Name; if (isCallOp && Subtarget->isTargetELF() && TM.getRelocationModel() == Reloc::PIC_) O << "(PLT)"; @@ -357,9 +417,12 @@ void ARMAsmPrinter::printOperand(const MachineInstr *MI, int opNum, } } -static void printSOImm(raw_ostream &O, int64_t V, bool VerboseAsm, +static void printSOImm(formatted_raw_ostream &O, int64_t V, bool VerboseAsm, const TargetAsmInfo *TAI) { - assert(V < (1 << 12) && "Not a valid so_imm value!"); + // 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); @@ -391,7 +454,7 @@ 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, TAI); O << "\n\torr"; printPredicateOperand(MI, 2); O << " "; @@ -399,35 +462,13 @@ void ARMAsmPrinter::printSOImm2PartOperand(const MachineInstr *MI, int OpNum) { O << ", "; printOperand(MI, 0); O << ", "; - printSOImm(O, ARM_AM::getSOImmVal(V2), VerboseAsm, TAI); -} - -// Constant shifts so_reg is a 3-operand unit corresponding to register forms of -// the A5.1 "Addressing Mode 1 - Data-processing operands" forms. This -// includes: -// REG 0 - e.g. R5 -// REG IMM, SH_OPC - e.g. R5, LSL #3 -void ARMAsmPrinter::printSOOperand(const MachineInstr *MI, int OpNum) { - const MachineOperand &MO1 = MI->getOperand(OpNum); - const MachineOperand &MO2 = MI->getOperand(OpNum+1); - - unsigned Reg = MO1.getReg(); - assert(TargetRegisterInfo::isPhysicalRegister(Reg)); - O << TM.getRegisterInfo()->getAsmName(Reg); - - // Print the shift opc. - O << ", " - << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO2.getImm())) - << " "; - - assert(MO2.isImm() && "Not a valid t2_so_reg value!"); - O << "#" << ARM_AM::getSORegOffset(MO2.getImm()); + printSOImm(O, V2, VerboseAsm, 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 -// REG REG 0,SH_OPC - e.g. R5, ROR R3 +// REG 0 0 - e.g. R5 +// REG REG 0,SH_OPC - e.g. R5, ROR R3 // REG 0 IMM,SH_OPC - e.g. R5, LSL #3 void ARMAsmPrinter::printSORegOperand(const MachineInstr *MI, int Op) { const MachineOperand &MO1 = MI->getOperand(Op); @@ -435,7 +476,7 @@ void ARMAsmPrinter::printSORegOperand(const MachineInstr *MI, int Op) { const MachineOperand &MO3 = MI->getOperand(Op+2); assert(TargetRegisterInfo::isPhysicalRegister(MO1.getReg())); - O << TM.getRegisterInfo()->get(MO1.getReg()).AsmName; + O << TRI->getAsmName(MO1.getReg()); // Print the shift opc. O << ", " @@ -444,31 +485,13 @@ void ARMAsmPrinter::printSORegOperand(const MachineInstr *MI, int Op) { if (MO2.getReg()) { assert(TargetRegisterInfo::isPhysicalRegister(MO2.getReg())); - O << TM.getRegisterInfo()->get(MO2.getReg()).AsmName; + O << TRI->getAsmName(MO2.getReg()); assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0); } else { O << "#" << ARM_AM::getSORegOffset(MO3.getImm()); } } -static void printT2SOImm(raw_ostream &O, int64_t V) { - unsigned Imm = ARM_AM::getT2SOImmValDecode(V); - - // Always print the immediate directly, as the "rotate" form - // is deprecated in some contexts. - O << "#" << Imm; -} - -/// 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!"); - printT2SOImm(O, MO.getImm()); -} - void ARMAsmPrinter::printAddrMode2Operand(const MachineInstr *MI, int Op) { const MachineOperand &MO1 = MI->getOperand(Op); const MachineOperand &MO2 = MI->getOperand(Op+1); @@ -479,7 +502,7 @@ void ARMAsmPrinter::printAddrMode2Operand(const MachineInstr *MI, int Op) { return; } - O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName; + O << "[" << TRI->getAsmName(MO1.getReg()); if (!MO2.getReg()) { if (ARM_AM::getAM2Offset(MO3.getImm())) // Don't print +0. @@ -492,7 +515,7 @@ void ARMAsmPrinter::printAddrMode2Operand(const MachineInstr *MI, int Op) { O << ", " << (char)ARM_AM::getAM2Op(MO3.getImm()) - << TM.getRegisterInfo()->get(MO2.getReg()).AsmName; + << TRI->getAsmName(MO2.getReg()); if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm())) O << ", " @@ -515,7 +538,7 @@ void ARMAsmPrinter::printAddrMode2OffsetOperand(const MachineInstr *MI, int Op){ } O << (char)ARM_AM::getAM2Op(MO2.getImm()) - << TM.getRegisterInfo()->get(MO1.getReg()).AsmName; + << TRI->getAsmName(MO1.getReg()); if (unsigned ShImm = ARM_AM::getAM2Offset(MO2.getImm())) O << ", " @@ -529,12 +552,12 @@ void ARMAsmPrinter::printAddrMode3Operand(const MachineInstr *MI, int Op) { const MachineOperand &MO3 = MI->getOperand(Op+2); assert(TargetRegisterInfo::isPhysicalRegister(MO1.getReg())); - O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName; + O << "[" << TRI->getAsmName(MO1.getReg()); if (MO2.getReg()) { O << ", " << (char)ARM_AM::getAM3Op(MO3.getImm()) - << TM.getRegisterInfo()->get(MO2.getReg()).AsmName + << TRI->getAsmName(MO2.getReg()) << "]"; return; } @@ -552,7 +575,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; + << TRI->getAsmName(MO1.getReg()); return; } @@ -605,13 +628,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()).AsmName; + O << TRI->getAsmName(MO1.getReg()); if (ARM_AM::getAM5WBFlag(MO2.getImm())) O << "!"; return; } - O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName; + O << "[" << TRI->getAsmName(MO1.getReg()); if (unsigned ImmOffs = ARM_AM::getAM5Offset(MO2.getImm())) { O << ", #" @@ -621,6 +644,22 @@ void ARMAsmPrinter::printAddrMode5Operand(const MachineInstr *MI, int Op, O << "]"; } +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); + + // FIXME: No support yet for specifying alignment. + O << "[" << TRI->getAsmName(MO1.getReg()) << "]"; + + if (ARM_AM::getAM6WBFlag(MO3.getImm())) { + if (MO2.getReg() == 0) + O << "!"; + else + O << ", " << TRI->getAsmName(MO2.getReg()); + } +} + void ARMAsmPrinter::printAddrModePCOperand(const MachineInstr *MI, int Op, const char *Modifier) { if (Modifier && strcmp(Modifier, "label") == 0) { @@ -630,25 +669,42 @@ 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, +" << TRI->getAsmName(MO1.getReg()) << "]"; } void ARMAsmPrinter::printBitfieldInvMaskImmOperand(const MachineInstr *MI, int Op) { const MachineOperand &MO = MI->getOperand(Op); uint32_t v = ~MO.getImm(); - int32_t lsb = ffs (v) - 1; + int32_t lsb = CountTrailingZeros_32(v); int32_t width = (32 - CountLeadingZeros_32 (v)) - lsb; assert(MO.isImm() && "Not a valid bf_inv_mask_imm value!"); O << "#" << lsb << ", #" << width; } +//===--------------------------------------------------------------------===// + +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 << "[" << TRI->getAsmName(MO1.getReg()); + O << ", " << TRI->getAsmName(MO2.getReg()) << "]"; } void @@ -663,9 +719,9 @@ ARMAsmPrinter::printThumbAddrModeRI5Operand(const MachineInstr *MI, int Op, return; } - O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName; + O << "[" << TRI->getAsmName(MO1.getReg()); if (MO3.getReg()) - O << ", " << TM.getRegisterInfo()->get(MO3.getReg()).AsmName; + O << ", " << TRI->getAsmName(MO3.getReg()); else if (unsigned ImmOffs = MO2.getImm()) { O << ", #" << ImmOffs; if (Scale > 1) @@ -690,52 +746,154 @@ 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 << "[" << TRI->getAsmName(MO1.getReg()); if (unsigned ImmOffs = MO2.getImm()) O << ", #" << ImmOffs << " * 4"; O << "]"; } -void ARMAsmPrinter::printPredicateOperand(const MachineInstr *MI, int opNum) { - ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(opNum).getImm(); +//===--------------------------------------------------------------------===// + +// Constant shifts t2_so_reg is a 2-operand unit corresponding to the Thumb2 +// register with shift forms. +// REG 0 0 - e.g. R5 +// REG IMM, SH_OPC - e.g. R5, LSL #3 +void ARMAsmPrinter::printT2SOOperand(const MachineInstr *MI, int OpNum) { + const MachineOperand &MO1 = MI->getOperand(OpNum); + const MachineOperand &MO2 = MI->getOperand(OpNum+1); + + unsigned Reg = MO1.getReg(); + assert(TargetRegisterInfo::isPhysicalRegister(Reg)); + O << TRI->getAsmName(Reg); + + // Print the shift opc. + O << ", " + << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO2.getImm())) + << " "; + + assert(MO2.isImm() && "Not a valid t2_so_reg value!"); + O << "#" << ARM_AM::getSORegOffset(MO2.getImm()); +} + +void ARMAsmPrinter::printT2AddrModeImm12Operand(const MachineInstr *MI, + int OpNum) { + const MachineOperand &MO1 = MI->getOperand(OpNum); + const MachineOperand &MO2 = MI->getOperand(OpNum+1); + + O << "[" << TRI->getAsmName(MO1.getReg()); + + unsigned OffImm = MO2.getImm(); + if (OffImm) // Don't print +0. + O << ", #+" << OffImm; + O << "]"; +} + +void ARMAsmPrinter::printT2AddrModeImm8Operand(const MachineInstr *MI, + int OpNum) { + const MachineOperand &MO1 = MI->getOperand(OpNum); + const MachineOperand &MO2 = MI->getOperand(OpNum+1); + + O << "[" << TRI->getAsmName(MO1.getReg()); + + int32_t OffImm = (int32_t)MO2.getImm(); + // Don't print +0. + if (OffImm < 0) + O << ", #-" << -OffImm; + else if (OffImm > 0) + O << ", #+" << OffImm; + O << "]"; +} + +void ARMAsmPrinter::printT2AddrModeImm8s4Operand(const MachineInstr *MI, + int OpNum) { + const MachineOperand &MO1 = MI->getOperand(OpNum); + const MachineOperand &MO2 = MI->getOperand(OpNum+1); + + O << "[" << TRI->getAsmName(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); + int32_t OffImm = (int32_t)MO1.getImm(); + // Don't print +0. + if (OffImm < 0) + O << "#-" << -OffImm; + else if (OffImm > 0) + O << "#+" << OffImm; +} + +void ARMAsmPrinter::printT2AddrModeSoRegOperand(const MachineInstr *MI, + int OpNum) { + const MachineOperand &MO1 = MI->getOperand(OpNum); + const MachineOperand &MO2 = MI->getOperand(OpNum+1); + const MachineOperand &MO3 = MI->getOperand(OpNum+2); + + O << "[" << TRI->getAsmName(MO1.getReg()); + + if (MO2.getReg()) { + O << ", +" << TRI->getAsmName(MO2.getReg()); + + unsigned ShAmt = MO3.getImm(); + if (ShAmt) { + assert(ShAmt <= 3 && "Not a valid Thumb2 addressing mode!"); + O << ", lsl #" << ShAmt; + } + } + O << "]"; +} + + +//===--------------------------------------------------------------------===// + +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(); +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).getImm(); +void ARMAsmPrinter::printPCLabel(const MachineInstr *MI, int OpNum) { + int Id = (int)MI->getOperand(OpNum).getImm(); O << TAI->getPrivateGlobalPrefix() << "PC" << Id; } -void ARMAsmPrinter::printRegisterList(const MachineInstr *MI, int opNum) { +void ARMAsmPrinter::printRegisterList(const MachineInstr *MI, int OpNum) { O << "{"; - for (unsigned i = opNum, e = MI->getNumOperands(); i != e; ++i) { + for (unsigned i = OpNum, e = MI->getNumOperands(); i != e; ++i) { printOperand(MI, i); if (i != e-1) O << ", "; } O << "}"; } -void ARMAsmPrinter::printCPInstOperand(const MachineInstr *MI, int OpNo, +void ARMAsmPrinter::printCPInstOperand(const MachineInstr *MI, int OpNum, const char *Modifier) { assert(Modifier && "This operand only works with a modifier!"); // There are two aspects to a CONSTANTPOOL_ENTRY operand, the label and the // data itself. if (!strcmp(Modifier, "label")) { - unsigned ID = MI->getOperand(OpNo).getImm(); + unsigned ID = MI->getOperand(OpNum).getImm(); O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_' << ID << ":\n"; } else { assert(!strcmp(Modifier, "cpentry") && "Unknown modifier for CPE"); - unsigned CPI = MI->getOperand(OpNo).getIndex(); + unsigned CPI = MI->getOperand(OpNum).getIndex(); const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPI]; @@ -747,9 +905,9 @@ void ARMAsmPrinter::printCPInstOperand(const MachineInstr *MI, int OpNo, } } -void ARMAsmPrinter::printJTBlockOperand(const MachineInstr *MI, int OpNo) { - const MachineOperand &MO1 = MI->getOperand(OpNo); - const MachineOperand &MO2 = MI->getOperand(OpNo+1); // Unique Id +void ARMAsmPrinter::printJTBlockOperand(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 << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() << '_' << JTI << '_' << MO2.getImm() << ":\n"; @@ -788,7 +946,7 @@ void ARMAsmPrinter::printJTBlockOperand(const MachineInstr *MI, int OpNo) { } -bool ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, +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]) { @@ -796,12 +954,17 @@ bool ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 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, OpNo, "no_hash"); + case 'a': // Print as a memory address. + if (MI->getOperand(OpNum).isReg()) { + O << "[" << TRI->getAsmName(MI->getOperand(OpNum).getReg()) << "]"; + return false; + } + // Fallthrough + case 'c': // Don't print "#" before an immediate operand. + printOperand(MI, OpNum, "no_hash"); return false; case 'P': // Print a VFP double precision register. - printOperand(MI, OpNo); + printOperand(MI, OpNum); return false; case 'Q': if (TM.getTargetData()->isLittleEndian()) @@ -813,24 +976,24 @@ bool ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, // Fallthrough case 'H': // Write second word of DI / DF reference. // Verify that this operand has two consecutive registers. - if (!MI->getOperand(OpNo).isReg() || - OpNo+1 == MI->getNumOperands() || - !MI->getOperand(OpNo+1).isReg()) + if (!MI->getOperand(OpNum).isReg() || + OpNum+1 == MI->getNumOperands() || + !MI->getOperand(OpNum+1).isReg()) return true; - ++OpNo; // Return the high-part. + ++OpNum; // Return the high-part. } } - printOperand(MI, OpNo); + printOperand(MI, OpNum); return false; } bool ARMAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, - unsigned OpNo, unsigned AsmVariant, + unsigned OpNum, unsigned AsmVariant, const char *ExtraCode) { if (ExtraCode && ExtraCode[0]) return true; // Unknown modifier. - printAddrMode2Operand(MI, OpNo); + printAddrMode2Operand(MI, OpNum); return false; } @@ -859,8 +1022,8 @@ bool ARMAsmPrinter::doInitialization(Module &M) { bool Result = AsmPrinter::doInitialization(M); DW = getAnalysisIfAvailable(); - // 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 @@ -896,7 +1059,7 @@ bool ARMAsmPrinter::doInitialization(Module &M) { /// 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) { +static void PrintUnmangledNameSafely(const Value *V, formatted_raw_ostream &OS) { for (const char *Name = V->getNameStart(), *E = Name+V->getNameLen(); Name != E; ++Name) if (isprint(*Name)) @@ -922,9 +1085,9 @@ 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(C)) + if (isa(C) || isa(C)) return; const Type *Type = C->getType(); unsigned Size = TD->getTypeAllocSize(Type); @@ -1024,8 +1187,7 @@ void ARMAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) { case GlobalValue::InternalLinkage: break; default: - assert(0 && "Unknown linkage type!"); - break; + llvm_unreachable("Unknown linkage type!"); } EmitAlignment(Align, GVar); @@ -1051,9 +1213,11 @@ bool ARMAsmPrinter::doFinalization(Module &M) { if (Subtarget->isTargetDarwin()) { SwitchToDataSection(""); + O << '\n'; // Output stubs for dynamically-linked functions - for (StringSet<>::iterator i = FnStubs.begin(), e = FnStubs.end(); - i != e; ++i) { + for (StringMap::iterator I = FnStubs.begin(), E = FnStubs.end(); + I != E; ++I) { + const FnStubInfo &Info = I->second; if (TM.getRelocationModel() == Reloc::PIC_) SwitchToTextSection(".section __TEXT,__picsymbolstub4,symbol_stubs," "none,16", 0); @@ -1064,59 +1228,45 @@ bool ARMAsmPrinter::doFinalization(Module &M) { 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"; + O << Info.Stub << ":\n"; + O << "\t.indirect_symbol " << I->getKeyData() << '\n'; + O << "\tldr ip, " << Info.SLP << '\n'; if (TM.getRelocationModel() == Reloc::PIC_) { - printSuffixedName(p, "$scv"); - O << ":\n"; + O << Info.SCV << ":\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"; + O << Info.SLP << ":\n"; + O << "\t.long\t" << Info.LazyPtr; + if (TM.getRelocationModel() == Reloc::PIC_) + O << "-(" << Info.SCV << "+8)"; + O << '\n'; + SwitchToDataSection(".lazy_symbol_pointer", 0); - printSuffixedName(p, "$lazy_ptr"); - O << ":\n"; - O << "\t.indirect_symbol " << p << "\n"; + O << Info.LazyPtr << ":\n"; + O << "\t.indirect_symbol " << I->getKeyData() << "\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"; + for (StringMap::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(); + for (StringMap::iterator I = HiddenGVNonLazyPtrs.begin(), + E = HiddenGVNonLazyPtrs.end(); I != E; ++I) { EmitAlignment(2); - printSuffixedName(p, "$non_lazy_ptr"); - O << ":\n"; - O << "\t.long " << p << "\n"; + O << I->second << ":\n"; + O << "\t.long " << I->getKeyData() << "\n"; } } @@ -1137,20 +1287,15 @@ bool ARMAsmPrinter::doFinalization(Module &M) { /// using the given target machine description. This should work /// regardless of whether the function is in SSA form. /// -FunctionPass *llvm::createARMCodePrinterPass(raw_ostream &o, - ARMTargetMachine &tm, - CodeGenOpt::Level OptLevel, +FunctionPass *llvm::createARMCodePrinterPass(formatted_raw_ostream &o, + TargetMachine &tm, bool verbose) { - return new ARMAsmPrinter(o, tm, tm.getTargetAsmInfo(), OptLevel, verbose); -} - -namespace { - static struct Register { - Register() { - ARMTargetMachine::registerAsmPrinter(createARMCodePrinterPass); - } - } Registrator; + return new ARMAsmPrinter(o, tm, tm.getTargetAsmInfo(), verbose); } // Force static initialization. -extern "C" void LLVMInitializeARMAsmPrinter() { } +extern "C" void LLVMInitializeARMAsmPrinter() { + extern Target TheARMTarget, TheThumbTarget; + TargetRegistry::RegisterAsmPrinter(TheARMTarget, createARMCodePrinterPass); + TargetRegistry::RegisterAsmPrinter(TheThumbTarget, createARMCodePrinterPass); +}