index 7422988e74a43c0ddd1e9f176b6b0a7b5c08da50..c0f36860a80a7920ed9a048aafd6cba32eacc8bf 100644 (file)
#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/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"
+#include "WinCodeViewLineTables.h"
using namespace llvm;
static const char *const DWARFGroupName = "DWARF Emission";
-static const char *const DbgTimerName = "DWARF Debug Writer";
+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");
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();
}
const_cast<TargetLoweringObjectFile&>(getObjFileLowering())
.Initialize(OutContext, TM);
- OutStreamer.InitStreamer();
+ OutStreamer.InitSections(false);
- Mang = new Mangler(&TM);
+ Mang = new Mangler(TM.getDataLayout());
// Allow the target to emit any magic that it wants at the start of the file.
EmitStartOfAsmFile(M);
}
if (MAI->doesSupportDebugInformation()) {
- DD = new DwarfDebug(this, &M);
- Handlers.push_back(HandlerInfo(DD, DbgTimerName, DWARFGroupName));
+ 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;
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;
+ }
+
+ GlobalStatus GS;
+ if (!GlobalStatus::analyzeGlobal(GV, GS) && !GS.IsCompared)
+ return true;
+
+ return false;
+}
+
void AsmPrinter::EmitLinkage(const GlobalValue *GV, MCSymbol *GVSym) const {
GlobalValue::LinkageTypes Linkage = GV->getLinkage();
switch (Linkage) {
// .globl _foo
OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Global);
- bool CanBeHidden = false;
-
- if (Linkage == GlobalValue::LinkOnceODRLinkage) {
- if (GV->hasUnnamedAddr()) {
- CanBeHidden = true;
- } else {
- GlobalStatus GS;
- if (!GlobalStatus::analyzeGlobal(GV, GS) && !GS.IsCompared)
- CanBeHidden = true;
- }
- }
-
- if (!CanBeHidden)
+ if (!canBeHidden(GV, *MAI))
// .weak_definition _foo
OutStreamer.EmitSymbolAttribute(GVSym, MCSA_WeakDefinition);
else
OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Weak);
}
return;
- 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.
return;
case GlobalValue::AvailableExternallyLinkage:
llvm_unreachable("Should never emit this");
- case GlobalValue::DLLImportLinkage:
case GlobalValue::ExternalWeakLinkage:
llvm_unreachable("Don't know how to emit these");
}
}
MCSymbol *AsmPrinter::getSymbol(const GlobalValue *GV) const {
- return getObjFileLowering().getSymbol(*Mang, GV);
+ return getObjFileLowering().getSymbol(GV, *Mang);
}
/// EmitGlobalVariable - Emit the specified global variable to the .s file.
return;
if (isVerbose()) {
- WriteAsOperand(OutStreamer.GetCommentOS(), GV,
+ GV->printAsOperand(OutStreamer.GetCommentOS(),
/*PrintType=*/false, GV->getParent());
OutStreamer.GetCommentOS() << '\n';
}
// 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.
// 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, CurrentFnSym);
OutStreamer.EmitSymbolAttribute(CurrentFnSym, MCSA_ELF_TypeFunction);
if (isVerbose()) {
- WriteAsOperand(OutStreamer.GetCommentOS(), F,
+ F->printAsOperand(OutStreamer.GetCommentOS(),
/*PrintType=*/false, F->getParent());
OutStreamer.GetCommentOS() << '\n';
}
SmallString<128> Str;
raw_svector_ostream OS(Str);
- OS << '\t' << AP.MAI->getCommentString() << "DEBUG_VALUE: ";
+ OS << "DEBUG_VALUE: ";
DIVariable V(MI->getOperand(2).getMetadata());
if (V.getContext().isSubprogram()) {
// 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 << '+' << 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) {
const MCSymbol *Label = MI.getOperand(0).getMCSymbol();
if (isVerbose()) emitKill(II, *this);
break;
default:
- if (!TM.hasMCUseLoc())
- MCLineEntry::Make(&OutStreamer, getCurrentSection());
-
EmitInstruction(II);
break;
}
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"));
}
bool Indirect) const {
const TargetRegisterInfo *TRI = TM.getRegisterInfo();
int Reg = TRI->getDwarfRegNum(MLoc.getReg(), false);
+ bool isSubRegister = Reg < 0;
+ unsigned Idx = 0;
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
+ if (Reg >= 0)
+ Idx = TRI->getSubRegIndex(*SR, MLoc.getReg());
}
// FIXME: Handle cases like a super register being encoded as
}
}
- // FIXME: Produce a DW_OP_bit_piece if we used a superregister
+ // Emit Mask
+ if (isSubRegister) {
+ unsigned Size = TRI->getSubRegIdxSize(Idx);
+ unsigned Offset = TRI->getSubRegIdxOffset(Idx);
+ if (Offset > 0) {
+ OutStreamer.AddComment("DW_OP_bit_piece");
+ EmitInt8(dwarf::DW_OP_bit_piece);
+ OutStreamer.AddComment(Twine(Size));
+ EmitULEB128(Size);
+ OutStreamer.AddComment(Twine(Offset));
+ EmitULEB128(Offset);
+ } else {
+ OutStreamer.AddComment("DW_OP_piece");
+ EmitInt8(dwarf::DW_OP_piece);
+ OutStreamer.AddComment(Twine(Size));
+ EmitULEB128(Size);
+ }
+ }
}
bool AsmPrinter::doFinalization(Module &M) {
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();
/// 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))
+ if (GV && getObjFileLowering().shouldEmitUsedDirectiveFor(GV, *Mang))
OutStreamer.EmitSymbolAttribute(getSymbol(GV), MCSA_NoDeadStrip);
}
}
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 &&
+ 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());
@@ -1487,7 +1535,7 @@ void AsmPrinter::EmitAlignment(unsigned NumBits, const GlobalValue *GV) const {
if (getCurrentSection()->getKind().isText())
OutStreamer.EmitCodeAlignment(1 << NumBits);
else
- OutStreamer.EmitValueToAlignment(1 << NumBits, 0, 1, 0);
+ OutStreamer.EmitValueToAlignment(1 << NumBits);
}
//===----------------------------------------------------------------------===//
llvm_unreachable("Unknown constant value to lower!");
}
+ if (const MCExpr *RelocExpr =
+ AP.getObjFileLowering().getExecutableRelativeSymbol(CE, *AP.Mang))
+ 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());
}
/// 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));
}
@@ -2031,14 +2086,15 @@ MCSymbol *AsmPrinter::GetJTISymbol(unsigned JTID, bool isLinkerPrivate) const {
/// 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));
}
MCSymbol *AsmPrinter::getSymbolWithGlobalValueBase(const GlobalValue *GV,
StringRef Suffix) const {
- return getObjFileLowering().getSymbolWithGlobalValueBase(*Mang, GV, Suffix);
+ return getObjFileLowering().getSymbolWithGlobalValueBase(GV, Suffix, *Mang);
}
/// 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() {}