From adec555f966175b0c5f7ea9f7579de9e5ff017fe Mon Sep 17 00:00:00 2001 From: Anton Korobeynikov Date: Sat, 28 Jun 2008 11:08:27 +0000 Subject: [PATCH] Remove X86SharedAsmPrinter llvm-svn: 52860 --- lib/Target/X86/X86ATTAsmPrinter.cpp | 433 ++++++++++++++++++++++++++- lib/Target/X86/X86ATTAsmPrinter.h | 68 ++++- lib/Target/X86/X86AsmPrinter.cpp | 435 ---------------------------- lib/Target/X86/X86AsmPrinter.h | 80 ----- 4 files changed, 487 insertions(+), 529 deletions(-) diff --git a/lib/Target/X86/X86ATTAsmPrinter.cpp b/lib/Target/X86/X86ATTAsmPrinter.cpp index 3e80a6b7573..69914e57c24 100644 --- a/lib/Target/X86/X86ATTAsmPrinter.cpp +++ b/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(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(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(); - 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(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(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 (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& 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 (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" diff --git a/lib/Target/X86/X86ATTAsmPrinter.h b/lib/Target/X86/X86ATTAsmPrinter.h index de167e737ba..2c80df41fcd 100644 --- a/lib/Target/X86/X86ATTAsmPrinter.h +++ b/lib/Target/X86/X86ATTAsmPrinter.h @@ -14,21 +14,49 @@ #ifndef X86ATTASMPRINTER_H #define X86ATTASMPRINTER_H -#include "X86AsmPrinter.h" +#include "X86.h" +#include "X86MachineFunctionInfo.h" +#include "X86TargetMachine.h" +#include "llvm/ADT/StringSet.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/DwarfWriter.h" +#include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/ValueTypes.h" +#include "llvm/Support/Compiler.h" namespace llvm { struct MachineJumpTableInfo; - -struct VISIBILITY_HIDDEN X86ATTAsmPrinter : public X86SharedAsmPrinter { - X86ATTAsmPrinter(std::ostream &O, X86TargetMachine &TM, const TargetAsmInfo *T) - : X86SharedAsmPrinter(O, TM, T) { } + +struct VISIBILITY_HIDDEN X86ATTAsmPrinter : public AsmPrinter { + DwarfWriter DW; + MachineModuleInfo *MMI; + + const X86Subtarget *Subtarget; + + X86ATTAsmPrinter(std::ostream &O, X86TargetMachine &TM, + const TargetAsmInfo *T) + : AsmPrinter(O, TM, T), DW(O, this, T), MMI(0) { + Subtarget = &TM.getSubtarget(); + } virtual const char *getPassName() const { return "X86 AT&T-Style Assembly Printer"; } + void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + if (Subtarget->isTargetDarwin() || + Subtarget->isTargetELF() || + Subtarget->isTargetCygMing()) { + AU.addRequired(); + } + AsmPrinter::getAnalysisUsage(AU); + } + + bool doInitialization(Module &M); + bool doFinalization(Module &M); + /// printInstruction - This method is automatically generated by tablegen /// from the instruction set description. This method returns true if the /// machine instruction was sufficiently described to print it, otherwise it @@ -68,13 +96,13 @@ struct VISIBILITY_HIDDEN X86ATTAsmPrinter : public X86SharedAsmPrinter { void printlea64_32mem(const MachineInstr *MI, unsigned OpNo) { printMemReference(MI, OpNo, "subreg64"); } - + bool printAsmMRegister(const MachineOperand &MO, const char Mode); bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, unsigned AsmVariant, const char *ExtraCode); bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, unsigned AsmVariant, const char *ExtraCode); - + void printMachineInstruction(const MachineInstr *MI); void printSSECC(const MachineInstr *MI, unsigned Op); void printMemReference(const MachineInstr *MI, unsigned Op, @@ -88,13 +116,35 @@ struct VISIBILITY_HIDDEN X86ATTAsmPrinter : public X86SharedAsmPrinter { void printPICJumpTableEntry(const MachineJumpTableInfo *MJTI, const MachineBasicBlock *MBB, unsigned uid) const; - + void printPICLabel(const MachineInstr *MI, unsigned Op); bool runOnMachineFunction(MachineFunction &F); - + /// getSectionForFunction - Return the section that we should emit the /// specified function body into. virtual std::string getSectionForFunction(const Function &F) const; + + // Necessary for Darwin to print out the apprioriate types of linker stubs + StringSet<> FnStubs, GVStubs, LinkOnceStubs; + + // Necessary for dllexport support + StringSet<> DLLExportedFns, DLLExportedGVs; + + // We have to propagate some information about MachineFunction to + // AsmPrinter. It's ok, when we're printing the function, since we have + // access to MachineFunction and can get the appropriate MachineFunctionInfo. + // Unfortunately, this is not possible when we're printing reference to + // Function (e.g. calling it and so on). Even more, there is no way to get the + // corresponding MachineFunctions: it can even be not created at all. That's + // why we should use additional structure, when we're collecting all necessary + // information. + // + // This structure is using e.g. for name decoration for stdcall & fastcall'ed + // function, since we have to use arguments' size for decoration. + typedef std::map FMFInfoMap; + FMFInfoMap FunctionInfoMap; + + void decorateName(std::string& Name, const GlobalValue* GV); }; } // end namespace llvm diff --git a/lib/Target/X86/X86AsmPrinter.cpp b/lib/Target/X86/X86AsmPrinter.cpp index 2b6e7148821..5659282ff10 100644 --- a/lib/Target/X86/X86AsmPrinter.cpp +++ b/lib/Target/X86/X86AsmPrinter.cpp @@ -14,446 +14,11 @@ // //===----------------------------------------------------------------------===// -#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->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"); - } -} - -/// 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() || 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(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(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 (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& 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 (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); -} - /// createX86CodePrinterPass - Returns a pass that prints the X86 assembly code /// for a MachineFunction to the given output stream, using the given target /// machine description. diff --git a/lib/Target/X86/X86AsmPrinter.h b/lib/Target/X86/X86AsmPrinter.h index b9c79fee4b6..e69de29bb2d 100644 --- a/lib/Target/X86/X86AsmPrinter.h +++ b/lib/Target/X86/X86AsmPrinter.h @@ -1,80 +0,0 @@ -//===-- X86AsmPrinter.h - Convert X86 LLVM code to Intel 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'. -// -//===----------------------------------------------------------------------===// - -#ifndef X86ASMPRINTER_H -#define X86ASMPRINTER_H - -#include "X86.h" -#include "X86MachineFunctionInfo.h" -#include "X86TargetMachine.h" -#include "llvm/ADT/StringSet.h" -#include "llvm/CodeGen/AsmPrinter.h" -#include "llvm/CodeGen/DwarfWriter.h" -#include "llvm/CodeGen/MachineModuleInfo.h" -#include "llvm/Support/Compiler.h" - -namespace llvm { - -struct VISIBILITY_HIDDEN X86SharedAsmPrinter : public AsmPrinter { - DwarfWriter DW; - MachineModuleInfo *MMI; - - X86SharedAsmPrinter(std::ostream &O, X86TargetMachine &TM, - const TargetAsmInfo *T) - : AsmPrinter(O, TM, T), DW(O, this, T), MMI(0) { - Subtarget = &TM.getSubtarget(); - } - - // We have to propagate some information about MachineFunction to - // AsmPrinter. It's ok, when we're printing the function, since we have - // access to MachineFunction and can get the appropriate MachineFunctionInfo. - // Unfortunately, this is not possible when we're printing reference to - // Function (e.g. calling it and so on). Even more, there is no way to get the - // corresponding MachineFunctions: it can even be not created at all. That's - // why we should use additional structure, when we're collecting all necessary - // information. - // - // This structure is using e.g. for name decoration for stdcall & fastcall'ed - // function, since we have to use arguments' size for decoration. - typedef std::map FMFInfoMap; - FMFInfoMap FunctionInfoMap; - - void decorateName(std::string& Name, const GlobalValue* GV); - - bool doInitialization(Module &M); - bool doFinalization(Module &M); - - void getAnalysisUsage(AnalysisUsage &AU) const { - AU.setPreservesAll(); - if (Subtarget->isTargetDarwin() || - Subtarget->isTargetELF() || - Subtarget->isTargetCygMing()) { - AU.addRequired(); - } - AsmPrinter::getAnalysisUsage(AU); - } - - const X86Subtarget *Subtarget; - - // Necessary for Darwin to print out the apprioriate types of linker stubs - StringSet<> FnStubs, GVStubs, LinkOnceStubs; - - // Necessary for dllexport support - StringSet<> DLLExportedFns, DLLExportedGVs; -}; - -} // end namespace llvm - -#endif