X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FX86%2FX86AsmPrinter.cpp;h=0ded0864ab9b39e33fa4728ca17a3dfd427bfe52;hb=b3cb36026abd673d8ee13105647b678c3ba88b0e;hp=20110ad788cd1fa21b85e56cb6aa57f6941d741e;hpb=5c1d941f00a3cdb4bdcefa95b4ff34ae8922cf15;p=oota-llvm.git diff --git a/lib/Target/X86/X86AsmPrinter.cpp b/lib/Target/X86/X86AsmPrinter.cpp index 20110ad788c..0ded0864ab9 100644 --- a/lib/Target/X86/X86AsmPrinter.cpp +++ b/lib/Target/X86/X86AsmPrinter.cpp @@ -13,47 +13,36 @@ //===----------------------------------------------------------------------===// #include "X86AsmPrinter.h" -#include "AsmPrinter/X86ATTInstPrinter.h" -#include "AsmPrinter/X86IntelInstPrinter.h" -#include "X86MCInstLower.h" -#include "X86.h" +#include "InstPrinter/X86ATTInstPrinter.h" +#include "MCTargetDesc/X86BaseInfo.h" #include "X86COFFMachineModuleInfo.h" +#include "X86InstrInfo.h" #include "X86MachineFunctionInfo.h" -#include "X86TargetMachine.h" -#include "llvm/CallingConv.h" -#include "llvm/DerivedTypes.h" -#include "llvm/Module.h" -#include "llvm/Type.h" -#include "llvm/Analysis/DebugInfo.h" -#include "llvm/Assembly/Writer.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/CodeGen/MachineModuleInfoImpls.h" +#include "llvm/CodeGen/MachineValueType.h" +#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" +#include "llvm/IR/DebugInfo.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Mangler.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/Type.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCSectionMachO.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" -#include "llvm/CodeGen/MachineJumpTableInfo.h" -#include "llvm/CodeGen/MachineModuleInfoImpls.h" -#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" #include "llvm/Support/COFF.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Target/Mangler.h" -#include "llvm/Target/TargetOptions.h" -#include "llvm/Target/TargetRegistry.h" -#include "llvm/ADT/SmallString.h" +#include "llvm/Support/TargetRegistry.h" using namespace llvm; //===----------------------------------------------------------------------===// // Primitive Helper Functions. //===----------------------------------------------------------------------===// -void X86AsmPrinter::PrintPICBaseSymbol(raw_ostream &O) const { - const TargetLowering *TLI = TM.getTargetLowering(); - O << *static_cast(TLI)->getPICBaseSymbol(MF, - OutContext); -} - /// runOnMachineFunction - Emit the function body. /// bool X86AsmPrinter::runOnMachineFunction(MachineFunction &MF) { @@ -62,7 +51,7 @@ bool X86AsmPrinter::runOnMachineFunction(MachineFunction &MF) { if (Subtarget->isTargetCOFF()) { bool Intrn = MF.getFunction()->hasInternalLinkage(); OutStreamer.BeginCOFFSymbolDef(CurrentFnSym); - OutStreamer.EmitCOFFSymbolStorageClass(Intrn ? COFF::IMAGE_SYM_CLASS_STATIC + OutStreamer.EmitCOFFSymbolStorageClass(Intrn ? COFF::IMAGE_SYM_CLASS_STATIC : COFF::IMAGE_SYM_CLASS_EXTERNAL); OutStreamer.EmitCOFFSymbolType(COFF::IMAGE_SYM_DTYPE_FUNCTION << COFF::SCT_COMPLEX_TYPE_SHIFT); @@ -82,98 +71,68 @@ bool X86AsmPrinter::runOnMachineFunction(MachineFunction &MF) { /// printSymbolOperand - Print a raw symbol reference operand. This handles /// jump tables, constant pools, global address and external symbols, all of /// which print to a label with various suffixes for relocation types etc. -void X86AsmPrinter::printSymbolOperand(const MachineOperand &MO, - raw_ostream &O) { +static void printSymbolOperand(X86AsmPrinter &P, const MachineOperand &MO, + raw_ostream &O) { switch (MO.getType()) { default: llvm_unreachable("unknown symbol type!"); - case MachineOperand::MO_JumpTableIndex: - O << *GetJTISymbol(MO.getIndex()); - break; case MachineOperand::MO_ConstantPoolIndex: - O << *GetCPISymbol(MO.getIndex()); - printOffset(MO.getOffset(), O); + O << *P.GetCPISymbol(MO.getIndex()); + P.printOffset(MO.getOffset(), O); break; case MachineOperand::MO_GlobalAddress: { const GlobalValue *GV = MO.getGlobal(); - + MCSymbol *GVSym; if (MO.getTargetFlags() == X86II::MO_DARWIN_STUB) - GVSym = GetSymbolWithGlobalValueBase(GV, "$stub"); + GVSym = P.getSymbolWithGlobalValueBase(GV, "$stub"); else if (MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY || MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY_PIC_BASE || MO.getTargetFlags() == X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE) - GVSym = GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr"); + GVSym = P.getSymbolWithGlobalValueBase(GV, "$non_lazy_ptr"); else - GVSym = Mang->getSymbol(GV); + GVSym = P.getSymbol(GV); // Handle dllimport linkage. if (MO.getTargetFlags() == X86II::MO_DLLIMPORT) - GVSym = OutContext.GetOrCreateSymbol(Twine("__imp_") + GVSym->getName()); - + GVSym = + P.OutContext.GetOrCreateSymbol(Twine("__imp_") + GVSym->getName()); + if (MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY || MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY_PIC_BASE) { - MCSymbol *Sym = GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr"); - MachineModuleInfoImpl::StubValueTy &StubSym = - MMI->getObjFileInfo().getGVStubEntry(Sym); + MCSymbol *Sym = P.getSymbolWithGlobalValueBase(GV, "$non_lazy_ptr"); + MachineModuleInfoImpl::StubValueTy &StubSym = + P.MMI->getObjFileInfo().getGVStubEntry(Sym); if (StubSym.getPointer() == 0) StubSym = MachineModuleInfoImpl:: - StubValueTy(Mang->getSymbol(GV), !GV->hasInternalLinkage()); + StubValueTy(P.getSymbol(GV), !GV->hasInternalLinkage()); } else if (MO.getTargetFlags() == X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE){ - MCSymbol *Sym = GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr"); + MCSymbol *Sym = P.getSymbolWithGlobalValueBase(GV, "$non_lazy_ptr"); MachineModuleInfoImpl::StubValueTy &StubSym = - MMI->getObjFileInfo().getHiddenGVStubEntry(Sym); + P.MMI->getObjFileInfo().getHiddenGVStubEntry( + Sym); if (StubSym.getPointer() == 0) StubSym = MachineModuleInfoImpl:: - StubValueTy(Mang->getSymbol(GV), !GV->hasInternalLinkage()); + StubValueTy(P.getSymbol(GV), !GV->hasInternalLinkage()); } else if (MO.getTargetFlags() == X86II::MO_DARWIN_STUB) { - MCSymbol *Sym = GetSymbolWithGlobalValueBase(GV, "$stub"); + MCSymbol *Sym = P.getSymbolWithGlobalValueBase(GV, "$stub"); MachineModuleInfoImpl::StubValueTy &StubSym = - MMI->getObjFileInfo().getFnStubEntry(Sym); + P.MMI->getObjFileInfo().getFnStubEntry(Sym); if (StubSym.getPointer() == 0) StubSym = MachineModuleInfoImpl:: - StubValueTy(Mang->getSymbol(GV), !GV->hasInternalLinkage()); + StubValueTy(P.getSymbol(GV), !GV->hasInternalLinkage()); } - + // If the name begins with a dollar-sign, enclose it in parens. We do this // to avoid having it look like an integer immediate to the assembler. if (GVSym->getName()[0] != '$') O << *GVSym; else O << '(' << *GVSym << ')'; - printOffset(MO.getOffset(), O); - break; - } - case MachineOperand::MO_ExternalSymbol: { - const MCSymbol *SymToPrint; - if (MO.getTargetFlags() == X86II::MO_DARWIN_STUB) { - SmallString<128> TempNameStr; - TempNameStr += StringRef(MO.getSymbolName()); - TempNameStr += StringRef("$stub"); - - MCSymbol *Sym = GetExternalSymbolSymbol(TempNameStr.str()); - MachineModuleInfoImpl::StubValueTy &StubSym = - MMI->getObjFileInfo().getFnStubEntry(Sym); - if (StubSym.getPointer() == 0) { - TempNameStr.erase(TempNameStr.end()-5, TempNameStr.end()); - StubSym = MachineModuleInfoImpl:: - StubValueTy(OutContext.GetOrCreateSymbol(TempNameStr.str()), - true); - } - SymToPrint = StubSym.getPointer(); - } else { - SymToPrint = GetExternalSymbolSymbol(MO.getSymbolName()); - } - - // If the name begins with a dollar-sign, enclose it in parens. We do this - // to avoid having it look like an integer immediate to the assembler. - if (SymToPrint->getName()[0] != '$') - O << *SymToPrint; - else - O << '(' << *SymToPrint << '('; + P.printOffset(MO.getOffset(), O); break; } } - + switch (MO.getTargetFlags()) { default: llvm_unreachable("Unknown target flag on GV operand"); @@ -185,69 +144,71 @@ void X86AsmPrinter::printSymbolOperand(const MachineOperand &MO, // These affect the name of the symbol, not any suffix. break; case X86II::MO_GOT_ABSOLUTE_ADDRESS: - O << " + [.-"; - PrintPICBaseSymbol(O); - O << ']'; - break; + O << " + [.-" << *P.MF->getPICBaseSymbol() << ']'; + break; case X86II::MO_PIC_BASE_OFFSET: case X86II::MO_DARWIN_NONLAZY_PIC_BASE: case X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE: - O << '-'; - PrintPICBaseSymbol(O); + O << '-' << *P.MF->getPICBaseSymbol(); break; case X86II::MO_TLSGD: O << "@TLSGD"; break; + case X86II::MO_TLSLD: O << "@TLSLD"; break; + case X86II::MO_TLSLDM: O << "@TLSLDM"; break; case X86II::MO_GOTTPOFF: O << "@GOTTPOFF"; break; case X86II::MO_INDNTPOFF: O << "@INDNTPOFF"; break; case X86II::MO_TPOFF: O << "@TPOFF"; break; + case X86II::MO_DTPOFF: O << "@DTPOFF"; break; case X86II::MO_NTPOFF: O << "@NTPOFF"; break; + case X86II::MO_GOTNTPOFF: O << "@GOTNTPOFF"; break; case X86II::MO_GOTPCREL: O << "@GOTPCREL"; break; case X86II::MO_GOT: O << "@GOT"; break; case X86II::MO_GOTOFF: O << "@GOTOFF"; break; case X86II::MO_PLT: O << "@PLT"; break; case X86II::MO_TLVP: O << "@TLVP"; break; case X86II::MO_TLVP_PIC_BASE: - O << "@TLVP" << '-'; - PrintPICBaseSymbol(O); + O << "@TLVP" << '-' << *P.MF->getPICBaseSymbol(); break; + case X86II::MO_SECREL: O << "@SECREL32"; break; } } -/// print_pcrel_imm - This is used to print an immediate value that ends up +static void printOperand(X86AsmPrinter &P, const MachineInstr *MI, + unsigned OpNo, raw_ostream &O, + const char *Modifier = 0, unsigned AsmVariant = 0); + +/// printPCRelImm - This is used to print an immediate value that ends up /// being encoded as a pc-relative value. These print slightly differently, for /// example, a $ is not emitted. -void X86AsmPrinter::print_pcrel_imm(const MachineInstr *MI, unsigned OpNo, - raw_ostream &O) { +static void printPCRelImm(X86AsmPrinter &P, const MachineInstr *MI, + unsigned OpNo, raw_ostream &O) { const MachineOperand &MO = MI->getOperand(OpNo); switch (MO.getType()) { default: llvm_unreachable("Unknown pcrel immediate operand"); case MachineOperand::MO_Register: // pc-relativeness was handled when computing the value in the reg. - printOperand(MI, OpNo, O); + printOperand(P, MI, OpNo, O); return; case MachineOperand::MO_Immediate: O << MO.getImm(); return; - case MachineOperand::MO_MachineBasicBlock: - O << *MO.getMBB()->getSymbol(); - return; case MachineOperand::MO_GlobalAddress: - case MachineOperand::MO_ExternalSymbol: - printSymbolOperand(MO, O); + printSymbolOperand(P, MO, O); return; } } - -void X86AsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo, - raw_ostream &O, const char *Modifier) { +static void printOperand(X86AsmPrinter &P, const MachineInstr *MI, + unsigned OpNo, raw_ostream &O, const char *Modifier, + unsigned AsmVariant) { const MachineOperand &MO = MI->getOperand(OpNo); switch (MO.getType()) { default: llvm_unreachable("unknown operand type!"); case MachineOperand::MO_Register: { - O << '%'; + // FIXME: Enumerating AsmVariant, so we can remove magic number. + if (AsmVariant == 0) O << '%'; unsigned Reg = MO.getReg(); if (Modifier && strncmp(Modifier, "subreg", strlen("subreg")) == 0) { - EVT VT = (strcmp(Modifier+6,"64") == 0) ? + MVT::SimpleValueType 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); @@ -257,60 +218,50 @@ void X86AsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo, } case MachineOperand::MO_Immediate: - O << '$' << MO.getImm(); + if (AsmVariant == 0) O << '$'; + O << MO.getImm(); return; - case MachineOperand::MO_JumpTableIndex: - case MachineOperand::MO_ConstantPoolIndex: - case MachineOperand::MO_GlobalAddress: - case MachineOperand::MO_ExternalSymbol: { - O << '$'; - printSymbolOperand(MO, O); + case MachineOperand::MO_GlobalAddress: { + if (AsmVariant == 0) O << '$'; + printSymbolOperand(P, MO, O); break; } } } -void X86AsmPrinter::printSSECC(const MachineInstr *MI, unsigned Op, - raw_ostream &O) { - 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 X86AsmPrinter::printLeaMemReference(const MachineInstr *MI, unsigned Op, - raw_ostream &O, const char *Modifier) { - const MachineOperand &BaseReg = MI->getOperand(Op); - const MachineOperand &IndexReg = MI->getOperand(Op+2); - const MachineOperand &DispSpec = MI->getOperand(Op+3); +static void printLeaMemReference(X86AsmPrinter &P, const MachineInstr *MI, + unsigned Op, raw_ostream &O, + const char *Modifier = NULL) { + const MachineOperand &BaseReg = MI->getOperand(Op+X86::AddrBaseReg); + const MachineOperand &IndexReg = MI->getOperand(Op+X86::AddrIndexReg); + const MachineOperand &DispSpec = MI->getOperand(Op+X86::AddrDisp); // If we really don't want to print out (rip), don't. bool HasBaseReg = BaseReg.getReg() != 0; if (HasBaseReg && Modifier && !strcmp(Modifier, "no-rip") && BaseReg.getReg() == X86::RIP) HasBaseReg = false; - + // HasParenPart - True if we will print out the () part of the mem ref. bool HasParenPart = IndexReg.getReg() || HasBaseReg; - - if (DispSpec.isImm()) { + + switch (DispSpec.getType()) { + default: + llvm_unreachable("unknown operand type!"); + case MachineOperand::MO_Immediate: { int DispVal = DispSpec.getImm(); if (DispVal || !HasParenPart) O << DispVal; - } else { - assert(DispSpec.isGlobal() || DispSpec.isCPI() || - DispSpec.isJTI() || DispSpec.isSymbol()); - printSymbolOperand(MI->getOperand(Op+3), O); + break; } + case MachineOperand::MO_GlobalAddress: + case MachineOperand::MO_ConstantPoolIndex: + printSymbolOperand(P, DispSpec, O); + } + + if (Modifier && strcmp(Modifier, "H") == 0) + O << "+8"; if (HasParenPart) { assert(IndexReg.getReg() != X86::ESP && @@ -318,12 +269,12 @@ void X86AsmPrinter::printLeaMemReference(const MachineInstr *MI, unsigned Op, O << '('; if (HasBaseReg) - printOperand(MI, Op, O, Modifier); + printOperand(P, MI, Op+X86::AddrBaseReg, O, Modifier); if (IndexReg.getReg()) { O << ','; - printOperand(MI, Op+2, O, Modifier); - unsigned ScaleVal = MI->getOperand(Op+1).getImm(); + printOperand(P, MI, Op+X86::AddrIndexReg, O, Modifier); + unsigned ScaleVal = MI->getOperand(Op+X86::AddrScaleAmt).getImm(); if (ScaleVal != 1) O << ',' << ScaleVal; } @@ -331,27 +282,72 @@ void X86AsmPrinter::printLeaMemReference(const MachineInstr *MI, unsigned Op, } } -void X86AsmPrinter::printMemReference(const MachineInstr *MI, unsigned Op, - raw_ostream &O, const char *Modifier) { +static void printMemReference(X86AsmPrinter &P, const MachineInstr *MI, + unsigned Op, raw_ostream &O, + const char *Modifier = NULL) { assert(isMem(MI, Op) && "Invalid memory reference!"); - const MachineOperand &Segment = MI->getOperand(Op+4); + const MachineOperand &Segment = MI->getOperand(Op+X86::AddrSegmentReg); if (Segment.getReg()) { - printOperand(MI, Op+4, O, Modifier); + printOperand(P, MI, Op+X86::AddrSegmentReg, O, Modifier); O << ':'; } - printLeaMemReference(MI, Op, O, Modifier); + printLeaMemReference(P, MI, Op, O, Modifier); } -void X86AsmPrinter::printPICLabel(const MachineInstr *MI, unsigned Op, - raw_ostream &O) { - PrintPICBaseSymbol(O); - O << '\n'; - PrintPICBaseSymbol(O); - O << ':'; +static void printIntelMemReference(X86AsmPrinter &P, const MachineInstr *MI, + unsigned Op, raw_ostream &O, + const char *Modifier = NULL, + unsigned AsmVariant = 1) { + const MachineOperand &BaseReg = MI->getOperand(Op+X86::AddrBaseReg); + unsigned ScaleVal = MI->getOperand(Op+X86::AddrScaleAmt).getImm(); + const MachineOperand &IndexReg = MI->getOperand(Op+X86::AddrIndexReg); + const MachineOperand &DispSpec = MI->getOperand(Op+X86::AddrDisp); + const MachineOperand &SegReg = MI->getOperand(Op+X86::AddrSegmentReg); + + // If this has a segment register, print it. + if (SegReg.getReg()) { + printOperand(P, MI, Op+X86::AddrSegmentReg, O, Modifier, AsmVariant); + O << ':'; + } + + O << '['; + + bool NeedPlus = false; + if (BaseReg.getReg()) { + printOperand(P, MI, Op+X86::AddrBaseReg, O, Modifier, AsmVariant); + NeedPlus = true; + } + + if (IndexReg.getReg()) { + if (NeedPlus) O << " + "; + if (ScaleVal != 1) + O << ScaleVal << '*'; + printOperand(P, MI, Op+X86::AddrIndexReg, O, Modifier, AsmVariant); + NeedPlus = true; + } + + if (!DispSpec.isImm()) { + if (NeedPlus) O << " + "; + printOperand(P, MI, Op+X86::AddrDisp, O, Modifier, AsmVariant); + } else { + int64_t DispVal = DispSpec.getImm(); + if (DispVal || (!IndexReg.getReg() && !BaseReg.getReg())) { + if (NeedPlus) { + if (DispVal > 0) + O << " + "; + else { + O << " - "; + DispVal = -DispVal; + } + } + O << DispVal; + } + } + O << ']'; } -bool X86AsmPrinter::printAsmMRegister(const MachineOperand &MO, char Mode, - raw_ostream &O) { +static bool printAsmMRegister(X86AsmPrinter &P, const MachineOperand &MO, + char Mode, raw_ostream &O) { unsigned Reg = MO.getReg(); switch (Mode) { default: return true; // Unknown mode. @@ -367,8 +363,11 @@ bool X86AsmPrinter::printAsmMRegister(const MachineOperand &MO, char Mode, case 'k': // Print SImode register Reg = getX86SubSuperRegister(Reg, MVT::i32); break; - case 'q': // Print DImode register - Reg = getX86SubSuperRegister(Reg, MVT::i64); + case 'q': + // Print 64-bit register names if 64-bit integer registers are available. + // Otherwise, print 32-bit register names. + MVT::SimpleValueType Ty = P.getSubtarget().is64Bit() ? MVT::i64 : MVT::i32; + Reg = getX86SubSuperRegister(Reg, Ty); break; } @@ -386,41 +385,56 @@ bool X86AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, if (ExtraCode[1] != 0) return true; // Unknown modifier. const MachineOperand &MO = MI->getOperand(OpNo); - + switch (ExtraCode[0]) { - default: return true; // Unknown modifier. + default: + // See if this is a generic print operand + return AsmPrinter::PrintAsmOperand(MI, OpNo, AsmVariant, ExtraCode, O); case 'a': // This is an address. Currently only 'i' and 'r' are expected. - if (MO.isImm()) { + switch (MO.getType()) { + default: + return true; + case MachineOperand::MO_Immediate: O << MO.getImm(); return false; - } - if (MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isSymbol()) { - printSymbolOperand(MO, O); + case MachineOperand::MO_ConstantPoolIndex: + case MachineOperand::MO_JumpTableIndex: + case MachineOperand::MO_ExternalSymbol: + llvm_unreachable("unexpected operand type!"); + case MachineOperand::MO_GlobalAddress: + printSymbolOperand(*this, MO, O); if (Subtarget->isPICStyleRIPRel()) O << "(%rip)"; return false; - } - if (MO.isReg()) { + case MachineOperand::MO_Register: O << '('; - printOperand(MI, OpNo, O); + printOperand(*this, MI, OpNo, O); O << ')'; return false; } - return true; case 'c': // Don't print "$" before a global var name or constant. - if (MO.isImm()) + switch (MO.getType()) { + default: + printOperand(*this, MI, OpNo, O); + break; + case MachineOperand::MO_Immediate: O << MO.getImm(); - else if (MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isSymbol()) - printSymbolOperand(MO, O); - else - printOperand(MI, OpNo, O); + break; + case MachineOperand::MO_ConstantPoolIndex: + case MachineOperand::MO_JumpTableIndex: + case MachineOperand::MO_ExternalSymbol: + llvm_unreachable("unexpected operand type!"); + case MachineOperand::MO_GlobalAddress: + printSymbolOperand(*this, MO, O); + break; + } return false; case 'A': // Print '*' before a register (it must be a register) if (MO.isReg()) { O << '*'; - printOperand(MI, OpNo, O); + printOperand(*this, MI, OpNo, O); return false; } return true; @@ -431,12 +445,12 @@ bool X86AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, case 'k': // Print SImode register case 'q': // Print DImode register if (MO.isReg()) - return printAsmMRegister(MO, ExtraCode[0], O); - printOperand(MI, OpNo, O); + return printAsmMRegister(*this, MO, ExtraCode[0], O); + printOperand(*this, MI, OpNo, O); return false; case 'P': // This is the operand of a call, treat specially. - print_pcrel_imm(MI, OpNo, O); + printPCRelImm(*this, MI, OpNo, O); return false; case 'n': // Negate the immediate or print a '-' before the operand. @@ -450,7 +464,7 @@ bool X86AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, } } - printOperand(MI, OpNo, O); + printOperand(*this, MI, OpNo, O, /*Modifier*/ 0, AsmVariant); return false; } @@ -458,6 +472,11 @@ bool X86AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, unsigned AsmVariant, const char *ExtraCode, raw_ostream &O) { + if (AsmVariant) { + printIntelMemReference(*this, MI, OpNo, O); + return false; + } + if (ExtraCode && ExtraCode[0]) { if (ExtraCode[1] != 0) return true; // Unknown modifier. @@ -470,37 +489,61 @@ bool X86AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, case 'q': // Print SImode register // These only apply to registers, ignore on mem. break; + case 'H': + printMemReference(*this, MI, OpNo, O, "H"); + return false; case 'P': // Don't print @PLT, but do print as memory. - printMemReference(MI, OpNo, O, "no-rip"); + printMemReference(*this, MI, OpNo, O, "no-rip"); return false; } } - printMemReference(MI, OpNo, O); + printMemReference(*this, MI, OpNo, O); return false; } void X86AsmPrinter::EmitStartOfAsmFile(Module &M) { - if (Subtarget->isTargetDarwin()) + if (Subtarget->isTargetMacho()) OutStreamer.SwitchSection(getObjFileLowering().getTextSection()); + + if (Subtarget->isTargetCOFF()) { + // Emit an absolute @feat.00 symbol. This appears to be some kind of + // compiler features bitfield read by link.exe. + if (!Subtarget->is64Bit()) { + MCSymbol *S = MMI->getContext().GetOrCreateSymbol(StringRef("@feat.00")); + OutStreamer.BeginCOFFSymbolDef(S); + OutStreamer.EmitCOFFSymbolStorageClass(COFF::IMAGE_SYM_CLASS_STATIC); + OutStreamer.EmitCOFFSymbolType(COFF::IMAGE_SYM_DTYPE_NULL); + OutStreamer.EndCOFFSymbolDef(); + // According to the PE-COFF spec, the LSB of this value marks the object + // for "registered SEH". This means that all SEH handler entry points + // must be registered in .sxdata. Use of any unregistered handlers will + // cause the process to terminate immediately. LLVM does not know how to + // register any SEH handlers, so its object files should be safe. + S->setAbsolute(); + OutStreamer.EmitSymbolAttribute(S, MCSA_Global); + OutStreamer.EmitAssignment( + S, MCConstantExpr::Create(int64_t(1), MMI->getContext())); + } + } } void X86AsmPrinter::EmitEndOfAsmFile(Module &M) { - if (Subtarget->isTargetDarwin()) { + if (Subtarget->isTargetMacho()) { // All darwin targets use mach-o. MachineModuleInfoMachO &MMIMacho = MMI->getObjFileInfo(); - + // Output stubs for dynamically-linked functions. MachineModuleInfoMachO::SymbolListTy Stubs; Stubs = MMIMacho.GetFnStubList(); if (!Stubs.empty()) { - const MCSection *TheSection = + const MCSection *TheSection = OutContext.getMachOSection("__IMPORT", "__jump_table", - MCSectionMachO::S_SYMBOL_STUBS | - MCSectionMachO::S_ATTR_SELF_MODIFYING_CODE | - MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, + MachO::S_SYMBOL_STUBS | + MachO::S_ATTR_SELF_MODIFYING_CODE | + MachO::S_ATTR_PURE_INSTRUCTIONS, 5, SectionKind::getMetadata()); OutStreamer.SwitchSection(TheSection); @@ -510,11 +553,11 @@ void X86AsmPrinter::EmitEndOfAsmFile(Module &M) { // .indirect_symbol _foo OutStreamer.EmitSymbolAttribute(Stubs[i].second.getPointer(), MCSA_IndirectSymbol); - // hlt; hlt; hlt; hlt; hlt hlt = 0xf4 = -12. - const char HltInsts[] = { -12, -12, -12, -12, -12 }; - OutStreamer.EmitBytes(StringRef(HltInsts, 5), 0/*addrspace*/); + // hlt; hlt; hlt; hlt; hlt hlt = 0xf4. + const char HltInsts[] = "\xf4\xf4\xf4\xf4\xf4"; + OutStreamer.EmitBytes(StringRef(HltInsts, 5)); } - + Stubs.clear(); OutStreamer.AddBlankLine(); } @@ -522,9 +565,9 @@ void X86AsmPrinter::EmitEndOfAsmFile(Module &M) { // Output stubs for external and common global variables. Stubs = MMIMacho.GetGVStubList(); if (!Stubs.empty()) { - const MCSection *TheSection = + const MCSection *TheSection = OutContext.getMachOSection("__IMPORT", "__pointers", - MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS, + MachO::S_NON_LAZY_SYMBOL_POINTERS, SectionKind::getMetadata()); OutStreamer.SwitchSection(TheSection); @@ -538,7 +581,7 @@ void X86AsmPrinter::EmitEndOfAsmFile(Module &M) { // .long 0 if (MCSym.getInt()) // External to current translation unit. - OutStreamer.EmitIntValue(0, 4/*size*/, 0/*addrspace*/); + OutStreamer.EmitIntValue(0, 4/*size*/); else // Internal to current translation unit. // @@ -547,8 +590,7 @@ void X86AsmPrinter::EmitEndOfAsmFile(Module &M) { // using NLPs. However, sometimes the types are local to the file. So // we need to fill in the value for the NLP in those cases. OutStreamer.EmitValue(MCSymbolRefExpr::Create(MCSym.getPointer(), - OutContext), - 4/*size*/, 0/*addrspace*/); + OutContext), 4/*size*/); } Stubs.clear(); OutStreamer.AddBlankLine(); @@ -565,13 +607,14 @@ void X86AsmPrinter::EmitEndOfAsmFile(Module &M) { // .long _foo OutStreamer.EmitValue(MCSymbolRefExpr:: Create(Stubs[i].second.getPointer(), - OutContext), - 4/*size*/, 0/*addrspace*/); + OutContext), 4/*size*/); } Stubs.clear(); OutStreamer.AddBlankLine(); } + SM.serializeToStackMapSection(); + // 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 @@ -580,6 +623,13 @@ void X86AsmPrinter::EmitEndOfAsmFile(Module &M) { OutStreamer.EmitAssemblerFlag(MCAF_SubsectionsViaSymbols); } + if (Subtarget->isTargetWindows() && !Subtarget->isTargetCygMing() && + MMI->usesVAFloatArgument()) { + StringRef SymbolName = Subtarget->is64Bit() ? "_fltused" : "__fltused"; + MCSymbol *S = MMI->getContext().GetOrCreateSymbol(SymbolName); + OutStreamer.EmitSymbolAttribute(S, MCSA_Global); + } + if (Subtarget->isTargetCOFF()) { X86COFFMachineModuleInfo &COFFMMI = MMI->getObjFileInfo(); @@ -599,20 +649,35 @@ void X86AsmPrinter::EmitEndOfAsmFile(Module &M) { // Necessary for dllexport support std::vector DLLExportedFns, DLLExportedGlobals; - const TargetLoweringObjectFileCOFF &TLOFCOFF = - static_cast(getObjFileLowering()); - for (Module::const_iterator I = M.begin(), E = M.end(); I != E; ++I) - if (I->hasDLLExportLinkage()) - DLLExportedFns.push_back(Mang->getSymbol(I)); + if (I->hasDLLExportStorageClass()) + DLLExportedFns.push_back(getSymbol(I)); for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) - if (I->hasDLLExportLinkage()) - DLLExportedGlobals.push_back(Mang->getSymbol(I)); + if (I->hasDLLExportStorageClass()) + DLLExportedGlobals.push_back(getSymbol(I)); + + for (Module::const_alias_iterator I = M.alias_begin(), E = M.alias_end(); + I != E; ++I) { + const GlobalValue *GV = I; + if (!GV->hasDLLExportStorageClass()) + continue; + + while (const GlobalAlias *A = dyn_cast(GV)) + GV = A->getAliasedGlobal(); + + if (isa(GV)) + DLLExportedFns.push_back(getSymbol(I)); + else if (isa(GV)) + DLLExportedGlobals.push_back(getSymbol(I)); + } // Output linker support code for dllexported globals on windows. if (!DLLExportedGlobals.empty() || !DLLExportedFns.empty()) { + const TargetLoweringObjectFileCOFF &TLOFCOFF = + static_cast(getObjFileLowering()); + OutStreamer.SwitchSection(TLOFCOFF.getDrectveSection()); SmallString<128> name; for (unsigned i = 0, e = DLLExportedGlobals.size(); i != e; ++i) { @@ -625,7 +690,7 @@ void X86AsmPrinter::EmitEndOfAsmFile(Module &M) { name += ",DATA"; else name += ",data"; - OutStreamer.EmitBytes(name, 0); + OutStreamer.EmitBytes(name); } for (unsigned i = 0, e = DLLExportedFns.size(); i != e; ++i) { @@ -634,7 +699,7 @@ void X86AsmPrinter::EmitEndOfAsmFile(Module &M) { else name = " -export:"; name += DLLExportedFns[i]->getName(); - OutStreamer.EmitBytes(name, 0); + OutStreamer.EmitBytes(name); } } } @@ -649,79 +714,24 @@ void X86AsmPrinter::EmitEndOfAsmFile(Module &M) { MachineModuleInfoELF::SymbolListTy Stubs = MMIELF.GetGVStubList(); if (!Stubs.empty()) { OutStreamer.SwitchSection(TLOFELF.getDataRelSection()); - const TargetData *TD = TM.getTargetData(); + const DataLayout *TD = TM.getDataLayout(); for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { OutStreamer.EmitLabel(Stubs[i].first); OutStreamer.EmitSymbolValue(Stubs[i].second.getPointer(), - TD->getPointerSize(), 0); + TD->getPointerSize()); } Stubs.clear(); } } } -MachineLocation -X86AsmPrinter::getDebugValueLocation(const MachineInstr *MI) const { - MachineLocation Location; - assert (MI->getNumOperands() == 7 && "Invalid no. of machine operands!"); - // Frame address. Currently handles register +- offset only. - - if (MI->getOperand(0).isReg() && MI->getOperand(3).isImm()) - Location.set(MI->getOperand(0).getReg(), MI->getOperand(3).getImm()); - else { - DEBUG(dbgs() << "DBG_VALUE instruction ignored! " << *MI << "\n"); - } - return Location; -} - -void X86AsmPrinter::PrintDebugValueComment(const MachineInstr *MI, - raw_ostream &O) { - // Only the target-dependent form of DBG_VALUE should get here. - // Referencing the offset and metadata as NOps-2 and NOps-1 is - // probably portable to other targets; frame pointer location is not. - unsigned NOps = MI->getNumOperands(); - assert(NOps==7); - O << '\t' << MAI->getCommentString() << "DEBUG_VALUE: "; - // cast away const; DIetc do not take const operands for some reason. - DIVariable V(const_cast(MI->getOperand(NOps-1).getMetadata())); - if (V.getContext().isSubprogram()) - O << DISubprogram(V.getContext()).getDisplayName() << ":"; - O << V.getName(); - O << " <- "; - // Frame address. Currently handles register +- offset only. - O << '['; - if (MI->getOperand(0).isReg() && MI->getOperand(0).getReg()) - printOperand(MI, 0, O); - else - O << "undef"; - O << '+'; printOperand(MI, 3, O); - O << ']'; - O << "+"; - printOperand(MI, NOps-2, O); -} - - - //===----------------------------------------------------------------------===// // Target Registry Stuff //===----------------------------------------------------------------------===// -static MCInstPrinter *createX86MCInstPrinter(const Target &T, - unsigned SyntaxVariant, - const MCAsmInfo &MAI) { - if (SyntaxVariant == 0) - return new X86ATTInstPrinter(MAI); - if (SyntaxVariant == 1) - return new X86IntelInstPrinter(MAI); - return 0; -} - // Force static initialization. -extern "C" void LLVMInitializeX86AsmPrinter() { +extern "C" void LLVMInitializeX86AsmPrinter() { RegisterAsmPrinter X(TheX86_32Target); RegisterAsmPrinter Y(TheX86_64Target); - - TargetRegistry::RegisterMCInstPrinter(TheX86_32Target,createX86MCInstPrinter); - TargetRegistry::RegisterMCInstPrinter(TheX86_64Target,createX86MCInstPrinter); }