//===-- X86AsmPrinter.cpp - Convert X86 LLVM IR to X86 assembly -----------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file the shared super class printer that converts from our internal // representation of machine-dependent LLVM code to Intel and AT&T format // assembly language. // This printer is the output mechanism used by `llc'. // //===----------------------------------------------------------------------===// #include "X86AsmPrinter.h" #include "X86ATTAsmPrinter.h" #include "X86COFF.h" #include "X86IntelAsmPrinter.h" #include "X86MachineFunctionInfo.h" #include "X86Subtarget.h" #include "llvm/ADT/StringExtras.h" #include "llvm/CallingConv.h" #include "llvm/Constants.h" #include "llvm/Module.h" #include "llvm/DerivedTypes.h" #include "llvm/ParameterAttributes.h" #include "llvm/Type.h" #include "llvm/Assembly/Writer.h" #include "llvm/Support/Mangler.h" #include "llvm/Target/TargetAsmInfo.h" #include "llvm/Target/TargetOptions.h" using namespace llvm; 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(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; } /// decorateName - Query FunctionInfoMap and use this information for various /// name decoration. void X86SharedAsmPrinter::decorateName(std::string &Name, const GlobalValue *GV) { const Function *F = dyn_cast(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->isStructReturn())) 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->isStructReturn())) Name += '@' + utostr_32(Info->getBytesToPopOnReturn()); if (Name[0] == '_') { Name[0] = '@'; } else { Name = '@' + Name; } break; default: assert(0 && "Unsupported DecorationStyle"); } } /// doInitialization bool X86SharedAsmPrinter::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; } /// 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 X86SharedAsmPrinter::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())) { 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 { 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::LinkOnceLinkage: case GlobalValue::WeakLinkage: if (Subtarget->isTargetDarwin()) { O << "\t.globl " << name << "\n" << TAI->getWeakDefDirective() << name << "\n"; SwitchToDataSection("\t.section __DATA,__datacoal_nt,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(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(C)) if (GV->hasExternalWeakLinkage()) ExtWeakSymbols.insert(GV); EmitGlobalConstant(C); } // Output linker support code for dllexported globals if (!DLLExportedGVs.empty()) { SwitchToDataSection(".section .drectve"); } for (std::set::iterator i = DLLExportedGVs.begin(), e = DLLExportedGVs.end(); i != e; ++i) { O << "\t.ascii \" -export:" << *i << ",data\"\n"; } if (!DLLExportedFns.empty()) { SwitchToDataSection(".section .drectve"); } for (std::set::iterator i = DLLExportedFns.begin(), e = DLLExportedFns.end(); i != e; ++i) { O << "\t.ascii \" -export:" << *i << "\"\n"; } if (Subtarget->isTargetDarwin()) { SwitchToDataSection(""); // Output stubs for dynamically-linked functions unsigned j = 1; for (std::set::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); O << "L" << *i << "$stub:\n"; O << "\t.indirect_symbol " << *i << "\n"; O << "\thlt ; hlt ; hlt ; hlt ; hlt\n"; } O << "\n"; if (ExceptionHandling && TAI->doesSupportExceptionHandling() && MMI && !Subtarget->is64Bit()) { // Add the (possibly multiple) personalities to the set of global values. const std::vector& Personalities = MMI->getPersonalities(); for (std::vector::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 (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 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 (std::set::iterator i = FnStubs.begin(), e = FnStubs.end(); i != e; ++i) { O << "\t.def\t " << *i << ";\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); } /// createX86CodePrinterPass - Returns a pass that prints the X86 assembly code /// for a MachineFunction to the given output stream, using the given target /// machine description. /// FunctionPass *llvm::createX86CodePrinterPass(std::ostream &o, X86TargetMachine &tm) { const X86Subtarget *Subtarget = &tm.getSubtarget(); if (Subtarget->isFlavorIntel()) { return new X86IntelAsmPrinter(o, tm, tm.getTargetAsmInfo()); } else { return new X86ATTAsmPrinter(o, tm, tm.getTargetAsmInfo()); } }