#include "llvm/CodeGen/AsmPrinter.h"
#include "DwarfDebug.h"
#include "DwarfException.h"
+#include "WinCodeViewLineTables.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/ConstantFolding.h"
-#include "llvm/Assembly/Writer.h"
#include "llvm/CodeGen/GCMetadataPrinter.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineInstrBundle.h"
#include "llvm/CodeGen/MachineJumpTableInfo.h"
#include "llvm/CodeGen/MachineLoopInfo.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
-#include "llvm/DebugInfo.h"
#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/DebugInfo.h"
+#include "llvm/IR/Mangler.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Operator.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/Timer.h"
-#include "llvm/Target/Mangler.h"
#include "llvm/Target/TargetFrameLowering.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetLowering.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Target/TargetRegisterInfo.h"
+#include "llvm/Target/TargetSubtargetInfo.h"
+#include "llvm/Transforms/Utils/GlobalStatus.h"
using namespace llvm;
-static const char *DWARFGroupName = "DWARF Emission";
-static const char *DbgTimerName = "DWARF Debug Writer";
-static const char *EHTimerName = "DWARF Exception Writer";
+static const char *const DWARFGroupName = "DWARF Emission";
+static const char *const DbgTimerName = "Debug Info Emission";
+static const char *const EHTimerName = "DWARF Exception Writer";
+static const char *const CodeViewLineTablesGroupName = "CodeView Line Tables";
STATISTIC(EmittedInsts, "Number of machine instrs printed");
AsmPrinter::AsmPrinter(TargetMachine &tm, MCStreamer &Streamer)
: MachineFunctionPass(ID),
- TM(tm), MAI(tm.getMCAsmInfo()),
+ TM(tm), MAI(tm.getMCAsmInfo()), MII(tm.getInstrInfo()),
OutContext(Streamer.getContext()),
OutStreamer(Streamer),
LastMI(0), LastFn(0), Counter(~0U), SetCounter(0) {
- DD = 0; DE = 0; MMI = 0; LI = 0;
+ DD = 0; MMI = 0; LI = 0; MF = 0;
CurrentFnSym = CurrentFnSymForSize = 0;
GCMetadataPrinters = 0;
VerboseAsm = Streamer.isVerboseAsm();
}
AsmPrinter::~AsmPrinter() {
- assert(DD == 0 && DE == 0 && "Debug/EH info didn't get finalized");
+ assert(DD == 0 && Handlers.empty() && "Debug/EH info didn't get finalized");
if (GCMetadataPrinters != 0) {
gcp_map_type &GCMap = getGCMap(GCMetadataPrinters);
return *TM.getDataLayout();
}
+const MCSubtargetInfo &AsmPrinter::getSubtargetInfo() const {
+ return TM.getSubtarget<MCSubtargetInfo>();
+}
+
+void AsmPrinter::EmitToStreamer(MCStreamer &S, const MCInst &Inst) {
+ S.EmitInstruction(Inst, getSubtargetInfo());
+}
+
StringRef AsmPrinter::getTargetTriple() const {
return TM.getTargetTriple();
}
}
bool AsmPrinter::doInitialization(Module &M) {
- OutStreamer.InitStreamer();
-
MMI = getAnalysisIfAvailable<MachineModuleInfo>();
MMI->AnalyzeModule(M);
const_cast<TargetLoweringObjectFile&>(getObjFileLowering())
.Initialize(OutContext, TM);
- Mang = new Mangler(OutContext, &TM);
+ OutStreamer.InitSections();
+
+ Mang = new Mangler(TM.getDataLayout());
// Allow the target to emit any magic that it wants at the start of the file.
EmitStartOfAsmFile(M);
OutStreamer.AddBlankLine();
}
- if (MAI->doesSupportDebugInformation())
- DD = new DwarfDebug(this, &M);
+ if (MAI->doesSupportDebugInformation()) {
+ if (Triple(TM.getTargetTriple()).getOS() == Triple::Win32) {
+ Handlers.push_back(HandlerInfo(new WinCodeViewLineTables(this),
+ DbgTimerName,
+ CodeViewLineTablesGroupName));
+ } else {
+ DD = new DwarfDebug(this, &M);
+ Handlers.push_back(HandlerInfo(DD, DbgTimerName, DWARFGroupName));
+ }
+ }
+ DwarfException *DE = 0;
switch (MAI->getExceptionHandlingType()) {
case ExceptionHandling::None:
- return false;
+ break;
case ExceptionHandling::SjLj:
case ExceptionHandling::DwarfCFI:
DE = new DwarfCFIException(this);
- return false;
+ break;
case ExceptionHandling::ARM:
DE = new ARMException(this);
- return false;
+ break;
case ExceptionHandling::Win64:
DE = new Win64Exception(this);
+ break;
+ }
+ if (DE)
+ Handlers.push_back(HandlerInfo(DE, EHTimerName, DWARFGroupName));
+ return false;
+}
+
+static bool canBeHidden(const GlobalValue *GV, const MCAsmInfo &MAI) {
+ GlobalValue::LinkageTypes Linkage = GV->getLinkage();
+ if (Linkage != GlobalValue::LinkOnceODRLinkage)
return false;
+
+ if (!MAI.hasWeakDefCanBeHiddenDirective())
+ return false;
+
+ if (GV->hasUnnamedAddr())
+ return true;
+
+ // This is only used for MachO, so right now it doesn't really matter how
+ // we handle alias. Revisit this once the MachO linker implements aliases.
+ if (isa<GlobalAlias>(GV))
+ return false;
+
+ // If it is a non constant variable, it needs to be uniqued across shared
+ // objects.
+ if (const GlobalVariable *Var = dyn_cast<GlobalVariable>(GV)) {
+ if (!Var->isConstant())
+ return false;
}
- llvm_unreachable("Unknown exception type.");
+ GlobalStatus GS;
+ if (!GlobalStatus::analyzeGlobal(GV, GS) && !GS.IsCompared)
+ return true;
+
+ return false;
}
-void AsmPrinter::EmitLinkage(unsigned Linkage, MCSymbol *GVSym) const {
- switch ((GlobalValue::LinkageTypes)Linkage) {
+void AsmPrinter::EmitLinkage(const GlobalValue *GV, MCSymbol *GVSym) const {
+ GlobalValue::LinkageTypes Linkage = GV->getLinkage();
+ switch (Linkage) {
case GlobalValue::CommonLinkage:
case GlobalValue::LinkOnceAnyLinkage:
case GlobalValue::LinkOnceODRLinkage:
- case GlobalValue::LinkOnceODRAutoHideLinkage:
case GlobalValue::WeakAnyLinkage:
case GlobalValue::WeakODRLinkage:
case GlobalValue::LinkerPrivateWeakLinkage:
- if (MAI->getWeakDefDirective() != 0) {
+ if (MAI->hasWeakDefDirective()) {
// .globl _foo
OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Global);
- if ((GlobalValue::LinkageTypes)Linkage !=
- GlobalValue::LinkOnceODRAutoHideLinkage)
+ if (!canBeHidden(GV, *MAI))
// .weak_definition _foo
OutStreamer.EmitSymbolAttribute(GVSym, MCSA_WeakDefinition);
else
OutStreamer.EmitSymbolAttribute(GVSym, MCSA_WeakDefAutoPrivate);
- } else if (MAI->getLinkOnceDirective() != 0) {
+ } else if (MAI->hasLinkOnceDirective()) {
// .globl _foo
OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Global);
//NOTE: linkonce is handled by the section the symbol was assigned to.
// .weak _foo
OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Weak);
}
- break;
- case GlobalValue::DLLExportLinkage:
+ return;
case GlobalValue::AppendingLinkage:
// FIXME: appending linkage variables should go into a section of
// their name or something. For now, just emit them as external.
// If external or appending, declare as a global symbol.
// .globl _foo
OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Global);
- break;
+ return;
case GlobalValue::PrivateLinkage:
case GlobalValue::InternalLinkage:
case GlobalValue::LinkerPrivateLinkage:
- break;
- default:
- llvm_unreachable("Unknown linkage type!");
+ return;
+ case GlobalValue::AvailableExternallyLinkage:
+ llvm_unreachable("Should never emit this");
+ case GlobalValue::ExternalWeakLinkage:
+ llvm_unreachable("Don't know how to emit these");
}
+ llvm_unreachable("Unknown linkage type!");
+}
+
+void AsmPrinter::getNameWithPrefix(SmallVectorImpl<char> &Name,
+ const GlobalValue *GV) const {
+ TM.getNameWithPrefix(Name, GV, *Mang);
}
+MCSymbol *AsmPrinter::getSymbol(const GlobalValue *GV) const {
+ return TM.getSymbol(GV, *Mang);
+}
/// EmitGlobalVariable - Emit the specified global variable to the .s file.
void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) {
return;
if (isVerbose()) {
- WriteAsOperand(OutStreamer.GetCommentOS(), GV,
+ GV->printAsOperand(OutStreamer.GetCommentOS(),
/*PrintType=*/false, GV->getParent());
OutStreamer.GetCommentOS() << '\n';
}
}
- MCSymbol *GVSym = Mang->getSymbol(GV);
+ MCSymbol *GVSym = getSymbol(GV);
EmitVisibility(GVSym, GV->getVisibility(), !GV->isDeclaration());
if (!GV->hasInitializer()) // External globals require no extra code.
SectionKind GVKind = TargetLoweringObjectFile::getKindForGlobal(GV, TM);
- const DataLayout *TD = TM.getDataLayout();
- uint64_t Size = TD->getTypeAllocSize(GV->getType()->getElementType());
+ const DataLayout *DL = TM.getDataLayout();
+ uint64_t Size = DL->getTypeAllocSize(GV->getType()->getElementType());
// If the alignment is specified, we *must* obey it. Overaligning a global
// with a specified alignment is a prompt way to break globals emitted to
// sections and expected to be contiguous (e.g. ObjC metadata).
- unsigned AlignLog = getGVAlignmentLog2(GV, *TD);
+ unsigned AlignLog = getGVAlignmentLog2(GV, *DL);
+
+ for (unsigned I = 0, E = Handlers.size(); I != E; ++I) {
+ const HandlerInfo &OI = Handlers[I];
+ NamedRegionTimer T(OI.TimerName, OI.TimerGroupName, TimePassesIsEnabled);
+ OI.Handler->setSymbolSize(GVSym, Size);
+ }
// Handle common and BSS local symbols (.lcomm).
if (GVKind.isCommon() || GVKind.isBSSLocal()) {
// Handle local BSS symbols.
if (MAI->hasMachoZeroFillDirective()) {
const MCSection *TheSection =
- getObjFileLowering().SectionForGlobal(GV, GVKind, Mang, TM);
+ getObjFileLowering().SectionForGlobal(GV, GVKind, *Mang, TM);
// .zerofill __DATA, __bss, _foo, 400, 5
OutStreamer.EmitZerofill(TheSection, GVSym, Size, Align);
return;
}
const MCSection *TheSection =
- getObjFileLowering().SectionForGlobal(GV, GVKind, Mang, TM);
+ getObjFileLowering().SectionForGlobal(GV, GVKind, *Mang, TM);
// Handle the zerofill directive on darwin, which is a special form of BSS
// emission.
MCSymbol *MangSym =
OutContext.GetOrCreateSymbol(GVSym->getName() + Twine("$tlv$init"));
- if (GVKind.isThreadBSS())
+ if (GVKind.isThreadBSS()) {
+ TheSection = getObjFileLowering().getTLSBSSSection();
OutStreamer.EmitTBSSSymbol(TheSection, MangSym, Size, 1 << AlignLog);
- else if (GVKind.isThreadData()) {
+ } else if (GVKind.isThreadData()) {
OutStreamer.SwitchSection(TheSection);
EmitAlignment(AlignLog, GV);
OutStreamer.SwitchSection(TLVSect);
// Emit the linkage here.
- EmitLinkage(GV->getLinkage(), GVSym);
+ EmitLinkage(GV, GVSym);
OutStreamer.EmitLabel(GVSym);
// Three pointers in size:
// - __tlv_bootstrap - used to make sure support exists
// - spare pointer, used when mapped by the runtime
// - pointer to mangled symbol above with initializer
- unsigned PtrSize = TD->getPointerSizeInBits()/8;
+ unsigned PtrSize = DL->getPointerTypeSize(GV->getType());
OutStreamer.EmitSymbolValue(GetExternalSymbolSymbol("_tlv_bootstrap"),
- PtrSize);
+ PtrSize);
OutStreamer.EmitIntValue(0, PtrSize);
OutStreamer.EmitSymbolValue(MangSym, PtrSize);
OutStreamer.SwitchSection(TheSection);
- EmitLinkage(GV->getLinkage(), GVSym);
+ EmitLinkage(GV, GVSym);
EmitAlignment(AlignLog, GV);
OutStreamer.EmitLabel(GVSym);
// Print the 'header' of function.
const Function *F = MF->getFunction();
- OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(F, Mang, TM));
+ OutStreamer.SwitchSection(
+ getObjFileLowering().SectionForGlobal(F, *Mang, TM));
EmitVisibility(CurrentFnSym, F->getVisibility());
- EmitLinkage(F->getLinkage(), CurrentFnSym);
+ EmitLinkage(F, CurrentFnSym);
EmitAlignment(MF->getAlignment(), F);
if (MAI->hasDotTypeDotSizeDirective())
OutStreamer.EmitSymbolAttribute(CurrentFnSym, MCSA_ELF_TypeFunction);
if (isVerbose()) {
- WriteAsOperand(OutStreamer.GetCommentOS(), F,
+ F->printAsOperand(OutStreamer.GetCommentOS(),
/*PrintType=*/false, F->getParent());
OutStreamer.GetCommentOS() << '\n';
}
OutStreamer.EmitLabel(DeadBlockSyms[i]);
}
- // Add some workaround for linkonce linkage on Cygwin\MinGW.
- if (MAI->getLinkOnceDirective() != 0 &&
- (F->hasLinkOnceLinkage() || F->hasWeakLinkage())) {
- // FIXME: What is this?
- MCSymbol *FakeStub =
- OutContext.GetOrCreateSymbol(Twine("Lllvm$workaround$fake$stub$")+
- CurrentFnSym->getName());
- OutStreamer.EmitLabel(FakeStub);
- }
-
// Emit pre-function debug and/or EH information.
- if (DE) {
- NamedRegionTimer T(EHTimerName, DWARFGroupName, TimePassesIsEnabled);
- DE->BeginFunction(MF);
- }
- if (DD) {
- NamedRegionTimer T(DbgTimerName, DWARFGroupName, TimePassesIsEnabled);
- DD->beginFunction(MF);
+ for (unsigned I = 0, E = Handlers.size(); I != E; ++I) {
+ const HandlerInfo &OI = Handlers[I];
+ NamedRegionTimer T(OI.TimerName, OI.TimerGroupName, TimePassesIsEnabled);
+ OI.Handler->beginFunction(MF);
}
+
+ // Emit the prefix data.
+ if (F->hasPrefixData())
+ EmitGlobalConstant(F->getPrefixData());
}
/// EmitFunctionEntryLabel - Emit the label that is the entrypoint for the
/// emitImplicitDef - This method emits the specified machine instruction
/// that is an implicit def.
-static void emitImplicitDef(const MachineInstr *MI, AsmPrinter &AP) {
+void AsmPrinter::emitImplicitDef(const MachineInstr *MI) const {
unsigned RegNo = MI->getOperand(0).getReg();
- AP.OutStreamer.AddComment(Twine("implicit-def: ") +
- AP.TM.getRegisterInfo()->getName(RegNo));
- AP.OutStreamer.AddBlankLine();
+ OutStreamer.AddComment(Twine("implicit-def: ") +
+ TM.getRegisterInfo()->getName(RegNo));
+ OutStreamer.AddBlankLine();
}
static void emitKill(const MachineInstr *MI, AsmPrinter &AP) {
SmallString<128> Str;
raw_svector_ostream OS(Str);
- OS << '\t' << AP.MAI->getCommentString() << "DEBUG_VALUE: ";
+ OS << "DEBUG_VALUE: ";
- // cast away const; DIetc do not take const operands for some reason.
- DIVariable V(const_cast<MDNode*>(MI->getOperand(2).getMetadata()));
+ DIVariable V(MI->getOperand(2).getMetadata());
if (V.getContext().isSubprogram()) {
StringRef Name = DISubprogram(V.getContext()).getDisplayName();
if (!Name.empty())
}
OS << V.getName() << " <- ";
- int64_t Offset = MI->getOperand(1).getImm();
- bool Deref = false;
+ // The second operand is only an offset if it's an immediate.
+ bool Deref = MI->getOperand(0).isReg() && MI->getOperand(1).isImm();
+ int64_t Offset = Deref ? MI->getOperand(1).getImm() : 0;
+
// Register or immediate value. Register 0 means undef.
if (MI->getOperand(0).isFPImm()) {
APFloat APF = APFloat(MI->getOperand(0).getFPImm()->getValueAPF());
unsigned Reg;
if (MI->getOperand(0).isReg()) {
Reg = MI->getOperand(0).getReg();
- Deref = Offset != 0; // FIXME: use a better sentinel value so that deref
- // of a reg with a zero offset is valid
} else {
assert(MI->getOperand(0).isFI() && "Unknown operand type");
const TargetFrameLowering *TFI = AP.TM.getFrameLowering();
- Offset += TFI->getFrameIndexReference(*AP.MF, MI->getOperand(0).getIndex(), Reg);
+ Offset += TFI->getFrameIndexReference(*AP.MF,
+ MI->getOperand(0).getIndex(), Reg);
Deref = true;
}
if (Reg == 0) {
// Suppress offset, it is not meaningful here.
OS << "undef";
// NOTE: Want this comment at start of line, don't emit with AddComment.
- AP.OutStreamer.EmitRawText(OS.str());
+ AP.OutStreamer.emitRawComment(OS.str());
return true;
}
if (Deref)
OS << AP.TM.getRegisterInfo()->getName(Reg);
}
- if (Offset)
- OS << '+' << Offset;
if (Deref)
- OS << ']';
+ OS << '+' << Offset << ']';
+
// NOTE: Want this comment at start of line, don't emit with AddComment.
- AP.OutStreamer.EmitRawText(OS.str());
+ AP.OutStreamer.emitRawComment(OS.str());
return true;
}
MF->getFunction()->needsUnwindTableEntry();
}
-bool AsmPrinter::needsRelocationsForDwarfStringPool() const {
- return MAI->doesDwarfUseRelocationsAcrossSections();
-}
-
-void AsmPrinter::emitPrologLabel(const MachineInstr &MI) {
- MCSymbol *Label = MI.getOperand(0).getMCSymbol();
-
- if (MAI->getExceptionHandlingType() != ExceptionHandling::DwarfCFI)
+void AsmPrinter::emitCFIInstruction(const MachineInstr &MI) {
+ ExceptionHandling::ExceptionsType ExceptionHandlingType =
+ MAI->getExceptionHandlingType();
+ if (ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
+ ExceptionHandlingType != ExceptionHandling::ARM)
return;
if (needsCFIMoves() == CFI_M_None)
if (MMI->getCompactUnwindEncoding() != 0)
OutStreamer.EmitCompactUnwindEncoding(MMI->getCompactUnwindEncoding());
- MachineModuleInfo &MMI = MF->getMMI();
- std::vector<MCCFIInstruction> Instructions = MMI.getFrameInstructions();
- bool FoundOne = false;
- (void)FoundOne;
- for (std::vector<MCCFIInstruction>::iterator I = Instructions.begin(),
- E = Instructions.end(); I != E; ++I) {
- if (I->getLabel() == Label) {
- emitCFIInstruction(*I);
- FoundOne = true;
- }
- }
- assert(FoundOne);
+ const MachineModuleInfo &MMI = MF->getMMI();
+ const std::vector<MCCFIInstruction> &Instrs = MMI.getFrameInstructions();
+ unsigned CFIIndex = MI.getOperand(0).getCFIIndex();
+ const MCCFIInstruction &CFI = Instrs[CFIIndex];
+ emitCFIInstruction(CFI);
}
/// EmitFunctionBody - This method emits the body and trailer for a
// Emit target-specific gunk before the function body.
EmitFunctionBodyStart();
- bool ShouldPrintDebugScopes = DD && MMI->hasDebugInfo();
+ bool ShouldPrintDebugScopes = MMI->hasDebugInfo();
// Print out code for the function.
bool HasAnyRealCode = false;
LastMI = II;
// Print the assembly for the instruction.
- if (!II->isLabel() && !II->isImplicitDef() && !II->isKill() &&
+ if (!II->isPosition() && !II->isImplicitDef() && !II->isKill() &&
!II->isDebugValue()) {
HasAnyRealCode = true;
++EmittedInsts;
}
if (ShouldPrintDebugScopes) {
- NamedRegionTimer T(DbgTimerName, DWARFGroupName, TimePassesIsEnabled);
- DD->beginInstruction(II);
+ for (unsigned III = 0, EEE = Handlers.size(); III != EEE; ++III) {
+ const HandlerInfo &OI = Handlers[III];
+ NamedRegionTimer T(OI.TimerName, OI.TimerGroupName,
+ TimePassesIsEnabled);
+ OI.Handler->beginInstruction(II);
+ }
}
if (isVerbose())
emitComments(*II, OutStreamer.GetCommentOS());
switch (II->getOpcode()) {
- case TargetOpcode::PROLOG_LABEL:
- emitPrologLabel(*II);
+ case TargetOpcode::CFI_INSTRUCTION:
+ emitCFIInstruction(*II);
break;
case TargetOpcode::EH_LABEL:
}
break;
case TargetOpcode::IMPLICIT_DEF:
- if (isVerbose()) emitImplicitDef(II, *this);
+ if (isVerbose()) emitImplicitDef(II);
break;
case TargetOpcode::KILL:
if (isVerbose()) emitKill(II, *this);
break;
default:
- if (!TM.hasMCUseLoc())
- MCLineEntry::Make(&OutStreamer, getCurrentSection());
-
EmitInstruction(II);
break;
}
if (ShouldPrintDebugScopes) {
- NamedRegionTimer T(DbgTimerName, DWARFGroupName, TimePassesIsEnabled);
- DD->endInstruction(II);
+ for (unsigned III = 0, EEE = Handlers.size(); III != EEE; ++III) {
+ const HandlerInfo &OI = Handlers[III];
+ NamedRegionTimer T(OI.TimerName, OI.TimerGroupName,
+ TimePassesIsEnabled);
+ OI.Handler->endInstruction();
+ }
}
}
}
// label equaling the end of function label and an invalid "row" in the
// FDE. We need to emit a noop in this situation so that the FDE's rows are
// valid.
- bool RequiresNoop = LastMI && LastMI->isPrologLabel();
+ bool RequiresNoop = LastMI && LastMI->isCFIInstruction();
// If the function is empty and the object file uses .subsections_via_symbols,
// then we need to emit *something* to the function body to prevent the
TM.getInstrInfo()->getNoopForMachoTarget(Noop);
if (Noop.getOpcode()) {
OutStreamer.AddComment("avoids zero-length function");
- OutStreamer.EmitInstruction(Noop);
+ OutStreamer.EmitInstruction(Noop, getSubtargetInfo());
} else // Target not mc-ized yet.
OutStreamer.EmitRawText(StringRef("\tnop\n"));
}
OutStreamer.EmitELFSize(CurrentFnSym, SizeExp);
}
- // Emit post-function debug information.
- if (DD) {
- NamedRegionTimer T(DbgTimerName, DWARFGroupName, TimePassesIsEnabled);
- DD->endFunction(MF);
- }
- if (DE) {
- NamedRegionTimer T(EHTimerName, DWARFGroupName, TimePassesIsEnabled);
- DE->EndFunction();
+ // Emit post-function debug and/or EH information.
+ for (unsigned I = 0, E = Handlers.size(); I != E; ++I) {
+ const HandlerInfo &OI = Handlers[I];
+ NamedRegionTimer T(OI.TimerName, OI.TimerGroupName, TimePassesIsEnabled);
+ OI.Handler->endFunction(MF);
}
MMI->EndFunction();
OutStreamer.AddBlankLine();
}
-/// getDebugValueLocation - Get location information encoded by DBG_VALUE
-/// operands.
-MachineLocation AsmPrinter::
-getDebugValueLocation(const MachineInstr *MI) const {
- // Target specific DBG_VALUE instructions are handled by each target.
- return MachineLocation();
-}
-
-/// EmitDwarfRegOp - Emit dwarf register operation.
-void AsmPrinter::EmitDwarfRegOp(const MachineLocation &MLoc) const {
- const TargetRegisterInfo *TRI = TM.getRegisterInfo();
- int Reg = TRI->getDwarfRegNum(MLoc.getReg(), false);
-
- for (MCSuperRegIterator SR(MLoc.getReg(), TRI); SR.isValid() && Reg < 0;
- ++SR) {
- Reg = TRI->getDwarfRegNum(*SR, false);
- // FIXME: Get the bit range this register uses of the superregister
- // so that we can produce a DW_OP_bit_piece
- }
-
- // FIXME: Handle cases like a super register being encoded as
- // DW_OP_reg 32 DW_OP_piece 4 DW_OP_reg 33
-
- // FIXME: We have no reasonable way of handling errors in here. The
- // caller might be in the middle of an dwarf expression. We should
- // probably assert that Reg >= 0 once debug info generation is more mature.
-
- if (MLoc.isIndirect()) {
- if (Reg < 32) {
- OutStreamer.AddComment(
- dwarf::OperationEncodingString(dwarf::DW_OP_breg0 + Reg));
- EmitInt8(dwarf::DW_OP_breg0 + Reg);
- } else {
- OutStreamer.AddComment("DW_OP_bregx");
- EmitInt8(dwarf::DW_OP_bregx);
- OutStreamer.AddComment(Twine(Reg));
- EmitULEB128(Reg);
- }
- EmitSLEB128(MLoc.getOffset());
- } else {
- if (Reg < 32) {
- OutStreamer.AddComment(
- dwarf::OperationEncodingString(dwarf::DW_OP_reg0 + Reg));
- EmitInt8(dwarf::DW_OP_reg0 + Reg);
- } else {
- OutStreamer.AddComment("DW_OP_regx");
- EmitInt8(dwarf::DW_OP_regx);
- OutStreamer.AddComment(Twine(Reg));
- EmitULEB128(Reg);
- }
- }
-
- // FIXME: Produce a DW_OP_bit_piece if we used a superregister
-}
-
bool AsmPrinter::doFinalization(Module &M) {
// Emit global variables.
for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
if (V == GlobalValue::DefaultVisibility)
continue;
- MCSymbol *Name = Mang->getSymbol(&F);
+ MCSymbol *Name = getSymbol(&F);
EmitVisibility(Name, V, false);
}
SmallVector<Module::ModuleFlagEntry, 8> ModuleFlags;
M.getModuleFlagsMetadata(ModuleFlags);
if (!ModuleFlags.empty())
- getObjFileLowering().emitModuleFlags(OutStreamer, ModuleFlags, Mang, TM);
+ getObjFileLowering().emitModuleFlags(OutStreamer, ModuleFlags, *Mang, TM);
+
+ // Make sure we wrote out everything we need.
+ OutStreamer.Flush();
// Finalize debug and EH information.
- if (DE) {
- {
- NamedRegionTimer T(EHTimerName, DWARFGroupName, TimePassesIsEnabled);
- DE->EndModule();
- }
- delete DE; DE = 0;
- }
- if (DD) {
- {
- NamedRegionTimer T(DbgTimerName, DWARFGroupName, TimePassesIsEnabled);
- DD->endModule();
- }
- delete DD; DD = 0;
+ for (unsigned I = 0, E = Handlers.size(); I != E; ++I) {
+ const HandlerInfo &OI = Handlers[I];
+ NamedRegionTimer T(OI.TimerName, OI.TimerGroupName,
+ TimePassesIsEnabled);
+ OI.Handler->endModule();
+ delete OI.Handler;
}
+ Handlers.clear();
+ DD = 0;
// If the target wants to know about weak references, print them all.
if (MAI->getWeakRefDirective()) {
for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
I != E; ++I) {
if (!I->hasExternalWeakLinkage()) continue;
- OutStreamer.EmitSymbolAttribute(Mang->getSymbol(I), MCSA_WeakReference);
+ OutStreamer.EmitSymbolAttribute(getSymbol(I), MCSA_WeakReference);
}
for (Module::const_iterator I = M.begin(), E = M.end(); I != E; ++I) {
if (!I->hasExternalWeakLinkage()) continue;
- OutStreamer.EmitSymbolAttribute(Mang->getSymbol(I), MCSA_WeakReference);
+ OutStreamer.EmitSymbolAttribute(getSymbol(I), MCSA_WeakReference);
}
}
OutStreamer.AddBlankLine();
for (Module::const_alias_iterator I = M.alias_begin(), E = M.alias_end();
I != E; ++I) {
- MCSymbol *Name = Mang->getSymbol(I);
+ MCSymbol *Name = getSymbol(I);
const GlobalValue *GV = I->getAliasedGlobal();
- MCSymbol *Target = Mang->getSymbol(GV);
+ if (GV->isDeclaration()) {
+ report_fatal_error(Name->getName() +
+ ": Target doesn't support aliases to declarations");
+ }
+
+ MCSymbol *Target = getSymbol(GV);
if (I->hasExternalLinkage() || !MAI->getWeakRefDirective())
OutStreamer.EmitSymbolAttribute(Name, MCSA_Global);
- else if (I->hasWeakLinkage())
+ else if (I->hasWeakLinkage() || I->hasLinkOnceLinkage())
OutStreamer.EmitSymbolAttribute(Name, MCSA_WeakReference);
else
assert(I->hasLocalLinkage() && "Invalid alias linkage");
if (GCMetadataPrinter *MP = GetOrCreateGCPrinter(*--I))
MP->finishAssembly(*this);
+ // Emit llvm.ident metadata in an '.ident' directive.
+ EmitModuleIdents(M);
+
// If we don't have any trampolines, then we don't require stack memory
// to be executable. Some targets have a directive to declare this.
Function *InitTrampolineIntrinsic = M.getFunction("llvm.init.trampoline");
void AsmPrinter::SetupMachineFunction(MachineFunction &MF) {
this->MF = &MF;
// Get the function symbol.
- CurrentFnSym = Mang->getSymbol(MF.getFunction());
+ CurrentFnSym = getSymbol(MF.getFunction());
CurrentFnSymForSize = CurrentFnSym;
if (isVerbose())
/// by the current function to the current output stream.
///
void AsmPrinter::EmitJumpTableInfo() {
+ const DataLayout *DL = MF->getTarget().getDataLayout();
const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
if (MJTI == 0) return;
if (MJTI->getEntryKind() == MachineJumpTableInfo::EK_Inline) return;
// FIXME: this isn't the right predicate, should be based on the MCSection
// for the function.
F->isWeakForLinker()) {
- OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(F,Mang,TM));
+ OutStreamer.SwitchSection(
+ getObjFileLowering().SectionForGlobal(F, *Mang, TM));
} else {
// Otherwise, drop it in the readonly section.
const MCSection *ReadOnlySection =
// before each jump table. The first label is never referenced, but tells
// the assembler and linker the extents of the jump table object. The
// second label is actually referenced by the code.
- if (JTInDiffSection && MAI->getLinkerPrivateGlobalPrefix()[0])
+ if (JTInDiffSection && DL->hasLinkerPrivateGlobalPrefix())
// FIXME: This doesn't have to have any specific name, just any randomly
// named and numbered 'l' label would work. Simplify GetJTISymbol.
OutStreamer.EmitLabel(GetJTISymbol(JTI, true));
for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) {
const GlobalValue *GV =
dyn_cast<GlobalValue>(InitList->getOperand(i)->stripPointerCasts());
- if (GV && getObjFileLowering().shouldEmitUsedDirectiveFor(GV, Mang))
- OutStreamer.EmitSymbolAttribute(Mang->getSymbol(GV), MCSA_NoDeadStrip);
+ if (GV)
+ OutStreamer.EmitSymbolAttribute(getSymbol(GV), MCSA_NoDeadStrip);
}
}
-typedef std::pair<unsigned, Constant*> Structor;
-
-static bool priority_order(const Structor& lhs, const Structor& rhs) {
- return lhs.first < rhs.first;
-}
-
/// EmitXXStructorList - Emit the ctor or dtor list taking into account the init
/// priority.
void AsmPrinter::EmitXXStructorList(const Constant *List, bool isCtor) {
!isa<PointerType>(ETy->getTypeAtIndex(1U))) return; // Not (int, ptr).
// Gather the structors in a form that's convenient for sorting by priority.
+ typedef std::pair<unsigned, Constant *> Structor;
SmallVector<Structor, 8> Structors;
for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) {
ConstantStruct *CS = dyn_cast<ConstantStruct>(InitList->getOperand(i));
}
// Emit the function pointers in the target-specific order
- const DataLayout *TD = TM.getDataLayout();
- unsigned Align = Log2_32(TD->getPointerPrefAlignment());
- std::stable_sort(Structors.begin(), Structors.end(), priority_order);
+ const DataLayout *DL = TM.getDataLayout();
+ unsigned Align = Log2_32(DL->getPointerPrefAlignment());
+ std::stable_sort(Structors.begin(), Structors.end(), less_first());
for (unsigned i = 0, e = Structors.size(); i != e; ++i) {
const MCSection *OutputSection =
(isCtor ?
}
}
+void AsmPrinter::EmitModuleIdents(Module &M) {
+ if (!MAI->hasIdentDirective())
+ return;
+
+ if (const NamedMDNode *NMD = M.getNamedMetadata("llvm.ident")) {
+ for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {
+ const MDNode *N = NMD->getOperand(i);
+ assert(N->getNumOperands() == 1 &&
+ "llvm.ident metadata entry can have only one operand");
+ const MDString *S = cast<MDString>(N->getOperand(0));
+ OutStreamer.EmitIdent(S->getString());
+ }
+ }
+}
+
//===--------------------------------------------------------------------===//
// Emission and print routines
//
/// where the size in bytes of the directive is specified by Size and Hi/Lo
/// specify the labels. This implicitly uses .set if it is available.
void AsmPrinter::EmitLabelOffsetDifference(const MCSymbol *Hi, uint64_t Offset,
- const MCSymbol *Lo, unsigned Size)
- const {
+ const MCSymbol *Lo,
+ unsigned Size) const {
// Emit Hi+Offset - Lo
// Get the Hi+Offset expression.
OutContext);
if (!MAI->hasSetDirective())
- OutStreamer.EmitValue(Diff, 4);
+ OutStreamer.EmitValue(Diff, Size);
else {
// Otherwise, emit with .set (aka assignment).
MCSymbol *SetLabel = GetTempSymbol("set", SetCounter++);
OutStreamer.EmitAssignment(SetLabel, Diff);
- OutStreamer.EmitSymbolValue(SetLabel, 4);
+ OutStreamer.EmitSymbolValue(SetLabel, Size);
}
}
/// where the size in bytes of the directive is specified by Size and Label
/// specifies the label. This implicitly uses .set if it is available.
void AsmPrinter::EmitLabelPlusOffset(const MCSymbol *Label, uint64_t Offset,
- unsigned Size)
- const {
+ unsigned Size,
+ bool IsSectionRelative) const {
+ if (MAI->needsDwarfSectionOffsetDirective() && IsSectionRelative) {
+ OutStreamer.EmitCOFFSecRel32(Label);
+ return;
+ }
// Emit Label+Offset (or just Label if Offset is zero)
const MCExpr *Expr = MCSymbolRefExpr::Create(Label, OutContext);
if (Offset)
- Expr = MCBinaryExpr::CreateAdd(Expr,
- MCConstantExpr::Create(Offset, OutContext),
- OutContext);
+ Expr = MCBinaryExpr::CreateAdd(
+ Expr, MCConstantExpr::Create(Offset, OutContext), OutContext);
OutStreamer.EmitValue(Expr, Size);
}
-
//===----------------------------------------------------------------------===//
// EmitAlignment - Emit an alignment directive to the specified power of
if (getCurrentSection()->getKind().isText())
OutStreamer.EmitCodeAlignment(1 << NumBits);
else
- OutStreamer.EmitValueToAlignment(1 << NumBits, 0, 1, 0);
+ OutStreamer.EmitValueToAlignment(1 << NumBits);
}
//===----------------------------------------------------------------------===//
return MCConstantExpr::Create(CI->getZExtValue(), Ctx);
if (const GlobalValue *GV = dyn_cast<GlobalValue>(CV))
- return MCSymbolRefExpr::Create(AP.Mang->getSymbol(GV), Ctx);
+ return MCSymbolRefExpr::Create(AP.getSymbol(GV), Ctx);
if (const BlockAddress *BA = dyn_cast<BlockAddress>(CV))
return MCSymbolRefExpr::Create(AP.GetBlockAddressSymbol(BA), Ctx);
llvm_unreachable("Unknown constant value to lower!");
}
+ if (const MCExpr *RelocExpr =
+ AP.getObjFileLowering().getExecutableRelativeSymbol(CE, *AP.Mang,
+ AP.TM))
+ return RelocExpr;
+
switch (CE->getOpcode()) {
default:
// If the code isn't optimized, there may be outstanding folding
std::string S;
raw_string_ostream OS(S);
OS << "Unsupported expression in static initializer: ";
- WriteAsOperand(OS, CE, /*PrintType=*/false,
+ CE->printAsOperand(OS, /*PrintType=*/false,
!AP.MF ? 0 : AP.MF->getFunction()->getParent());
report_fatal_error(OS.str());
}
case Instruction::GetElementPtr: {
- const DataLayout &TD = *AP.TM.getDataLayout();
+ const DataLayout &DL = *AP.TM.getDataLayout();
// Generate a symbolic expression for the byte address
- APInt OffsetAI(TD.getPointerSizeInBits(), 0);
- cast<GEPOperator>(CE)->accumulateConstantOffset(TD, OffsetAI);
+ APInt OffsetAI(DL.getPointerTypeSizeInBits(CE->getType()), 0);
+ cast<GEPOperator>(CE)->accumulateConstantOffset(DL, OffsetAI);
const MCExpr *Base = lowerConstant(CE->getOperand(0), AP);
if (!OffsetAI)
return lowerConstant(CE->getOperand(0), AP);
case Instruction::IntToPtr: {
- const DataLayout &TD = *AP.TM.getDataLayout();
+ const DataLayout &DL = *AP.TM.getDataLayout();
// Handle casts to pointers by changing them into casts to the appropriate
// integer type. This promotes constant folding and simplifies this code.
Constant *Op = CE->getOperand(0);
- Op = ConstantExpr::getIntegerCast(Op, TD.getIntPtrType(CV->getContext()),
+ Op = ConstantExpr::getIntegerCast(Op, DL.getIntPtrType(CV->getType()),
false/*ZExt*/);
return lowerConstant(Op, AP);
}
case Instruction::PtrToInt: {
- const DataLayout &TD = *AP.TM.getDataLayout();
+ const DataLayout &DL = *AP.TM.getDataLayout();
// Support only foldable casts to/from pointers that can be eliminated by
// changing the pointer to the appropriately sized integer type.
Constant *Op = CE->getOperand(0);
// We can emit the pointer value into this slot if the slot is an
// integer slot equal to the size of the pointer.
- if (TD.getTypeAllocSize(Ty) == TD.getTypeAllocSize(Op->getType()))
+ if (DL.getTypeAllocSize(Ty) == DL.getTypeAllocSize(Op->getType()))
return OpExpr;
// Otherwise the pointer is smaller than the resultant integer, mask off
// the high bits so we are sure to get a proper truncation if the input is
// a constant expr.
- unsigned InBits = TD.getTypeAllocSizeInBits(Op->getType());
+ unsigned InBits = DL.getTypeAllocSizeInBits(Op->getType());
const MCExpr *MaskExpr = MCConstantExpr::Create(~0ULL >> (64-InBits), Ctx);
return MCBinaryExpr::CreateAnd(OpExpr, MaskExpr, Ctx);
}
}
}
-static void emitGlobalConstantImpl(const Constant *C, unsigned AddrSpace,
- AsmPrinter &AP);
+static void emitGlobalConstantImpl(const Constant *C, AsmPrinter &AP);
/// isRepeatedByteSequence - Determine whether the given value is
/// composed of a repeated sequence of identical bytes and return the
}
static void emitGlobalConstantDataSequential(const ConstantDataSequential *CDS,
- unsigned AddrSpace,AsmPrinter &AP){
+ AsmPrinter &AP){
// See if we can aggregate this into a .fill, if so, emit it as such.
int Value = isRepeatedByteSequence(CDS, AP.TM);
uint64_t Bytes = AP.TM.getDataLayout()->getTypeAllocSize(CDS->getType());
// Don't emit a 1-byte object as a .fill.
if (Bytes > 1)
- return AP.OutStreamer.EmitFill(Bytes, Value, AddrSpace);
+ return AP.OutStreamer.EmitFill(Bytes, Value);
}
// If this can be emitted with .ascii/.asciz, emit it as such.
if (CDS->isString())
- return AP.OutStreamer.EmitBytes(CDS->getAsString(), AddrSpace);
+ return AP.OutStreamer.EmitBytes(CDS->getAsString());
// Otherwise, emit the values in successive locations.
unsigned ElementByteSize = CDS->getElementByteSize();
AP.OutStreamer.GetCommentOS() << format("0x%" PRIx64 "\n",
CDS->getElementAsInteger(i));
AP.OutStreamer.EmitIntValue(CDS->getElementAsInteger(i),
- ElementByteSize, AddrSpace);
+ ElementByteSize);
}
} else if (ElementByteSize == 4) {
// FP Constants are printed as integer constants to avoid losing
F = CDS->getElementAsFloat(i);
if (AP.isVerbose())
AP.OutStreamer.GetCommentOS() << "float " << F << '\n';
- AP.OutStreamer.EmitIntValue(I, 4, AddrSpace);
+ AP.OutStreamer.EmitIntValue(I, 4);
}
} else {
assert(CDS->getElementType()->isDoubleTy());
F = CDS->getElementAsDouble(i);
if (AP.isVerbose())
AP.OutStreamer.GetCommentOS() << "double " << F << '\n';
- AP.OutStreamer.EmitIntValue(I, 8, AddrSpace);
+ AP.OutStreamer.EmitIntValue(I, 8);
}
}
- const DataLayout &TD = *AP.TM.getDataLayout();
- unsigned Size = TD.getTypeAllocSize(CDS->getType());
- unsigned EmittedSize = TD.getTypeAllocSize(CDS->getType()->getElementType()) *
+ const DataLayout &DL = *AP.TM.getDataLayout();
+ unsigned Size = DL.getTypeAllocSize(CDS->getType());
+ unsigned EmittedSize = DL.getTypeAllocSize(CDS->getType()->getElementType()) *
CDS->getNumElements();
if (unsigned Padding = Size - EmittedSize)
- AP.OutStreamer.EmitZeros(Padding, AddrSpace);
+ AP.OutStreamer.EmitZeros(Padding);
}
-static void emitGlobalConstantArray(const ConstantArray *CA, unsigned AddrSpace,
- AsmPrinter &AP) {
+static void emitGlobalConstantArray(const ConstantArray *CA, AsmPrinter &AP) {
// See if we can aggregate some values. Make sure it can be
// represented as a series of bytes of the constant value.
int Value = isRepeatedByteSequence(CA, AP.TM);
if (Value != -1) {
uint64_t Bytes = AP.TM.getDataLayout()->getTypeAllocSize(CA->getType());
- AP.OutStreamer.EmitFill(Bytes, Value, AddrSpace);
+ AP.OutStreamer.EmitFill(Bytes, Value);
}
else {
for (unsigned i = 0, e = CA->getNumOperands(); i != e; ++i)
- emitGlobalConstantImpl(CA->getOperand(i), AddrSpace, AP);
+ emitGlobalConstantImpl(CA->getOperand(i), AP);
}
}
-static void emitGlobalConstantVector(const ConstantVector *CV,
- unsigned AddrSpace, AsmPrinter &AP) {
+static void emitGlobalConstantVector(const ConstantVector *CV, AsmPrinter &AP) {
for (unsigned i = 0, e = CV->getType()->getNumElements(); i != e; ++i)
- emitGlobalConstantImpl(CV->getOperand(i), AddrSpace, AP);
+ emitGlobalConstantImpl(CV->getOperand(i), AP);
- const DataLayout &TD = *AP.TM.getDataLayout();
- unsigned Size = TD.getTypeAllocSize(CV->getType());
- unsigned EmittedSize = TD.getTypeAllocSize(CV->getType()->getElementType()) *
+ const DataLayout &DL = *AP.TM.getDataLayout();
+ unsigned Size = DL.getTypeAllocSize(CV->getType());
+ unsigned EmittedSize = DL.getTypeAllocSize(CV->getType()->getElementType()) *
CV->getType()->getNumElements();
if (unsigned Padding = Size - EmittedSize)
- AP.OutStreamer.EmitZeros(Padding, AddrSpace);
+ AP.OutStreamer.EmitZeros(Padding);
}
-static void emitGlobalConstantStruct(const ConstantStruct *CS,
- unsigned AddrSpace, AsmPrinter &AP) {
+static void emitGlobalConstantStruct(const ConstantStruct *CS, AsmPrinter &AP) {
// Print the fields in successive locations. Pad to align if needed!
- const DataLayout *TD = AP.TM.getDataLayout();
- unsigned Size = TD->getTypeAllocSize(CS->getType());
- const StructLayout *Layout = TD->getStructLayout(CS->getType());
+ const DataLayout *DL = AP.TM.getDataLayout();
+ unsigned Size = DL->getTypeAllocSize(CS->getType());
+ const StructLayout *Layout = DL->getStructLayout(CS->getType());
uint64_t SizeSoFar = 0;
for (unsigned i = 0, e = CS->getNumOperands(); i != e; ++i) {
const Constant *Field = CS->getOperand(i);
// Check if padding is needed and insert one or more 0s.
- uint64_t FieldSize = TD->getTypeAllocSize(Field->getType());
+ uint64_t FieldSize = DL->getTypeAllocSize(Field->getType());
uint64_t PadSize = ((i == e-1 ? Size : Layout->getElementOffset(i+1))
- Layout->getElementOffset(i)) - FieldSize;
SizeSoFar += FieldSize + PadSize;
// Now print the actual field value.
- emitGlobalConstantImpl(Field, AddrSpace, AP);
+ emitGlobalConstantImpl(Field, AP);
// Insert padding - this may include padding to increase the size of the
// current field up to the ABI size (if the struct is not packed) as well
// as padding to ensure that the next field starts at the right offset.
- AP.OutStreamer.EmitZeros(PadSize, AddrSpace);
+ AP.OutStreamer.EmitZeros(PadSize);
}
assert(SizeSoFar == Layout->getSizeInBytes() &&
"Layout of constant struct may be incorrect!");
}
-static void emitGlobalConstantFP(const ConstantFP *CFP, unsigned AddrSpace,
- AsmPrinter &AP) {
+static void emitGlobalConstantFP(const ConstantFP *CFP, AsmPrinter &AP) {
APInt API = CFP->getValueAPF().bitcastToAPInt();
// First print a comment with what we think the original floating-point value
int Chunk = API.getNumWords() - 1;
if (TrailingBytes)
- AP.OutStreamer.EmitIntValue(p[Chunk--], TrailingBytes, AddrSpace);
+ AP.OutStreamer.EmitIntValue(p[Chunk--], TrailingBytes);
for (; Chunk >= 0; --Chunk)
- AP.OutStreamer.EmitIntValue(p[Chunk], sizeof(uint64_t), AddrSpace);
+ AP.OutStreamer.EmitIntValue(p[Chunk], sizeof(uint64_t));
} else {
unsigned Chunk;
for (Chunk = 0; Chunk < NumBytes / sizeof(uint64_t); ++Chunk)
- AP.OutStreamer.EmitIntValue(p[Chunk], sizeof(uint64_t), AddrSpace);
+ AP.OutStreamer.EmitIntValue(p[Chunk], sizeof(uint64_t));
if (TrailingBytes)
- AP.OutStreamer.EmitIntValue(p[Chunk], TrailingBytes, AddrSpace);
+ AP.OutStreamer.EmitIntValue(p[Chunk], TrailingBytes);
}
// Emit the tail padding for the long double.
- const DataLayout &TD = *AP.TM.getDataLayout();
- AP.OutStreamer.EmitZeros(TD.getTypeAllocSize(CFP->getType()) -
- TD.getTypeStoreSize(CFP->getType()), AddrSpace);
+ const DataLayout &DL = *AP.TM.getDataLayout();
+ AP.OutStreamer.EmitZeros(DL.getTypeAllocSize(CFP->getType()) -
+ DL.getTypeStoreSize(CFP->getType()));
}
-static void emitGlobalConstantLargeInt(const ConstantInt *CI,
- unsigned AddrSpace, AsmPrinter &AP) {
- const DataLayout *TD = AP.TM.getDataLayout();
+static void emitGlobalConstantLargeInt(const ConstantInt *CI, AsmPrinter &AP) {
+ const DataLayout *DL = AP.TM.getDataLayout();
unsigned BitWidth = CI->getBitWidth();
// Copy the value as we may massage the layout for constants whose bit width
// Big endian:
// * Record the extra bits to emit.
// * Realign the raw data to emit the chunks of 64-bits.
- if (TD->isBigEndian()) {
+ if (DL->isBigEndian()) {
// Basically the structure of the raw data is a chunk of 64-bits cells:
// 0 1 BitWidth / 64
// [chunk1][chunk2] ... [chunkN].
// quantities at a time.
const uint64_t *RawData = Realigned.getRawData();
for (unsigned i = 0, e = BitWidth / 64; i != e; ++i) {
- uint64_t Val = TD->isBigEndian() ? RawData[e - i - 1] : RawData[i];
- AP.OutStreamer.EmitIntValue(Val, 8, AddrSpace);
+ uint64_t Val = DL->isBigEndian() ? RawData[e - i - 1] : RawData[i];
+ AP.OutStreamer.EmitIntValue(Val, 8);
}
if (ExtraBitsSize) {
assert(Size && Size * 8 >= ExtraBitsSize &&
(ExtraBits & (((uint64_t)-1) >> (64 - ExtraBitsSize)))
== ExtraBits && "Directive too small for extra bits.");
- AP.OutStreamer.EmitIntValue(ExtraBits, Size, AddrSpace);
+ AP.OutStreamer.EmitIntValue(ExtraBits, Size);
}
}
-static void emitGlobalConstantImpl(const Constant *CV, unsigned AddrSpace,
- AsmPrinter &AP) {
- const DataLayout *TD = AP.TM.getDataLayout();
- uint64_t Size = TD->getTypeAllocSize(CV->getType());
+static void emitGlobalConstantImpl(const Constant *CV, AsmPrinter &AP) {
+ const DataLayout *DL = AP.TM.getDataLayout();
+ uint64_t Size = DL->getTypeAllocSize(CV->getType());
if (isa<ConstantAggregateZero>(CV) || isa<UndefValue>(CV))
- return AP.OutStreamer.EmitZeros(Size, AddrSpace);
+ return AP.OutStreamer.EmitZeros(Size);
if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) {
switch (Size) {
if (AP.isVerbose())
AP.OutStreamer.GetCommentOS() << format("0x%" PRIx64 "\n",
CI->getZExtValue());
- AP.OutStreamer.EmitIntValue(CI->getZExtValue(), Size, AddrSpace);
+ AP.OutStreamer.EmitIntValue(CI->getZExtValue(), Size);
return;
default:
- emitGlobalConstantLargeInt(CI, AddrSpace, AP);
+ emitGlobalConstantLargeInt(CI, AP);
return;
}
}
if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV))
- return emitGlobalConstantFP(CFP, AddrSpace, AP);
+ return emitGlobalConstantFP(CFP, AP);
if (isa<ConstantPointerNull>(CV)) {
- AP.OutStreamer.EmitIntValue(0, Size, AddrSpace);
+ AP.OutStreamer.EmitIntValue(0, Size);
return;
}
if (const ConstantDataSequential *CDS = dyn_cast<ConstantDataSequential>(CV))
- return emitGlobalConstantDataSequential(CDS, AddrSpace, AP);
+ return emitGlobalConstantDataSequential(CDS, AP);
if (const ConstantArray *CVA = dyn_cast<ConstantArray>(CV))
- return emitGlobalConstantArray(CVA, AddrSpace, AP);
+ return emitGlobalConstantArray(CVA, AP);
if (const ConstantStruct *CVS = dyn_cast<ConstantStruct>(CV))
- return emitGlobalConstantStruct(CVS, AddrSpace, AP);
+ return emitGlobalConstantStruct(CVS, AP);
if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) {
// Look through bitcasts, which might not be able to be MCExpr'ized (e.g. of
// vectors).
if (CE->getOpcode() == Instruction::BitCast)
- return emitGlobalConstantImpl(CE->getOperand(0), AddrSpace, AP);
+ return emitGlobalConstantImpl(CE->getOperand(0), AP);
if (Size > 8) {
// If the constant expression's size is greater than 64-bits, then we have
// to emit the value in chunks. Try to constant fold the value and emit it
// that way.
- Constant *New = ConstantFoldConstantExpression(CE, TD);
+ Constant *New = ConstantFoldConstantExpression(CE, DL);
if (New && New != CE)
- return emitGlobalConstantImpl(New, AddrSpace, AP);
+ return emitGlobalConstantImpl(New, AP);
}
}
if (const ConstantVector *V = dyn_cast<ConstantVector>(CV))
- return emitGlobalConstantVector(V, AddrSpace, AP);
+ return emitGlobalConstantVector(V, AP);
// Otherwise, it must be a ConstantExpr. Lower it to an MCExpr, then emit it
// thread the streamer with EmitValue.
- AP.OutStreamer.EmitValue(lowerConstant(CV, AP), Size, AddrSpace);
+ AP.OutStreamer.EmitValue(lowerConstant(CV, AP), Size);
}
/// EmitGlobalConstant - Print a general LLVM constant to the .s file.
-void AsmPrinter::EmitGlobalConstant(const Constant *CV, unsigned AddrSpace) {
+void AsmPrinter::EmitGlobalConstant(const Constant *CV) {
uint64_t Size = TM.getDataLayout()->getTypeAllocSize(CV->getType());
if (Size)
- emitGlobalConstantImpl(CV, AddrSpace, *this);
+ emitGlobalConstantImpl(CV, *this);
else if (MAI->hasSubsectionsViaSymbols()) {
// If the global has zero size, emit a single byte so that two labels don't
// look like they are at the same location.
- OutStreamer.EmitIntValue(0, 1, AddrSpace);
+ OutStreamer.EmitIntValue(0, 1);
}
}
/// GetTempSymbol - Return the MCSymbol corresponding to the assembler
/// temporary label with the specified stem and unique ID.
MCSymbol *AsmPrinter::GetTempSymbol(StringRef Name, unsigned ID) const {
- return OutContext.GetOrCreateSymbol(Twine(MAI->getPrivateGlobalPrefix()) +
+ const DataLayout *DL = TM.getDataLayout();
+ return OutContext.GetOrCreateSymbol(Twine(DL->getPrivateGlobalPrefix()) +
Name + Twine(ID));
}
/// GetTempSymbol - Return an assembler temporary label with the specified
/// stem.
MCSymbol *AsmPrinter::GetTempSymbol(StringRef Name) const {
- return OutContext.GetOrCreateSymbol(Twine(MAI->getPrivateGlobalPrefix())+
+ const DataLayout *DL = TM.getDataLayout();
+ return OutContext.GetOrCreateSymbol(Twine(DL->getPrivateGlobalPrefix())+
Name);
}
/// GetCPISymbol - Return the symbol for the specified constant pool entry.
MCSymbol *AsmPrinter::GetCPISymbol(unsigned CPID) const {
+ const DataLayout *DL = TM.getDataLayout();
return OutContext.GetOrCreateSymbol
- (Twine(MAI->getPrivateGlobalPrefix()) + "CPI" + Twine(getFunctionNumber())
+ (Twine(DL->getPrivateGlobalPrefix()) + "CPI" + Twine(getFunctionNumber())
+ "_" + Twine(CPID));
}
/// GetJTSetSymbol - Return the symbol for the specified jump table .set
/// FIXME: privatize to AsmPrinter.
MCSymbol *AsmPrinter::GetJTSetSymbol(unsigned UID, unsigned MBBID) const {
+ const DataLayout *DL = TM.getDataLayout();
return OutContext.GetOrCreateSymbol
- (Twine(MAI->getPrivateGlobalPrefix()) + Twine(getFunctionNumber()) + "_" +
+ (Twine(DL->getPrivateGlobalPrefix()) + Twine(getFunctionNumber()) + "_" +
Twine(UID) + "_set_" + Twine(MBBID));
}
-/// GetSymbolWithGlobalValueBase - Return the MCSymbol for a symbol with
-/// global value name as its base, with the specified suffix, and where the
-/// symbol is forced to have private linkage if ForcePrivate is true.
-MCSymbol *AsmPrinter::GetSymbolWithGlobalValueBase(const GlobalValue *GV,
- StringRef Suffix,
- bool ForcePrivate) const {
- SmallString<60> NameStr;
- Mang->getNameWithPrefix(NameStr, GV, ForcePrivate);
- NameStr.append(Suffix.begin(), Suffix.end());
- return OutContext.GetOrCreateSymbol(NameStr.str());
+MCSymbol *AsmPrinter::getSymbolWithGlobalValueBase(const GlobalValue *GV,
+ StringRef Suffix) const {
+ return getObjFileLowering().getSymbolWithGlobalValueBase(GV, Suffix, *Mang,
+ TM);
}
/// GetExternalSymbolSymbol - Return the MCSymbol for the specified
// Print the main label for the block.
if (MBB->pred_empty() || isBlockOnlyReachableByFallthrough(MBB)) {
- if (isVerbose() && OutStreamer.hasRawTextSupport()) {
+ if (isVerbose()) {
// NOTE: Want this comment at start of line, don't emit with AddComment.
- OutStreamer.EmitRawText(Twine(MAI->getCommentString()) + " BB#" +
- Twine(MBB->getNumber()) + ":");
+ OutStreamer.emitRawComment(" BB#" + Twine(MBB->getNumber()) + ":", false);
}
} else {
OutStreamer.EmitLabel(MBB->getSymbol());
if (!MI.isBranch() || MI.isIndirectBranch())
return false;
- // If we are the operands of one of the branches, this is not
- // a fall through.
- for (MachineInstr::mop_iterator OI = MI.operands_begin(),
- OE = MI.operands_end(); OI != OE; ++OI) {
- const MachineOperand& OP = *OI;
- if (OP.isJTI())
+ // If we are the operands of one of the branches, this is not a fall
+ // through. Note that targets with delay slots will usually bundle
+ // terminators with the delay slot instruction.
+ for (ConstMIBundleOperands OP(&MI); OP.isValid(); ++OP) {
+ if (OP->isJTI())
return false;
- if (OP.isMBB() && OP.getMBB() == MBB)
+ if (OP->isMBB() && OP->getMBB() == MBB)
return false;
}
}
report_fatal_error("no GCMetadataPrinter registered for GC: " + Twine(Name));
}
+
+/// Pin vtable to this file.
+AsmPrinterHandler::~AsmPrinterHandler() {}