//===----------------------------------------------------------------------===//
//
// 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'.
+// of machine-dependent LLVM code to X86 machine code.
//
//===----------------------------------------------------------------------===//
-#define DEBUG_TYPE "asm-printer"
#include "X86AsmPrinter.h"
#include "X86ATTInstPrinter.h"
#include "X86IntelInstPrinter.h"
#include "llvm/Module.h"
#include "llvm/Type.h"
#include "llvm/Assembly/Writer.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/ErrorHandling.h"
-#include "llvm/Support/FormattedStream.h"
-#include "llvm/MC/MCAsmInfo.h"
-#include "llvm/Target/TargetLoweringObjectFile.h"
+#include "llvm/Target/Mangler.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Target/TargetRegistry.h"
#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/Statistic.h"
using namespace llvm;
-STATISTIC(EmittedInsts, "Number of machine instrs printed");
-
//===----------------------------------------------------------------------===//
// Primitive Helper Functions.
//===----------------------------------------------------------------------===//
-void X86AsmPrinter::printMCInst(const MCInst *MI) {
- if (MAI->getAssemblerDialect() == 0)
- X86ATTInstPrinter(O, *MAI).printInstruction(MI);
- else
- X86IntelInstPrinter(O, *MAI).printInstruction(MI);
+void X86AsmPrinter::PrintPICBaseSymbol(raw_ostream &O) const {
+ const TargetLowering *TLI = TM.getTargetLowering();
+ O << *static_cast<const X86TargetLowering*>(TLI)->getPICBaseSymbol(MF,
+ OutContext);
}
-void X86AsmPrinter::PrintPICBaseSymbol() const {
- // FIXME: Gross const cast hack.
- X86AsmPrinter *AP = const_cast<X86AsmPrinter*>(this);
- O << *X86MCInstLower(OutContext, 0, *AP).GetPICBaseSymbol();
-}
-
-void X86AsmPrinter::emitFunctionHeader(const MachineFunction &MF) {
- unsigned FnAlign = MF.getAlignment();
- const Function *F = MF.getFunction();
-
- if (Subtarget->isTargetCygMing()) {
- X86COFFMachineModuleInfo &COFFMMI =
- MMI->getObjFileInfo<X86COFFMachineModuleInfo>();
- COFFMMI.DecorateCygMingName(CurrentFnSym, OutContext, F,
- *TM.getTargetData());
- }
-
- OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(F, Mang, TM));
- EmitAlignment(FnAlign, F);
-
- switch (F->getLinkage()) {
- default: llvm_unreachable("Unknown linkage type!");
- case Function::InternalLinkage: // Symbols default to internal.
- case Function::PrivateLinkage:
- break;
- case Function::DLLExportLinkage:
- case Function::ExternalLinkage:
- OutStreamer.EmitSymbolAttribute(CurrentFnSym, MCStreamer::Global);
- break;
- case Function::LinkerPrivateLinkage:
- case Function::LinkOnceAnyLinkage:
- case Function::LinkOnceODRLinkage:
- case Function::WeakAnyLinkage:
- case Function::WeakODRLinkage:
- if (Subtarget->isTargetDarwin()) {
- OutStreamer.EmitSymbolAttribute(CurrentFnSym, MCStreamer::Global);
- O << MAI->getWeakDefDirective() << *CurrentFnSym << '\n';
- } else if (Subtarget->isTargetCygMing()) {
- OutStreamer.EmitSymbolAttribute(CurrentFnSym, MCStreamer::Global);
- O << "\t.linkonce discard\n";
- } else {
- O << "\t.weak\t" << *CurrentFnSym << '\n';
- }
- break;
- }
-
- printVisibility(CurrentFnSym, F->getVisibility());
-
- if (Subtarget->isTargetELF()) {
- O << "\t.type\t" << *CurrentFnSym << ",@function\n";
- } else if (Subtarget->isTargetCygMing()) {
- O << "\t.def\t " << *CurrentFnSym;
- O << ";\t.scl\t" <<
- (F->hasInternalLinkage() ? COFF::C_STAT : COFF::C_EXT)
- << ";\t.type\t" << (COFF::DT_FCN << COFF::N_BTSHFT)
- << ";\t.endef\n";
- }
-
- O << *CurrentFnSym << ':';
- if (VerboseAsm) {
- O.PadToColumn(MAI->getCommentColumn());
- O << MAI->getCommentString() << ' ';
- WriteAsOperand(O, F, /*PrintType=*/false, F->getParent());
- }
- O << '\n';
-
- // Add some workaround for linkonce linkage on Cygwin\MinGW
- if (Subtarget->isTargetCygMing() &&
- (F->hasLinkOnceLinkage() || F->hasWeakLinkage()))
- O << "Lllvm$workaround$fake$stub$" << *CurrentFnSym << ":\n";
-}
-
-/// runOnMachineFunction - This uses the printMachineInstruction()
-/// method to print assembly for each instruction.
+/// runOnMachineFunction - Emit the function body.
///
bool X86AsmPrinter::runOnMachineFunction(MachineFunction &MF) {
- const Function *F = MF.getFunction();
- this->MF = &MF;
- CallingConv::ID CC = F->getCallingConv();
-
SetupMachineFunction(MF);
- O << "\n\n";
if (Subtarget->isTargetCOFF()) {
- X86COFFMachineModuleInfo &COFFMMI =
- MMI->getObjFileInfo<X86COFFMachineModuleInfo>();
-
- // Populate function information map. Don't want to populate
- // non-stdcall or non-fastcall functions' information right now.
- if (CC == CallingConv::X86_StdCall || CC == CallingConv::X86_FastCall)
- COFFMMI.AddFunctionInfo(F, *MF.getInfo<X86MachineFunctionInfo>());
- }
-
- // Print out constants referenced by the function
- EmitConstantPool(MF.getConstantPool());
-
- // Print the 'header' of function
- emitFunctionHeader(MF);
-
- // Emit pre-function debug and/or EH information.
- if (MAI->doesSupportDebugInformation() || MAI->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.
- EmitBasicBlockStart(I);
- 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);
- }
+ const Function *F = MF.getFunction();
+ OutStreamer.EmitRawText("\t.def\t " + Twine(CurrentFnSym->getName()) +
+ ";\t.scl\t" +
+ Twine(F->hasInternalLinkage() ? COFF::C_STAT : COFF::C_EXT) +
+ ";\t.type\t" + Twine(COFF::DT_FCN << COFF::N_BTSHFT)
+ + ";\t.endef");
}
- 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 (MAI->hasDotTypeDotSizeDirective())
- O << "\t.size\t" << *CurrentFnSym << ", .-" << *CurrentFnSym << '\n';
-
- // Emit post-function debug information.
- if (MAI->doesSupportDebugInformation() || MAI->doesSupportExceptionHandling())
- DW->EndFunction(&MF);
+ // Have common code print out the function header with linkage info etc.
+ EmitFunctionHeader();
- // Print out jump tables referenced by the function.
- EmitJumpTableInfo(MF.getJumpTableInfo(), MF);
+ // Emit the rest of the function body.
+ EmitFunctionBody();
// We didn't modify anything.
return false;
/// 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) {
+void X86AsmPrinter::printSymbolOperand(const MachineOperand &MO,
+ raw_ostream &O) {
switch (MO.getType()) {
default: llvm_unreachable("unknown symbol type!");
case MachineOperand::MO_JumpTableIndex:
- O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() << '_'
- << MO.getIndex();
+ O << *GetJTISymbol(MO.getIndex());
break;
case MachineOperand::MO_ConstantPoolIndex:
- O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_'
- << MO.getIndex();
- printOffset(MO.getOffset());
+ O << *GetCPISymbol(MO.getIndex());
+ printOffset(MO.getOffset(), O);
break;
case MachineOperand::MO_GlobalAddress: {
const GlobalValue *GV = MO.getGlobal();
MO.getTargetFlags() == X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE)
GVSym = GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr");
else
- GVSym = GetGlobalValueSymbol(GV);
+ GVSym = Mang->getSymbol(GV);
- if (Subtarget->isTargetCygMing()) {
- X86COFFMachineModuleInfo &COFFMMI =
- MMI->getObjFileInfo<X86COFFMachineModuleInfo>();
- COFFMMI.DecorateCygMingName(GVSym, OutContext, GV, *TM.getTargetData());
- }
-
// Handle dllimport linkage.
if (MO.getTargetFlags() == X86II::MO_DLLIMPORT)
GVSym = 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");
-
- const MCSymbol *&StubSym =
+ MachineModuleInfoImpl::StubValueTy &StubSym =
MMI->getObjFileInfo<MachineModuleInfoMachO>().getGVStubEntry(Sym);
- if (StubSym == 0)
- StubSym = GetGlobalValueSymbol(GV);
-
+ if (StubSym.getPointer() == 0)
+ StubSym = MachineModuleInfoImpl::
+ StubValueTy(Mang->getSymbol(GV), !GV->hasInternalLinkage());
} else if (MO.getTargetFlags() == X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE){
MCSymbol *Sym = GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr");
- const MCSymbol *&StubSym =
+ MachineModuleInfoImpl::StubValueTy &StubSym =
MMI->getObjFileInfo<MachineModuleInfoMachO>().getHiddenGVStubEntry(Sym);
- if (StubSym == 0)
- StubSym = GetGlobalValueSymbol(GV);
+ if (StubSym.getPointer() == 0)
+ StubSym = MachineModuleInfoImpl::
+ StubValueTy(Mang->getSymbol(GV), !GV->hasInternalLinkage());
} else if (MO.getTargetFlags() == X86II::MO_DARWIN_STUB) {
MCSymbol *Sym = GetSymbolWithGlobalValueBase(GV, "$stub");
- const MCSymbol *&StubSym =
+ MachineModuleInfoImpl::StubValueTy &StubSym =
MMI->getObjFileInfo<MachineModuleInfoMachO>().getFnStubEntry(Sym);
- if (StubSym == 0)
- StubSym = GetGlobalValueSymbol(GV);
+ if (StubSym.getPointer() == 0)
+ StubSym = MachineModuleInfoImpl::
+ StubValueTy(Mang->getSymbol(GV), !GV->hasInternalLinkage());
}
// If the name begins with a dollar-sign, enclose it in parens. We do this
O << *GVSym;
else
O << '(' << *GVSym << ')';
- printOffset(MO.getOffset());
+ printOffset(MO.getOffset(), O);
break;
}
case MachineOperand::MO_ExternalSymbol: {
TempNameStr += StringRef(MO.getSymbolName());
TempNameStr += StringRef("$stub");
- const MCSymbol *Sym = GetExternalSymbolSymbol(TempNameStr.str());
- const MCSymbol *&StubSym =
+ MCSymbol *Sym = GetExternalSymbolSymbol(TempNameStr.str());
+ MachineModuleInfoImpl::StubValueTy &StubSym =
MMI->getObjFileInfo<MachineModuleInfoMachO>().getFnStubEntry(Sym);
- if (StubSym == 0) {
+ if (StubSym.getPointer() == 0) {
TempNameStr.erase(TempNameStr.end()-5, TempNameStr.end());
- StubSym = OutContext.GetOrCreateSymbol(TempNameStr.str());
+ StubSym = MachineModuleInfoImpl::
+ StubValueTy(OutContext.GetOrCreateSymbol(TempNameStr.str()),
+ true);
}
- SymToPrint = StubSym;
+ SymToPrint = StubSym.getPointer();
} else {
SymToPrint = GetExternalSymbolSymbol(MO.getSymbolName());
}
break;
case X86II::MO_GOT_ABSOLUTE_ADDRESS:
O << " + [.-";
- PrintPICBaseSymbol();
+ PrintPICBaseSymbol(O);
O << ']';
break;
case X86II::MO_PIC_BASE_OFFSET:
case X86II::MO_DARWIN_NONLAZY_PIC_BASE:
case X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE:
O << '-';
- PrintPICBaseSymbol();
+ PrintPICBaseSymbol(O);
break;
case X86II::MO_TLSGD: O << "@TLSGD"; break;
case X86II::MO_GOTTPOFF: O << "@GOTTPOFF"; break;
/// print_pcrel_imm - 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) {
+void X86AsmPrinter::print_pcrel_imm(const MachineInstr *MI, unsigned OpNo,
+ raw_ostream &O) {
const MachineOperand &MO = MI->getOperand(OpNo);
switch (MO.getType()) {
default: llvm_unreachable("Unknown pcrel immediate operand");
O << MO.getImm();
return;
case MachineOperand::MO_MachineBasicBlock:
- O << *GetMBBSymbol(MO.getMBB()->getNumber());
+ O << *MO.getMBB()->getSymbol();
return;
case MachineOperand::MO_GlobalAddress:
case MachineOperand::MO_ExternalSymbol:
- printSymbolOperand(MO);
+ printSymbolOperand(MO, O);
return;
}
}
void X86AsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,
- const char *Modifier) {
+ raw_ostream &O, const char *Modifier) {
const MachineOperand &MO = MI->getOperand(OpNo);
switch (MO.getType()) {
default: llvm_unreachable("unknown operand type!");
case MachineOperand::MO_GlobalAddress:
case MachineOperand::MO_ExternalSymbol: {
O << '$';
- printSymbolOperand(MO);
+ printSymbolOperand(MO, O);
break;
}
}
}
-void X86AsmPrinter::printSSECC(const MachineInstr *MI, unsigned Op) {
+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) {
}
void X86AsmPrinter::printLeaMemReference(const MachineInstr *MI, unsigned Op,
- const char *Modifier) {
+ 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);
} else {
assert(DispSpec.isGlobal() || DispSpec.isCPI() ||
DispSpec.isJTI() || DispSpec.isSymbol());
- printSymbolOperand(MI->getOperand(Op+3));
+ printSymbolOperand(MI->getOperand(Op+3), O);
}
if (HasParenPart) {
O << '(';
if (HasBaseReg)
- printOperand(MI, Op, Modifier);
+ printOperand(MI, Op, O, Modifier);
if (IndexReg.getReg()) {
O << ',';
- printOperand(MI, Op+2, Modifier);
+ printOperand(MI, Op+2, O, Modifier);
unsigned ScaleVal = MI->getOperand(Op+1).getImm();
if (ScaleVal != 1)
O << ',' << ScaleVal;
}
void X86AsmPrinter::printMemReference(const MachineInstr *MI, unsigned Op,
- const char *Modifier) {
+ raw_ostream &O, const char *Modifier) {
assert(isMem(MI, Op) && "Invalid memory reference!");
const MachineOperand &Segment = MI->getOperand(Op+4);
if (Segment.getReg()) {
- printOperand(MI, Op+4, Modifier);
+ printOperand(MI, Op+4, O, Modifier);
O << ':';
}
- printLeaMemReference(MI, Op, Modifier);
+ printLeaMemReference(MI, Op, O, Modifier);
}
-void X86AsmPrinter::printPICJumpTableSetLabel(unsigned uid,
- const MachineBasicBlock *MBB) const {
- if (!MAI->getSetDirective())
- return;
-
- // We don't need .set machinery if we have GOT-style relocations
- if (Subtarget->isPICStyleGOT())
- return;
-
- O << MAI->getSetDirective() << ' ' << MAI->getPrivateGlobalPrefix()
- << getFunctionNumber() << '_' << uid << "_set_" << MBB->getNumber() << ',';
-
- O << *GetMBBSymbol(MBB->getNumber());
-
- if (Subtarget->isPICStyleRIPRel())
- O << '-' << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
- << '_' << uid << '\n';
- else {
- O << '-';
- PrintPICBaseSymbol();
- O << '\n';
- }
-}
-
-
-void X86AsmPrinter::printPICLabel(const MachineInstr *MI, unsigned Op) {
- PrintPICBaseSymbol();
+void X86AsmPrinter::printPICLabel(const MachineInstr *MI, unsigned Op,
+ raw_ostream &O) {
+ PrintPICBaseSymbol(O);
O << '\n';
- PrintPICBaseSymbol();
+ PrintPICBaseSymbol(O);
O << ':';
}
-void X86AsmPrinter::printPICJumpTableEntry(const MachineJumpTableInfo *MJTI,
- const MachineBasicBlock *MBB,
- unsigned uid) const {
- const char *JTEntryDirective = MJTI->getEntrySize() == 4 ?
- MAI->getData32bitsDirective() : MAI->getData64bitsDirective();
-
- O << JTEntryDirective << ' ';
-
- if (Subtarget->isPICStyleRIPRel() || Subtarget->isPICStyleStubPIC()) {
- O << MAI->getPrivateGlobalPrefix() << getFunctionNumber()
- << '_' << uid << "_set_" << MBB->getNumber();
- } else if (Subtarget->isPICStyleGOT())
- O << *GetMBBSymbol(MBB->getNumber()) << "@GOTOFF";
- else
- O << *GetMBBSymbol(MBB->getNumber());
-}
-
-bool X86AsmPrinter::printAsmMRegister(const MachineOperand &MO, char Mode) {
+bool X86AsmPrinter::printAsmMRegister(const MachineOperand &MO, char Mode,
+ raw_ostream &O) {
unsigned Reg = MO.getReg();
switch (Mode) {
default: return true; // Unknown mode.
///
bool X86AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
unsigned AsmVariant,
- const char *ExtraCode) {
+ const char *ExtraCode, raw_ostream &O) {
// Does this asm operand have a single letter operand modifier?
if (ExtraCode && ExtraCode[0]) {
if (ExtraCode[1] != 0) return true; // Unknown modifier.
return false;
}
if (MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isSymbol()) {
- printSymbolOperand(MO);
+ printSymbolOperand(MO, O);
return false;
}
if (MO.isReg()) {
O << '(';
- printOperand(MI, OpNo);
+ printOperand(MI, OpNo, O);
O << ')';
return false;
}
if (MO.isImm())
O << MO.getImm();
else if (MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isSymbol())
- printSymbolOperand(MO);
+ printSymbolOperand(MO, O);
else
- printOperand(MI, OpNo);
+ printOperand(MI, OpNo, O);
return false;
case 'A': // Print '*' before a register (it must be a register)
if (MO.isReg()) {
O << '*';
- printOperand(MI, OpNo);
+ printOperand(MI, OpNo, O);
return false;
}
return true;
case 'k': // Print SImode register
case 'q': // Print DImode register
if (MO.isReg())
- return printAsmMRegister(MO, ExtraCode[0]);
- printOperand(MI, OpNo);
+ return printAsmMRegister(MO, ExtraCode[0], O);
+ printOperand(MI, OpNo, O);
return false;
case 'P': // This is the operand of a call, treat specially.
- print_pcrel_imm(MI, OpNo);
+ print_pcrel_imm(MI, OpNo, O);
return false;
case 'n': // Negate the immediate or print a '-' before the operand.
}
}
- printOperand(MI, OpNo);
+ printOperand(MI, OpNo, O);
return false;
}
bool X86AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
unsigned OpNo, unsigned AsmVariant,
- const char *ExtraCode) {
+ const char *ExtraCode,
+ raw_ostream &O) {
if (ExtraCode && ExtraCode[0]) {
if (ExtraCode[1] != 0) return true; // Unknown modifier.
// These only apply to registers, ignore on mem.
break;
case 'P': // Don't print @PLT, but do print as memory.
- printMemReference(MI, OpNo, "no-rip");
+ printMemReference(MI, OpNo, O, "no-rip");
return false;
}
}
- printMemReference(MI, OpNo);
+ printMemReference(MI, OpNo, O);
return false;
}
-
-
-/// printMachineInstruction -- Print out a single X86 LLVM instruction MI in
-/// AT&T syntax to the current output stream.
-///
-void X86AsmPrinter::printMachineInstruction(const MachineInstr *MI) {
- ++EmittedInsts;
-
- processDebugLoc(MI, true);
-
- printInstructionThroughMCStreamer(MI);
-
- if (VerboseAsm)
- EmitComments(*MI);
- O << '\n';
-
- processDebugLoc(MI, false);
+void X86AsmPrinter::EmitStartOfAsmFile(Module &M) {
+ if (Subtarget->isTargetDarwin())
+ OutStreamer.SwitchSection(getObjFileLowering().getTextSection());
}
-void X86AsmPrinter::PrintGlobalVariable(const GlobalVariable* GVar) {
- MCSymbol *GVarSym = GetGlobalValueSymbol(GVar);
- printVisibility(GVarSym, GVar->getVisibility());
-
- if (MAI->hasDotTypeDotSizeDirective()) {
- O << "\t.type\t" << *GVarSym;
- if (MAI->getCommentString()[0] != '@')
- O << ",@object\n";
- else
- O << ",%object\n";
- }
-
- SectionKind GVKind = TargetLoweringObjectFile::getKindForGlobal(GVar, TM);
-
- const Type *Type = GVar->getType()->getElementType();
-
- const TargetData *TD = TM.getTargetData();
- unsigned Size = TD->getTypeAllocSize(Type);
- unsigned AlignLog = TD->getPreferredAlignmentLog(GVar);
-
- // Handle normal common symbols.
- if (GVKind.isCommon()) {
- if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
-
- O << ".comm " << *GVarSym << ',' << Size;
- if (MAI->getCOMMDirectiveTakesAlignment())
- O << ',' << (MAI->getAlignmentIsInBytes() ? (1 << AlignLog) : AlignLog);
-
- if (VerboseAsm) {
- O << "\t\t" << MAI->getCommentString() << " '";
- WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent());
- O << '\'';
- }
- O << '\n';
- return;
- }
-
- if (GVKind.isBSSLocal()) {
- if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
-
- if (const char *LComm = MAI->getLCOMMDirective()) {
- if (GVar->hasLocalLinkage()) {
- O << LComm << *GVarSym << ',' << Size;
- if (MAI->getLCOMMDirectiveTakesAlignment())
- O << ',' << AlignLog;
- }
- } else {
- if (!Subtarget->isTargetCygMing())
- O << "\t.local\t" << *GVarSym << '\n';
- O << MAI->getCOMMDirective() << *GVarSym << ',' << Size;
- if (MAI->getCOMMDirectiveTakesAlignment())
- O << ',' << (MAI->getAlignmentIsInBytes() ? (1 << AlignLog) : AlignLog);
- }
- if (VerboseAsm) {
- O.PadToColumn(MAI->getCommentColumn());
- O << MAI->getCommentString() << ' ';
- WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent());
- }
- O << '\n';
- return;
- }
-
- const MCSection *TheSection =
- getObjFileLowering().SectionForGlobal(GVar, GVKind, Mang, TM);
-
- // Handle the zerofill directive on darwin, which is a special form of BSS
- // emission.
- if (GVKind.isBSSExtern() && MAI->hasMachoZeroFillDirective()) {
- // .globl _foo
- OutStreamer.EmitSymbolAttribute(GVarSym, MCStreamer::Global);
- // .zerofill __DATA, __common, _foo, 400, 5
- OutStreamer.EmitZerofill(TheSection, GVarSym, Size, 1 << AlignLog);
- return;
- }
-
- OutStreamer.SwitchSection(TheSection);
-
- switch (GVar->getLinkage()) {
- case GlobalValue::CommonLinkage:
- case GlobalValue::LinkOnceAnyLinkage:
- case GlobalValue::LinkOnceODRLinkage:
- case GlobalValue::WeakAnyLinkage:
- case GlobalValue::WeakODRLinkage:
- case GlobalValue::LinkerPrivateLinkage:
- if (Subtarget->isTargetDarwin()) {
- OutStreamer.EmitSymbolAttribute(GVarSym, MCStreamer::Global);
- O << MAI->getWeakDefDirective() << *GVarSym << '\n';
- } else if (Subtarget->isTargetCygMing()) {
- OutStreamer.EmitSymbolAttribute(GVarSym, MCStreamer::Global);
- O << "\t.linkonce same_size\n";
- } else
- O << "\t.weak\t" << *GVarSym << '\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
- OutStreamer.EmitSymbolAttribute(GVarSym, MCStreamer::Global);
- break;
- case GlobalValue::PrivateLinkage:
- case GlobalValue::InternalLinkage:
- break;
- default:
- llvm_unreachable("Unknown linkage type!");
- }
-
- EmitAlignment(AlignLog, GVar);
- O << *GVarSym << ":";
- if (VerboseAsm){
- O.PadToColumn(MAI->getCommentColumn());
- O << MAI->getCommentString() << ' ';
- WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent());
- }
- O << '\n';
-
- EmitGlobalConstant(GVar->getInitializer());
-
- if (MAI->hasDotTypeDotSizeDirective())
- O << "\t.size\t" << *GVarSym << ", " << Size << '\n';
-}
void X86AsmPrinter::EmitEndOfAsmFile(Module &M) {
if (Subtarget->isTargetDarwin()) {
// All darwin targets use mach-o.
- TargetLoweringObjectFileMachO &TLOFMacho =
- static_cast<TargetLoweringObjectFileMachO &>(getObjFileLowering());
-
MachineModuleInfoMachO &MMIMacho =
MMI->getObjFileInfo<MachineModuleInfoMachO>();
Stubs = MMIMacho.GetFnStubList();
if (!Stubs.empty()) {
const MCSection *TheSection =
- TLOFMacho.getMachOSection("__IMPORT", "__jump_table",
- MCSectionMachO::S_SYMBOL_STUBS |
- MCSectionMachO::S_ATTR_SELF_MODIFYING_CODE |
- MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
- 5, SectionKind::getMetadata());
+ OutContext.getMachOSection("__IMPORT", "__jump_table",
+ MCSectionMachO::S_SYMBOL_STUBS |
+ MCSectionMachO::S_ATTR_SELF_MODIFYING_CODE |
+ MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
+ 5, SectionKind::getMetadata());
OutStreamer.SwitchSection(TheSection);
for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
- O << *Stubs[i].first << ":\n";
- // Get the MCSymbol without the $stub suffix.
- O << "\t.indirect_symbol " << *Stubs[i].second;
- O << "\n\thlt ; hlt ; hlt ; hlt ; hlt\n";
+ // L_foo$stub:
+ OutStreamer.EmitLabel(Stubs[i].first);
+ // .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*/);
}
- O << '\n';
Stubs.clear();
+ OutStreamer.AddBlankLine();
}
// Output stubs for external and common global variables.
Stubs = MMIMacho.GetGVStubList();
if (!Stubs.empty()) {
const MCSection *TheSection =
- TLOFMacho.getMachOSection("__IMPORT", "__pointers",
- MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS,
- SectionKind::getMetadata());
+ OutContext.getMachOSection("__IMPORT", "__pointers",
+ MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS,
+ SectionKind::getMetadata());
OutStreamer.SwitchSection(TheSection);
for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
- O << *Stubs[i].first << ":\n\t.indirect_symbol " << *Stubs[i].second;
- O << "\n\t.long\t0\n";
+ // L_foo$non_lazy_ptr:
+ OutStreamer.EmitLabel(Stubs[i].first);
+ // .indirect_symbol _foo
+ MachineModuleInfoImpl::StubValueTy &MCSym = Stubs[i].second;
+ OutStreamer.EmitSymbolAttribute(MCSym.getPointer(),
+ MCSA_IndirectSymbol);
+ // .long 0
+ if (MCSym.getInt())
+ // External to current translation unit.
+ OutStreamer.EmitIntValue(0, 4/*size*/, 0/*addrspace*/);
+ else
+ // Internal to current translation unit.
+ //
+ // When we place the LSDA into the TEXT section, the type info
+ // pointers need to be indirect and pc-rel. We accomplish this by
+ // 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*/);
}
Stubs.clear();
+ OutStreamer.AddBlankLine();
}
Stubs = MMIMacho.GetHiddenGVStubList();
EmitAlignment(2);
for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
- O << *Stubs[i].first << ":\n" << MAI->getData32bitsDirective();
- O << *Stubs[i].second << '\n';
+ // L_foo$non_lazy_ptr:
+ OutStreamer.EmitLabel(Stubs[i].first);
+ // .long _foo
+ OutStreamer.EmitValue(MCSymbolRefExpr::
+ Create(Stubs[i].second.getPointer(),
+ OutContext),
+ 4/*size*/, 0/*addrspace*/);
}
Stubs.clear();
+ OutStreamer.AddBlankLine();
}
// Funny Darwin hack: This flag tells the linker that no global symbols
// 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.
- OutStreamer.EmitAssemblerFlag(MCStreamer::SubsectionsViaSymbols);
+ OutStreamer.EmitAssemblerFlag(MCAF_SubsectionsViaSymbols);
}
if (Subtarget->isTargetCOFF()) {
// Emit type information for external functions
for (X86COFFMachineModuleInfo::stub_iterator I = COFFMMI.stub_begin(),
E = COFFMMI.stub_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";
+ OutStreamer.EmitRawText("\t.def\t " + Twine(I->getKeyData()) +
+ ";\t.scl\t" + Twine(COFF::C_EXT) +
+ ";\t.type\t" +
+ Twine(COFF::DT_FCN << COFF::N_BTSHFT) +
+ ";\t.endef");
}
if (Subtarget->isTargetCygMing()) {
// Necessary for dllexport support
std::vector<const MCSymbol*> DLLExportedFns, DLLExportedGlobals;
- TargetLoweringObjectFileCOFF &TLOFCOFF =
- static_cast<TargetLoweringObjectFileCOFF&>(getObjFileLowering());
+ const TargetLoweringObjectFileCOFF &TLOFCOFF =
+ static_cast<const TargetLoweringObjectFileCOFF&>(getObjFileLowering());
for (Module::const_iterator I = M.begin(), E = M.end(); I != E; ++I)
- if (I->hasDLLExportLinkage()) {
- MCSymbol *Sym = GetGlobalValueSymbol(I);
- COFFMMI.DecorateCygMingName(Sym, OutContext, I, *TM.getTargetData());
- DLLExportedFns.push_back(Sym);
- }
+ if (I->hasDLLExportLinkage())
+ DLLExportedFns.push_back(Mang->getSymbol(I));
for (Module::const_global_iterator I = M.global_begin(),
E = M.global_end(); I != E; ++I)
if (I->hasDLLExportLinkage())
- DLLExportedGlobals.push_back(GetGlobalValueSymbol(I));
+ DLLExportedGlobals.push_back(Mang->getSymbol(I));
// Output linker support code for dllexported globals on windows.
if (!DLLExportedGlobals.empty() || !DLLExportedFns.empty()) {
- OutStreamer.SwitchSection(TLOFCOFF.getCOFFSection(".section .drectve",
- true,
- SectionKind::getMetadata()));
+ OutStreamer.SwitchSection(TLOFCOFF.getDrectveSection());
for (unsigned i = 0, e = DLLExportedGlobals.size(); i != e; ++i)
- O << "\t.ascii \" -export:" << *DLLExportedGlobals[i] << ",data\"\n";
+ OutStreamer.EmitRawText("\t.ascii \" -export:" +
+ Twine(DLLExportedGlobals[i]->getName()) +
+ ",data\"");
for (unsigned i = 0, e = DLLExportedFns.size(); i != e; ++i)
- O << "\t.ascii \" -export:" << *DLLExportedFns[i] << "\"\n";
+ OutStreamer.EmitRawText("\t.ascii \" -export:" +
+ Twine(DLLExportedFns[i]->getName()) + "\"");
}
}
}
+
+ if (Subtarget->isTargetELF()) {
+ const TargetLoweringObjectFileELF &TLOFELF =
+ static_cast<const TargetLoweringObjectFileELF &>(getObjFileLowering());
+
+ MachineModuleInfoELF &MMIELF = MMI->getObjFileInfo<MachineModuleInfoELF>();
+
+ // Output stubs for external and common global variables.
+ MachineModuleInfoELF::SymbolListTy Stubs = MMIELF.GetGVStubList();
+ if (!Stubs.empty()) {
+ OutStreamer.SwitchSection(TLOFELF.getDataRelSection());
+ const TargetData *TD = TM.getTargetData();
+
+ for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
+ OutStreamer.EmitLabel(Stubs[i].first);
+ OutStreamer.EmitSymbolValue(Stubs[i].second.getPointer(),
+ TD->getPointerSize(), 0);
+ }
+ Stubs.clear();
+ }
+ }
}
static MCInstPrinter *createX86MCInstPrinter(const Target &T,
unsigned SyntaxVariant,
- const MCAsmInfo &MAI,
- raw_ostream &O) {
+ const MCAsmInfo &MAI) {
if (SyntaxVariant == 0)
- return new X86ATTInstPrinter(O, MAI);
+ return new X86ATTInstPrinter(MAI);
if (SyntaxVariant == 1)
- return new X86IntelInstPrinter(O, MAI);
+ return new X86IntelInstPrinter(MAI);
return 0;
}