diff options
Diffstat (limited to 'llvm/lib/Target/X86/X86ATTAsmPrinter.cpp')
| -rw-r--r-- | llvm/lib/Target/X86/X86ATTAsmPrinter.cpp | 433 |
1 files changed, 428 insertions, 5 deletions
diff --git a/llvm/lib/Target/X86/X86ATTAsmPrinter.cpp b/llvm/lib/Target/X86/X86ATTAsmPrinter.cpp index 3e80a6b7573..69914e57c24 100644 --- a/llvm/lib/Target/X86/X86ATTAsmPrinter.cpp +++ b/llvm/lib/Target/X86/X86ATTAsmPrinter.cpp @@ -20,14 +20,16 @@ #include "X86MachineFunctionInfo.h" #include "X86TargetMachine.h" #include "X86TargetAsmInfo.h" -#include "llvm/ADT/StringExtras.h" #include "llvm/CallingConv.h" -#include "llvm/CodeGen/MachineJumpTableInfo.h" +#include "llvm/DerivedTypes.h" #include "llvm/Module.h" +#include "llvm/Type.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/CodeGen/MachineJumpTableInfo.h" #include "llvm/Support/Mangler.h" #include "llvm/Target/TargetAsmInfo.h" #include "llvm/Target/TargetOptions.h" -#include "llvm/ADT/Statistic.h" using namespace llvm; STATISTIC(EmittedInsts, "Number of machine instrs printed"); @@ -46,6 +48,103 @@ static std::string getPICLabelString(unsigned FnNum, return label; } +static X86MachineFunctionInfo calculateFunctionInfo(const Function *F, + const TargetData *TD) { + X86MachineFunctionInfo Info; + uint64_t Size = 0; + + switch (F->getCallingConv()) { + case CallingConv::X86_StdCall: + Info.setDecorationStyle(StdCall); + break; + case CallingConv::X86_FastCall: + Info.setDecorationStyle(FastCall); + break; + default: + return Info; + } + + unsigned argNum = 1; + for (Function::const_arg_iterator AI = F->arg_begin(), AE = F->arg_end(); + AI != AE; ++AI, ++argNum) { + const Type* Ty = AI->getType(); + + // 'Dereference' type in case of byval parameter attribute + if (F->paramHasAttr(argNum, ParamAttr::ByVal)) + Ty = cast<PointerType>(Ty)->getElementType(); + + // Size should be aligned to DWORD boundary + Size += ((TD->getABITypeSize(Ty) + 3)/4)*4; + } + + // We're not supporting tooooo huge arguments :) + Info.setBytesToPopOnReturn((unsigned int)Size); + return Info; +} + +/// 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; +} + +/// decorateName - Query FunctionInfoMap and use this information for various +/// name decoration. +void X86ATTAsmPrinter::decorateName(std::string &Name, + const GlobalValue *GV) { + const Function *F = dyn_cast<Function>(GV); + if (!F) return; + + // We don't want to decorate non-stdcall or non-fastcall functions right now + unsigned CC = F->getCallingConv(); + if (CC != CallingConv::X86_StdCall && CC != CallingConv::X86_FastCall) + return; + + // Decorate names only when we're targeting Cygwin/Mingw32 targets + if (!Subtarget->isTargetCygMing()) + return; + + FMFInfoMap::const_iterator info_item = FunctionInfoMap.find(F); + + const X86MachineFunctionInfo *Info; + if (info_item == FunctionInfoMap.end()) { + // Calculate apropriate function info and populate map + FunctionInfoMap[F] = calculateFunctionInfo(F, TM.getTargetData()); + Info = &FunctionInfoMap[F]; + } else { + Info = &info_item->second; + } + + const FunctionType *FT = F->getFunctionType(); + switch (Info->getDecorationStyle()) { + case None: + break; + case StdCall: + // "Pure" variadic functions do not receive @0 suffix. + if (!FT->isVarArg() || (FT->getNumParams() == 0) || + (FT->getNumParams() == 1 && F->hasStructRetAttr())) + Name += '@' + utostr_32(Info->getBytesToPopOnReturn()); + break; + case FastCall: + // "Pure" variadic functions do not receive @0 suffix. + if (!FT->isVarArg() || (FT->getNumParams() == 0) || + (FT->getNumParams() == 1 && F->hasStructRetAttr())) + Name += '@' + utostr_32(Info->getBytesToPopOnReturn()); + + if (Name[0] == '_') { + Name[0] = '@'; + } else { + Name = '@' + Name; + } + break; + default: + assert(0 && "Unsupported DecorationStyle"); + } +} + /// getSectionForFunction - Return the section that we should emit the /// specified function body into. std::string X86ATTAsmPrinter::getSectionForFunction(const Function &F) const { @@ -94,7 +193,7 @@ bool X86ATTAsmPrinter::runOnMachineFunction(MachineFunction &MF) { if (CC == CallingConv::X86_StdCall || CC == CallingConv::X86_FastCall) FunctionInfoMap[F] = *MF.getInfo<X86MachineFunctionInfo>(); - X86SharedAsmPrinter::decorateName(CurrentFnName, F); + decorateName(CurrentFnName, F); SwitchToTextSection(getSectionForFunction(*F).c_str(), F); @@ -298,7 +397,7 @@ void X86ATTAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo, bool isThreadLocal = GVar && GVar->isThreadLocal(); std::string Name = Mang->getValueName(GV); - X86SharedAsmPrinter::decorateName(Name, GV); + decorateName(Name, GV); if (!isMemOp && !isCallOp) O << '$'; @@ -649,5 +748,329 @@ void X86ATTAsmPrinter::printMachineInstruction(const MachineInstr *MI) { printInstruction(MI); } +/// doInitialization +bool X86ATTAsmPrinter::doInitialization(Module &M) { + if (TAI->doesSupportDebugInformation()) { + // Emit initial debug information. + DW.BeginModule(&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; +} + + +bool X86ATTAsmPrinter::doFinalization(Module &M) { + // Note: this code is not shared by the Intel printer as it is too different + // from how MASM does things. When making changes here don't forget to look + // at X86IntelAsmPrinter::doFinalization(). + 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) { + if (!I->hasInitializer()) + continue; // External global require no code + + // Check to see if this is a special global used by LLVM, if so, emit it. + 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(); + const Type *Type = C->getType(); + unsigned Size = TD->getABITypeSize(Type); + unsigned Align = TD->getPreferredAlignmentLog(I); + + if (I->hasHiddenVisibility()) { + if (const char *Directive = TAI->getHiddenDirective()) + O << Directive << name << "\n"; + } else if (I->hasProtectedVisibility()) { + if (const char *Directive = TAI->getProtectedDirective()) + O << Directive << name << "\n"; + } + + if (Subtarget->isTargetELF()) + O << "\t.type\t" << name << ",@object\n"; + + if (C->isNullValue() && !I->hasSection()) { + if (I->hasExternalLinkage()) { + if (const char *Directive = TAI->getZeroFillDirective()) { + O << "\t.globl " << name << "\n"; + O << Directive << "__DATA, __common, " << name << ", " + << Size << ", " << Align << "\n"; + continue; + } + } + + if (!I->isThreadLocal() && + (I->hasInternalLinkage() || I->hasWeakLinkage() || + I->hasLinkOnceLinkage() || I->hasCommonLinkage())) { + 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->isTargetDarwin()) + O << "," << Align; + } else if (Subtarget->isTargetDarwin() && !I->hasCommonLinkage()) { + O << "\t.globl " << name << "\n" + << TAI->getWeakDefDirective() << name << "\n"; + SwitchToDataSection("\t.section __DATA,__datacoal_nt,coalesced", I); + EmitAlignment(Align, I); + O << name << ":\t\t\t\t" << TAI->getCommentString() << " "; + PrintUnmangledNameSafely(I, O); + O << "\n"; + EmitGlobalConstant(C); + continue; + } else { + O << TAI->getCOMMDirective() << name << "," << Size; + + // Leopard and above support aligned common symbols. + if (Subtarget->getDarwinVers() >= 9) + O << "," << Align; + } + } else { + if (!Subtarget->isTargetCygMing()) { + if (I->hasInternalLinkage()) + O << "\t.local\t" << name << "\n"; + } + O << TAI->getCOMMDirective() << name << "," << Size; + if (TAI->getCOMMDirectiveTakesAlignment()) + O << "," << (TAI->getAlignmentIsInBytes() ? (1 << Align) : Align); + } + O << "\t\t" << TAI->getCommentString() << " "; + PrintUnmangledNameSafely(I, O); + O << "\n"; + continue; + } + } + + switch (I->getLinkage()) { + case GlobalValue::CommonLinkage: + case GlobalValue::LinkOnceLinkage: + case GlobalValue::WeakLinkage: + if (Subtarget->isTargetDarwin()) { + O << "\t.globl " << name << "\n" + << TAI->getWeakDefDirective() << name << "\n"; + if (!I->isConstant()) + SwitchToDataSection("\t.section __DATA,__datacoal_nt,coalesced", I); + else { + const ArrayType *AT = dyn_cast<ArrayType>(Type); + if (AT && AT->getElementType()==Type::Int8Ty) + SwitchToDataSection("\t.section __TEXT,__const_coal,coalesced", I); + else + SwitchToDataSection("\t.section __DATA,__const_coal,coalesced", I); + } + } else if (Subtarget->isTargetCygMing()) { + std::string SectionName(".section\t.data$linkonce." + + name + + ",\"aw\""); + SwitchToDataSection(SectionName.c_str(), I); + O << "\t.globl\t" << name << "\n" + << "\t.linkonce same_size\n"; + } else { + std::string SectionName("\t.section\t.llvm.linkonce.d." + + name + + ",\"aw\",@progbits"); + SwitchToDataSection(SectionName.c_str(), I); + O << "\t.weak\t" << name << "\n"; + } + break; + case GlobalValue::DLLExportLinkage: + DLLExportedGVs.insert(Mang->makeNameProper(I->getName(),"")); + // FALL THROUGH + 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: { + if (I->isConstant()) { + const ConstantArray *CVA = dyn_cast<ConstantArray>(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")) { + std::string SectionName = ".section " + I->getSection(); + + if (Subtarget->isTargetCygMing()) { + SectionName += ",\"aw\""; + } else { + assert(!Subtarget->isTargetDarwin()); + 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; + } + default: + assert(0 && "Unknown linkage type!"); + } + + EmitAlignment(Align, I); + O << name << ":\t\t\t\t" << TAI->getCommentString() << " "; + PrintUnmangledNameSafely(I, O); + O << "\n"; + if (TAI->hasDotTypeDotSizeDirective()) + O << "\t.size\t" << name << ", " << Size << "\n"; + // If the initializer is a extern weak symbol, remember to emit the weak + // reference! + if (const GlobalValue *GV = dyn_cast<GlobalValue>(C)) + if (GV->hasExternalWeakLinkage()) + ExtWeakSymbols.insert(GV); + + EmitGlobalConstant(C); + } + + // Output linker support code for dllexported globals + if (!DLLExportedGVs.empty()) { + SwitchToDataSection(".section .drectve"); + } + + for (StringSet<>::iterator i = DLLExportedGVs.begin(), + e = DLLExportedGVs.end(); + i != e; ++i) { + O << "\t.ascii \" -export:" << i->getKeyData() << ",data\"\n"; + } + + if (!DLLExportedFns.empty()) { + SwitchToDataSection(".section .drectve"); + } + + for (StringSet<>::iterator i = DLLExportedFns.begin(), + e = DLLExportedFns.end(); + i != e; ++i) { + O << "\t.ascii \" -export:" << i->getKeyData() << "\"\n"; + } + + if (Subtarget->isTargetDarwin()) { + SwitchToDataSection(""); + + // Output stubs for dynamically-linked functions + unsigned j = 1; + for (StringSet<>::iterator i = FnStubs.begin(), e = FnStubs.end(); + i != e; ++i, ++j) { + SwitchToDataSection("\t.section __IMPORT,__jump_table,symbol_stubs," + "self_modifying_code+pure_instructions,5", 0); + std::string p = i->getKeyData(); + printSuffixedName(p, "$stub"); + O << ":\n"; + O << "\t.indirect_symbol " << p << "\n"; + O << "\thlt ; hlt ; hlt ; hlt ; hlt\n"; + } + + O << "\n"; + + if (TAI->doesSupportExceptionHandling() && MMI && !Subtarget->is64Bit()) { + // Add the (possibly multiple) personalities to the set of global values. + // Only referenced functions get into the Personalities list. + const std::vector<Function *>& Personalities = MMI->getPersonalities(); + + for (std::vector<Function *>::const_iterator I = Personalities.begin(), + E = Personalities.end(); I != E; ++I) + if (*I) GVStubs.insert("_" + (*I)->getName()); + } + + // Output stubs for external and common global variables. + if (!GVStubs.empty()) + SwitchToDataSection( + "\t.section __IMPORT,__pointers,non_lazy_symbol_pointers"); + for (StringSet<>::iterator i = GVStubs.begin(), e = GVStubs.end(); + i != e; ++i) { + std::string p = i->getKeyData(); + printSuffixedName(p, "$non_lazy_ptr"); + O << ":\n"; + O << "\t.indirect_symbol " << p << "\n"; + O << "\t.long\t0\n"; + } + + // Emit final 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"; + } else if (Subtarget->isTargetCygMing()) { + // Emit type information for external functions + for (StringSet<>::iterator i = FnStubs.begin(), e = FnStubs.end(); + i != e; ++i) { + O << "\t.def\t " << i->getKeyData() + << ";\t.scl\t" << COFF::C_EXT + << ";\t.type\t" << (COFF::DT_FCN << COFF::N_BTSHFT) + << ";\t.endef\n"; + } + + // Emit final debug information. + DW.EndModule(); + } else if (Subtarget->isTargetELF()) { + // Emit final debug information. + DW.EndModule(); + } + + return AsmPrinter::doFinalization(M); +} + // Include the auto-generated portion of the assembly writer. #include "X86GenAsmWriter.inc" |

