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