X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FX86%2FX86AsmPrinter.cpp;h=990951ea7b8126fdb3dcffcd1cbe2319a428d226;hb=c60bd97b94261366800c2eb57e95ddd44092e6f8;hp=85cc3c28bdfae834f307181a85ffd0bc24eb04e5;hpb=ac2902bcb5568c9a4ff8fe1bbe794f656498ff89;p=oota-llvm.git diff --git a/lib/Target/X86/X86AsmPrinter.cpp b/lib/Target/X86/X86AsmPrinter.cpp index 85cc3c28bdf..990951ea7b8 100644 --- a/lib/Target/X86/X86AsmPrinter.cpp +++ b/lib/Target/X86/X86AsmPrinter.cpp @@ -14,20 +14,20 @@ // //===----------------------------------------------------------------------===// +#include "X86AsmPrinter.h" #include "X86ATTAsmPrinter.h" #include "X86IntelAsmPrinter.h" #include "X86Subtarget.h" -#include "X86.h" +#include "llvm/Constants.h" #include "llvm/Module.h" #include "llvm/Type.h" #include "llvm/Assembly/Writer.h" #include "llvm/Support/Mangler.h" #include "llvm/Support/CommandLine.h" using namespace llvm; -using namespace x86; -Statistic<> llvm::x86::EmittedInsts("asm-printer", - "Number of machine instrs printed"); +Statistic<> llvm::EmittedInsts("asm-printer", + "Number of machine instrs printed"); enum AsmWriterFlavorTy { att, intel }; cl::opt @@ -44,6 +44,7 @@ bool X86SharedAsmPrinter::doInitialization(Module &M) { const X86Subtarget *Subtarget = &TM.getSubtarget(); forDarwin = false; + PrivateGlobalPrefix = ".L"; switch (Subtarget->TargetType) { case X86Subtarget::isDarwin: @@ -57,6 +58,9 @@ bool X86SharedAsmPrinter::doInitialization(Module &M) { COMMDirectiveTakesAlignment = false; HasDotTypeDotSizeDirective = false; forDarwin = true; + StaticCtorsSection = ".mod_init_func"; + StaticDtorsSection = ".mod_term_func"; + InlineAsmStart = InlineAsmEnd = ""; // Don't use #APP/#NO_APP break; case X86Subtarget::isCygwin: GlobalPrefix = "_"; @@ -70,6 +74,11 @@ bool X86SharedAsmPrinter::doInitialization(Module &M) { default: break; } + if (forDarwin) { + // Emit initial debug information. + DW.BeginModule(&M); + } + return AsmPrinter::doInitialization(M); } @@ -77,110 +86,119 @@ bool X86SharedAsmPrinter::doFinalization(Module &M) { const TargetData &TD = TM.getTargetData(); // Print out module-level global variables here. - for (Module::const_global_iterator I = M.global_begin(), - E = M.global_end(); I != E; ++I) { + for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); + I != E; ++I) { if (!I->hasInitializer()) continue; // External global require no code - O << "\n\n"; + // Check to see if this is a special global used by LLVM, if so, emit it. + if (EmitSpecialLLVMGlobal(I)) + continue; + std::string name = Mang->getValueName(I); Constant *C = I->getInitializer(); unsigned Size = TD.getTypeSize(C->getType()); - unsigned Align = TD.getTypeAlignmentShift(C->getType()); - - switch (I->getLinkage()) { - default: assert(0 && "Unknown linkage type!"); - case GlobalValue::LinkOnceLinkage: - case GlobalValue::WeakLinkage: // FIXME: Verify correct for weak. - if (C->isNullValue()) { - O << COMMDirective << name << "," << Size; - if (COMMDirectiveTakesAlignment) - O << "," << (1 << Align); - O << "\t\t" << CommentString << " " << I->getName() << "\n"; - continue; - } - - // Nonnull linkonce -> weak - O << "\t.weak " << name << "\n"; - O << "\t.section\t.llvm.linkonce.d." << name << ",\"aw\",@progbits\n"; - SwitchSection("", I); - break; - case GlobalValue::InternalLinkage: - if (C->isNullValue()) { - if (LCOMMDirective) { - O << LCOMMDirective << name << "," << Size << "," << Align; - continue; + unsigned Align = getPreferredAlignmentLog(I); + + if (C->isNullValue() && /* FIXME: Verify correct */ + (I->hasInternalLinkage() || I->hasWeakLinkage() || + I->hasLinkOnceLinkage() || + (forDarwin && I->hasExternalLinkage() && !I->hasSection()))) { + if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it. + if (I->hasExternalLinkage()) { + O << "\t.globl\t" << name << "\n"; + O << "\t.zerofill __DATA__, __common, " << name << ", " + << Size << ", " << Align; + } else { + SwitchSection(".data", I); + if (LCOMMDirective != NULL) { + if (I->hasInternalLinkage()) { + O << LCOMMDirective << name << "," << Size; + if (forDarwin) + O << "," << (AlignmentIsInBytes ? (1 << Align) : Align); + } else + O << COMMDirective << name << "," << Size; } else { - SwitchSection(".bss", I); - O << "\t.local " << name << "\n"; - O << COMMDirective << name << "," << Size; + if (I->hasInternalLinkage()) + O << "\t.local\t" << name << "\n"; + O << COMMDirective << name << "," << Size; if (COMMDirectiveTakesAlignment) - O << "," << (1 << Align); - O << "\t\t# "; - WriteAsOperand(O, I, true, true, &M); - O << "\n"; - continue; + O << "," << (AlignmentIsInBytes ? (1 << Align) : Align); } } - SwitchSection(".data", I); - 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: - SwitchSection(C->isNullValue() ? ".bss" : ".data", I); - // If external or appending, declare as a global symbol - O << "\t.globl " << name << "\n"; - break; - } + O << "\t\t" << CommentString << " " << I->getName() << "\n"; + } else { + switch (I->getLinkage()) { + case GlobalValue::LinkOnceLinkage: + case GlobalValue::WeakLinkage: + if (forDarwin) { + O << "\t.globl " << name << "\n" + << "\t.weak_definition " << name << "\n"; + SwitchSection(".section __DATA,__datacoal_nt,coalesced", I); + } else { + O << "\t.section\t.llvm.linkonce.d." << name << ",\"aw\",@progbits\n"; + 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: + // If external or appending, declare as a global symbol + O << "\t.globl " << name << "\n"; + // FALL THROUGH + case GlobalValue::InternalLinkage: + SwitchSection(".data", I); + break; + default: + assert(0 && "Unknown linkage type!"); + } + + EmitAlignment(Align, I); + O << name << ":\t\t\t\t" << CommentString << " " << I->getName() + << "\n"; + if (HasDotTypeDotSizeDirective) + O << "\t.size " << name << ", " << Size << "\n"; - EmitAlignment(Align); - if (HasDotTypeDotSizeDirective) { - O << "\t.type " << name << ",@object\n"; - O << "\t.size " << name << "," << Size << "\n"; + EmitGlobalConstant(C); + O << '\n'; } - O << name << ":\t\t\t" << CommentString << ' ' << I->getName() << '\n'; - EmitGlobalConstant(C); } if (forDarwin) { SwitchSection("", 0); - // Output stubs for external global variables - if (GVStubs.begin() != GVStubs.end()) - O << "\t.non_lazy_symbol_pointer\n"; - for (std::set::iterator i = GVStubs.begin(), e = GVStubs.end(); - i != e; ++i) { - O << "L" << *i << "$non_lazy_ptr:\n"; - O << "\t.indirect_symbol " << *i << "\n"; - O << "\t.long\t0\n"; - } // Output stubs for dynamically-linked functions unsigned j = 1; for (std::set::iterator i = FnStubs.begin(), e = FnStubs.end(); i != e; ++i, ++j) { - O << "\t.symbol_stub\n"; + SwitchSection(".section __IMPORT,__jump_table,symbol_stubs," + "self_modifying_code+pure_instructions,5", 0); O << "L" << *i << "$stub:\n"; O << "\t.indirect_symbol " << *i << "\n"; - O << "\tjmp\t*L" << j << "$lz\n"; - O << "L" << *i << "$stub_binder:\n"; - O << "\tpushl\t$L" << j << "$lz\n"; - O << "\tjmp\tdyld_stub_binding_helper\n"; - O << "\t.section __DATA, __la_sym_ptr3,lazy_symbol_pointers\n"; - O << "L" << j << "$lz:\n"; - O << "\t.indirect_symbol " << *i << "\n"; - O << "\t.long\tL" << *i << "$stub_binder\n"; + O << "\thlt ; hlt ; hlt ; hlt ; hlt\n"; } O << "\n"; - // Output stubs for link-once variables - if (LinkOnceStubs.begin() != LinkOnceStubs.end()) - O << ".data\n.align 2\n"; - for (std::set::iterator i = LinkOnceStubs.begin(), - e = LinkOnceStubs.end(); i != e; ++i) { - O << "L" << *i << "$non_lazy_ptr:\n" - << "\t.long\t" << *i << '\n'; + // Output stubs for external and common global variables. + if (GVStubs.begin() != GVStubs.end()) + SwitchSection(".section __IMPORT,__pointers,non_lazy_symbol_pointers", 0); + for (std::set::iterator i = GVStubs.begin(), e = GVStubs.end(); + i != e; ++i) { + O << "L" << *i << "$non_lazy_ptr:\n"; + O << "\t.indirect_symbol " << *i << "\n"; + O << "\t.long\t0\n"; } + + // Emit initial debug information. + 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 + // implementation of multiple entry points). If this doesn't occur, the + // linker can safely perform dead code stripping. Since LLVM never + // generates code that does this, it is always safe to set. + O << "\t.subsections_via_symbols\n"; } AsmPrinter::doFinalization(M); @@ -191,7 +209,8 @@ bool X86SharedAsmPrinter::doFinalization(Module &M) { /// for a MachineFunction to the given output stream, using the given target /// machine description. /// -FunctionPass *llvm::createX86CodePrinterPass(std::ostream &o,TargetMachine &tm){ +FunctionPass *llvm::createX86CodePrinterPass(std::ostream &o, + X86TargetMachine &tm){ switch (AsmWriterFlavor) { default: assert(0 && "Unknown asm flavor!");