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
This commit is contained in:
Kevin Enderby 2010-08-31 22:55:11 +00:00
parent 3f19c091bf
commit 232ab949d5
4 changed files with 121 additions and 7 deletions

View File

@ -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<const MCSection *, MCLineSection *> 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<StringRef> &getMCDwarfDirs() {
return MCDwarfDirs;
}
DenseMap<const MCSection *, MCLineSection *> &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; }
/// @}

View File

@ -17,9 +17,12 @@
#define LLVM_MC_MCDWARF_H
#include "llvm/ADT/StringRef.h"
#include <vector>
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<MCLineEntry> 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

View File

@ -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<char *>(Allocate(Directory.size()));

View File

@ -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<const MCSection *, MCLineSection *> &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<const MCSection *, MCLineSection *> &MCLineSections =
getContext().getMCLineSections();
for (DenseMap<const MCSection *, MCLineSection *>::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