From 232ab949d5ed04c4ab45c763e0597fc3fc3fa5bc Mon Sep 17 00:00:00 2001 From: Kevin Enderby Date: Tue, 31 Aug 2010 22:55:11 +0000 Subject: [PATCH] This is the second of three patches to implement support for the .loc directive and output the dwarf line number tables. This takes the current loc info after an instruction is assembled and saves the needed info into an object that has vector and for each section. These objects will be used for the final patch to build and emit the encoded dwarf line number tables. Again for now this is only in the Mach-O streamer but at some point will move to a more generic place. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@112668 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/MC/MCContext.h | 12 ++++++++ include/llvm/MC/MCDwarf.h | 58 +++++++++++++++++++++++++++++++++---- lib/MC/MCContext.cpp | 2 +- lib/MC/MCMachOStreamer.cpp | 56 +++++++++++++++++++++++++++++++++++ 4 files changed, 121 insertions(+), 7 deletions(-) diff --git a/include/llvm/MC/MCContext.h b/include/llvm/MC/MCContext.h index 6686950b72d..d22868cdbd0 100644 --- a/include/llvm/MC/MCContext.h +++ b/include/llvm/MC/MCContext.h @@ -26,6 +26,7 @@ namespace llvm { class MCLabel; class MCDwarfFile; class MCDwarfLoc; + class MCLineSection; class StringRef; class Twine; class MCSectionMachO; @@ -75,6 +76,10 @@ namespace llvm { MCDwarfLoc CurrentDwarfLoc; bool DwarfLocSeen; + /// The dwarf line information from the .loc directives for the sections + /// with assembled machine instructions have after seeing .loc directives. + DenseMap MCLineSections; + /// Allocator - Allocator object used for creating machine code objects. /// /// We use a bump pointer allocator to avoid the need to track all allocated @@ -163,6 +168,9 @@ namespace llvm { const std::vector &getMCDwarfDirs() { return MCDwarfDirs; } + DenseMap &getMCLineSections() { + return MCLineSections; + } /// setCurrentDwarfLoc - saves the information from the currently parsed /// dwarf .loc directive and sets DwarfLocSeen. When the next instruction /// is assembled an entry in the line number table with this information and @@ -176,6 +184,10 @@ namespace llvm { CurrentDwarfLoc.setIsa(Isa); DwarfLocSeen = true; } + void clearDwarfLocSeen() { DwarfLocSeen = false; } + + bool getDwarfLocSeen() { return DwarfLocSeen; } + const MCDwarfLoc &getCurrentDwarfLoc() { return CurrentDwarfLoc; } /// @} diff --git a/include/llvm/MC/MCDwarf.h b/include/llvm/MC/MCDwarf.h index 4f39f793978..99a341f507b 100644 --- a/include/llvm/MC/MCDwarf.h +++ b/include/llvm/MC/MCDwarf.h @@ -17,9 +17,12 @@ #define LLVM_MC_MCDWARF_H #include "llvm/ADT/StringRef.h" +#include namespace llvm { class MCContext; + class MCSection; + class MCSymbol; class raw_ostream; /// MCDwarfFile - Instances of this class represent the name of the dwarf @@ -57,6 +60,11 @@ namespace llvm { void dump() const; }; + inline raw_ostream &operator<<(raw_ostream &OS, const MCDwarfFile &DwarfFile){ + DwarfFile.print(OS); + return OS; + } + /// MCDwarfLoc - Instances of this class represent the information from a /// dwarf .loc directive. class MCDwarfLoc { @@ -78,12 +86,14 @@ namespace llvm { private: // MCContext manages these friend class MCContext; + friend class MCLineEntry; MCDwarfLoc(unsigned fileNum, unsigned line, unsigned column, unsigned flags, unsigned isa) : FileNum(fileNum), Line(line), Column(column), Flags(flags), Isa(isa) {} - MCDwarfLoc(const MCDwarfLoc&); // DO NOT IMPLEMENT - void operator=(const MCDwarfLoc&); // DO NOT IMPLEMENT + // Allow the default copy constructor and assignment operator to be used + // for an MCDwarfLoc object. + public: /// setFileNum - Set the FileNum of this MCDwarfLoc. void setFileNum(unsigned fileNum) { FileNum = fileNum; } @@ -101,10 +111,46 @@ namespace llvm { void setIsa(unsigned isa) { Isa = isa; } }; - inline raw_ostream &operator<<(raw_ostream &OS, const MCDwarfFile &DwarfFile){ - DwarfFile.print(OS); - return OS; - } + /// MCLineEntry - Instances of this class represent the line information for + /// the dwarf line table entries. Which is created after a machine + /// instruction is assembled and uses an address from a temporary label + /// created at the current address in the current section and the info from + /// the last .loc directive seen as stored in the context. + class MCLineEntry : public MCDwarfLoc { + MCSymbol *Label; + + private: + // Allow the default copy constructor and assignment operator to be used + // for an MCLineEntry object. + + public: + // Constructor to create an MCLineEntry given a symbol and the dwarf loc. + MCLineEntry(MCSymbol *label, const MCDwarfLoc loc) : MCDwarfLoc(loc), + Label(label) {} + }; + + /// MCLineSection - Instances of this class represent the line information + /// for a section where machine instructions have been assembled after seeing + /// .loc directives. This is the information used to build the dwarf line + /// table for a section. + class MCLineSection { + std::vector MCLineEntries; + + private: + MCLineSection(const MCLineSection&); // DO NOT IMPLEMENT + void operator=(const MCLineSection&); // DO NOT IMPLEMENT + + public: + // Constructor to create an MCLineSection with an empty MCLineEntries + // vector. + MCLineSection(): MCLineEntries() {}; + + // addLineEntry - adds an entry to this MCLineSection's line entries + void addLineEntry(const MCLineEntry &LineEntry) { + MCLineEntries.push_back(LineEntry); + } + }; + } // end namespace llvm #endif diff --git a/lib/MC/MCContext.cpp b/lib/MC/MCContext.cpp index 13cf9a80482..e5586a0d7c3 100644 --- a/lib/MC/MCContext.cpp +++ b/lib/MC/MCContext.cpp @@ -227,7 +227,7 @@ unsigned MCContext::GetDwarfFile(StringRef FileName, unsigned FileNumber) { Name = Slash.second; for (DirIndex = 0; DirIndex < MCDwarfDirs.size(); DirIndex++) { if (Directory == MCDwarfDirs[DirIndex]) - break; + break; } if (DirIndex >= MCDwarfDirs.size()) { char *Buf = static_cast(Allocate(Directory.size())); diff --git a/lib/MC/MCMachOStreamer.cpp b/lib/MC/MCMachOStreamer.cpp index 88d9982bd2a..639aa27fce4 100644 --- a/lib/MC/MCMachOStreamer.cpp +++ b/lib/MC/MCMachOStreamer.cpp @@ -33,6 +33,7 @@ private: void EmitInstToFragment(const MCInst &Inst); void EmitInstToData(const MCInst &Inst); // FIXME: These will likely moved to a better place. + void MakeLineEntryForSection(const MCSection *Section); const MCExpr * MakeStartMinusEndExpr(MCSymbol *Start, MCSymbol *End, int IntVal); void EmitDwarfFileTable(void); @@ -409,6 +410,10 @@ void MCMachOStreamer::EmitInstruction(const MCInst &Inst) { getCurrentSectionData()->setHasInstructions(true); + // Now that a machine instruction has been assembled into this section, make + // a line entry for any .loc directive that has been seen. + MakeLineEntryForSection(getCurrentSection()); + // If this instruction doesn't need relaxation, just emit it as data. if (!getAssembler().getBackend().MayNeedRelaxation(Inst)) { EmitInstToData(Inst); @@ -430,6 +435,47 @@ void MCMachOStreamer::EmitInstruction(const MCInst &Inst) { EmitInstToFragment(Inst); } +// +// 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. +// +void MCMachOStreamer::MakeLineEntryForSection(const MCSection *Section) { + if (!getContext().getDwarfLocSeen()) + return; + + // Create a symbol at in the current section for use in the line entry. + MCSymbol *LineSym = getContext().CreateTempSymbol(); + // Set the value of the symbol to use for the MCLineEntry. + EmitLabel(LineSym); + + // Get the current .loc info saved in the context. + const MCDwarfLoc &DwarfLoc = getContext().getCurrentDwarfLoc(); + + // Create a (local) line entry with the symbol and the current .loc info. + MCLineEntry LineEntry(LineSym, DwarfLoc); + + // clear DwarfLocSeen saying the current .loc info is now used. + getContext().clearDwarfLocSeen(); + + // Get the MCLineSection for this section, if one does not exist for this + // section create it. + DenseMap &MCLineSections = + getContext().getMCLineSections(); + MCLineSection *LineSection = MCLineSections[Section]; + if (!LineSection) { + // Create a new MCLineSection. This will be deleted after the dwarf line + // table is created using it by iterating through the MCLineSections + // DenseMap. + LineSection = new MCLineSection; + // Save a pointer to the new LineSection into the MCLineSections DenseMap. + MCLineSections[Section] = LineSection; + } + + // Add the line entry to this section's entries. + LineSection->addLineEntry(LineEntry); +} + // // This helper routine returns an expression of End - Start + IntVal for use // by EmitDwarfFileTable() below. @@ -552,6 +598,16 @@ void MCMachOStreamer::EmitDwarfFileTable(void) { // TODO: This is the point where the line tables would be emitted. + // Delete the MCLineSections that were created in + // MCMachOStreamer::MakeLineEntryForSection() and used to emit the line + // tables. + DenseMap &MCLineSections = + getContext().getMCLineSections(); + for (DenseMap::iterator it = + MCLineSections.begin(), ie = MCLineSections.end(); it != ie; ++it) { + delete it->second; + } + // If there are no line tables emited then we emit: // The following DW_LNE_set_address sequence to set the address to zero // TODO test for 32-bit or 64-bit output