diff --git a/llvm/include/llvm/MC/MCDwarf.h b/llvm/include/llvm/MC/MCDwarf.h index 6bcb751a2d10..425535d36489 100644 --- a/llvm/include/llvm/MC/MCDwarf.h +++ b/llvm/include/llvm/MC/MCDwarf.h @@ -167,7 +167,7 @@ namespace llvm { // This is called when an instruction is assembled into the specified // section and if there is information from the last .loc directive that // has yet to have a line entry made for it is made. - static void Make(MCObjectStreamer *MCOS, const MCSection *Section); + static void Make(MCStreamer *MCOS, const MCSection *Section); }; /// MCLineSection - Instances of this class represent the line information @@ -205,7 +205,8 @@ namespace llvm { // // This emits the Dwarf file and the line tables. // - static void Emit(MCObjectStreamer *MCOS, const MCSection *DwarfLineSection); + static void Emit(MCStreamer *MCOS, const MCSection *DwarfLineSection, + MCSectionData *DLS, int PointerSize); }; class MCDwarfLineAddr { @@ -214,7 +215,7 @@ namespace llvm { static void Encode(int64_t LineDelta, uint64_t AddrDelta, raw_ostream &OS); /// Utility function to emit the encoding to a streamer. - static void Emit(MCObjectStreamer *MCOS, + static void Emit(MCStreamer *MCOS, int64_t LineDelta,uint64_t AddrDelta); /// Utility function to compute the size of the encoding. diff --git a/llvm/include/llvm/MC/MCStreamer.h b/llvm/include/llvm/MC/MCStreamer.h index 2505d4d53a97..55dc6f102b6b 100644 --- a/llvm/include/llvm/MC/MCStreamer.h +++ b/llvm/include/llvm/MC/MCStreamer.h @@ -28,6 +28,7 @@ namespace llvm { class MCSymbol; class StringRef; class TargetAsmBackend; + class TargetLoweringObjectFile; class Twine; class raw_ostream; class formatted_raw_ostream; @@ -388,6 +389,14 @@ namespace llvm { MCCodeEmitter *CE = 0, bool ShowInst = false); + MCStreamer *createAsmStreamerNoLoc(MCContext &Ctx, formatted_raw_ostream &OS, + bool isLittleEndian, bool isVerboseAsm, + const TargetLoweringObjectFile *TLOF, + int PointerSize, + MCInstPrinter *InstPrint = 0, + MCCodeEmitter *CE = 0, + bool ShowInst = false); + /// createMachOStreamer - Create a machine code streamer which will generate /// Mach-O format object files. /// diff --git a/llvm/include/llvm/Target/TargetMachine.h b/llvm/include/llvm/Target/TargetMachine.h index 01dc1b0c4149..11d2a142579e 100644 --- a/llvm/include/llvm/Target/TargetMachine.h +++ b/llvm/include/llvm/Target/TargetMachine.h @@ -104,6 +104,7 @@ protected: // Can only create subclasses. const MCAsmInfo *AsmInfo; unsigned MCRelaxAll : 1; + unsigned MCUseLoc : 1; public: virtual ~TargetMachine(); @@ -169,6 +170,12 @@ public: /// relaxed. void setMCRelaxAll(bool Value) { MCRelaxAll = Value; } + /// hasMCUseLoc - Check whether we should use dwarf's .loc directive. + bool hasMCUseLoc() const { return MCUseLoc; } + + /// setMCUseLoc - Set whether all we should use dwarf's .loc directive. + void setMCUseLoc(bool Value) { MCUseLoc = Value; } + /// getRelocationModel - Returns the code generation relocation model. The /// choices are static, PIC, and dynamic-no-pic, and target default. static Reloc::Model getRelocationModel(); diff --git a/llvm/lib/CodeGen/LLVMTargetMachine.cpp b/llvm/lib/CodeGen/LLVMTargetMachine.cpp index 0abbe72e9b3a..5954f62da954 100644 --- a/llvm/lib/CodeGen/LLVMTargetMachine.cpp +++ b/llvm/lib/CodeGen/LLVMTargetMachine.cpp @@ -20,6 +20,7 @@ #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/GCStrategy.h" #include "llvm/CodeGen/Passes.h" +#include "llvm/Target/TargetLowering.h" #include "llvm/Target/TargetOptions.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCStreamer.h" @@ -144,11 +145,28 @@ bool LLVMTargetMachine::addPassesToEmitFile(PassManagerBase &PM, if (ShowMCEncoding) MCE = getTarget().createCodeEmitter(*this, *Context); - AsmStreamer.reset(getTarget().createAsmStreamer(*Context, Out, - getTargetData()->isLittleEndian(), - getVerboseAsm(), - InstPrinter, MCE, - ShowMCInst)); + const TargetLoweringObjectFile &TLOF = + getTargetLowering()->getObjFileLowering(); + int PointerSize = getTargetData()->getPointerSize(); + + MCStreamer *S; + if (hasMCUseLoc()) + S = getTarget().createAsmStreamer(*Context, Out, + getTargetData()->isLittleEndian(), + getVerboseAsm(), + InstPrinter, + MCE, + ShowMCInst); + else + S = createAsmStreamerNoLoc(*Context, Out, + getTargetData()->isLittleEndian(), + getVerboseAsm(), + &TLOF, + PointerSize, + InstPrinter, + MCE, + ShowMCInst); + AsmStreamer.reset(S); break; } case CGFT_ObjectFile: { diff --git a/llvm/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp index a9cf4b163dd6..b3c47367056d 100644 --- a/llvm/lib/MC/MCAsmStreamer.cpp +++ b/llvm/lib/MC/MCAsmStreamer.cpp @@ -23,6 +23,7 @@ #include "llvm/Support/MathExtras.h" #include "llvm/Support/Format.h" #include "llvm/Support/FormattedStream.h" +#include "llvm/Target/TargetLoweringObjectFile.h" using namespace llvm; namespace { @@ -36,16 +37,21 @@ class MCAsmStreamer : public MCStreamer { SmallString<128> CommentToEmit; raw_svector_ostream CommentStream; + const TargetLoweringObjectFile *TLOF; + int PointerSize; + unsigned IsLittleEndian : 1; unsigned IsVerboseAsm : 1; unsigned ShowInst : 1; public: MCAsmStreamer(MCContext &Context, formatted_raw_ostream &os, - bool isLittleEndian, bool isVerboseAsm, MCInstPrinter *printer, - MCCodeEmitter *emitter, bool showInst) + bool isLittleEndian, bool isVerboseAsm, + const TargetLoweringObjectFile *tlof, int pointerSize, + MCInstPrinter *printer, MCCodeEmitter *emitter, bool showInst) : MCStreamer(Context), OS(os), MAI(Context.getAsmInfo()), InstPrinter(printer), Emitter(emitter), CommentStream(CommentToEmit), + TLOF(tlof), PointerSize(pointerSize), IsLittleEndian(isLittleEndian), IsVerboseAsm(isVerboseAsm), ShowInst(showInst) { if (InstPrinter && IsVerboseAsm) @@ -637,9 +643,11 @@ void MCAsmStreamer::EmitFileDirective(StringRef Filename) { } bool MCAsmStreamer::EmitDwarfFileDirective(unsigned FileNo, StringRef Filename){ - OS << "\t.file\t" << FileNo << ' '; - PrintQuotedString(Filename, OS); - EmitEOL(); + if (!TLOF) { + OS << "\t.file\t" << FileNo << ' '; + PrintQuotedString(Filename, OS); + EmitEOL(); + } return this->MCStreamer::EmitDwarfFileDirective(FileNo, Filename); } @@ -647,6 +655,11 @@ void MCAsmStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line, unsigned Column, unsigned Flags, unsigned Isa, unsigned Discriminator) { + this->MCStreamer::EmitDwarfLocDirective(FileNo, Line, Column, Flags, + Isa, Discriminator); + if (TLOF) + return; + OS << "\t.loc\t" << FileNo << " " << Line << " " << Column; if (Flags & DWARF2_FLAG_BASIC_BLOCK) OS << " basic_block"; @@ -670,8 +683,6 @@ void MCAsmStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line, if (Discriminator) OS << "discriminator " << Discriminator; EmitEOL(); - return this->MCStreamer::EmitDwarfLocDirective(FileNo, Line, Column, Flags, - Isa, Discriminator); } void MCAsmStreamer::AddEncodingComment(const MCInst &Inst) { @@ -755,6 +766,9 @@ void MCAsmStreamer::AddEncodingComment(const MCInst &Inst) { void MCAsmStreamer::EmitInstruction(const MCInst &Inst) { assert(CurSection && "Cannot emit contents before setting section!"); + if (TLOF) + MCLineEntry::Make(this, getCurrentSection()); + // Show the encoding in a comment if we have a code emitter. if (Emitter) AddEncodingComment(Inst); @@ -784,6 +798,11 @@ void MCAsmStreamer::EmitRawText(StringRef String) { } void MCAsmStreamer::Finish() { + // Dump out the dwarf file & directory tables and line tables. + if (getContext().hasDwarfFiles() && TLOF) { + MCDwarfFileTable::Emit(this, TLOF->getDwarfLineSection(), NULL, + PointerSize); + } } MCStreamer *llvm::createAsmStreamer(MCContext &Context, @@ -792,5 +811,18 @@ MCStreamer *llvm::createAsmStreamer(MCContext &Context, bool isVerboseAsm, MCInstPrinter *IP, MCCodeEmitter *CE, bool ShowInst) { return new MCAsmStreamer(Context, OS, isLittleEndian, isVerboseAsm, - IP, CE, ShowInst); + NULL, 0, IP, CE, ShowInst); +} + + +MCStreamer *llvm::createAsmStreamerNoLoc(MCContext &Context, + formatted_raw_ostream &OS, + bool isLittleEndian, + bool isVerboseAsm, + const TargetLoweringObjectFile *TLOF, + int PointerSize, + MCInstPrinter *IP, + MCCodeEmitter *CE, bool ShowInst) { + return new MCAsmStreamer(Context, OS, isLittleEndian, isVerboseAsm, + TLOF, PointerSize, IP, CE, ShowInst); } diff --git a/llvm/lib/MC/MCDwarf.cpp b/llvm/lib/MC/MCDwarf.cpp index 679f4eeec1f9..1462d5740283 100644 --- a/llvm/lib/MC/MCDwarf.cpp +++ b/llvm/lib/MC/MCDwarf.cpp @@ -60,7 +60,7 @@ static inline uint64_t ScaleAddrDelta(uint64_t AddrDelta) // and if there is information from the last .loc directive that has yet to have // a line entry made for it is made. // -void MCLineEntry::Make(MCObjectStreamer *MCOS, const MCSection *Section) { +void MCLineEntry::Make(MCStreamer *MCOS, const MCSection *Section) { if (!MCOS->getContext().getDwarfLocSeen()) return; @@ -99,7 +99,7 @@ void MCLineEntry::Make(MCObjectStreamer *MCOS, const MCSection *Section) { // // This helper routine returns an expression of End - Start + IntVal . // -static inline const MCExpr *MakeStartMinusEndExpr(MCObjectStreamer *MCOS, +static inline const MCExpr *MakeStartMinusEndExpr(MCStreamer *MCOS, MCSymbol *Start, MCSymbol *End, int IntVal) { MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None; @@ -120,33 +120,33 @@ static inline const MCExpr *MakeStartMinusEndExpr(MCObjectStreamer *MCOS, // This emits an "absolute" address used in the start of a dwarf line number // table. This will result in a relocatation entry for the address. // -static inline void EmitDwarfSetAddress(MCObjectStreamer *MCOS, - MCSymbol *Symbol) { +static inline void EmitDwarfSetAddress(MCStreamer *MCOS, + MCSymbol *Symbol, + int PointerSize) { MCOS->EmitIntValue(dwarf::DW_LNS_extended_op, 1); - int sizeof_address = MCOS->getAssembler().getBackend().getPointerSize(); - MCOS->EmitULEB128IntValue(sizeof_address + 1); + MCOS->EmitULEB128IntValue(PointerSize + 1); MCOS->EmitIntValue(dwarf::DW_LNE_set_address, 1); - MCOS->EmitSymbolValue(Symbol, sizeof_address); + MCOS->EmitSymbolValue(Symbol, PointerSize); } // // This emits the Dwarf line table for the specified section from the entries // in the LineSection. // -static inline void EmitDwarfLineTable(MCObjectStreamer *MCOS, +static inline void EmitDwarfLineTable(MCStreamer *MCOS, const MCSection *Section, MCLineSection *LineSection, - const MCSection *DwarfLineSection) { + const MCSection *DwarfLineSection, + MCSectionData *DLS, + int PointerSize) { unsigned FileNum = 1; unsigned LastLine = 1; unsigned Column = 0; unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0; unsigned Isa = 0; MCSymbol *LastLabel = NULL; - MCSectionData &DLS = - MCOS->getAssembler().getOrCreateSectionData(*DwarfLineSection); // Loop through each MCLineEntry and encode the dwarf line number table. for (MCLineSection::iterator @@ -185,9 +185,9 @@ static inline void EmitDwarfLineTable(MCObjectStreamer *MCOS, // At this point we want to emit/create the sequence to encode the delta in // line numbers and the increment of the address from the previous Label // and the current Label. - if (LastLabel == NULL) { + if (LastLabel == NULL || DLS == NULL) { // emit the sequence to set the address - EmitDwarfSetAddress(MCOS, Label); + EmitDwarfSetAddress(MCOS, Label, PointerSize); // emit the sequence for the LineDelta (from 1) and a zero address delta. MCDwarfLineAddr::Emit(MCOS, LineDelta, 0); } @@ -196,7 +196,7 @@ static inline void EmitDwarfLineTable(MCObjectStreamer *MCOS, // this Label (plus 0). const MCExpr *AddrDelta = MakeStartMinusEndExpr(MCOS, LastLabel, Label,0); // Create a Dwarf Line fragment for the LineDelta and AddrDelta. - new MCDwarfLineAddrFragment(LineDelta, *AddrDelta, &DLS); + new MCDwarfLineAddrFragment(LineDelta, *AddrDelta, DLS); } LastLine = it->getLine(); @@ -218,19 +218,29 @@ static inline void EmitDwarfLineTable(MCObjectStreamer *MCOS, // Switch back the the dwarf line section. MCOS->SwitchSection(DwarfLineSection); - // Create an expression for the address delta from the LastLabel and this - // SectionEnd label. - const MCExpr *AddrDelta = MakeStartMinusEndExpr(MCOS, LastLabel, SectionEnd, - 0); - // Create a Dwarf Line fragment for the LineDelta and AddrDelta. - new MCDwarfLineAddrFragment(INT64_MAX, *AddrDelta, &DLS); + + if (DLS == NULL) { + // emit the sequence to set the address + EmitDwarfSetAddress(MCOS, SectionEnd, PointerSize); + // emit the sequence for the LineDelta (from 1) and a zero address delta. + MCDwarfLineAddr::Emit(MCOS, INT64_MAX, 0); + } else { + // Create an expression for the address delta from the LastLabel and this + // SectionEnd label. + const MCExpr *AddrDelta = MakeStartMinusEndExpr(MCOS, LastLabel, SectionEnd, + 0); + // Create a Dwarf Line fragment for the LineDelta and AddrDelta. + new MCDwarfLineAddrFragment(INT64_MAX, *AddrDelta, DLS); + } } // // This emits the Dwarf file and the line tables. // -void MCDwarfFileTable::Emit(MCObjectStreamer *MCOS, - const MCSection *DwarfLineSection) { +void MCDwarfFileTable::Emit(MCStreamer *MCOS, + const MCSection *DwarfLineSection, + MCSectionData *DLS, + int PointerSize) { // Switch to the section where the table will be emitted into. MCOS->SwitchSection(DwarfLineSection); @@ -315,7 +325,8 @@ void MCDwarfFileTable::Emit(MCObjectStreamer *MCOS, MCOS->getContext().getMCLineSections(); for (DenseMap::iterator it = MCLineSections.begin(), ie = MCLineSections.end(); it != ie; ++it) { - EmitDwarfLineTable(MCOS, it->first, it->second, DwarfLineSection); + EmitDwarfLineTable(MCOS, it->first, it->second, DwarfLineSection, DLS, + PointerSize); // Now delete the MCLineSections that were created in MCLineEntry::Make() // and used to emit the line table. @@ -345,7 +356,7 @@ void MCDwarfLineAddr::Write(MCObjectWriter *OW, int64_t LineDelta, } /// Utility function to emit the encoding to a streamer. -void MCDwarfLineAddr::Emit(MCObjectStreamer *MCOS, int64_t LineDelta, +void MCDwarfLineAddr::Emit(MCStreamer *MCOS, int64_t LineDelta, uint64_t AddrDelta) { SmallString<256> Tmp; raw_svector_ostream OS(Tmp); diff --git a/llvm/lib/MC/MCELFStreamer.cpp b/llvm/lib/MC/MCELFStreamer.cpp index 75e58de3199a..cac48170642d 100644 --- a/llvm/lib/MC/MCELFStreamer.cpp +++ b/llvm/lib/MC/MCELFStreamer.cpp @@ -490,7 +490,10 @@ void MCELFStreamer::Finish() { const MCSection *DwarfLineSection = getContext().getELFSection(".debug_line", 0, 0, SectionKind::getDataRelLocal()); - MCDwarfFileTable::Emit(this, DwarfLineSection); + MCSectionData &DLS = + getAssembler().getOrCreateSectionData(*DwarfLineSection); + int PointerSize = getAssembler().getBackend().getPointerSize(); + MCDwarfFileTable::Emit(this, DwarfLineSection, &DLS, PointerSize); } for (std::vector::const_iterator i = LocalCommons.begin(), diff --git a/llvm/lib/MC/MCMachOStreamer.cpp b/llvm/lib/MC/MCMachOStreamer.cpp index 67a144a34120..3236432fb8d8 100644 --- a/llvm/lib/MC/MCMachOStreamer.cpp +++ b/llvm/lib/MC/MCMachOStreamer.cpp @@ -414,7 +414,10 @@ void MCMachOStreamer::Finish() { "__debug_line", MCSectionMachO::S_ATTR_DEBUG, 0, SectionKind::getDataRelLocal()); - MCDwarfFileTable::Emit(this, DwarfLineSection); + MCSectionData &DLS = + getAssembler().getOrCreateSectionData(*DwarfLineSection); + int PointerSize = getAssembler().getBackend().getPointerSize(); + MCDwarfFileTable::Emit(this, DwarfLineSection, &DLS, PointerSize); } // We have to set the fragment atom associations so we can relax properly for diff --git a/llvm/lib/Target/TargetMachine.cpp b/llvm/lib/Target/TargetMachine.cpp index 705b1c097e55..c4790a289937 100644 --- a/llvm/lib/Target/TargetMachine.cpp +++ b/llvm/lib/Target/TargetMachine.cpp @@ -219,7 +219,8 @@ FunctionSections("ffunction-sections", TargetMachine::TargetMachine(const Target &T) : TheTarget(T), AsmInfo(0), - MCRelaxAll(false) { + MCRelaxAll(false), + MCUseLoc(true) { // Typically it will be subtargets that will adjust FloatABIType from Default // to Soft or Hard. if (UseSoftFloat)