From: Anton Korobeynikov Date: Sun, 17 Aug 2008 13:53:59 +0000 (+0000) Subject: Move X86 assembler printers into separate directory. This allows JIT-only users not... X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=3c3bc48d331db26aaff3ff4f7a61f60a17fea112;p=oota-llvm.git Move X86 assembler printers into separate directory. This allows JIT-only users not to link it in (use 'x86codegen' llvm-config arg for this) git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@54886 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/X86/AsmPrinter/Makefile b/lib/Target/X86/AsmPrinter/Makefile new file mode 100644 index 00000000000..ba75b43a8ae --- /dev/null +++ b/lib/Target/X86/AsmPrinter/Makefile @@ -0,0 +1,15 @@ +##===- lib/Target/X86/Makefile -----------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +LEVEL = ../../../.. +LIBRARYNAME = LLVMX86AsmPrinter + +# Hack: we need to include 'main' x86 target directory to grab private headers +CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. + +include $(LEVEL)/Makefile.common diff --git a/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.cpp b/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.cpp new file mode 100644 index 00000000000..8a6b60425ec --- /dev/null +++ b/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.cpp @@ -0,0 +1,985 @@ +//===-- X86ATTAsmPrinter.cpp - Convert X86 LLVM code to AT&T assembly -----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains a printer that converts from our internal representation +// of machine-dependent LLVM code to AT&T format assembly +// language. This printer is the output mechanism used by `llc'. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "asm-printer" +#include "X86ATTAsmPrinter.h" +#include "X86.h" +#include "X86COFF.h" +#include "X86MachineFunctionInfo.h" +#include "X86TargetMachine.h" +#include "X86TargetAsmInfo.h" +#include "llvm/CallingConv.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" +using namespace llvm; + +STATISTIC(EmittedInsts, "Number of machine instrs printed"); + +static std::string getPICLabelString(unsigned FnNum, + const TargetAsmInfo *TAI, + const X86Subtarget* Subtarget) { + std::string label; + if (Subtarget->isTargetDarwin()) + label = "\"L" + utostr_32(FnNum) + "$pb\""; + else if (Subtarget->isTargetELF()) + label = ".Lllvm$" + utostr_32(FnNum) + "." "$piclabel"; + else + assert(0 && "Don't know how to print PIC label!\n"); + + 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"); + } +} + +// Substitute old hook with new one temporary +std::string X86ATTAsmPrinter::getSectionForFunction(const Function &F) const { + return TAI->SectionForGlobal(&F); +} + +void X86ATTAsmPrinter::emitFunctionHeader(const MachineFunction &MF) { + const Function *F = MF.getFunction(); + std::string SectionName = TAI->SectionForGlobal(F); + + decorateName(CurrentFnName, F); + + SwitchToTextSection(SectionName.c_str()); + + unsigned FnAlign = OptimizeForSize ? 1 : 4; + switch (F->getLinkage()) { + default: assert(0 && "Unknown linkage type!"); + case Function::InternalLinkage: // Symbols default to internal. + EmitAlignment(FnAlign, F); + break; + case Function::DLLExportLinkage: + case Function::ExternalLinkage: + EmitAlignment(FnAlign, F); + O << "\t.globl\t" << CurrentFnName << '\n'; + break; + case Function::LinkOnceLinkage: + case Function::WeakLinkage: + EmitAlignment(FnAlign, F); + if (Subtarget->isTargetDarwin()) { + O << "\t.globl\t" << CurrentFnName << '\n'; + O << TAI->getWeakDefDirective() << CurrentFnName << '\n'; + } else if (Subtarget->isTargetCygMing()) { + O << "\t.globl\t" << CurrentFnName << "\n" + "\t.linkonce discard\n"; + } else { + O << "\t.weak\t" << CurrentFnName << '\n'; + } + break; + } + + printVisibility(CurrentFnName, F->getVisibility()); + + if (Subtarget->isTargetELF()) + O << "\t.type\t" << CurrentFnName << ",@function\n"; + else if (Subtarget->isTargetCygMing()) { + O << "\t.def\t " << CurrentFnName + << ";\t.scl\t" << + (F->getLinkage() == Function::InternalLinkage ? COFF::C_STAT : COFF::C_EXT) + << ";\t.type\t" << (COFF::DT_FCN << COFF::N_BTSHFT) + << ";\t.endef\n"; + } + + O << CurrentFnName << ":\n"; + // Add some workaround for linkonce linkage on Cygwin\MinGW + if (Subtarget->isTargetCygMing() && + (F->getLinkage() == Function::LinkOnceLinkage || + F->getLinkage() == Function::WeakLinkage)) + O << "Lllvm$workaround$fake$stub$" << CurrentFnName << ":\n"; +} + +/// runOnMachineFunction - This uses the printMachineInstruction() +/// method to print assembly for each instruction. +/// +bool X86ATTAsmPrinter::runOnMachineFunction(MachineFunction &MF) { + const Function *F = MF.getFunction(); + unsigned CC = F->getCallingConv(); + + SetupMachineFunction(MF); + O << "\n\n"; + + // Populate function information map. Actually, We don't want to populate + // non-stdcall or non-fastcall functions' information right now. + if (CC == CallingConv::X86_StdCall || CC == CallingConv::X86_FastCall) + FunctionInfoMap[F] = *MF.getInfo(); + + // Print out constants referenced by the function + EmitConstantPool(MF.getConstantPool()); + + if (F->hasDLLExportLinkage()) + DLLExportedFns.insert(Mang->makeNameProper(F->getName(), "")); + + // Print the 'header' of function + emitFunctionHeader(MF); + + // Emit pre-function debug and/or EH information. + if (TAI->doesSupportDebugInformation() || TAI->doesSupportExceptionHandling()) + DW.BeginFunction(&MF); + + // Print out code for the function. + bool hasAnyRealCode = false; + for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); + I != E; ++I) { + // Print a label for the basic block. + if (!I->pred_empty()) { + printBasicBlockLabel(I, true, true); + O << '\n'; + } + for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end(); + II != IE; ++II) { + // Print the assembly for the instruction. + if (!II->isLabel()) + hasAnyRealCode = true; + printMachineInstruction(II); + } + } + + if (Subtarget->isTargetDarwin() && !hasAnyRealCode) { + // If the function is empty, then we need to emit *something*. Otherwise, + // the function's label might be associated with something that it wasn't + // meant to be associated with. We emit a noop in this situation. + // We are assuming inline asms are code. + O << "\tnop\n"; + } + + if (TAI->hasDotTypeDotSizeDirective()) + O << "\t.size\t" << CurrentFnName << ", .-" << CurrentFnName << '\n'; + + // Emit post-function debug information. + if (TAI->doesSupportDebugInformation()) + DW.EndFunction(); + + // Print out jump tables referenced by the function. + EmitJumpTableInfo(MF.getJumpTableInfo(), MF); + + // We didn't modify anything. + return false; +} + +static inline bool shouldPrintGOT(TargetMachine &TM, const X86Subtarget* ST) { + return ST->isPICStyleGOT() && TM.getRelocationModel() == Reloc::PIC_; +} + +static inline bool shouldPrintPLT(TargetMachine &TM, const X86Subtarget* ST) { + return ST->isTargetELF() && TM.getRelocationModel() == Reloc::PIC_ && + (ST->isPICStyleRIPRel() || ST->isPICStyleGOT()); +} + +static inline bool shouldPrintStub(TargetMachine &TM, const X86Subtarget* ST) { + return ST->isPICStyleStub() && TM.getRelocationModel() != Reloc::Static; +} + +void X86ATTAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo, + const char *Modifier, bool NotRIPRel) { + const MachineOperand &MO = MI->getOperand(OpNo); + switch (MO.getType()) { + case MachineOperand::MO_Register: { + assert(TargetRegisterInfo::isPhysicalRegister(MO.getReg()) && + "Virtual registers should not make it this far!"); + O << '%'; + unsigned Reg = MO.getReg(); + if (Modifier && strncmp(Modifier, "subreg", strlen("subreg")) == 0) { + MVT VT = (strcmp(Modifier+6,"64") == 0) ? + MVT::i64 : ((strcmp(Modifier+6, "32") == 0) ? MVT::i32 : + ((strcmp(Modifier+6,"16") == 0) ? MVT::i16 : MVT::i8)); + Reg = getX86SubSuperRegister(Reg, VT); + } + O << TRI->getAsmName(Reg); + return; + } + + case MachineOperand::MO_Immediate: + if (!Modifier || + (strcmp(Modifier, "debug") && strcmp(Modifier, "mem"))) + O << '$'; + O << MO.getImm(); + return; + case MachineOperand::MO_MachineBasicBlock: + printBasicBlockLabel(MO.getMBB()); + return; + case MachineOperand::MO_JumpTableIndex: { + bool isMemOp = Modifier && !strcmp(Modifier, "mem"); + if (!isMemOp) O << '$'; + O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() << '_' + << MO.getIndex(); + + if (TM.getRelocationModel() == Reloc::PIC_) { + if (Subtarget->isPICStyleStub()) + O << "-\"" << TAI->getPrivateGlobalPrefix() << getFunctionNumber() + << "$pb\""; + else if (Subtarget->isPICStyleGOT()) + O << "@GOTOFF"; + } + + if (isMemOp && Subtarget->isPICStyleRIPRel() && !NotRIPRel) + O << "(%rip)"; + return; + } + case MachineOperand::MO_ConstantPoolIndex: { + bool isMemOp = Modifier && !strcmp(Modifier, "mem"); + if (!isMemOp) O << '$'; + O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_' + << MO.getIndex(); + + if (TM.getRelocationModel() == Reloc::PIC_) { + if (Subtarget->isPICStyleStub()) + O << "-\"" << TAI->getPrivateGlobalPrefix() << getFunctionNumber() + << "$pb\""; + else if (Subtarget->isPICStyleGOT()) + O << "@GOTOFF"; + } + + int Offset = MO.getOffset(); + if (Offset > 0) + O << '+' << Offset; + else if (Offset < 0) + O << Offset; + + if (isMemOp && Subtarget->isPICStyleRIPRel() && !NotRIPRel) + O << "(%rip)"; + return; + } + case MachineOperand::MO_GlobalAddress: { + bool isCallOp = Modifier && !strcmp(Modifier, "call"); + bool isMemOp = Modifier && !strcmp(Modifier, "mem"); + bool needCloseParen = false; + + const GlobalValue *GV = MO.getGlobal(); + const GlobalVariable *GVar = dyn_cast(GV); + if (!GVar) { + // If GV is an alias then use the aliasee for determining + // thread-localness. + if (const GlobalAlias *GA = dyn_cast(GV)) + GVar = dyn_cast_or_null(GA->resolveAliasedGlobal()); + } + + bool isThreadLocal = GVar && GVar->isThreadLocal(); + + std::string Name = Mang->getValueName(GV); + decorateName(Name, GV); + + if (!isMemOp && !isCallOp) + O << '$'; + else if (Name[0] == '$') { + // The name begins with a dollar-sign. In order to avoid having it look + // like an integer immediate to the assembler, enclose it in parens. + O << '('; + needCloseParen = true; + } + + if (shouldPrintStub(TM, Subtarget)) { + // Link-once, declaration, or Weakly-linked global variables need + // non-lazily-resolved stubs + if (GV->isDeclaration() || GV->isWeakForLinker()) { + // Dynamically-resolved functions need a stub for the function. + if (isCallOp && isa(GV)) { + FnStubs.insert(Name); + printSuffixedName(Name, "$stub"); + } else { + GVStubs.insert(Name); + printSuffixedName(Name, "$non_lazy_ptr"); + } + } else { + if (GV->hasDLLImportLinkage()) + O << "__imp_"; + O << Name; + } + + if (!isCallOp && TM.getRelocationModel() == Reloc::PIC_) + O << '-' << getPICLabelString(getFunctionNumber(), TAI, Subtarget); + } else { + if (GV->hasDLLImportLinkage()) { + O << "__imp_"; + } + O << Name; + + if (isCallOp) { + if (shouldPrintPLT(TM, Subtarget)) { + // Assemble call via PLT for externally visible symbols + if (!GV->hasHiddenVisibility() && !GV->hasProtectedVisibility() && + !GV->hasInternalLinkage()) + O << "@PLT"; + } + if (Subtarget->isTargetCygMing() && GV->isDeclaration()) + // Save function name for later type emission + FnStubs.insert(Name); + } + } + + if (GV->hasExternalWeakLinkage()) + ExtWeakSymbols.insert(GV); + + int Offset = MO.getOffset(); + if (Offset > 0) + O << '+' << Offset; + else if (Offset < 0) + O << Offset; + + if (isThreadLocal) { + if (TM.getRelocationModel() == Reloc::PIC_ || Subtarget->is64Bit()) + O << "@TLSGD"; // general dynamic TLS model + else + if (GV->isDeclaration()) + O << "@INDNTPOFF"; // initial exec TLS model + else + O << "@NTPOFF"; // local exec TLS model + } else if (isMemOp) { + if (shouldPrintGOT(TM, Subtarget)) { + if (Subtarget->GVRequiresExtraLoad(GV, TM, false)) + O << "@GOT"; + else + O << "@GOTOFF"; + } else if (Subtarget->isPICStyleRIPRel() && !NotRIPRel && + TM.getRelocationModel() != Reloc::Static) { + if (Subtarget->GVRequiresExtraLoad(GV, TM, false)) + O << "@GOTPCREL"; + + if (needCloseParen) { + needCloseParen = false; + O << ')'; + } + + // Use rip when possible to reduce code size, except when + // index or base register are also part of the address. e.g. + // foo(%rip)(%rcx,%rax,4) is not legal + O << "(%rip)"; + } + } + + if (needCloseParen) + O << ')'; + + return; + } + case MachineOperand::MO_ExternalSymbol: { + bool isCallOp = Modifier && !strcmp(Modifier, "call"); + bool needCloseParen = false; + std::string Name(TAI->getGlobalPrefix()); + Name += MO.getSymbolName(); + if (isCallOp && shouldPrintStub(TM, Subtarget)) { + FnStubs.insert(Name); + printSuffixedName(Name, "$stub"); + return; + } + if (!isCallOp) + O << '$'; + else if (Name[0] == '$') { + // The name begins with a dollar-sign. In order to avoid having it look + // like an integer immediate to the assembler, enclose it in parens. + O << '('; + needCloseParen = true; + } + + O << Name; + + if (shouldPrintPLT(TM, Subtarget)) { + std::string GOTName(TAI->getGlobalPrefix()); + GOTName+="_GLOBAL_OFFSET_TABLE_"; + if (Name == GOTName) + // HACK! Emit extra offset to PC during printing GOT offset to + // compensate for the size of popl instruction. The resulting code + // should look like: + // call .piclabel + // piclabel: + // popl %some_register + // addl $_GLOBAL_ADDRESS_TABLE_ + [.-piclabel], %some_register + O << " + [.-" + << getPICLabelString(getFunctionNumber(), TAI, Subtarget) << ']'; + + if (isCallOp) + O << "@PLT"; + } + + if (needCloseParen) + O << ')'; + + if (!isCallOp && Subtarget->isPICStyleRIPRel()) + O << "(%rip)"; + + return; + } + default: + O << ""; return; + } +} + +void X86ATTAsmPrinter::printSSECC(const MachineInstr *MI, unsigned Op) { + unsigned char value = MI->getOperand(Op).getImm(); + assert(value <= 7 && "Invalid ssecc argument!"); + switch (value) { + case 0: O << "eq"; break; + case 1: O << "lt"; break; + case 2: O << "le"; break; + case 3: O << "unord"; break; + case 4: O << "neq"; break; + case 5: O << "nlt"; break; + case 6: O << "nle"; break; + case 7: O << "ord"; break; + } +} + +void X86ATTAsmPrinter::printMemReference(const MachineInstr *MI, unsigned Op, + const char *Modifier){ + assert(isMem(MI, Op) && "Invalid memory reference!"); + MachineOperand BaseReg = MI->getOperand(Op); + MachineOperand IndexReg = MI->getOperand(Op+2); + const MachineOperand &DispSpec = MI->getOperand(Op+3); + + bool NotRIPRel = IndexReg.getReg() || BaseReg.getReg(); + if (DispSpec.isGlobalAddress() || + DispSpec.isConstantPoolIndex() || + DispSpec.isJumpTableIndex()) { + printOperand(MI, Op+3, "mem", NotRIPRel); + } else { + int DispVal = DispSpec.getImm(); + if (DispVal || (!IndexReg.getReg() && !BaseReg.getReg())) + O << DispVal; + } + + if (IndexReg.getReg() || BaseReg.getReg()) { + unsigned ScaleVal = MI->getOperand(Op+1).getImm(); + unsigned BaseRegOperand = 0, IndexRegOperand = 2; + + // There are cases where we can end up with ESP/RSP in the indexreg slot. + // If this happens, swap the base/index register to support assemblers that + // don't work when the index is *SP. + if (IndexReg.getReg() == X86::ESP || IndexReg.getReg() == X86::RSP) { + assert(ScaleVal == 1 && "Scale not supported for stack pointer!"); + std::swap(BaseReg, IndexReg); + std::swap(BaseRegOperand, IndexRegOperand); + } + + O << '('; + if (BaseReg.getReg()) + printOperand(MI, Op+BaseRegOperand, Modifier); + + if (IndexReg.getReg()) { + O << ','; + printOperand(MI, Op+IndexRegOperand, Modifier); + if (ScaleVal != 1) + O << ',' << ScaleVal; + } + O << ')'; + } +} + +void X86ATTAsmPrinter::printPICJumpTableSetLabel(unsigned uid, + const MachineBasicBlock *MBB) const { + if (!TAI->getSetDirective()) + return; + + // We don't need .set machinery if we have GOT-style relocations + if (Subtarget->isPICStyleGOT()) + return; + + O << TAI->getSetDirective() << ' ' << TAI->getPrivateGlobalPrefix() + << getFunctionNumber() << '_' << uid << "_set_" << MBB->getNumber() << ','; + printBasicBlockLabel(MBB, false, false, false); + if (Subtarget->isPICStyleRIPRel()) + O << '-' << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() + << '_' << uid << '\n'; + else + O << '-' << getPICLabelString(getFunctionNumber(), TAI, Subtarget) << '\n'; +} + +void X86ATTAsmPrinter::printPICLabel(const MachineInstr *MI, unsigned Op) { + std::string label = getPICLabelString(getFunctionNumber(), TAI, Subtarget); + O << label << '\n' << label << ':'; +} + + +void X86ATTAsmPrinter::printPICJumpTableEntry(const MachineJumpTableInfo *MJTI, + const MachineBasicBlock *MBB, + unsigned uid) const +{ + const char *JTEntryDirective = MJTI->getEntrySize() == 4 ? + TAI->getData32bitsDirective() : TAI->getData64bitsDirective(); + + O << JTEntryDirective << ' '; + + if (TM.getRelocationModel() == Reloc::PIC_) { + if (Subtarget->isPICStyleRIPRel() || Subtarget->isPICStyleStub()) { + O << TAI->getPrivateGlobalPrefix() << getFunctionNumber() + << '_' << uid << "_set_" << MBB->getNumber(); + } else if (Subtarget->isPICStyleGOT()) { + printBasicBlockLabel(MBB, false, false, false); + O << "@GOTOFF"; + } else + assert(0 && "Don't know how to print MBB label for this PIC mode"); + } else + printBasicBlockLabel(MBB, false, false, false); +} + +bool X86ATTAsmPrinter::printAsmMRegister(const MachineOperand &MO, + const char Mode) { + unsigned Reg = MO.getReg(); + switch (Mode) { + default: return true; // Unknown mode. + case 'b': // Print QImode register + Reg = getX86SubSuperRegister(Reg, MVT::i8); + break; + case 'h': // Print QImode high register + Reg = getX86SubSuperRegister(Reg, MVT::i8, true); + break; + case 'w': // Print HImode register + Reg = getX86SubSuperRegister(Reg, MVT::i16); + break; + case 'k': // Print SImode register + Reg = getX86SubSuperRegister(Reg, MVT::i32); + break; + case 'q': // Print DImode register + Reg = getX86SubSuperRegister(Reg, MVT::i64); + break; + } + + O << '%'<< TRI->getAsmName(Reg); + return false; +} + +/// PrintAsmOperand - Print out an operand for an inline asm expression. +/// +bool X86ATTAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, + const char *ExtraCode) { + // Does this asm operand have a single letter operand modifier? + if (ExtraCode && ExtraCode[0]) { + if (ExtraCode[1] != 0) return true; // Unknown modifier. + + switch (ExtraCode[0]) { + default: return true; // Unknown modifier. + case 'c': // Don't print "$" before a global var name or constant. + printOperand(MI, OpNo, "mem"); + return false; + case 'b': // Print QImode register + case 'h': // Print QImode high register + case 'w': // Print HImode register + case 'k': // Print SImode register + case 'q': // Print DImode register + if (MI->getOperand(OpNo).isRegister()) + return printAsmMRegister(MI->getOperand(OpNo), ExtraCode[0]); + printOperand(MI, OpNo); + return false; + + case 'P': // Don't print @PLT, but do print as memory. + printOperand(MI, OpNo, "mem"); + return false; + } + } + + printOperand(MI, OpNo); + return false; +} + +bool X86ATTAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, + unsigned OpNo, + unsigned AsmVariant, + const char *ExtraCode) { + if (ExtraCode && ExtraCode[0]) { + if (ExtraCode[1] != 0) return true; // Unknown modifier. + + switch (ExtraCode[0]) { + default: return true; // Unknown modifier. + case 'b': // Print QImode register + case 'h': // Print QImode high register + case 'w': // Print HImode register + case 'k': // Print SImode register + case 'q': // Print SImode register + // These only apply to registers, ignore on mem. + break; + } + } + printMemReference(MI, OpNo); + return false; +} + +/// printMachineInstruction -- Print out a single X86 LLVM instruction +/// MI in AT&T syntax to the current output stream. +/// +void X86ATTAsmPrinter::printMachineInstruction(const MachineInstr *MI) { + ++EmittedInsts; + + // Call the autogenerated instruction printer routines. + printInstruction(MI); +} + +/// doInitialization +bool X86ATTAsmPrinter::doInitialization(Module &M) { + if (TAI->doesSupportDebugInformation()) { + // Emit initial debug information. + DW.BeginModule(&M); + } + + bool Result = AsmPrinter::doInitialization(M); + + if (TAI->doesSupportDebugInformation()) { + // Let PassManager know we need debug information and relay + // the MachineModuleInfo address on to DwarfWriter. + // AsmPrinter::doInitialization did this analysis. + MMI = getAnalysisToUpdate(); + DW.SetModuleInfo(MMI); + } + + // Darwin wants symbols to be quoted if they have complex names. + if (Subtarget->isTargetDarwin()) + Mang->setUseQuotes(true); + + return Result; +} + + +void X86ATTAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) { + const TargetData *TD = TM.getTargetData(); + + if (!GVar->hasInitializer()) + return; // External global require no code + + // Check to see if this is a special global used by LLVM, if so, emit it. + if (EmitSpecialLLVMGlobal(GVar)) { + if (Subtarget->isTargetDarwin() && + TM.getRelocationModel() == Reloc::Static) { + if (GVar->getName() == "llvm.global_ctors") + O << ".reference .constructors_used\n"; + else if (GVar->getName() == "llvm.global_dtors") + O << ".reference .destructors_used\n"; + } + 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 Align = TD->getPreferredAlignmentLog(GVar); + + printVisibility(name, GVar->getVisibility()); + + if (Subtarget->isTargetELF()) + O << "\t.type\t" << name << ",@object\n"; + + SwitchToDataSection(SectionName.c_str()); + + if (C->isNullValue() && !GVar->hasSection()) { + // FIXME: This seems to be pretty darwin-specific + if (GVar->hasExternalLinkage()) { + if (const char *Directive = TAI->getZeroFillDirective()) { + O << "\t.globl " << name << '\n'; + O << Directive << "__DATA, __common, " << name << ", " + << Size << ", " << Align << '\n'; + return; + } + } + + if (!GVar->isThreadLocal() && + (GVar->hasInternalLinkage() || GVar->isWeakForLinker())) { + if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it. + + if (TAI->getLCOMMDirective() != NULL) { + if (GVar->hasInternalLinkage()) { + O << TAI->getLCOMMDirective() << name << ',' << Size; + if (Subtarget->isTargetDarwin()) + O << ',' << Align; + } else if (Subtarget->isTargetDarwin() && !GVar->hasCommonLinkage()) { + 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 { + O << TAI->getCOMMDirective() << name << ',' << Size; + if (TAI->getCOMMDirectiveTakesAlignment()) + O << ',' << (TAI->getAlignmentIsInBytes() ? (1 << Align) : Align); + } + } else { + if (!Subtarget->isTargetCygMing()) { + if (GVar->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(GVar, O); + O << '\n'; + return; + } + } + + switch (GVar->getLinkage()) { + case GlobalValue::CommonLinkage: + case GlobalValue::LinkOnceLinkage: + case GlobalValue::WeakLinkage: + if (Subtarget->isTargetDarwin()) { + O << "\t.globl " << name << '\n' + << TAI->getWeakDefDirective() << name << '\n'; + } else if (Subtarget->isTargetCygMing()) { + O << "\t.globl\t" << name << "\n" + "\t.linkonce same_size\n"; + } else { + O << "\t.weak\t" << name << '\n'; + } + break; + case GlobalValue::DLLExportLinkage: + 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: + break; + default: + assert(0 && "Unknown linkage type!"); + } + + EmitAlignment(Align, GVar); + O << name << ":\t\t\t\t" << TAI->getCommentString() << ' '; + PrintUnmangledNameSafely(GVar, 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); +} + +/// printGVStub - Print stub for a global value. +/// +void X86ATTAsmPrinter::printGVStub(const char *GV, const char *Prefix) { + printSuffixedName(GV, "$non_lazy_ptr", Prefix); + O << ":\n\t.indirect_symbol "; + if (Prefix) O << Prefix; + O << GV << "\n\t.long\t0\n"; +} + + +bool X86ATTAsmPrinter::doFinalization(Module &M) { + // Print out module-level global variables here. + for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); + I != E; ++I) { + printModuleLevelGV(I); + + if (I->hasDLLExportLinkage()) + DLLExportedGVs.insert(Mang->makeNameProper(I->getName(),"")); + } + + // 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); + const char *p = i->getKeyData(); + printSuffixedName(p, "$stub"); + O << ":\n" + "\t.indirect_symbol " << p << "\n" + "\thlt ; hlt ; hlt ; hlt ; hlt\n"; + } + + O << '\n'; + + // Print global value stubs. + bool InStubSection = false; + 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) + continue; + if (!InStubSection) { + SwitchToDataSection( + "\t.section __IMPORT,__pointers,non_lazy_symbol_pointers"); + InStubSection = true; + } + printGVStub((*I)->getNameStart(), "_"); + } + } + + // Output stubs for external and common global variables. + if (!InStubSection && !GVStubs.empty()) + SwitchToDataSection( + "\t.section __IMPORT,__pointers,non_lazy_symbol_pointers"); + for (StringSet<>::iterator i = GVStubs.begin(), e = GVStubs.end(); + i != e; ++i) + printGVStub(i->getKeyData()); + + // 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/AsmPrinter/X86ATTAsmPrinter.h b/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.h new file mode 100644 index 00000000000..f9479fd41d4 --- /dev/null +++ b/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.h @@ -0,0 +1,158 @@ +//===-- X86ATTAsmPrinter.h - Convert X86 LLVM code to AT&T assembly -------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// AT&T assembly code printer class. +// +//===----------------------------------------------------------------------===// + +#ifndef X86ATTASMPRINTER_H +#define X86ATTASMPRINTER_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 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 + /// returns false. + bool printInstruction(const MachineInstr *MI); + + // These methods are used by the tablegen'erated instruction printer. + void printOperand(const MachineInstr *MI, unsigned OpNo, + const char *Modifier = 0, bool NotRIPRel = false); + void printi8mem(const MachineInstr *MI, unsigned OpNo) { + printMemReference(MI, OpNo); + } + void printi16mem(const MachineInstr *MI, unsigned OpNo) { + printMemReference(MI, OpNo); + } + void printi32mem(const MachineInstr *MI, unsigned OpNo) { + printMemReference(MI, OpNo); + } + void printi64mem(const MachineInstr *MI, unsigned OpNo) { + printMemReference(MI, OpNo); + } + void printi128mem(const MachineInstr *MI, unsigned OpNo) { + printMemReference(MI, OpNo); + } + void printf32mem(const MachineInstr *MI, unsigned OpNo) { + printMemReference(MI, OpNo); + } + void printf64mem(const MachineInstr *MI, unsigned OpNo) { + printMemReference(MI, OpNo); + } + void printf80mem(const MachineInstr *MI, unsigned OpNo) { + printMemReference(MI, OpNo); + } + void printf128mem(const MachineInstr *MI, unsigned OpNo) { + printMemReference(MI, OpNo); + } + 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, + const char *Modifier=NULL); + void printPICJumpTableSetLabel(unsigned uid, + const MachineBasicBlock *MBB) const; + void printPICJumpTableSetLabel(unsigned uid, unsigned uid2, + const MachineBasicBlock *MBB) const { + AsmPrinter::printPICJumpTableSetLabel(uid, uid2, MBB); + } + void printPICJumpTableEntry(const MachineJumpTableInfo *MJTI, + const MachineBasicBlock *MBB, + unsigned uid) const; + + void printPICLabel(const MachineInstr *MI, unsigned Op); + void printModuleLevelGV(const GlobalVariable* GVar); + + void printGVStub(const char *GV, const char *Prefix = NULL); + + 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; + + void emitFunctionHeader(const MachineFunction &MF); + + // 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 + +#endif diff --git a/lib/Target/X86/AsmPrinter/X86AsmPrinter.cpp b/lib/Target/X86/AsmPrinter/X86AsmPrinter.cpp new file mode 100644 index 00000000000..8144ee85a9e --- /dev/null +++ b/lib/Target/X86/AsmPrinter/X86AsmPrinter.cpp @@ -0,0 +1,43 @@ +//===-- 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 "X86ATTAsmPrinter.h" +#include "X86IntelAsmPrinter.h" +#include "X86Subtarget.h" +using namespace llvm; + +/// 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()); + } +} + +namespace { + static struct Register { + Register() { + X86TargetMachine::registerAsmPrinter(createX86CodePrinterPass); + } + } Registrator; +} diff --git a/lib/Target/X86/AsmPrinter/X86AsmPrinter.h b/lib/Target/X86/AsmPrinter/X86AsmPrinter.h new file mode 100644 index 00000000000..e69de29bb2d diff --git a/lib/Target/X86/AsmPrinter/X86IntelAsmPrinter.cpp b/lib/Target/X86/AsmPrinter/X86IntelAsmPrinter.cpp new file mode 100644 index 00000000000..1822c1f914a --- /dev/null +++ b/lib/Target/X86/AsmPrinter/X86IntelAsmPrinter.cpp @@ -0,0 +1,597 @@ +//===-- X86IntelAsmPrinter.cpp - 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 contains a printer that converts from our internal representation +// of machine-dependent LLVM code to Intel format assembly language. +// This printer is the output mechanism used by `llc'. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "asm-printer" +#include "X86IntelAsmPrinter.h" +#include "X86InstrInfo.h" +#include "X86TargetAsmInfo.h" +#include "X86.h" +#include "llvm/CallingConv.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Module.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Assembly/Writer.h" +#include "llvm/Support/Mangler.h" +#include "llvm/Target/TargetAsmInfo.h" +#include "llvm/Target/TargetOptions.h" +using namespace llvm; + +STATISTIC(EmittedInsts, "Number of machine instrs printed"); + +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 X86IntelAsmPrinter::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; + + 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"); + } +} + + +std::string X86IntelAsmPrinter::getSectionForFunction(const Function &F) const { + // Intel asm always emits functions to _text. + return "_text"; +} + +/// runOnMachineFunction - This uses the printMachineInstruction() +/// method to print assembly for each instruction. +/// +bool X86IntelAsmPrinter::runOnMachineFunction(MachineFunction &MF) { + SetupMachineFunction(MF); + O << "\n\n"; + + // Print out constants referenced by the function + EmitConstantPool(MF.getConstantPool()); + + // Print out labels for the function. + const Function *F = MF.getFunction(); + unsigned CC = F->getCallingConv(); + + // Populate function information map. Actually, We don't want to populate + // non-stdcall or non-fastcall functions' information right now. + if (CC == CallingConv::X86_StdCall || CC == CallingConv::X86_FastCall) + FunctionInfoMap[F] = *MF.getInfo(); + + decorateName(CurrentFnName, F); + + SwitchToTextSection(getSectionForFunction(*F).c_str(), F); + + unsigned FnAlign = OptimizeForSize ? 1 : 4; + switch (F->getLinkage()) { + default: assert(0 && "Unsupported linkage type!"); + case Function::InternalLinkage: + EmitAlignment(FnAlign); + break; + case Function::DLLExportLinkage: + DLLExportedFns.insert(CurrentFnName); + //FALLS THROUGH + case Function::ExternalLinkage: + O << "\tpublic " << CurrentFnName << "\n"; + EmitAlignment(FnAlign); + break; + } + + O << CurrentFnName << "\tproc near\n"; + + // Print out code for the function. + for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); + I != E; ++I) { + // Print a label for the basic block if there are any predecessors. + if (!I->pred_empty()) { + printBasicBlockLabel(I, true, true); + O << '\n'; + } + for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end(); + II != E; ++II) { + // Print the assembly for the instruction. + printMachineInstruction(II); + } + } + + // Print out jump tables referenced by the function. + EmitJumpTableInfo(MF.getJumpTableInfo(), MF); + + O << CurrentFnName << "\tendp\n"; + + // We didn't modify anything. + return false; +} + +void X86IntelAsmPrinter::printSSECC(const MachineInstr *MI, unsigned Op) { + unsigned char value = MI->getOperand(Op).getImm(); + assert(value <= 7 && "Invalid ssecc argument!"); + switch (value) { + case 0: O << "eq"; break; + case 1: O << "lt"; break; + case 2: O << "le"; break; + case 3: O << "unord"; break; + case 4: O << "neq"; break; + case 5: O << "nlt"; break; + case 6: O << "nle"; break; + case 7: O << "ord"; break; + } +} + +void X86IntelAsmPrinter::printOp(const MachineOperand &MO, + const char *Modifier) { + switch (MO.getType()) { + case MachineOperand::MO_Register: { + if (TargetRegisterInfo::isPhysicalRegister(MO.getReg())) { + unsigned Reg = MO.getReg(); + if (Modifier && strncmp(Modifier, "subreg", strlen("subreg")) == 0) { + MVT VT = (strcmp(Modifier,"subreg64") == 0) ? + MVT::i64 : ((strcmp(Modifier, "subreg32") == 0) ? MVT::i32 : + ((strcmp(Modifier,"subreg16") == 0) ? MVT::i16 :MVT::i8)); + Reg = getX86SubSuperRegister(Reg, VT); + } + O << TRI->getName(Reg); + } else + O << "reg" << MO.getReg(); + return; + } + case MachineOperand::MO_Immediate: + O << MO.getImm(); + return; + case MachineOperand::MO_MachineBasicBlock: + printBasicBlockLabel(MO.getMBB()); + return; + case MachineOperand::MO_JumpTableIndex: { + bool isMemOp = Modifier && !strcmp(Modifier, "mem"); + if (!isMemOp) O << "OFFSET "; + O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() + << "_" << MO.getIndex(); + return; + } + case MachineOperand::MO_ConstantPoolIndex: { + bool isMemOp = Modifier && !strcmp(Modifier, "mem"); + if (!isMemOp) O << "OFFSET "; + O << "[" << TAI->getPrivateGlobalPrefix() << "CPI" + << getFunctionNumber() << "_" << MO.getIndex(); + int Offset = MO.getOffset(); + if (Offset > 0) + O << " + " << Offset; + else if (Offset < 0) + O << Offset; + O << "]"; + return; + } + case MachineOperand::MO_GlobalAddress: { + bool isCallOp = Modifier && !strcmp(Modifier, "call"); + bool isMemOp = Modifier && !strcmp(Modifier, "mem"); + GlobalValue *GV = MO.getGlobal(); + std::string Name = Mang->getValueName(GV); + + decorateName(Name, GV); + + if (!isMemOp && !isCallOp) O << "OFFSET "; + if (GV->hasDLLImportLinkage()) { + // FIXME: This should be fixed with full support of stdcall & fastcall + // CC's + O << "__imp_"; + } + O << Name; + int Offset = MO.getOffset(); + if (Offset > 0) + O << " + " << Offset; + else if (Offset < 0) + O << Offset; + return; + } + case MachineOperand::MO_ExternalSymbol: { + bool isCallOp = Modifier && !strcmp(Modifier, "call"); + if (!isCallOp) O << "OFFSET "; + O << TAI->getGlobalPrefix() << MO.getSymbolName(); + return; + } + default: + O << ""; return; + } +} + +void X86IntelAsmPrinter::printMemReference(const MachineInstr *MI, unsigned Op, + const char *Modifier) { + assert(isMem(MI, Op) && "Invalid memory reference!"); + + const MachineOperand &BaseReg = MI->getOperand(Op); + int ScaleVal = MI->getOperand(Op+1).getImm(); + const MachineOperand &IndexReg = MI->getOperand(Op+2); + const MachineOperand &DispSpec = MI->getOperand(Op+3); + + O << "["; + bool NeedPlus = false; + if (BaseReg.getReg()) { + printOp(BaseReg, Modifier); + NeedPlus = true; + } + + if (IndexReg.getReg()) { + if (NeedPlus) O << " + "; + if (ScaleVal != 1) + O << ScaleVal << "*"; + printOp(IndexReg, Modifier); + NeedPlus = true; + } + + if (DispSpec.isGlobalAddress() || DispSpec.isConstantPoolIndex() || + DispSpec.isJumpTableIndex()) { + if (NeedPlus) + O << " + "; + printOp(DispSpec, "mem"); + } else { + int DispVal = DispSpec.getImm(); + if (DispVal || (!BaseReg.getReg() && !IndexReg.getReg())) { + if (NeedPlus) { + if (DispVal > 0) + O << " + "; + else { + O << " - "; + DispVal = -DispVal; + } + } + O << DispVal; + } + } + O << "]"; +} + +void X86IntelAsmPrinter::printPICJumpTableSetLabel(unsigned uid, + const MachineBasicBlock *MBB) const { + if (!TAI->getSetDirective()) + return; + + O << TAI->getSetDirective() << ' ' << TAI->getPrivateGlobalPrefix() + << getFunctionNumber() << '_' << uid << "_set_" << MBB->getNumber() << ','; + printBasicBlockLabel(MBB, false, false, false); + O << '-' << "\"L" << getFunctionNumber() << "$pb\"'\n"; +} + +void X86IntelAsmPrinter::printPICLabel(const MachineInstr *MI, unsigned Op) { + O << "\"L" << getFunctionNumber() << "$pb\"\n"; + O << "\"L" << getFunctionNumber() << "$pb\":"; +} + +bool X86IntelAsmPrinter::printAsmMRegister(const MachineOperand &MO, + const char Mode) { + unsigned Reg = MO.getReg(); + switch (Mode) { + default: return true; // Unknown mode. + case 'b': // Print QImode register + Reg = getX86SubSuperRegister(Reg, MVT::i8); + break; + case 'h': // Print QImode high register + Reg = getX86SubSuperRegister(Reg, MVT::i8, true); + break; + case 'w': // Print HImode register + Reg = getX86SubSuperRegister(Reg, MVT::i16); + break; + case 'k': // Print SImode register + Reg = getX86SubSuperRegister(Reg, MVT::i32); + break; + } + + O << '%' << TRI->getName(Reg); + return false; +} + +/// PrintAsmOperand - Print out an operand for an inline asm expression. +/// +bool X86IntelAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, + const char *ExtraCode) { + // Does this asm operand have a single letter operand modifier? + if (ExtraCode && ExtraCode[0]) { + if (ExtraCode[1] != 0) return true; // Unknown modifier. + + switch (ExtraCode[0]) { + default: return true; // Unknown modifier. + case 'b': // Print QImode register + case 'h': // Print QImode high register + case 'w': // Print HImode register + case 'k': // Print SImode register + return printAsmMRegister(MI->getOperand(OpNo), ExtraCode[0]); + } + } + + printOperand(MI, OpNo); + return false; +} + +bool X86IntelAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, + unsigned OpNo, + unsigned AsmVariant, + const char *ExtraCode) { + if (ExtraCode && ExtraCode[0]) + return true; // Unknown modifier. + printMemReference(MI, OpNo); + return false; +} + +/// printMachineInstruction -- Print out a single X86 LLVM instruction +/// MI in Intel syntax to the current output stream. +/// +void X86IntelAsmPrinter::printMachineInstruction(const MachineInstr *MI) { + ++EmittedInsts; + + // Call the autogenerated instruction printer routines. + printInstruction(MI); +} + +bool X86IntelAsmPrinter::doInitialization(Module &M) { + bool Result = AsmPrinter::doInitialization(M); + + Mang->markCharUnacceptable('.'); + + O << "\t.686\n\t.model flat\n\n"; + + // Emit declarations for external functions. + for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) + if (I->isDeclaration()) { + std::string Name = Mang->getValueName(I); + decorateName(Name, I); + + O << "\textern " ; + if (I->hasDLLImportLinkage()) { + O << "__imp_"; + } + O << Name << ":near\n"; + } + + // Emit declarations for external globals. Note that VC++ always declares + // external globals to have type byte, and if that's good enough for VC++... + for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); + I != E; ++I) { + if (I->isDeclaration()) { + std::string Name = Mang->getValueName(I); + + O << "\textern " ; + if (I->hasDLLImportLinkage()) { + O << "__imp_"; + } + O << Name << ":byte\n"; + } + } + + return Result; +} + +bool X86IntelAsmPrinter::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) { + if (I->isDeclaration()) 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)) + continue; + + std::string name = Mang->getValueName(I); + Constant *C = I->getInitializer(); + unsigned Align = TD->getPreferredAlignmentLog(I); + bool bCustomSegment = false; + + switch (I->getLinkage()) { + case GlobalValue::CommonLinkage: + case GlobalValue::LinkOnceLinkage: + case GlobalValue::WeakLinkage: + SwitchToDataSection(""); + O << name << "?\tsegment common 'COMMON'\n"; + bCustomSegment = true; + // FIXME: the default alignment is 16 bytes, but 1, 2, 4, and 256 + // are also available. + break; + case GlobalValue::AppendingLinkage: + SwitchToDataSection(""); + O << name << "?\tsegment public 'DATA'\n"; + bCustomSegment = true; + // FIXME: the default alignment is 16 bytes, but 1, 2, 4, and 256 + // are also available. + break; + case GlobalValue::DLLExportLinkage: + DLLExportedGVs.insert(name); + // FALL THROUGH + case GlobalValue::ExternalLinkage: + O << "\tpublic " << name << "\n"; + // FALL THROUGH + case GlobalValue::InternalLinkage: + SwitchToDataSection(TAI->getDataSection(), I); + break; + default: + assert(0 && "Unknown linkage type!"); + } + + if (!bCustomSegment) + EmitAlignment(Align, I); + + O << name << ":\t\t\t\t" << TAI->getCommentString() + << " " << I->getName() << '\n'; + + EmitGlobalConstant(C); + + if (bCustomSegment) + O << name << "?\tends\n"; + } + + // Output linker support code for dllexported globals + if (!DLLExportedGVs.empty() || !DLLExportedFns.empty()) { + SwitchToDataSection(""); + O << "; WARNING: The following code is valid only with MASM v8.x and (possible) higher\n" + << "; This version of MASM is usually shipped with Microsoft Visual Studio 2005\n" + << "; or (possible) further versions. Unfortunately, there is no way to support\n" + << "; dllexported symbols in the earlier versions of MASM in fully automatic way\n\n"; + O << "_drectve\t segment info alias('.drectve')\n"; + } + + for (StringSet<>::iterator i = DLLExportedGVs.begin(), + e = DLLExportedGVs.end(); + i != e; ++i) + O << "\t db ' /EXPORT:" << i->getKeyData() << ",data'\n"; + + for (StringSet<>::iterator i = DLLExportedFns.begin(), + e = DLLExportedFns.end(); + i != e; ++i) + O << "\t db ' /EXPORT:" << i->getKeyData() << "'\n"; + + if (!DLLExportedGVs.empty() || !DLLExportedFns.empty()) + O << "_drectve\t ends\n"; + + // Bypass X86SharedAsmPrinter::doFinalization(). + bool Result = AsmPrinter::doFinalization(M); + SwitchToDataSection(""); + O << "\tend\n"; + return Result; +} + +void X86IntelAsmPrinter::EmitString(const ConstantArray *CVA) const { + unsigned NumElts = CVA->getNumOperands(); + if (NumElts) { + // ML does not have escape sequences except '' for '. It also has a maximum + // string length of 255. + unsigned len = 0; + bool inString = false; + for (unsigned i = 0; i < NumElts; i++) { + int n = cast(CVA->getOperand(i))->getZExtValue() & 255; + if (len == 0) + O << "\tdb "; + + if (n >= 32 && n <= 127) { + if (!inString) { + if (len > 0) { + O << ",'"; + len += 2; + } else { + O << "'"; + len++; + } + inString = true; + } + if (n == '\'') { + O << "'"; + len++; + } + O << char(n); + } else { + if (inString) { + O << "'"; + len++; + inString = false; + } + if (len > 0) { + O << ","; + len++; + } + O << n; + len += 1 + (n > 9) + (n > 99); + } + + if (len > 60) { + if (inString) { + O << "'"; + inString = false; + } + O << "\n"; + len = 0; + } + } + + if (len > 0) { + if (inString) + O << "'"; + O << "\n"; + } + } +} + +// Include the auto-generated portion of the assembly writer. +#include "X86GenAsmWriter1.inc" diff --git a/lib/Target/X86/AsmPrinter/X86IntelAsmPrinter.h b/lib/Target/X86/AsmPrinter/X86IntelAsmPrinter.h new file mode 100644 index 00000000000..c9ca072baf5 --- /dev/null +++ b/lib/Target/X86/AsmPrinter/X86IntelAsmPrinter.h @@ -0,0 +1,145 @@ +//===-- X86IntelAsmPrinter.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. +// +//===----------------------------------------------------------------------===// +// +// Intel assembly code printer class. +// +//===----------------------------------------------------------------------===// + +#ifndef X86INTELASMPRINTER_H +#define X86INTELASMPRINTER_H + +#include "X86.h" +#include "X86MachineFunctionInfo.h" +#include "X86TargetMachine.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/ADT/StringSet.h" +#include "llvm/Support/Compiler.h" + +namespace llvm { + +struct VISIBILITY_HIDDEN X86IntelAsmPrinter : public AsmPrinter { + X86IntelAsmPrinter(std::ostream &O, X86TargetMachine &TM, + const TargetAsmInfo *T) + : AsmPrinter(O, TM, T) { + } + + virtual const char *getPassName() const { + return "X86 Intel-Style Assembly Printer"; + } + + /// 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 + /// returns false. + bool printInstruction(const MachineInstr *MI); + + // This method is used by the tablegen'erated instruction printer. + void printOperand(const MachineInstr *MI, unsigned OpNo, + const char *Modifier = 0) { + const MachineOperand &MO = MI->getOperand(OpNo); + if (MO.isRegister()) { + assert(TargetRegisterInfo::isPhysicalRegister(MO.getReg()) && + "Not physreg??"); + O << TM.getRegisterInfo()->get(MO.getReg()).Name; // Capitalized names + } else { + printOp(MO, Modifier); + } + } + + void printi8mem(const MachineInstr *MI, unsigned OpNo) { + O << "BYTE PTR "; + printMemReference(MI, OpNo); + } + void printi16mem(const MachineInstr *MI, unsigned OpNo) { + O << "WORD PTR "; + printMemReference(MI, OpNo); + } + void printi32mem(const MachineInstr *MI, unsigned OpNo) { + O << "DWORD PTR "; + printMemReference(MI, OpNo); + } + void printi64mem(const MachineInstr *MI, unsigned OpNo) { + O << "QWORD PTR "; + printMemReference(MI, OpNo); + } + void printi128mem(const MachineInstr *MI, unsigned OpNo) { + O << "XMMWORD PTR "; + printMemReference(MI, OpNo); + } + void printf32mem(const MachineInstr *MI, unsigned OpNo) { + O << "DWORD PTR "; + printMemReference(MI, OpNo); + } + void printf64mem(const MachineInstr *MI, unsigned OpNo) { + O << "QWORD PTR "; + printMemReference(MI, OpNo); + } + void printf80mem(const MachineInstr *MI, unsigned OpNo) { + O << "XWORD PTR "; + printMemReference(MI, OpNo); + } + void printf128mem(const MachineInstr *MI, unsigned OpNo) { + O << "XMMWORD PTR "; + printMemReference(MI, OpNo); + } + void printlea64_32mem(const MachineInstr *MI, unsigned OpNo) { + O << "QWORD PTR "; + 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 printOp(const MachineOperand &MO, const char *Modifier = 0); + void printSSECC(const MachineInstr *MI, unsigned Op); + void printMemReference(const MachineInstr *MI, unsigned Op, + const char *Modifier=NULL); + void printPICJumpTableSetLabel(unsigned uid, + const MachineBasicBlock *MBB) const; + void printPICJumpTableSetLabel(unsigned uid, unsigned uid2, + const MachineBasicBlock *MBB) const { + AsmPrinter::printPICJumpTableSetLabel(uid, uid2, MBB); + } + void printPICLabel(const MachineInstr *MI, unsigned Op); + bool runOnMachineFunction(MachineFunction &F); + bool doInitialization(Module &M); + bool doFinalization(Module &M); + + // 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); + + /// getSectionForFunction - Return the section that we should emit the + /// specified function body into. + virtual std::string getSectionForFunction(const Function &F) const; + + virtual void EmitString(const ConstantArray *CVA) const; + + // Necessary for dllexport support + StringSet<> DLLExportedFns, DLLExportedGVs; +}; + +} // end namespace llvm + +#endif diff --git a/lib/Target/X86/Makefile b/lib/Target/X86/Makefile index c6af978a734..cb3f0ac299f 100644 --- a/lib/Target/X86/Makefile +++ b/lib/Target/X86/Makefile @@ -7,7 +7,7 @@ # ##===----------------------------------------------------------------------===## LEVEL = ../../.. -LIBRARYNAME = LLVMX86 +LIBRARYNAME = LLVMX86CodeGen TARGET = X86 # Make sure that tblgen is run, first thing. @@ -18,4 +18,6 @@ BUILT_SOURCES = X86GenRegisterInfo.h.inc X86GenRegisterNames.inc \ X86GenFastISel.inc \ X86GenCallingConv.inc X86GenSubtarget.inc +DIRS = AsmPrinter + include $(LEVEL)/Makefile.common diff --git a/lib/Target/X86/X86ATTAsmPrinter.cpp b/lib/Target/X86/X86ATTAsmPrinter.cpp deleted file mode 100644 index 8a6b60425ec..00000000000 --- a/lib/Target/X86/X86ATTAsmPrinter.cpp +++ /dev/null @@ -1,985 +0,0 @@ -//===-- X86ATTAsmPrinter.cpp - Convert X86 LLVM code to AT&T assembly -----===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file contains a printer that converts from our internal representation -// of machine-dependent LLVM code to AT&T format assembly -// language. This printer is the output mechanism used by `llc'. -// -//===----------------------------------------------------------------------===// - -#define DEBUG_TYPE "asm-printer" -#include "X86ATTAsmPrinter.h" -#include "X86.h" -#include "X86COFF.h" -#include "X86MachineFunctionInfo.h" -#include "X86TargetMachine.h" -#include "X86TargetAsmInfo.h" -#include "llvm/CallingConv.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" -using namespace llvm; - -STATISTIC(EmittedInsts, "Number of machine instrs printed"); - -static std::string getPICLabelString(unsigned FnNum, - const TargetAsmInfo *TAI, - const X86Subtarget* Subtarget) { - std::string label; - if (Subtarget->isTargetDarwin()) - label = "\"L" + utostr_32(FnNum) + "$pb\""; - else if (Subtarget->isTargetELF()) - label = ".Lllvm$" + utostr_32(FnNum) + "." "$piclabel"; - else - assert(0 && "Don't know how to print PIC label!\n"); - - 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"); - } -} - -// Substitute old hook with new one temporary -std::string X86ATTAsmPrinter::getSectionForFunction(const Function &F) const { - return TAI->SectionForGlobal(&F); -} - -void X86ATTAsmPrinter::emitFunctionHeader(const MachineFunction &MF) { - const Function *F = MF.getFunction(); - std::string SectionName = TAI->SectionForGlobal(F); - - decorateName(CurrentFnName, F); - - SwitchToTextSection(SectionName.c_str()); - - unsigned FnAlign = OptimizeForSize ? 1 : 4; - switch (F->getLinkage()) { - default: assert(0 && "Unknown linkage type!"); - case Function::InternalLinkage: // Symbols default to internal. - EmitAlignment(FnAlign, F); - break; - case Function::DLLExportLinkage: - case Function::ExternalLinkage: - EmitAlignment(FnAlign, F); - O << "\t.globl\t" << CurrentFnName << '\n'; - break; - case Function::LinkOnceLinkage: - case Function::WeakLinkage: - EmitAlignment(FnAlign, F); - if (Subtarget->isTargetDarwin()) { - O << "\t.globl\t" << CurrentFnName << '\n'; - O << TAI->getWeakDefDirective() << CurrentFnName << '\n'; - } else if (Subtarget->isTargetCygMing()) { - O << "\t.globl\t" << CurrentFnName << "\n" - "\t.linkonce discard\n"; - } else { - O << "\t.weak\t" << CurrentFnName << '\n'; - } - break; - } - - printVisibility(CurrentFnName, F->getVisibility()); - - if (Subtarget->isTargetELF()) - O << "\t.type\t" << CurrentFnName << ",@function\n"; - else if (Subtarget->isTargetCygMing()) { - O << "\t.def\t " << CurrentFnName - << ";\t.scl\t" << - (F->getLinkage() == Function::InternalLinkage ? COFF::C_STAT : COFF::C_EXT) - << ";\t.type\t" << (COFF::DT_FCN << COFF::N_BTSHFT) - << ";\t.endef\n"; - } - - O << CurrentFnName << ":\n"; - // Add some workaround for linkonce linkage on Cygwin\MinGW - if (Subtarget->isTargetCygMing() && - (F->getLinkage() == Function::LinkOnceLinkage || - F->getLinkage() == Function::WeakLinkage)) - O << "Lllvm$workaround$fake$stub$" << CurrentFnName << ":\n"; -} - -/// runOnMachineFunction - This uses the printMachineInstruction() -/// method to print assembly for each instruction. -/// -bool X86ATTAsmPrinter::runOnMachineFunction(MachineFunction &MF) { - const Function *F = MF.getFunction(); - unsigned CC = F->getCallingConv(); - - SetupMachineFunction(MF); - O << "\n\n"; - - // Populate function information map. Actually, We don't want to populate - // non-stdcall or non-fastcall functions' information right now. - if (CC == CallingConv::X86_StdCall || CC == CallingConv::X86_FastCall) - FunctionInfoMap[F] = *MF.getInfo(); - - // Print out constants referenced by the function - EmitConstantPool(MF.getConstantPool()); - - if (F->hasDLLExportLinkage()) - DLLExportedFns.insert(Mang->makeNameProper(F->getName(), "")); - - // Print the 'header' of function - emitFunctionHeader(MF); - - // Emit pre-function debug and/or EH information. - if (TAI->doesSupportDebugInformation() || TAI->doesSupportExceptionHandling()) - DW.BeginFunction(&MF); - - // Print out code for the function. - bool hasAnyRealCode = false; - for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); - I != E; ++I) { - // Print a label for the basic block. - if (!I->pred_empty()) { - printBasicBlockLabel(I, true, true); - O << '\n'; - } - for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end(); - II != IE; ++II) { - // Print the assembly for the instruction. - if (!II->isLabel()) - hasAnyRealCode = true; - printMachineInstruction(II); - } - } - - if (Subtarget->isTargetDarwin() && !hasAnyRealCode) { - // If the function is empty, then we need to emit *something*. Otherwise, - // the function's label might be associated with something that it wasn't - // meant to be associated with. We emit a noop in this situation. - // We are assuming inline asms are code. - O << "\tnop\n"; - } - - if (TAI->hasDotTypeDotSizeDirective()) - O << "\t.size\t" << CurrentFnName << ", .-" << CurrentFnName << '\n'; - - // Emit post-function debug information. - if (TAI->doesSupportDebugInformation()) - DW.EndFunction(); - - // Print out jump tables referenced by the function. - EmitJumpTableInfo(MF.getJumpTableInfo(), MF); - - // We didn't modify anything. - return false; -} - -static inline bool shouldPrintGOT(TargetMachine &TM, const X86Subtarget* ST) { - return ST->isPICStyleGOT() && TM.getRelocationModel() == Reloc::PIC_; -} - -static inline bool shouldPrintPLT(TargetMachine &TM, const X86Subtarget* ST) { - return ST->isTargetELF() && TM.getRelocationModel() == Reloc::PIC_ && - (ST->isPICStyleRIPRel() || ST->isPICStyleGOT()); -} - -static inline bool shouldPrintStub(TargetMachine &TM, const X86Subtarget* ST) { - return ST->isPICStyleStub() && TM.getRelocationModel() != Reloc::Static; -} - -void X86ATTAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo, - const char *Modifier, bool NotRIPRel) { - const MachineOperand &MO = MI->getOperand(OpNo); - switch (MO.getType()) { - case MachineOperand::MO_Register: { - assert(TargetRegisterInfo::isPhysicalRegister(MO.getReg()) && - "Virtual registers should not make it this far!"); - O << '%'; - unsigned Reg = MO.getReg(); - if (Modifier && strncmp(Modifier, "subreg", strlen("subreg")) == 0) { - MVT VT = (strcmp(Modifier+6,"64") == 0) ? - MVT::i64 : ((strcmp(Modifier+6, "32") == 0) ? MVT::i32 : - ((strcmp(Modifier+6,"16") == 0) ? MVT::i16 : MVT::i8)); - Reg = getX86SubSuperRegister(Reg, VT); - } - O << TRI->getAsmName(Reg); - return; - } - - case MachineOperand::MO_Immediate: - if (!Modifier || - (strcmp(Modifier, "debug") && strcmp(Modifier, "mem"))) - O << '$'; - O << MO.getImm(); - return; - case MachineOperand::MO_MachineBasicBlock: - printBasicBlockLabel(MO.getMBB()); - return; - case MachineOperand::MO_JumpTableIndex: { - bool isMemOp = Modifier && !strcmp(Modifier, "mem"); - if (!isMemOp) O << '$'; - O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() << '_' - << MO.getIndex(); - - if (TM.getRelocationModel() == Reloc::PIC_) { - if (Subtarget->isPICStyleStub()) - O << "-\"" << TAI->getPrivateGlobalPrefix() << getFunctionNumber() - << "$pb\""; - else if (Subtarget->isPICStyleGOT()) - O << "@GOTOFF"; - } - - if (isMemOp && Subtarget->isPICStyleRIPRel() && !NotRIPRel) - O << "(%rip)"; - return; - } - case MachineOperand::MO_ConstantPoolIndex: { - bool isMemOp = Modifier && !strcmp(Modifier, "mem"); - if (!isMemOp) O << '$'; - O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_' - << MO.getIndex(); - - if (TM.getRelocationModel() == Reloc::PIC_) { - if (Subtarget->isPICStyleStub()) - O << "-\"" << TAI->getPrivateGlobalPrefix() << getFunctionNumber() - << "$pb\""; - else if (Subtarget->isPICStyleGOT()) - O << "@GOTOFF"; - } - - int Offset = MO.getOffset(); - if (Offset > 0) - O << '+' << Offset; - else if (Offset < 0) - O << Offset; - - if (isMemOp && Subtarget->isPICStyleRIPRel() && !NotRIPRel) - O << "(%rip)"; - return; - } - case MachineOperand::MO_GlobalAddress: { - bool isCallOp = Modifier && !strcmp(Modifier, "call"); - bool isMemOp = Modifier && !strcmp(Modifier, "mem"); - bool needCloseParen = false; - - const GlobalValue *GV = MO.getGlobal(); - const GlobalVariable *GVar = dyn_cast(GV); - if (!GVar) { - // If GV is an alias then use the aliasee for determining - // thread-localness. - if (const GlobalAlias *GA = dyn_cast(GV)) - GVar = dyn_cast_or_null(GA->resolveAliasedGlobal()); - } - - bool isThreadLocal = GVar && GVar->isThreadLocal(); - - std::string Name = Mang->getValueName(GV); - decorateName(Name, GV); - - if (!isMemOp && !isCallOp) - O << '$'; - else if (Name[0] == '$') { - // The name begins with a dollar-sign. In order to avoid having it look - // like an integer immediate to the assembler, enclose it in parens. - O << '('; - needCloseParen = true; - } - - if (shouldPrintStub(TM, Subtarget)) { - // Link-once, declaration, or Weakly-linked global variables need - // non-lazily-resolved stubs - if (GV->isDeclaration() || GV->isWeakForLinker()) { - // Dynamically-resolved functions need a stub for the function. - if (isCallOp && isa(GV)) { - FnStubs.insert(Name); - printSuffixedName(Name, "$stub"); - } else { - GVStubs.insert(Name); - printSuffixedName(Name, "$non_lazy_ptr"); - } - } else { - if (GV->hasDLLImportLinkage()) - O << "__imp_"; - O << Name; - } - - if (!isCallOp && TM.getRelocationModel() == Reloc::PIC_) - O << '-' << getPICLabelString(getFunctionNumber(), TAI, Subtarget); - } else { - if (GV->hasDLLImportLinkage()) { - O << "__imp_"; - } - O << Name; - - if (isCallOp) { - if (shouldPrintPLT(TM, Subtarget)) { - // Assemble call via PLT for externally visible symbols - if (!GV->hasHiddenVisibility() && !GV->hasProtectedVisibility() && - !GV->hasInternalLinkage()) - O << "@PLT"; - } - if (Subtarget->isTargetCygMing() && GV->isDeclaration()) - // Save function name for later type emission - FnStubs.insert(Name); - } - } - - if (GV->hasExternalWeakLinkage()) - ExtWeakSymbols.insert(GV); - - int Offset = MO.getOffset(); - if (Offset > 0) - O << '+' << Offset; - else if (Offset < 0) - O << Offset; - - if (isThreadLocal) { - if (TM.getRelocationModel() == Reloc::PIC_ || Subtarget->is64Bit()) - O << "@TLSGD"; // general dynamic TLS model - else - if (GV->isDeclaration()) - O << "@INDNTPOFF"; // initial exec TLS model - else - O << "@NTPOFF"; // local exec TLS model - } else if (isMemOp) { - if (shouldPrintGOT(TM, Subtarget)) { - if (Subtarget->GVRequiresExtraLoad(GV, TM, false)) - O << "@GOT"; - else - O << "@GOTOFF"; - } else if (Subtarget->isPICStyleRIPRel() && !NotRIPRel && - TM.getRelocationModel() != Reloc::Static) { - if (Subtarget->GVRequiresExtraLoad(GV, TM, false)) - O << "@GOTPCREL"; - - if (needCloseParen) { - needCloseParen = false; - O << ')'; - } - - // Use rip when possible to reduce code size, except when - // index or base register are also part of the address. e.g. - // foo(%rip)(%rcx,%rax,4) is not legal - O << "(%rip)"; - } - } - - if (needCloseParen) - O << ')'; - - return; - } - case MachineOperand::MO_ExternalSymbol: { - bool isCallOp = Modifier && !strcmp(Modifier, "call"); - bool needCloseParen = false; - std::string Name(TAI->getGlobalPrefix()); - Name += MO.getSymbolName(); - if (isCallOp && shouldPrintStub(TM, Subtarget)) { - FnStubs.insert(Name); - printSuffixedName(Name, "$stub"); - return; - } - if (!isCallOp) - O << '$'; - else if (Name[0] == '$') { - // The name begins with a dollar-sign. In order to avoid having it look - // like an integer immediate to the assembler, enclose it in parens. - O << '('; - needCloseParen = true; - } - - O << Name; - - if (shouldPrintPLT(TM, Subtarget)) { - std::string GOTName(TAI->getGlobalPrefix()); - GOTName+="_GLOBAL_OFFSET_TABLE_"; - if (Name == GOTName) - // HACK! Emit extra offset to PC during printing GOT offset to - // compensate for the size of popl instruction. The resulting code - // should look like: - // call .piclabel - // piclabel: - // popl %some_register - // addl $_GLOBAL_ADDRESS_TABLE_ + [.-piclabel], %some_register - O << " + [.-" - << getPICLabelString(getFunctionNumber(), TAI, Subtarget) << ']'; - - if (isCallOp) - O << "@PLT"; - } - - if (needCloseParen) - O << ')'; - - if (!isCallOp && Subtarget->isPICStyleRIPRel()) - O << "(%rip)"; - - return; - } - default: - O << ""; return; - } -} - -void X86ATTAsmPrinter::printSSECC(const MachineInstr *MI, unsigned Op) { - unsigned char value = MI->getOperand(Op).getImm(); - assert(value <= 7 && "Invalid ssecc argument!"); - switch (value) { - case 0: O << "eq"; break; - case 1: O << "lt"; break; - case 2: O << "le"; break; - case 3: O << "unord"; break; - case 4: O << "neq"; break; - case 5: O << "nlt"; break; - case 6: O << "nle"; break; - case 7: O << "ord"; break; - } -} - -void X86ATTAsmPrinter::printMemReference(const MachineInstr *MI, unsigned Op, - const char *Modifier){ - assert(isMem(MI, Op) && "Invalid memory reference!"); - MachineOperand BaseReg = MI->getOperand(Op); - MachineOperand IndexReg = MI->getOperand(Op+2); - const MachineOperand &DispSpec = MI->getOperand(Op+3); - - bool NotRIPRel = IndexReg.getReg() || BaseReg.getReg(); - if (DispSpec.isGlobalAddress() || - DispSpec.isConstantPoolIndex() || - DispSpec.isJumpTableIndex()) { - printOperand(MI, Op+3, "mem", NotRIPRel); - } else { - int DispVal = DispSpec.getImm(); - if (DispVal || (!IndexReg.getReg() && !BaseReg.getReg())) - O << DispVal; - } - - if (IndexReg.getReg() || BaseReg.getReg()) { - unsigned ScaleVal = MI->getOperand(Op+1).getImm(); - unsigned BaseRegOperand = 0, IndexRegOperand = 2; - - // There are cases where we can end up with ESP/RSP in the indexreg slot. - // If this happens, swap the base/index register to support assemblers that - // don't work when the index is *SP. - if (IndexReg.getReg() == X86::ESP || IndexReg.getReg() == X86::RSP) { - assert(ScaleVal == 1 && "Scale not supported for stack pointer!"); - std::swap(BaseReg, IndexReg); - std::swap(BaseRegOperand, IndexRegOperand); - } - - O << '('; - if (BaseReg.getReg()) - printOperand(MI, Op+BaseRegOperand, Modifier); - - if (IndexReg.getReg()) { - O << ','; - printOperand(MI, Op+IndexRegOperand, Modifier); - if (ScaleVal != 1) - O << ',' << ScaleVal; - } - O << ')'; - } -} - -void X86ATTAsmPrinter::printPICJumpTableSetLabel(unsigned uid, - const MachineBasicBlock *MBB) const { - if (!TAI->getSetDirective()) - return; - - // We don't need .set machinery if we have GOT-style relocations - if (Subtarget->isPICStyleGOT()) - return; - - O << TAI->getSetDirective() << ' ' << TAI->getPrivateGlobalPrefix() - << getFunctionNumber() << '_' << uid << "_set_" << MBB->getNumber() << ','; - printBasicBlockLabel(MBB, false, false, false); - if (Subtarget->isPICStyleRIPRel()) - O << '-' << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() - << '_' << uid << '\n'; - else - O << '-' << getPICLabelString(getFunctionNumber(), TAI, Subtarget) << '\n'; -} - -void X86ATTAsmPrinter::printPICLabel(const MachineInstr *MI, unsigned Op) { - std::string label = getPICLabelString(getFunctionNumber(), TAI, Subtarget); - O << label << '\n' << label << ':'; -} - - -void X86ATTAsmPrinter::printPICJumpTableEntry(const MachineJumpTableInfo *MJTI, - const MachineBasicBlock *MBB, - unsigned uid) const -{ - const char *JTEntryDirective = MJTI->getEntrySize() == 4 ? - TAI->getData32bitsDirective() : TAI->getData64bitsDirective(); - - O << JTEntryDirective << ' '; - - if (TM.getRelocationModel() == Reloc::PIC_) { - if (Subtarget->isPICStyleRIPRel() || Subtarget->isPICStyleStub()) { - O << TAI->getPrivateGlobalPrefix() << getFunctionNumber() - << '_' << uid << "_set_" << MBB->getNumber(); - } else if (Subtarget->isPICStyleGOT()) { - printBasicBlockLabel(MBB, false, false, false); - O << "@GOTOFF"; - } else - assert(0 && "Don't know how to print MBB label for this PIC mode"); - } else - printBasicBlockLabel(MBB, false, false, false); -} - -bool X86ATTAsmPrinter::printAsmMRegister(const MachineOperand &MO, - const char Mode) { - unsigned Reg = MO.getReg(); - switch (Mode) { - default: return true; // Unknown mode. - case 'b': // Print QImode register - Reg = getX86SubSuperRegister(Reg, MVT::i8); - break; - case 'h': // Print QImode high register - Reg = getX86SubSuperRegister(Reg, MVT::i8, true); - break; - case 'w': // Print HImode register - Reg = getX86SubSuperRegister(Reg, MVT::i16); - break; - case 'k': // Print SImode register - Reg = getX86SubSuperRegister(Reg, MVT::i32); - break; - case 'q': // Print DImode register - Reg = getX86SubSuperRegister(Reg, MVT::i64); - break; - } - - O << '%'<< TRI->getAsmName(Reg); - return false; -} - -/// PrintAsmOperand - Print out an operand for an inline asm expression. -/// -bool X86ATTAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, - unsigned AsmVariant, - const char *ExtraCode) { - // Does this asm operand have a single letter operand modifier? - if (ExtraCode && ExtraCode[0]) { - if (ExtraCode[1] != 0) return true; // Unknown modifier. - - switch (ExtraCode[0]) { - default: return true; // Unknown modifier. - case 'c': // Don't print "$" before a global var name or constant. - printOperand(MI, OpNo, "mem"); - return false; - case 'b': // Print QImode register - case 'h': // Print QImode high register - case 'w': // Print HImode register - case 'k': // Print SImode register - case 'q': // Print DImode register - if (MI->getOperand(OpNo).isRegister()) - return printAsmMRegister(MI->getOperand(OpNo), ExtraCode[0]); - printOperand(MI, OpNo); - return false; - - case 'P': // Don't print @PLT, but do print as memory. - printOperand(MI, OpNo, "mem"); - return false; - } - } - - printOperand(MI, OpNo); - return false; -} - -bool X86ATTAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, - unsigned OpNo, - unsigned AsmVariant, - const char *ExtraCode) { - if (ExtraCode && ExtraCode[0]) { - if (ExtraCode[1] != 0) return true; // Unknown modifier. - - switch (ExtraCode[0]) { - default: return true; // Unknown modifier. - case 'b': // Print QImode register - case 'h': // Print QImode high register - case 'w': // Print HImode register - case 'k': // Print SImode register - case 'q': // Print SImode register - // These only apply to registers, ignore on mem. - break; - } - } - printMemReference(MI, OpNo); - return false; -} - -/// printMachineInstruction -- Print out a single X86 LLVM instruction -/// MI in AT&T syntax to the current output stream. -/// -void X86ATTAsmPrinter::printMachineInstruction(const MachineInstr *MI) { - ++EmittedInsts; - - // Call the autogenerated instruction printer routines. - printInstruction(MI); -} - -/// doInitialization -bool X86ATTAsmPrinter::doInitialization(Module &M) { - if (TAI->doesSupportDebugInformation()) { - // Emit initial debug information. - DW.BeginModule(&M); - } - - bool Result = AsmPrinter::doInitialization(M); - - if (TAI->doesSupportDebugInformation()) { - // Let PassManager know we need debug information and relay - // the MachineModuleInfo address on to DwarfWriter. - // AsmPrinter::doInitialization did this analysis. - MMI = getAnalysisToUpdate(); - DW.SetModuleInfo(MMI); - } - - // Darwin wants symbols to be quoted if they have complex names. - if (Subtarget->isTargetDarwin()) - Mang->setUseQuotes(true); - - return Result; -} - - -void X86ATTAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) { - const TargetData *TD = TM.getTargetData(); - - if (!GVar->hasInitializer()) - return; // External global require no code - - // Check to see if this is a special global used by LLVM, if so, emit it. - if (EmitSpecialLLVMGlobal(GVar)) { - if (Subtarget->isTargetDarwin() && - TM.getRelocationModel() == Reloc::Static) { - if (GVar->getName() == "llvm.global_ctors") - O << ".reference .constructors_used\n"; - else if (GVar->getName() == "llvm.global_dtors") - O << ".reference .destructors_used\n"; - } - 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 Align = TD->getPreferredAlignmentLog(GVar); - - printVisibility(name, GVar->getVisibility()); - - if (Subtarget->isTargetELF()) - O << "\t.type\t" << name << ",@object\n"; - - SwitchToDataSection(SectionName.c_str()); - - if (C->isNullValue() && !GVar->hasSection()) { - // FIXME: This seems to be pretty darwin-specific - if (GVar->hasExternalLinkage()) { - if (const char *Directive = TAI->getZeroFillDirective()) { - O << "\t.globl " << name << '\n'; - O << Directive << "__DATA, __common, " << name << ", " - << Size << ", " << Align << '\n'; - return; - } - } - - if (!GVar->isThreadLocal() && - (GVar->hasInternalLinkage() || GVar->isWeakForLinker())) { - if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it. - - if (TAI->getLCOMMDirective() != NULL) { - if (GVar->hasInternalLinkage()) { - O << TAI->getLCOMMDirective() << name << ',' << Size; - if (Subtarget->isTargetDarwin()) - O << ',' << Align; - } else if (Subtarget->isTargetDarwin() && !GVar->hasCommonLinkage()) { - 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 { - O << TAI->getCOMMDirective() << name << ',' << Size; - if (TAI->getCOMMDirectiveTakesAlignment()) - O << ',' << (TAI->getAlignmentIsInBytes() ? (1 << Align) : Align); - } - } else { - if (!Subtarget->isTargetCygMing()) { - if (GVar->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(GVar, O); - O << '\n'; - return; - } - } - - switch (GVar->getLinkage()) { - case GlobalValue::CommonLinkage: - case GlobalValue::LinkOnceLinkage: - case GlobalValue::WeakLinkage: - if (Subtarget->isTargetDarwin()) { - O << "\t.globl " << name << '\n' - << TAI->getWeakDefDirective() << name << '\n'; - } else if (Subtarget->isTargetCygMing()) { - O << "\t.globl\t" << name << "\n" - "\t.linkonce same_size\n"; - } else { - O << "\t.weak\t" << name << '\n'; - } - break; - case GlobalValue::DLLExportLinkage: - 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: - break; - default: - assert(0 && "Unknown linkage type!"); - } - - EmitAlignment(Align, GVar); - O << name << ":\t\t\t\t" << TAI->getCommentString() << ' '; - PrintUnmangledNameSafely(GVar, 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); -} - -/// printGVStub - Print stub for a global value. -/// -void X86ATTAsmPrinter::printGVStub(const char *GV, const char *Prefix) { - printSuffixedName(GV, "$non_lazy_ptr", Prefix); - O << ":\n\t.indirect_symbol "; - if (Prefix) O << Prefix; - O << GV << "\n\t.long\t0\n"; -} - - -bool X86ATTAsmPrinter::doFinalization(Module &M) { - // Print out module-level global variables here. - for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); - I != E; ++I) { - printModuleLevelGV(I); - - if (I->hasDLLExportLinkage()) - DLLExportedGVs.insert(Mang->makeNameProper(I->getName(),"")); - } - - // 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); - const char *p = i->getKeyData(); - printSuffixedName(p, "$stub"); - O << ":\n" - "\t.indirect_symbol " << p << "\n" - "\thlt ; hlt ; hlt ; hlt ; hlt\n"; - } - - O << '\n'; - - // Print global value stubs. - bool InStubSection = false; - 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) - continue; - if (!InStubSection) { - SwitchToDataSection( - "\t.section __IMPORT,__pointers,non_lazy_symbol_pointers"); - InStubSection = true; - } - printGVStub((*I)->getNameStart(), "_"); - } - } - - // Output stubs for external and common global variables. - if (!InStubSection && !GVStubs.empty()) - SwitchToDataSection( - "\t.section __IMPORT,__pointers,non_lazy_symbol_pointers"); - for (StringSet<>::iterator i = GVStubs.begin(), e = GVStubs.end(); - i != e; ++i) - printGVStub(i->getKeyData()); - - // 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 deleted file mode 100644 index f9479fd41d4..00000000000 --- a/lib/Target/X86/X86ATTAsmPrinter.h +++ /dev/null @@ -1,158 +0,0 @@ -//===-- X86ATTAsmPrinter.h - Convert X86 LLVM code to AT&T assembly -------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// AT&T assembly code printer class. -// -//===----------------------------------------------------------------------===// - -#ifndef X86ATTASMPRINTER_H -#define X86ATTASMPRINTER_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 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 - /// returns false. - bool printInstruction(const MachineInstr *MI); - - // These methods are used by the tablegen'erated instruction printer. - void printOperand(const MachineInstr *MI, unsigned OpNo, - const char *Modifier = 0, bool NotRIPRel = false); - void printi8mem(const MachineInstr *MI, unsigned OpNo) { - printMemReference(MI, OpNo); - } - void printi16mem(const MachineInstr *MI, unsigned OpNo) { - printMemReference(MI, OpNo); - } - void printi32mem(const MachineInstr *MI, unsigned OpNo) { - printMemReference(MI, OpNo); - } - void printi64mem(const MachineInstr *MI, unsigned OpNo) { - printMemReference(MI, OpNo); - } - void printi128mem(const MachineInstr *MI, unsigned OpNo) { - printMemReference(MI, OpNo); - } - void printf32mem(const MachineInstr *MI, unsigned OpNo) { - printMemReference(MI, OpNo); - } - void printf64mem(const MachineInstr *MI, unsigned OpNo) { - printMemReference(MI, OpNo); - } - void printf80mem(const MachineInstr *MI, unsigned OpNo) { - printMemReference(MI, OpNo); - } - void printf128mem(const MachineInstr *MI, unsigned OpNo) { - printMemReference(MI, OpNo); - } - 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, - const char *Modifier=NULL); - void printPICJumpTableSetLabel(unsigned uid, - const MachineBasicBlock *MBB) const; - void printPICJumpTableSetLabel(unsigned uid, unsigned uid2, - const MachineBasicBlock *MBB) const { - AsmPrinter::printPICJumpTableSetLabel(uid, uid2, MBB); - } - void printPICJumpTableEntry(const MachineJumpTableInfo *MJTI, - const MachineBasicBlock *MBB, - unsigned uid) const; - - void printPICLabel(const MachineInstr *MI, unsigned Op); - void printModuleLevelGV(const GlobalVariable* GVar); - - void printGVStub(const char *GV, const char *Prefix = NULL); - - 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; - - void emitFunctionHeader(const MachineFunction &MF); - - // 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 - -#endif diff --git a/lib/Target/X86/X86AsmPrinter.cpp b/lib/Target/X86/X86AsmPrinter.cpp deleted file mode 100644 index 5659282ff10..00000000000 --- a/lib/Target/X86/X86AsmPrinter.cpp +++ /dev/null @@ -1,35 +0,0 @@ -//===-- 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 "X86ATTAsmPrinter.h" -#include "X86IntelAsmPrinter.h" -#include "X86Subtarget.h" -using namespace llvm; - -/// 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()); - } -} diff --git a/lib/Target/X86/X86AsmPrinter.h b/lib/Target/X86/X86AsmPrinter.h deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/lib/Target/X86/X86IntelAsmPrinter.cpp b/lib/Target/X86/X86IntelAsmPrinter.cpp deleted file mode 100644 index 1822c1f914a..00000000000 --- a/lib/Target/X86/X86IntelAsmPrinter.cpp +++ /dev/null @@ -1,597 +0,0 @@ -//===-- X86IntelAsmPrinter.cpp - 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 contains a printer that converts from our internal representation -// of machine-dependent LLVM code to Intel format assembly language. -// This printer is the output mechanism used by `llc'. -// -//===----------------------------------------------------------------------===// - -#define DEBUG_TYPE "asm-printer" -#include "X86IntelAsmPrinter.h" -#include "X86InstrInfo.h" -#include "X86TargetAsmInfo.h" -#include "X86.h" -#include "llvm/CallingConv.h" -#include "llvm/Constants.h" -#include "llvm/DerivedTypes.h" -#include "llvm/Module.h" -#include "llvm/ADT/Statistic.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/Assembly/Writer.h" -#include "llvm/Support/Mangler.h" -#include "llvm/Target/TargetAsmInfo.h" -#include "llvm/Target/TargetOptions.h" -using namespace llvm; - -STATISTIC(EmittedInsts, "Number of machine instrs printed"); - -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 X86IntelAsmPrinter::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; - - 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"); - } -} - - -std::string X86IntelAsmPrinter::getSectionForFunction(const Function &F) const { - // Intel asm always emits functions to _text. - return "_text"; -} - -/// runOnMachineFunction - This uses the printMachineInstruction() -/// method to print assembly for each instruction. -/// -bool X86IntelAsmPrinter::runOnMachineFunction(MachineFunction &MF) { - SetupMachineFunction(MF); - O << "\n\n"; - - // Print out constants referenced by the function - EmitConstantPool(MF.getConstantPool()); - - // Print out labels for the function. - const Function *F = MF.getFunction(); - unsigned CC = F->getCallingConv(); - - // Populate function information map. Actually, We don't want to populate - // non-stdcall or non-fastcall functions' information right now. - if (CC == CallingConv::X86_StdCall || CC == CallingConv::X86_FastCall) - FunctionInfoMap[F] = *MF.getInfo(); - - decorateName(CurrentFnName, F); - - SwitchToTextSection(getSectionForFunction(*F).c_str(), F); - - unsigned FnAlign = OptimizeForSize ? 1 : 4; - switch (F->getLinkage()) { - default: assert(0 && "Unsupported linkage type!"); - case Function::InternalLinkage: - EmitAlignment(FnAlign); - break; - case Function::DLLExportLinkage: - DLLExportedFns.insert(CurrentFnName); - //FALLS THROUGH - case Function::ExternalLinkage: - O << "\tpublic " << CurrentFnName << "\n"; - EmitAlignment(FnAlign); - break; - } - - O << CurrentFnName << "\tproc near\n"; - - // Print out code for the function. - for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); - I != E; ++I) { - // Print a label for the basic block if there are any predecessors. - if (!I->pred_empty()) { - printBasicBlockLabel(I, true, true); - O << '\n'; - } - for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end(); - II != E; ++II) { - // Print the assembly for the instruction. - printMachineInstruction(II); - } - } - - // Print out jump tables referenced by the function. - EmitJumpTableInfo(MF.getJumpTableInfo(), MF); - - O << CurrentFnName << "\tendp\n"; - - // We didn't modify anything. - return false; -} - -void X86IntelAsmPrinter::printSSECC(const MachineInstr *MI, unsigned Op) { - unsigned char value = MI->getOperand(Op).getImm(); - assert(value <= 7 && "Invalid ssecc argument!"); - switch (value) { - case 0: O << "eq"; break; - case 1: O << "lt"; break; - case 2: O << "le"; break; - case 3: O << "unord"; break; - case 4: O << "neq"; break; - case 5: O << "nlt"; break; - case 6: O << "nle"; break; - case 7: O << "ord"; break; - } -} - -void X86IntelAsmPrinter::printOp(const MachineOperand &MO, - const char *Modifier) { - switch (MO.getType()) { - case MachineOperand::MO_Register: { - if (TargetRegisterInfo::isPhysicalRegister(MO.getReg())) { - unsigned Reg = MO.getReg(); - if (Modifier && strncmp(Modifier, "subreg", strlen("subreg")) == 0) { - MVT VT = (strcmp(Modifier,"subreg64") == 0) ? - MVT::i64 : ((strcmp(Modifier, "subreg32") == 0) ? MVT::i32 : - ((strcmp(Modifier,"subreg16") == 0) ? MVT::i16 :MVT::i8)); - Reg = getX86SubSuperRegister(Reg, VT); - } - O << TRI->getName(Reg); - } else - O << "reg" << MO.getReg(); - return; - } - case MachineOperand::MO_Immediate: - O << MO.getImm(); - return; - case MachineOperand::MO_MachineBasicBlock: - printBasicBlockLabel(MO.getMBB()); - return; - case MachineOperand::MO_JumpTableIndex: { - bool isMemOp = Modifier && !strcmp(Modifier, "mem"); - if (!isMemOp) O << "OFFSET "; - O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() - << "_" << MO.getIndex(); - return; - } - case MachineOperand::MO_ConstantPoolIndex: { - bool isMemOp = Modifier && !strcmp(Modifier, "mem"); - if (!isMemOp) O << "OFFSET "; - O << "[" << TAI->getPrivateGlobalPrefix() << "CPI" - << getFunctionNumber() << "_" << MO.getIndex(); - int Offset = MO.getOffset(); - if (Offset > 0) - O << " + " << Offset; - else if (Offset < 0) - O << Offset; - O << "]"; - return; - } - case MachineOperand::MO_GlobalAddress: { - bool isCallOp = Modifier && !strcmp(Modifier, "call"); - bool isMemOp = Modifier && !strcmp(Modifier, "mem"); - GlobalValue *GV = MO.getGlobal(); - std::string Name = Mang->getValueName(GV); - - decorateName(Name, GV); - - if (!isMemOp && !isCallOp) O << "OFFSET "; - if (GV->hasDLLImportLinkage()) { - // FIXME: This should be fixed with full support of stdcall & fastcall - // CC's - O << "__imp_"; - } - O << Name; - int Offset = MO.getOffset(); - if (Offset > 0) - O << " + " << Offset; - else if (Offset < 0) - O << Offset; - return; - } - case MachineOperand::MO_ExternalSymbol: { - bool isCallOp = Modifier && !strcmp(Modifier, "call"); - if (!isCallOp) O << "OFFSET "; - O << TAI->getGlobalPrefix() << MO.getSymbolName(); - return; - } - default: - O << ""; return; - } -} - -void X86IntelAsmPrinter::printMemReference(const MachineInstr *MI, unsigned Op, - const char *Modifier) { - assert(isMem(MI, Op) && "Invalid memory reference!"); - - const MachineOperand &BaseReg = MI->getOperand(Op); - int ScaleVal = MI->getOperand(Op+1).getImm(); - const MachineOperand &IndexReg = MI->getOperand(Op+2); - const MachineOperand &DispSpec = MI->getOperand(Op+3); - - O << "["; - bool NeedPlus = false; - if (BaseReg.getReg()) { - printOp(BaseReg, Modifier); - NeedPlus = true; - } - - if (IndexReg.getReg()) { - if (NeedPlus) O << " + "; - if (ScaleVal != 1) - O << ScaleVal << "*"; - printOp(IndexReg, Modifier); - NeedPlus = true; - } - - if (DispSpec.isGlobalAddress() || DispSpec.isConstantPoolIndex() || - DispSpec.isJumpTableIndex()) { - if (NeedPlus) - O << " + "; - printOp(DispSpec, "mem"); - } else { - int DispVal = DispSpec.getImm(); - if (DispVal || (!BaseReg.getReg() && !IndexReg.getReg())) { - if (NeedPlus) { - if (DispVal > 0) - O << " + "; - else { - O << " - "; - DispVal = -DispVal; - } - } - O << DispVal; - } - } - O << "]"; -} - -void X86IntelAsmPrinter::printPICJumpTableSetLabel(unsigned uid, - const MachineBasicBlock *MBB) const { - if (!TAI->getSetDirective()) - return; - - O << TAI->getSetDirective() << ' ' << TAI->getPrivateGlobalPrefix() - << getFunctionNumber() << '_' << uid << "_set_" << MBB->getNumber() << ','; - printBasicBlockLabel(MBB, false, false, false); - O << '-' << "\"L" << getFunctionNumber() << "$pb\"'\n"; -} - -void X86IntelAsmPrinter::printPICLabel(const MachineInstr *MI, unsigned Op) { - O << "\"L" << getFunctionNumber() << "$pb\"\n"; - O << "\"L" << getFunctionNumber() << "$pb\":"; -} - -bool X86IntelAsmPrinter::printAsmMRegister(const MachineOperand &MO, - const char Mode) { - unsigned Reg = MO.getReg(); - switch (Mode) { - default: return true; // Unknown mode. - case 'b': // Print QImode register - Reg = getX86SubSuperRegister(Reg, MVT::i8); - break; - case 'h': // Print QImode high register - Reg = getX86SubSuperRegister(Reg, MVT::i8, true); - break; - case 'w': // Print HImode register - Reg = getX86SubSuperRegister(Reg, MVT::i16); - break; - case 'k': // Print SImode register - Reg = getX86SubSuperRegister(Reg, MVT::i32); - break; - } - - O << '%' << TRI->getName(Reg); - return false; -} - -/// PrintAsmOperand - Print out an operand for an inline asm expression. -/// -bool X86IntelAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, - unsigned AsmVariant, - const char *ExtraCode) { - // Does this asm operand have a single letter operand modifier? - if (ExtraCode && ExtraCode[0]) { - if (ExtraCode[1] != 0) return true; // Unknown modifier. - - switch (ExtraCode[0]) { - default: return true; // Unknown modifier. - case 'b': // Print QImode register - case 'h': // Print QImode high register - case 'w': // Print HImode register - case 'k': // Print SImode register - return printAsmMRegister(MI->getOperand(OpNo), ExtraCode[0]); - } - } - - printOperand(MI, OpNo); - return false; -} - -bool X86IntelAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, - unsigned OpNo, - unsigned AsmVariant, - const char *ExtraCode) { - if (ExtraCode && ExtraCode[0]) - return true; // Unknown modifier. - printMemReference(MI, OpNo); - return false; -} - -/// printMachineInstruction -- Print out a single X86 LLVM instruction -/// MI in Intel syntax to the current output stream. -/// -void X86IntelAsmPrinter::printMachineInstruction(const MachineInstr *MI) { - ++EmittedInsts; - - // Call the autogenerated instruction printer routines. - printInstruction(MI); -} - -bool X86IntelAsmPrinter::doInitialization(Module &M) { - bool Result = AsmPrinter::doInitialization(M); - - Mang->markCharUnacceptable('.'); - - O << "\t.686\n\t.model flat\n\n"; - - // Emit declarations for external functions. - for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) - if (I->isDeclaration()) { - std::string Name = Mang->getValueName(I); - decorateName(Name, I); - - O << "\textern " ; - if (I->hasDLLImportLinkage()) { - O << "__imp_"; - } - O << Name << ":near\n"; - } - - // Emit declarations for external globals. Note that VC++ always declares - // external globals to have type byte, and if that's good enough for VC++... - for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); - I != E; ++I) { - if (I->isDeclaration()) { - std::string Name = Mang->getValueName(I); - - O << "\textern " ; - if (I->hasDLLImportLinkage()) { - O << "__imp_"; - } - O << Name << ":byte\n"; - } - } - - return Result; -} - -bool X86IntelAsmPrinter::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) { - if (I->isDeclaration()) 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)) - continue; - - std::string name = Mang->getValueName(I); - Constant *C = I->getInitializer(); - unsigned Align = TD->getPreferredAlignmentLog(I); - bool bCustomSegment = false; - - switch (I->getLinkage()) { - case GlobalValue::CommonLinkage: - case GlobalValue::LinkOnceLinkage: - case GlobalValue::WeakLinkage: - SwitchToDataSection(""); - O << name << "?\tsegment common 'COMMON'\n"; - bCustomSegment = true; - // FIXME: the default alignment is 16 bytes, but 1, 2, 4, and 256 - // are also available. - break; - case GlobalValue::AppendingLinkage: - SwitchToDataSection(""); - O << name << "?\tsegment public 'DATA'\n"; - bCustomSegment = true; - // FIXME: the default alignment is 16 bytes, but 1, 2, 4, and 256 - // are also available. - break; - case GlobalValue::DLLExportLinkage: - DLLExportedGVs.insert(name); - // FALL THROUGH - case GlobalValue::ExternalLinkage: - O << "\tpublic " << name << "\n"; - // FALL THROUGH - case GlobalValue::InternalLinkage: - SwitchToDataSection(TAI->getDataSection(), I); - break; - default: - assert(0 && "Unknown linkage type!"); - } - - if (!bCustomSegment) - EmitAlignment(Align, I); - - O << name << ":\t\t\t\t" << TAI->getCommentString() - << " " << I->getName() << '\n'; - - EmitGlobalConstant(C); - - if (bCustomSegment) - O << name << "?\tends\n"; - } - - // Output linker support code for dllexported globals - if (!DLLExportedGVs.empty() || !DLLExportedFns.empty()) { - SwitchToDataSection(""); - O << "; WARNING: The following code is valid only with MASM v8.x and (possible) higher\n" - << "; This version of MASM is usually shipped with Microsoft Visual Studio 2005\n" - << "; or (possible) further versions. Unfortunately, there is no way to support\n" - << "; dllexported symbols in the earlier versions of MASM in fully automatic way\n\n"; - O << "_drectve\t segment info alias('.drectve')\n"; - } - - for (StringSet<>::iterator i = DLLExportedGVs.begin(), - e = DLLExportedGVs.end(); - i != e; ++i) - O << "\t db ' /EXPORT:" << i->getKeyData() << ",data'\n"; - - for (StringSet<>::iterator i = DLLExportedFns.begin(), - e = DLLExportedFns.end(); - i != e; ++i) - O << "\t db ' /EXPORT:" << i->getKeyData() << "'\n"; - - if (!DLLExportedGVs.empty() || !DLLExportedFns.empty()) - O << "_drectve\t ends\n"; - - // Bypass X86SharedAsmPrinter::doFinalization(). - bool Result = AsmPrinter::doFinalization(M); - SwitchToDataSection(""); - O << "\tend\n"; - return Result; -} - -void X86IntelAsmPrinter::EmitString(const ConstantArray *CVA) const { - unsigned NumElts = CVA->getNumOperands(); - if (NumElts) { - // ML does not have escape sequences except '' for '. It also has a maximum - // string length of 255. - unsigned len = 0; - bool inString = false; - for (unsigned i = 0; i < NumElts; i++) { - int n = cast(CVA->getOperand(i))->getZExtValue() & 255; - if (len == 0) - O << "\tdb "; - - if (n >= 32 && n <= 127) { - if (!inString) { - if (len > 0) { - O << ",'"; - len += 2; - } else { - O << "'"; - len++; - } - inString = true; - } - if (n == '\'') { - O << "'"; - len++; - } - O << char(n); - } else { - if (inString) { - O << "'"; - len++; - inString = false; - } - if (len > 0) { - O << ","; - len++; - } - O << n; - len += 1 + (n > 9) + (n > 99); - } - - if (len > 60) { - if (inString) { - O << "'"; - inString = false; - } - O << "\n"; - len = 0; - } - } - - if (len > 0) { - if (inString) - O << "'"; - O << "\n"; - } - } -} - -// Include the auto-generated portion of the assembly writer. -#include "X86GenAsmWriter1.inc" diff --git a/lib/Target/X86/X86IntelAsmPrinter.h b/lib/Target/X86/X86IntelAsmPrinter.h deleted file mode 100644 index c9ca072baf5..00000000000 --- a/lib/Target/X86/X86IntelAsmPrinter.h +++ /dev/null @@ -1,145 +0,0 @@ -//===-- X86IntelAsmPrinter.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. -// -//===----------------------------------------------------------------------===// -// -// Intel assembly code printer class. -// -//===----------------------------------------------------------------------===// - -#ifndef X86INTELASMPRINTER_H -#define X86INTELASMPRINTER_H - -#include "X86.h" -#include "X86MachineFunctionInfo.h" -#include "X86TargetMachine.h" -#include "llvm/CodeGen/AsmPrinter.h" -#include "llvm/ADT/StringSet.h" -#include "llvm/Support/Compiler.h" - -namespace llvm { - -struct VISIBILITY_HIDDEN X86IntelAsmPrinter : public AsmPrinter { - X86IntelAsmPrinter(std::ostream &O, X86TargetMachine &TM, - const TargetAsmInfo *T) - : AsmPrinter(O, TM, T) { - } - - virtual const char *getPassName() const { - return "X86 Intel-Style Assembly Printer"; - } - - /// 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 - /// returns false. - bool printInstruction(const MachineInstr *MI); - - // This method is used by the tablegen'erated instruction printer. - void printOperand(const MachineInstr *MI, unsigned OpNo, - const char *Modifier = 0) { - const MachineOperand &MO = MI->getOperand(OpNo); - if (MO.isRegister()) { - assert(TargetRegisterInfo::isPhysicalRegister(MO.getReg()) && - "Not physreg??"); - O << TM.getRegisterInfo()->get(MO.getReg()).Name; // Capitalized names - } else { - printOp(MO, Modifier); - } - } - - void printi8mem(const MachineInstr *MI, unsigned OpNo) { - O << "BYTE PTR "; - printMemReference(MI, OpNo); - } - void printi16mem(const MachineInstr *MI, unsigned OpNo) { - O << "WORD PTR "; - printMemReference(MI, OpNo); - } - void printi32mem(const MachineInstr *MI, unsigned OpNo) { - O << "DWORD PTR "; - printMemReference(MI, OpNo); - } - void printi64mem(const MachineInstr *MI, unsigned OpNo) { - O << "QWORD PTR "; - printMemReference(MI, OpNo); - } - void printi128mem(const MachineInstr *MI, unsigned OpNo) { - O << "XMMWORD PTR "; - printMemReference(MI, OpNo); - } - void printf32mem(const MachineInstr *MI, unsigned OpNo) { - O << "DWORD PTR "; - printMemReference(MI, OpNo); - } - void printf64mem(const MachineInstr *MI, unsigned OpNo) { - O << "QWORD PTR "; - printMemReference(MI, OpNo); - } - void printf80mem(const MachineInstr *MI, unsigned OpNo) { - O << "XWORD PTR "; - printMemReference(MI, OpNo); - } - void printf128mem(const MachineInstr *MI, unsigned OpNo) { - O << "XMMWORD PTR "; - printMemReference(MI, OpNo); - } - void printlea64_32mem(const MachineInstr *MI, unsigned OpNo) { - O << "QWORD PTR "; - 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 printOp(const MachineOperand &MO, const char *Modifier = 0); - void printSSECC(const MachineInstr *MI, unsigned Op); - void printMemReference(const MachineInstr *MI, unsigned Op, - const char *Modifier=NULL); - void printPICJumpTableSetLabel(unsigned uid, - const MachineBasicBlock *MBB) const; - void printPICJumpTableSetLabel(unsigned uid, unsigned uid2, - const MachineBasicBlock *MBB) const { - AsmPrinter::printPICJumpTableSetLabel(uid, uid2, MBB); - } - void printPICLabel(const MachineInstr *MI, unsigned Op); - bool runOnMachineFunction(MachineFunction &F); - bool doInitialization(Module &M); - bool doFinalization(Module &M); - - // 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); - - /// getSectionForFunction - Return the section that we should emit the - /// specified function body into. - virtual std::string getSectionForFunction(const Function &F) const; - - virtual void EmitString(const ConstantArray *CVA) const; - - // Necessary for dllexport support - StringSet<> DLLExportedFns, DLLExportedGVs; -}; - -} // end namespace llvm - -#endif diff --git a/lib/Target/X86/X86TargetMachine.cpp b/lib/Target/X86/X86TargetMachine.cpp index fdf9bdfba3a..ba3314c6e77 100644 --- a/lib/Target/X86/X86TargetMachine.cpp +++ b/lib/Target/X86/X86TargetMachine.cpp @@ -35,6 +35,9 @@ X("x86", " 32-bit X86: Pentium-Pro and above"); static RegisterTarget Y("x86-64", " 64-bit X86: EM64T and AMD64"); +// No assembler printer by default +X86TargetMachine::AsmPrinterCtorFn X86TargetMachine::AsmPrinterCtor = 0; + const TargetAsmInfo *X86TargetMachine::createTargetAsmInfo() const { if (Subtarget.isFlavorIntel()) return new X86WinTargetAsmInfo(*this); @@ -187,7 +190,9 @@ bool X86TargetMachine::addPostRegAlloc(PassManagerBase &PM, bool Fast) { bool X86TargetMachine::addAssemblyEmitter(PassManagerBase &PM, bool Fast, std::ostream &Out) { - PM.add(createX86CodePrinterPass(Out, *this)); + assert(AsmPrinterCtor && "AsmPrinter was not linked in"); + if (AsmPrinterCtor) + PM.add(AsmPrinterCtor(Out, *this)); return false; } @@ -210,8 +215,11 @@ bool X86TargetMachine::addCodeEmitter(PassManagerBase &PM, bool Fast, } PM.add(createX86CodeEmitterPass(*this, MCE)); - if (DumpAsm) - PM.add(createX86CodePrinterPass(*cerr.stream(), *this)); + if (DumpAsm) { + assert(AsmPrinterCtor && "AsmPrinter was not linked in"); + if (AsmPrinterCtor) + PM.add(AsmPrinterCtor(*cerr.stream(), *this)); + } return false; } @@ -219,7 +227,11 @@ bool X86TargetMachine::addCodeEmitter(PassManagerBase &PM, bool Fast, bool X86TargetMachine::addSimpleCodeEmitter(PassManagerBase &PM, bool Fast, bool DumpAsm, MachineCodeEmitter &MCE) { PM.add(createX86CodeEmitterPass(*this, MCE)); - if (DumpAsm) - PM.add(createX86CodePrinterPass(*cerr.stream(), *this)); + if (DumpAsm) { + assert(AsmPrinterCtor && "AsmPrinter was not linked in"); + if (AsmPrinterCtor) + PM.add(AsmPrinterCtor(*cerr.stream(), *this)); + } + return false; } diff --git a/lib/Target/X86/X86TargetMachine.h b/lib/Target/X86/X86TargetMachine.h index 5f814ea7040..94b756671c4 100644 --- a/lib/Target/X86/X86TargetMachine.h +++ b/lib/Target/X86/X86TargetMachine.h @@ -38,7 +38,13 @@ class X86TargetMachine : public LLVMTargetMachine { protected: virtual const TargetAsmInfo *createTargetAsmInfo() const; - + + // To avoid having target depend on the asmprinter stuff libraries, asmprinter + // set this functions to ctor pointer at startup time if they are linked in. + typedef FunctionPass *(*AsmPrinterCtorFn)(std::ostream &o, + X86TargetMachine &tm); + static AsmPrinterCtorFn AsmPrinterCtor; + public: X86TargetMachine(const Module &M, const std::string &FS, bool is64Bit); @@ -59,7 +65,11 @@ public: static unsigned getModuleMatchQuality(const Module &M); static unsigned getJITMatchQuality(); - + + static void registerAsmPrinter(AsmPrinterCtorFn F) { + AsmPrinterCtor = F; + } + // Set up the pass pipeline. virtual bool addInstSelector(PassManagerBase &PM, bool Fast); virtual bool addPreRegAlloc(PassManagerBase &PM, bool Fast); diff --git a/tools/lli/Makefile b/tools/lli/Makefile index b070cee2714..8f6eeed486b 100644 --- a/tools/lli/Makefile +++ b/tools/lli/Makefile @@ -9,7 +9,7 @@ LEVEL := ../.. TOOLNAME := lli -LINK_COMPONENTS := jit interpreter native bitreader selectiondag +LINK_COMPONENTS := jit interpreter nativecodegen bitreader selectiondag # Enable JIT support include $(LEVEL)/Makefile.common diff --git a/tools/llvm-config/llvm-config.in.in b/tools/llvm-config/llvm-config.in.in index 296ba4266d0..36b5112bb67 100644 --- a/tools/llvm-config/llvm-config.in.in +++ b/tools/llvm-config/llvm-config.in.in @@ -326,8 +326,17 @@ sub build_name_map { } } + # Add target-specific entries + foreach my $target (@TARGETS_BUILT) { + # FIXME: Temporary, until we don't switch all targets + if (defined $NAME_MAP{$target.'asmprinter'}) { + $NAME_MAP{$target} = [$target.'asmprinter', $target.'codegen'] + } + } + # Add virtual entries. $NAME_MAP{'native'} = have_native_backend() ? [$ARCH] : []; + $NAME_MAP{'nativecodegen'} = have_native_backend() ? [$ARCH.'codegen'] : []; $NAME_MAP{'backend'} = have_native_backend() ? ['native'] : ['cbackend']; $NAME_MAP{'engine'} = find_best_engine; $NAME_MAP{'all'} = [name_map_entries]; # Must be last.