X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FARM%2FAsmPrinter%2FARMAsmPrinter.cpp;h=822cc2eb75b3c6a5590d62b4e041afdcad0e2d68;hb=caa0c2caddcfb56de09e016c4c153d0609ffcf6e;hp=e7e8f276a1f0d36a1151b30677a1842f705d82ae;hpb=6aa38987302a5c272900607b201aa95a0e1eafd3;p=oota-llvm.git diff --git a/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp b/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp index e7e8f276a1f..822cc2eb75b 100644 --- a/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp +++ b/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp @@ -29,12 +29,13 @@ #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" -#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/Statistic.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringSet.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/Mangler.h" #include "llvm/Support/MathExtras.h" +#include "llvm/Support/raw_ostream.h" #include using namespace llvm; @@ -42,13 +43,13 @@ STATISTIC(EmittedInsts, "Number of machine instrs printed"); namespace { struct VISIBILITY_HIDDEN ARMAsmPrinter : public AsmPrinter { - ARMAsmPrinter(std::ostream &O, TargetMachine &TM, const TargetAsmInfo *T) - : AsmPrinter(O, TM, T), DW(O, this, T), MMI(NULL), AFI(NULL), + ARMAsmPrinter(raw_ostream &O, TargetMachine &TM, const TargetAsmInfo *T) + : AsmPrinter(O, TM, T), DW(0), MMI(NULL), AFI(NULL), MCP(NULL), InCPMode(false) { Subtarget = &TM.getSubtarget(); } - DwarfWriter DW; + DwarfWriter *DW; MachineModuleInfo *MMI; /// Subtarget - Keep a pointer to the ARMSubtarget around so that we can @@ -56,9 +57,13 @@ namespace { const ARMSubtarget *Subtarget; /// AFI - Keep a pointer to ARMFunctionInfo for the current - /// MachineFunction + /// MachineFunction. ARMFunctionInfo *AFI; + /// MCP - Keep a pointer to constantpool entries of the current + /// MachineFunction. + const MachineConstantPool *MCP; + /// We name each basic block in a Function with a unique number, so /// that we can consistently refer to them later. This is cleared /// at the beginning of each call to runOnMachineFunction(). @@ -68,15 +73,15 @@ namespace { /// GVNonLazyPtrs - Keeps the set of GlobalValues that require /// non-lazy-pointers for indirect access. - std::set GVNonLazyPtrs; + StringSet<> 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. - std::set FnStubs; - - /// PCRelGVs - Keeps the set of GlobalValues used in pc relative - /// constantpool. - SmallPtrSet PCRelGVs; + StringSet<> FnStubs; /// True if asm printer is printing a series of CONSTPOOL_ENTRY. bool InCPMode; @@ -125,10 +130,6 @@ namespace { bool doInitialization(Module &M); bool doFinalization(Module &M); - /// getSectionForFunction - Return the section that we should emit the - /// specified function body into. - virtual std::string getSectionForFunction(const Function &F) const; - /// EmitMachineConstantPoolValue - Print a machine constantpool value to /// the .s file. virtual void EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) { @@ -140,7 +141,10 @@ namespace { if (!GV) Name += ACPV->getSymbol(); if (ACPV->isNonLazyPointer()) { - GVNonLazyPtrs.insert(Name); + if (GV->hasHiddenVisibility()) + HiddenGVNonLazyPtrs.insert(Name); + else + GVNonLazyPtrs.insert(Name); printSuffixedName(Name, "$non_lazy_ptr"); } else if (ACPV->isStub()) { FnStubs.insert(Name); @@ -168,22 +172,19 @@ namespace { AsmPrinter::getAnalysisUsage(AU); AU.setPreservesAll(); AU.addRequired(); + AU.addRequired(); } }; } // end of anonymous namespace #include "ARMGenAsmWriter.inc" -// Substitute old hook with new one temporary -std::string ARMAsmPrinter::getSectionForFunction(const Function &F) const { - return TAI->SectionForGlobal(&F); -} - /// runOnMachineFunction - This uses the printInstruction() /// method to print assembly for each instruction. /// bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) { AFI = MF.getInfo(); + MCP = MF.getConstantPool(); SetupMachineFunction(MF); O << "\n"; @@ -196,6 +197,7 @@ bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) { const Function *F = MF.getFunction(); switch (F->getLinkage()) { default: assert(0 && "Unknown linkage type!"); + case Function::PrivateLinkage: case Function::InternalLinkage: SwitchToTextSection("\t.text", F); break; @@ -231,8 +233,7 @@ bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) { O << CurrentFnName << ":\n"; // Emit pre-function debug information. - // FIXME: Dwarf support. - //DW.BeginFunction(&MF); + DW->BeginFunction(&MF); if (Subtarget->isTargetDarwin()) { // If the function is empty, then we need to emit *something*. Otherwise, @@ -263,8 +264,9 @@ bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) { O << "\t.size " << CurrentFnName << ", .-" << CurrentFnName << "\n"; // Emit post-function debug information. - // FIXME: Dwarf support. - //DW.EndFunction(); + DW->EndFunction(&MF); + + O.flush(); return false; } @@ -301,12 +303,9 @@ void ARMAsmPrinter::printOperand(const MachineInstr *MI, int opNum, FnStubs.insert(Name); } else O << Name; - - if (MO.getOffset() > 0) - O << '+' << MO.getOffset(); - else if (MO.getOffset() < 0) - O << MO.getOffset(); - + + printOffset(MO.getOffset()); + if (isCallOp && Subtarget->isTargetELF() && TM.getRelocationModel() == Reloc::PIC_) O << "(PLT)"; @@ -342,11 +341,11 @@ void ARMAsmPrinter::printOperand(const MachineInstr *MI, int opNum, } } -static void printSOImm(std::ostream &O, int64_t V, const TargetAsmInfo *TAI) { +static void printSOImm(raw_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". if (Rot) { @@ -362,15 +361,15 @@ static void printSOImm(std::ostream &O, int64_t V, const TargetAsmInfo *TAI) { /// 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!"); + assert(MO.isImm() && "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. +/// printSOImm2PartOperand - SOImm is broken into two pieces using a 'mov' +/// followed by an 'orr' 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!"); + 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), TAI); @@ -416,7 +415,7 @@ void ARMAsmPrinter::printAddrMode2Operand(const MachineInstr *MI, int 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. + if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right. printOperand(MI, Op); return; } @@ -529,7 +528,7 @@ void ARMAsmPrinter::printAddrMode5Operand(const MachineInstr *MI, int Op, const MachineOperand &MO1 = MI->getOperand(Op); const MachineOperand &MO2 = MI->getOperand(Op+1); - if (!MO1.isRegister()) { // FIXME: This is for CP entries, but isn't right. + if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right. printOperand(MI, Op); return; } @@ -590,7 +589,7 @@ ARMAsmPrinter::printThumbAddrModeRI5Operand(const MachineInstr *MI, int 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. + if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right. printOperand(MI, Op); return; } @@ -669,17 +668,10 @@ void ARMAsmPrinter::printCPInstOperand(const MachineInstr *MI, int OpNo, assert(!strcmp(Modifier, "cpentry") && "Unknown modifier for CPE"); unsigned CPI = MI->getOperand(OpNo).getIndex(); - const MachineConstantPoolEntry &MCPE = // Chasing pointers is fun? - MI->getParent()->getParent()->getConstantPool()->getConstants()[CPI]; + const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPI]; if (MCPE.isMachineConstantPoolEntry()) { EmitMachineConstantPoolValue(MCPE.Val.MachineCPVal); - ARMConstantPoolValue *ACPV = - static_cast(MCPE.Val.MachineCPVal); - if (ACPV->getPCAdjustment() != 0) { - const GlobalValue *GV = ACPV->getGV(); - PCRelGVs.insert(GV); - } } else { EmitGlobalConstant(MCPE.Val.ConstVal); // remember to emit the weak reference @@ -753,9 +745,9 @@ 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).isRegister() || + if (!MI->getOperand(OpNo).isReg() || OpNo+1 == MI->getNumOperands() || - !MI->getOperand(OpNo+1).isRegister()) + !MI->getOperand(OpNo+1).isReg()) return true; ++OpNo; // Return the high-part. } @@ -779,23 +771,6 @@ void ARMAsmPrinter::printMachineInstruction(const MachineInstr *MI) { 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; - } }} // Call the autogenerated instruction printer routines. @@ -803,17 +778,15 @@ void ARMAsmPrinter::printMachineInstruction(const MachineInstr *MI) { } bool ARMAsmPrinter::doInitialization(Module &M) { - // Emit initial debug information. - // FIXME: Dwarf support. - //DW.BeginModule(&M); - + bool Result = AsmPrinter::doInitialization(M); - // AsmPrinter::doInitialization should have done this analysis. - MMI = getAnalysisToUpdate(); + // Emit initial debug information. + MMI = getAnalysisIfAvailable(); assert(MMI); - // FIXME: Dwarf support. - //DW.SetModuleInfo(MMI); + DW = getAnalysisIfAvailable(); + assert(DW && "Dwarf Writer is not available"); + DW->BeginModule(&M, MMI, O, this, TAI); // Darwin wants symbols to be quoted if they have complex names. if (Subtarget->isTargetDarwin()) @@ -824,7 +797,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, std::ostream &OS) { +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)) @@ -850,24 +823,25 @@ void ARMAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) { return; } - std::string SectionName = TAI->SectionForGlobal(GVar); std::string name = Mang->getValueName(GVar); Constant *C = GVar->getInitializer(); const Type *Type = C->getType(); - unsigned Size = TD->getABITypeSize(Type); + unsigned Size = TD->getTypePaddedSize(Type); unsigned Align = TD->getPreferredAlignmentLog(GVar); + bool isDarwin = Subtarget->isTargetDarwin(); printVisibility(name, GVar->getVisibility()); if (Subtarget->isTargetELF()) O << "\t.type " << name << ",%object\n"; - SwitchToDataSection(SectionName.c_str()); - - if (C->isNullValue() && !GVar->hasSection() && !GVar->isThreadLocal()) { + if (C->isNullValue() && !GVar->hasSection() && !GVar->isThreadLocal() && + !(isDarwin && + TAI->SectionKindForGlobal(GVar) == SectionKind::RODataMergeStr)) { // FIXME: This seems to be pretty darwin-specific if (GVar->hasExternalLinkage()) { + SwitchToSection(TAI->SectionForGlobal(GVar)); if (const char *Directive = TAI->getZeroFillDirective()) { O << "\t.globl\t" << name << "\n"; O << Directive << "__DATA, __common, " << name << ", " @@ -876,18 +850,38 @@ void ARMAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) { } } - if (GVar->hasInternalLinkage() || GVar->isWeakForLinker()) { + if (GVar->hasLocalLinkage() || GVar->mayBeOverridden()) { if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it. - if (TAI->getLCOMMDirective() != NULL) { - if (PCRelGVs.count(GVar) || GVar->hasInternalLinkage()) { + if (isDarwin) { + if (GVar->hasLocalLinkage()) { + O << TAI->getLCOMMDirective() << name << "," << Size + << ',' << Align; + } else if (GVar->hasCommonLinkage()) { + O << TAI->getCOMMDirective() << name << "," << Size + << ',' << Align; + } else { + SwitchToSection(TAI->SectionForGlobal(GVar)); + O << "\t.globl " << name << '\n' + << TAI->getWeakDefDirective() << name << '\n'; + EmitAlignment(Align, GVar); + O << name << ":\t\t\t\t" << TAI->getCommentString() << ' '; + PrintUnmangledNameSafely(GVar, O); + O << '\n'; + EmitGlobalConstant(C); + return; + } + } else if (TAI->getLCOMMDirective() != NULL) { + if (GVar->hasLocalLinkage()) { O << TAI->getLCOMMDirective() << name << "," << Size; - if (Subtarget->isTargetDarwin()) - O << "," << Align; - } else + } else { O << TAI->getCOMMDirective() << name << "," << Size; + if (TAI->getCOMMDirectiveTakesAlignment()) + O << ',' << (TAI->getAlignmentIsInBytes() ? (1 << Align) : Align); + } } else { - if (GVar->hasInternalLinkage()) + SwitchToSection(TAI->SectionForGlobal(GVar)); + if (GVar->hasLocalLinkage()) O << "\t.local\t" << name << "\n"; O << TAI->getCOMMDirective() << name << "," << Size; if (TAI->getCOMMDirectiveTakesAlignment()) @@ -900,10 +894,12 @@ void ARMAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) { } } + SwitchToSection(TAI->SectionForGlobal(GVar)); switch (GVar->getLinkage()) { + case GlobalValue::CommonLinkage: case GlobalValue::LinkOnceLinkage: case GlobalValue::WeakLinkage: - if (Subtarget->isTargetDarwin()) { + if (isDarwin) { O << "\t.globl " << name << "\n" << "\t.weak_definition " << name << "\n"; } else { @@ -916,6 +912,7 @@ void ARMAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) { case GlobalValue::ExternalLinkage: O << "\t.globl " << name << "\n"; // FALL THROUGH + case GlobalValue::PrivateLinkage: case GlobalValue::InternalLinkage: break; default: @@ -950,9 +947,8 @@ bool ARMAsmPrinter::doFinalization(Module &M) { SwitchToDataSection(""); // Output stubs for dynamically-linked functions - unsigned j = 1; - for (std::set::iterator i = FnStubs.begin(), e = FnStubs.end(); - i != e; ++i, ++j) { + 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); @@ -963,10 +959,10 @@ bool ARMAsmPrinter::doFinalization(Module &M) { EmitAlignment(2); O << "\t.code\t32\n"; - std::string p = *i; + const char *p = i->getKeyData(); printSuffixedName(p, "$stub"); O << ":\n"; - O << "\t.indirect_symbol " << *i << "\n"; + O << "\t.indirect_symbol " << p << "\n"; O << "\tldr ip, "; printSuffixedName(p, "$slp"); O << "\n"; @@ -989,26 +985,39 @@ bool ARMAsmPrinter::doFinalization(Module &M) { SwitchToDataSection(".lazy_symbol_pointer", 0); printSuffixedName(p, "$lazy_ptr"); O << ":\n"; - O << "\t.indirect_symbol " << *i << "\n"; + O << "\t.indirect_symbol " << p << "\n"; O << "\t.long\tdyld_stub_binding_helper\n"; } O << "\n"; // Output non-lazy-pointers for external and common global variables. - if (!GVNonLazyPtrs.empty()) - SwitchToDataSection(".non_lazy_symbol_pointer", 0); - for (std::set::iterator i = GVNonLazyPtrs.begin(), - e = GVNonLazyPtrs.end(); i != e; ++i) { - std::string p = *i; - printSuffixedName(p, "$non_lazy_ptr"); - O << ":\n"; - O << "\t.indirect_symbol " << *i << "\n"; - O << "\t.long\t0\n"; + 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"; + 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"; + } + } + + // Emit initial debug information. - // FIXME: Dwarf support. - //DW.EndModule(); + DW->EndModule(); // 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 @@ -1018,8 +1027,7 @@ bool ARMAsmPrinter::doFinalization(Module &M) { O << "\t.subsections_via_symbols\n"; } else { // Emit final debug information for ELF. - // FIXME: Dwarf support. - //DW.EndModule(); + DW->EndModule(); } return AsmPrinter::doFinalization(M); @@ -1030,7 +1038,7 @@ 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(std::ostream &o, +FunctionPass *llvm::createARMCodePrinterPass(raw_ostream &o, ARMTargetMachine &tm) { return new ARMAsmPrinter(o, tm, tm.getTargetAsmInfo()); }