mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-21 00:32:23 +00:00
Adding basic support for Dwarf line number debug information.
I promise to keep future commits smaller. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@25396 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
08a0464763
commit
063e765345
@ -7,14 +7,26 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains support for writing dwarf debug info into asm files.
|
||||
// This file contains support for writing Dwarf debug info into asm files. For
|
||||
// Details on the Dwarf 3 specfication see DWARF Debugging Information Format
|
||||
// V.3 reference manual http://dwarf.freestandards.org ,
|
||||
//
|
||||
// The role of the Dwarf Writer class is to extract debug information from the
|
||||
// MachineDebugInfo object, organize it in Dwarf form and then emit it into asm
|
||||
// the current asm file using data and high level Dwarf directives.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CODEGEN_DWARFPRINTER_H
|
||||
#define LLVM_CODEGEN_DWARFPRINTER_H
|
||||
|
||||
#include "llvm/ADT/UniqueVector.h"
|
||||
|
||||
#include <iosfwd>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace llvm {
|
||||
|
||||
@ -23,6 +35,8 @@ namespace llvm {
|
||||
// reference manual http://dwarf.freestandards.org .
|
||||
//
|
||||
enum dwarf_constants {
|
||||
DWARF_VERSION = 2,
|
||||
|
||||
// Tags
|
||||
DW_TAG_array_type = 0x01,
|
||||
DW_TAG_class_type = 0x02,
|
||||
@ -425,23 +439,246 @@ namespace llvm {
|
||||
DW_CFA_hi_user = 0x3f
|
||||
};
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// DWLabel - Labels are used to track locations in the assembler file.
|
||||
// Labels appear in the form <prefix>debug_<Tag><Number>, where the tag is a
|
||||
// category of label (Ex. location) and number is a value unique in that
|
||||
// category.
|
||||
struct DWLabel {
|
||||
const char *Tag; // Label category tag. Should always be
|
||||
// a staticly declared C string.
|
||||
unsigned Number; // Unique number
|
||||
|
||||
DWLabel() : Tag(NULL), Number(0) {}
|
||||
DWLabel(const char *T, unsigned N) : Tag(T), Number(N) {}
|
||||
};
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// DIEAbbrev - Dwarf abbreviation, describes the organization of a debug
|
||||
// information object.
|
||||
//
|
||||
class DIEAbbrev {
|
||||
private:
|
||||
const unsigned char *Data; // Static array of bytes containing the
|
||||
// image of the raw abbreviation data.
|
||||
|
||||
public:
|
||||
|
||||
DIEAbbrev(const unsigned char *D)
|
||||
: Data(D)
|
||||
{}
|
||||
|
||||
/// operator== - Used by UniqueVector to locate entry.
|
||||
///
|
||||
bool operator==(const DIEAbbrev &DA) const {
|
||||
return Data == DA.Data;
|
||||
}
|
||||
|
||||
/// operator< - Used by UniqueVector to locate entry.
|
||||
///
|
||||
bool operator<(const DIEAbbrev &DA) const {
|
||||
return Data < DA.Data;
|
||||
}
|
||||
|
||||
// Accessors
|
||||
unsigned getTag() const { return Data[0]; }
|
||||
unsigned getChildrenFlag() const { return Data[1]; }
|
||||
unsigned getAttribute(unsigned i) const { return Data[2 + 2 * i + 0]; }
|
||||
unsigned getForm(unsigned i) const { return Data[2 + 2 * i + 1]; }
|
||||
};
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// DIEValue - A debug information entry value.
|
||||
//
|
||||
class DwarfWriter;
|
||||
class DIEValue {
|
||||
public:
|
||||
enum {
|
||||
isInteger,
|
||||
isString,
|
||||
isLabel,
|
||||
isDelta
|
||||
};
|
||||
|
||||
unsigned Type; // Type of the value
|
||||
|
||||
DIEValue(unsigned T) : Type(T) {}
|
||||
virtual ~DIEValue() {}
|
||||
|
||||
// Implement isa/cast/dyncast.
|
||||
static bool classof(const DIEValue *) { return true; }
|
||||
|
||||
/// EmitValue - Emit value via the Dwarf writer.
|
||||
///
|
||||
virtual void EmitValue(const DwarfWriter &DW, unsigned Form) const = 0;
|
||||
|
||||
/// SizeOf - Return the size of a value in bytes.
|
||||
///
|
||||
virtual unsigned SizeOf(const DwarfWriter &DW, unsigned Form) const = 0;
|
||||
};
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// DWInteger - An integer value DIE.
|
||||
//
|
||||
class DIEInteger : public DIEValue {
|
||||
private:
|
||||
int Value;
|
||||
|
||||
public:
|
||||
DIEInteger(int V) : DIEValue(isInteger), Value(V) {}
|
||||
|
||||
// Implement isa/cast/dyncast.
|
||||
static bool classof(const DIEInteger *) { return true; }
|
||||
static bool classof(const DIEValue *V) { return V->Type == isInteger; }
|
||||
|
||||
/// EmitValue - Emit integer of appropriate size.
|
||||
///
|
||||
virtual void EmitValue(const DwarfWriter &DW, unsigned Form) const;
|
||||
|
||||
/// SizeOf - Determine size of integer value in bytes.
|
||||
///
|
||||
virtual unsigned SizeOf(const DwarfWriter &DW, unsigned Form) const;
|
||||
};
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// DIEString - A string value DIE.
|
||||
//
|
||||
struct DIEString : public DIEValue {
|
||||
const std::string Value;
|
||||
|
||||
DIEString(const std::string &V) : DIEValue(isString), Value(V) {}
|
||||
|
||||
// Implement isa/cast/dyncast.
|
||||
static bool classof(const DIEString *) { return true; }
|
||||
static bool classof(const DIEValue *V) { return V->Type == isString; }
|
||||
|
||||
/// EmitValue - Emit string value.
|
||||
///
|
||||
virtual void EmitValue(const DwarfWriter &DW, unsigned Form) const;
|
||||
|
||||
/// SizeOf - Determine size of string value in bytes.
|
||||
///
|
||||
virtual unsigned SizeOf(const DwarfWriter &DW, unsigned Form) const;
|
||||
};
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// DIELabel - A simple label expression DIE.
|
||||
//
|
||||
struct DIELabel : public DIEValue {
|
||||
const DWLabel Value;
|
||||
|
||||
DIELabel(const DWLabel &V) : DIEValue(DW_FORM_ref4), Value(V) {}
|
||||
|
||||
// Implement isa/cast/dyncast.
|
||||
static bool classof(const DWLabel *) { return true; }
|
||||
static bool classof(const DIEValue *V) { return V->Type == isLabel; }
|
||||
|
||||
/// EmitValue - Emit label value.
|
||||
///
|
||||
virtual void EmitValue(const DwarfWriter &DW, unsigned Form) const;
|
||||
|
||||
/// SizeOf - Determine size of label value in bytes.
|
||||
///
|
||||
virtual unsigned SizeOf(const DwarfWriter &DW, unsigned Form) const;
|
||||
};
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// DIEDelta - A simple label difference DIE.
|
||||
//
|
||||
struct DIEDelta : public DIEValue {
|
||||
const DWLabel Value1;
|
||||
const DWLabel Value2;
|
||||
|
||||
DIEDelta(const DWLabel &V1, const DWLabel &V2)
|
||||
: DIEValue(DW_FORM_addr), Value1(V1), Value2(V2) {}
|
||||
|
||||
// Implement isa/cast/dyncast.
|
||||
static bool classof(const DIEDelta *) { return true; }
|
||||
static bool classof(const DIEValue *V) { return V->Type == isDelta; }
|
||||
|
||||
/// EmitValue - Emit delta value.
|
||||
///
|
||||
virtual void EmitValue(const DwarfWriter &DW, unsigned Form) const;
|
||||
|
||||
/// SizeOf - Determine size of delta value in bytes.
|
||||
///
|
||||
virtual unsigned SizeOf(const DwarfWriter &DW, unsigned Form) const;
|
||||
};
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// DIE - A structured debug information entry. Has an abbreviation which
|
||||
// describes it's organization.
|
||||
class DIE {
|
||||
private:
|
||||
unsigned AbbrevID; // Decribing abbreviation ID.
|
||||
unsigned Offset; // Offset in debug info section
|
||||
unsigned Size; // Size of instance + children
|
||||
std::vector<DIE *> Children; // Children DIEs
|
||||
std::vector<DIEValue *> Values; // Attributes values
|
||||
|
||||
public:
|
||||
DIE(unsigned AbbrevID)
|
||||
: AbbrevID(AbbrevID)
|
||||
, Offset(0)
|
||||
, Size(0)
|
||||
, Children()
|
||||
, Values()
|
||||
{}
|
||||
virtual ~DIE() {
|
||||
}
|
||||
|
||||
// Accessors
|
||||
unsigned getAbbrevID() const { return AbbrevID; }
|
||||
unsigned getOffset() const { return Offset; }
|
||||
unsigned getSize() const { return Size; }
|
||||
const std::vector<DIE *> &getChildren() const { return Children; }
|
||||
const std::vector<DIEValue *> &getValues() const { return Values; }
|
||||
void setOffset(unsigned O) { Offset = O; }
|
||||
void setSize(unsigned S) { Size = S; }
|
||||
|
||||
/// AddValue - Add an attribute value of appropriate type.
|
||||
///
|
||||
void AddValue(int Value) {
|
||||
Values.push_back(new DIEInteger(Value));
|
||||
}
|
||||
void AddValue(const std::string &Value) {
|
||||
Values.push_back(new DIEString(Value));
|
||||
}
|
||||
void AddValue(const DWLabel &Value) {
|
||||
Values.push_back(new DIELabel(Value));
|
||||
}
|
||||
void AddValue(const DWLabel &Value1, const DWLabel &Value2) {
|
||||
Values.push_back(new DIEDelta(Value1, Value2));
|
||||
}
|
||||
|
||||
/// SiblingOffset - Return the offset of the debug information entry's
|
||||
/// sibling.
|
||||
unsigned SiblingOffset() const { return Offset + Size; }
|
||||
};
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Forward declarations.
|
||||
//
|
||||
class AsmPrinter;
|
||||
class MachineDebugInfo;
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// DwarfWriter - emits dwarf debug and exception handling directives.
|
||||
// DwarfWriter - emits Dwarf debug and exception handling directives.
|
||||
//
|
||||
class DwarfWriter {
|
||||
|
||||
protected:
|
||||
|
||||
//===------------------------------------------------------------------===//
|
||||
// Core attributes used by the Dwarf writer.
|
||||
//
|
||||
|
||||
//
|
||||
/// O - Stream to .s file.
|
||||
///
|
||||
std::ostream &O;
|
||||
|
||||
/// Asm - Target of dwarf emission.
|
||||
/// Asm - Target of Dwarf emission.
|
||||
///
|
||||
AsmPrinter *Asm;
|
||||
|
||||
@ -453,9 +690,26 @@ namespace llvm {
|
||||
///
|
||||
bool didInitial;
|
||||
|
||||
//===------------------------------------------------------------------===//
|
||||
// Attributes used to construct specific Dwarf sections.
|
||||
//
|
||||
|
||||
/// CompileUnits - All the compile units involved in this build. The index
|
||||
/// of each entry in this vector corresponds to the sources in DebugInfo.
|
||||
std::vector<DIE *> CompileUnits;
|
||||
|
||||
/// Abbreviations - A UniqueVector of TAG structure abbreviations.
|
||||
///
|
||||
UniqueVector<DIEAbbrev> Abbreviations;
|
||||
|
||||
//===------------------------------------------------------------------===//
|
||||
// Properties to be set by the derived class ctor, used to configure the
|
||||
// dwarf writer.
|
||||
// Dwarf writer.
|
||||
//
|
||||
|
||||
/// AddressSize - Size of addresses used in file.
|
||||
///
|
||||
unsigned AddressSize;
|
||||
|
||||
/// hasLEB128 - True if target asm supports leb128 directives.
|
||||
///
|
||||
@ -473,93 +727,174 @@ namespace llvm {
|
||||
/// directives.
|
||||
bool needsSet; /// Defaults to false.
|
||||
|
||||
/// DwarfAbbrevSection - section directive arg for dwarf abbrev.
|
||||
/// DwarfAbbrevSection - Section directive for Dwarf abbrev.
|
||||
///
|
||||
const char *DwarfAbbrevSection; /// Defaults to ".debug_abbrev".
|
||||
|
||||
/// DwarfInfoSection - section directive arg for dwarf info.
|
||||
/// DwarfInfoSection - Section directive for Dwarf info.
|
||||
///
|
||||
const char *DwarfInfoSection; /// Defaults to ".debug_info".
|
||||
|
||||
/// DwarfLineSection - section directive arg for dwarf info.
|
||||
/// DwarfLineSection - Section directive for Dwarf info.
|
||||
///
|
||||
const char *DwarfLineSection; /// Defaults to ".debug_line".
|
||||
|
||||
/// TextSection - Section directive for standard text.
|
||||
///
|
||||
const char *TextSection; /// Defaults to ".text".
|
||||
|
||||
/// DataSection - Section directive for standard data.
|
||||
///
|
||||
const char *DataSection; /// Defaults to ".data".
|
||||
|
||||
//===------------------------------------------------------------------===//
|
||||
// Emission and print routines
|
||||
//
|
||||
|
||||
public:
|
||||
|
||||
// Ctor.
|
||||
DwarfWriter(std::ostream &o, AsmPrinter *ap)
|
||||
: O(o)
|
||||
, Asm(ap)
|
||||
, DebugInfo(NULL)
|
||||
, didInitial(false)
|
||||
, hasLEB128(false)
|
||||
, hasDotLoc(false)
|
||||
, hasDotFile(false)
|
||||
, needsSet(false)
|
||||
, DwarfAbbrevSection(".debug_abbrev")
|
||||
, DwarfInfoSection(".debug_info")
|
||||
, DwarfLineSection(".debug_line")
|
||||
{}
|
||||
|
||||
/// SetDebugInfo - Set DebugInfo at when it's know that pass manager
|
||||
/// has created it.
|
||||
void SetDebugInfo(MachineDebugInfo *di) { DebugInfo = di; }
|
||||
|
||||
/// EmitHex - Emit a hexidecimal string to the output stream.
|
||||
public:
|
||||
/// getAddressSize - Return the size of a target address in bytes.
|
||||
///
|
||||
void EmitHex(unsigned Value) const;
|
||||
|
||||
/// EmitComment - Emit a simple string comment.
|
||||
///
|
||||
void EmitComment(const char *Comment) const;
|
||||
unsigned getAddressSize() const { return AddressSize; }
|
||||
|
||||
/// EmitULEB128 - Emit a series of hexidecimal values (separated by commas)
|
||||
/// representing an unsigned leb128 value.
|
||||
/// PrintHex - Print a value as a hexidecimal value.
|
||||
///
|
||||
void EmitULEB128(unsigned Value) const;
|
||||
void PrintHex(int Value) const;
|
||||
|
||||
/// EmitSLEB128 - Emit a series of hexidecimal values (separated by commas)
|
||||
/// representing a signed leb128 value.
|
||||
///
|
||||
void EmitSLEB128(int Value) const;
|
||||
|
||||
/// EmitLabelName - Emit label name for internal use by dwarf.
|
||||
///
|
||||
void EmitLabelName(const char *Tag, int Num) const;
|
||||
|
||||
/// EmitLabel - Emit location label for internal use by dwarf.
|
||||
///
|
||||
void EmitLabel(const char *Tag, int Num) const;
|
||||
|
||||
/// EOL - Print a newline character to asm stream. If a comment is present
|
||||
/// then it will be printed first. Comments should not contain '\n'.
|
||||
void EOL(const std::string &Comment) const;
|
||||
|
||||
/// EmitULEB128Bytes - Emit an assembler byte data directive to compose an
|
||||
/// unsigned leb128 value. Comment is added to the end of the directive if
|
||||
/// DwarfVerbose is true (should not contain any newlines.)
|
||||
///
|
||||
void EmitULEB128Bytes(unsigned Value, const char *Comment) const;
|
||||
/// unsigned leb128 value.
|
||||
void EmitULEB128Bytes(unsigned Value) const;
|
||||
|
||||
/// EmitSLEB128Bytes - Emit an assembler byte data directive to compose a
|
||||
/// signed leb128 value. Comment is added to the end of the directive if
|
||||
/// DwarfVerbose is true (should not contain any newlines.)
|
||||
///
|
||||
void EmitSLEB128Bytes(int Value, const char *Comment) const;
|
||||
/// EmitSLEB128Bytes - print an assembler byte data directive to compose a
|
||||
/// signed leb128 value.
|
||||
void EmitSLEB128Bytes(int Value) const;
|
||||
|
||||
/// EmitInitial - Emit initial dwarf declarations.
|
||||
/// PrintULEB128 - Print a series of hexidecimal values (separated by
|
||||
/// commas) representing an unsigned leb128 value.
|
||||
void PrintULEB128(unsigned Value) const;
|
||||
|
||||
/// SizeULEB128 - Compute the number of bytes required for an unsigned
|
||||
/// leb128 value.
|
||||
static unsigned SizeULEB128(unsigned Value);
|
||||
|
||||
/// PrintSLEB128 - Print a series of hexidecimal values (separated by
|
||||
/// commas) representing a signed leb128 value.
|
||||
void PrintSLEB128(int Value) const;
|
||||
|
||||
/// SizeSLEB128 - Compute the number of bytes required for a signed leb128
|
||||
/// value.
|
||||
static unsigned SizeSLEB128(int Value);
|
||||
|
||||
/// EmitByte - Emit a byte directive and value.
|
||||
///
|
||||
void EmitByte(int Value) const;
|
||||
|
||||
/// EmitShort - Emit a short directive and value.
|
||||
///
|
||||
void EmitShort(int Value) const;
|
||||
|
||||
/// EmitLong - Emit a long directive and value.
|
||||
///
|
||||
void EmitLong(int Value) const;
|
||||
|
||||
/// EmitString - Emit a string with quotes and a null terminator.
|
||||
/// Special characters are emitted properly. (Eg. '\t')
|
||||
void DwarfWriter::EmitString(const std::string &String) const;
|
||||
|
||||
/// PrintLabelName - Print label name in form used by Dwarf writer.
|
||||
///
|
||||
void PrintLabelName(DWLabel Label) const {
|
||||
PrintLabelName(Label.Tag, Label.Number);
|
||||
}
|
||||
void PrintLabelName(const char *Tag, unsigned Number) const;
|
||||
|
||||
/// EmitLabel - Emit location label for internal use by Dwarf.
|
||||
///
|
||||
void EmitLabel(DWLabel Label) const {
|
||||
EmitLabel(Label.Tag, Label.Number);
|
||||
}
|
||||
void EmitLabel(const char *Tag, unsigned Number) const;
|
||||
|
||||
/// EmitLabelReference - Emit a reference to a label.
|
||||
///
|
||||
void EmitLabelReference(DWLabel Label) const {
|
||||
EmitLabelReference(Label.Tag, Label.Number);
|
||||
}
|
||||
void EmitLabelReference(const char *Tag, unsigned Number) const;
|
||||
|
||||
/// EmitDifference - Emit the difference between two labels. Some
|
||||
/// assemblers do not behave with absolute expressions with data directives,
|
||||
/// so there is an option (needsSet) to use an intermediary set expression.
|
||||
void EmitDifference(DWLabel Label1, DWLabel Label2) const {
|
||||
EmitDifference(Label1.Tag, Label1.Number, Label2.Tag, Label2.Number);
|
||||
}
|
||||
void EmitDifference(const char *Tag1, unsigned Number1,
|
||||
const char *Tag2, unsigned Number2) const;
|
||||
|
||||
private:
|
||||
/// NewDIE - Construct a new structured debug information entry.
|
||||
///
|
||||
DIE *NewDIE(const unsigned char *AbbrevData);
|
||||
|
||||
/// NewCompileUnit - Create new compile unit information.
|
||||
///
|
||||
DIE *NewCompileUnit(const std::string &Directory,
|
||||
const std::string &SourceName);
|
||||
|
||||
/// EmitInitial - Emit initial Dwarf declarations.
|
||||
///
|
||||
void EmitInitial() const;
|
||||
|
||||
/// ShouldEmitDwarf - Returns true if dwarf declarations should be made.
|
||||
/// When called it also checks to see if debug info is newly available. if
|
||||
/// so the initial dwarf headers are emitted.
|
||||
bool ShouldEmitDwarf();
|
||||
/// EmitDIE - Recusively Emits a debug information entry.
|
||||
///
|
||||
void EmitDIE(DIE *Die) const;
|
||||
|
||||
/// SizeAndOffsetDie - Compute the size and offset of a DIE.
|
||||
///
|
||||
unsigned SizeAndOffsetDie(DIE *Die, unsigned Offset) const;
|
||||
|
||||
/// BeginModule - Emit all dwarf sections that should come prior to the
|
||||
/// SizeAndOffsets - Compute the size and offset of all the DIEs.
|
||||
///
|
||||
void SizeAndOffsets();
|
||||
|
||||
/// EmitDebugInfo - Emit the debug info section.
|
||||
///
|
||||
void EmitDebugInfo() const;
|
||||
|
||||
/// EmitAbbreviations - Emit the abbreviation section.
|
||||
///
|
||||
void EmitAbbreviations() const;
|
||||
|
||||
/// EmitDebugLines - Emit source line information.
|
||||
///
|
||||
void EmitDebugLines() const;
|
||||
|
||||
/// ShouldEmitDwarf - Returns true if Dwarf declarations should be made.
|
||||
/// When called it also checks to see if debug info is newly available. if
|
||||
/// so the initial Dwarf headers are emitted.
|
||||
bool ShouldEmitDwarf();
|
||||
|
||||
public:
|
||||
|
||||
DwarfWriter(std::ostream &o, AsmPrinter *ap);
|
||||
virtual ~DwarfWriter();
|
||||
|
||||
/// SetDebugInfo - Set DebugInfo when it's known that pass manager has
|
||||
/// created it. Set by the target AsmPrinter.
|
||||
void SetDebugInfo(MachineDebugInfo *di) { DebugInfo = di; }
|
||||
|
||||
//===------------------------------------------------------------------===//
|
||||
// Main enties.
|
||||
//
|
||||
|
||||
/// BeginModule - Emit all Dwarf sections that should come prior to the
|
||||
/// content.
|
||||
void BeginModule();
|
||||
|
||||
/// EndModule - Emit all dwarf sections that should come after the content.
|
||||
/// EndModule - Emit all Dwarf sections that should come after the content.
|
||||
///
|
||||
void EndModule();
|
||||
|
||||
@ -571,7 +906,6 @@ namespace llvm {
|
||||
///
|
||||
void EndFunction();
|
||||
};
|
||||
|
||||
|
||||
} // end llvm namespace
|
||||
|
||||
|
@ -10,17 +10,83 @@
|
||||
// Collect debug information for a module. This information should be in a
|
||||
// neutral form that can be used by different debugging schemes.
|
||||
//
|
||||
// The organization of information is primarily clustered around the source
|
||||
// compile units. The main exception is source line coorespondence where
|
||||
// inlining may interleave code from various compile units.
|
||||
//
|
||||
// The following information can be retrieved from the MachineDebugInfo.
|
||||
//
|
||||
// -- Source directories - Directories are uniqued based on their canonical
|
||||
// string and assigned a sequential numeric ID (base 1.) A directory ID - 1
|
||||
// provides the index of directory information in a queried directory list.
|
||||
// -- Source files - Files are also uniqued based on their name and directory
|
||||
// ID. A file ID is sequential number (base 1.) A file ID - 1 provides the
|
||||
// index of source information in a queried file list.
|
||||
// -- Source line coorespondence - A vector of file ID, line#, column# triples.
|
||||
// A DEBUG_LOCATION instruction is generated by the DAG Legalizer
|
||||
// corresponding to each entry in the source line list. This allows a debug
|
||||
// information emitter to generate labels to map code addressed to debug
|
||||
// tables.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CODEGEN_MACHINEDEBUGINFO_H
|
||||
#define LLVM_CODEGEN_MACHINEDEBUGINFO_H
|
||||
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/ADT/UniqueVector.h"
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
/// SourceLineInfo - This class is used to record source line correspondence.
|
||||
///
|
||||
class SourceLineInfo {
|
||||
private:
|
||||
unsigned Line; // Source line number.
|
||||
unsigned Column; // Source column.
|
||||
unsigned SourceID; // Source ID number.
|
||||
|
||||
public:
|
||||
SourceLineInfo(unsigned L, unsigned C, unsigned S)
|
||||
: Line(L), Column(C), SourceID(S) {}
|
||||
|
||||
// Accessors
|
||||
unsigned getLine() const { return Line; }
|
||||
unsigned getColumn() const { return Column; }
|
||||
unsigned getSourceID() const { return SourceID; }
|
||||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
/// SourceFileInfo - This class is used to track source information.
|
||||
///
|
||||
class SourceFileInfo {
|
||||
private:
|
||||
unsigned DirectoryID; // Directory ID number.
|
||||
std::string Name; // File name (not including directory.)
|
||||
|
||||
public:
|
||||
SourceFileInfo(unsigned D, const std::string &N) : DirectoryID(D), Name(N) {}
|
||||
|
||||
// Accessors
|
||||
unsigned getDirectoryID() const { return DirectoryID; }
|
||||
const std::string &getName() const { return Name; }
|
||||
|
||||
/// operator== - Used by UniqueVector to locate entry.
|
||||
///
|
||||
bool operator==(const SourceFileInfo &SI) const {
|
||||
return getDirectoryID() == SI.getDirectoryID() && getName() == SI.getName();
|
||||
}
|
||||
|
||||
/// operator< - Used by UniqueVector to locate entry.
|
||||
///
|
||||
bool operator<(const SourceFileInfo &SI) const {
|
||||
return getDirectoryID() < SI.getDirectoryID() ||
|
||||
(getDirectoryID() == SI.getDirectoryID() && getName() < SI.getName());
|
||||
}
|
||||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
/// MachineDebugInfo - This class contains debug information specific to a
|
||||
/// module. Queries can be made by different debugging schemes and reformated
|
||||
@ -28,48 +94,70 @@ namespace llvm {
|
||||
///
|
||||
class MachineDebugInfo : public ImmutablePass {
|
||||
private:
|
||||
std::map<std::string, unsigned> SourceMap; // Map of source file path to id
|
||||
unsigned SourceCount; // Number of source files (used to
|
||||
// generate id)
|
||||
unsigned UniqueID; // Number used to unique labels used
|
||||
// by debugger.
|
||||
// DirectoryMap - UniqueVector for directories.
|
||||
UniqueVector<std::string> Directories;
|
||||
|
||||
// SourceMap - UniqueVector for source files.
|
||||
UniqueVector<SourceFileInfo> SourceFiles;
|
||||
|
||||
// Lines - List of of source line correspondence.
|
||||
std::vector<SourceLineInfo *> Lines;
|
||||
|
||||
public:
|
||||
// Ctor.
|
||||
MachineDebugInfo()
|
||||
: SourceMap()
|
||||
, SourceCount(0)
|
||||
, UniqueID(1)
|
||||
: Directories()
|
||||
, SourceFiles()
|
||||
, Lines()
|
||||
{}
|
||||
~MachineDebugInfo() { }
|
||||
|
||||
/// hasInfo - Returns true if debug info is present.
|
||||
/// doInitialization - Initialize the debug state for a new module.
|
||||
///
|
||||
// FIXME - need scheme to suppress debug output.
|
||||
bool hasInfo() const { return SourceCount != 0; }
|
||||
|
||||
/// getNextUniqueID - Returns a unique number for labels used by debugger.
|
||||
///
|
||||
unsigned getNextUniqueID() { return UniqueID++; }
|
||||
|
||||
/// RecordLabel - Records location information and associates it with a
|
||||
/// debug label. Returns unique label id.
|
||||
unsigned RecordLabel(unsigned Line, unsigned Col, unsigned SrcFile) {
|
||||
// FIXME - actually record.
|
||||
return getNextUniqueID();
|
||||
}
|
||||
|
||||
bool doInitialization();
|
||||
|
||||
|
||||
/// doFinalization - Tear down the debug state after completion of a module.
|
||||
///
|
||||
bool doFinalization();
|
||||
|
||||
/// getUniqueSourceID - Register a source file with debug info. Returns an id.
|
||||
/// hasInfo - Returns true if debug info is present.
|
||||
///
|
||||
unsigned getUniqueSourceID(const std::string &fname,
|
||||
const std::string &dirname);
|
||||
// FIXME - need proper scheme to suppress debug output.
|
||||
bool hasInfo() const { return !SourceFiles.empty(); }
|
||||
|
||||
/// getSourceFiles - Return a vector of files. Vector index + 1 equals id.
|
||||
/// RecordLabel - Records location information and associates it with a
|
||||
/// debug label. Returns a unique label ID used to generate a label and
|
||||
/// provide correspondence to the source line list.
|
||||
unsigned RecordLabel(unsigned Line, unsigned Column, unsigned Source) {
|
||||
Lines.push_back(new SourceLineInfo(Line, Column, Source));
|
||||
return Lines.size();
|
||||
}
|
||||
|
||||
/// RecordSource - Register a source file with debug info. Returns an source
|
||||
/// ID.
|
||||
unsigned RecordSource(const std::string &Directory,
|
||||
const std::string &Source) {
|
||||
unsigned DirectoryID = Directories.insert(Directory);
|
||||
return SourceFiles.insert(SourceFileInfo(DirectoryID, Source));
|
||||
}
|
||||
|
||||
/// getDirectories - Return the UniqueVector of std::string representing
|
||||
/// directories.
|
||||
const UniqueVector<std::string> &getDirectories() const {
|
||||
return Directories;
|
||||
}
|
||||
|
||||
/// getSourceFiles - Return the UniqueVector of source files.
|
||||
///
|
||||
std::vector<std::string> getSourceFiles() const;
|
||||
const UniqueVector<SourceFileInfo> &getSourceFiles() const {
|
||||
return SourceFiles;
|
||||
}
|
||||
|
||||
/// getSourceLines - Return a vector of source lines. Vector index + 1
|
||||
/// equals label ID.
|
||||
const std::vector<SourceLineInfo *> &getSourceLines() const {
|
||||
return Lines;
|
||||
}
|
||||
|
||||
}; // End class MachineDebugInfo
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -6,11 +6,6 @@
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Collect debug information for a module. This information should be in a
|
||||
// neutral form that can be used by different debugging schemes.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/CodeGen/MachineDebugInfo.h"
|
||||
|
||||
@ -20,7 +15,9 @@ using namespace llvm;
|
||||
namespace {
|
||||
RegisterPass<MachineDebugInfo> X("machinedebuginfo", "Debug Information");
|
||||
}
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
/// doInitialization - Initialize the debug state for a new module.
|
||||
///
|
||||
bool MachineDebugInfo::doInitialization() {
|
||||
@ -32,38 +29,3 @@ bool MachineDebugInfo::doInitialization() {
|
||||
bool MachineDebugInfo::doFinalization() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/// getUniqueSourceID - Register a source file with debug info. Returns an id.
|
||||
///
|
||||
unsigned MachineDebugInfo::getUniqueSourceID(const std::string &fname,
|
||||
const std::string &dirname) {
|
||||
// Compose a key
|
||||
const std::string path = dirname + "/" + fname;
|
||||
// Check if the source file is already recorded
|
||||
std::map<std::string, unsigned>::iterator
|
||||
SMI = SourceMap.lower_bound(path);
|
||||
// If already there return existing id
|
||||
if (SMI != SourceMap.end() && SMI->first == path) return SMI->second;
|
||||
// Bump up the count
|
||||
++SourceCount;
|
||||
// Record the count
|
||||
SourceMap.insert(SMI, std::make_pair(path, SourceCount));
|
||||
// Return id
|
||||
return SourceCount;
|
||||
}
|
||||
|
||||
/// getSourceFiles - Return a vector of files. Vector index + 1 equals id.
|
||||
///
|
||||
std::vector<std::string> MachineDebugInfo::getSourceFiles() const {
|
||||
std::vector<std::string> Sources(SourceCount);
|
||||
|
||||
for (std::map<std::string, unsigned>::const_iterator SMI = SourceMap.begin(),
|
||||
E = SourceMap.end();
|
||||
SMI != E; SMI++) {
|
||||
unsigned Index = SMI->second - 1;
|
||||
const std::string &Path = SMI->first;
|
||||
Sources[Index] = Path;
|
||||
}
|
||||
return Sources;
|
||||
}
|
||||
|
||||
|
@ -627,7 +627,7 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
|
||||
cast<StringSDNode>(Node->getOperand(3))->getValue();
|
||||
const std::string &DirName =
|
||||
cast<StringSDNode>(Node->getOperand(4))->getValue();
|
||||
unsigned SrcFile = DebugInfo->getUniqueSourceID(FName, DirName);
|
||||
unsigned SrcFile = DebugInfo->RecordSource(DirName, FName);
|
||||
|
||||
std::vector<SDOperand> Ops;
|
||||
Ops.push_back(Tmp1); // chain
|
||||
|
@ -215,9 +215,11 @@ namespace {
|
||||
: DwarfWriter(o, ap)
|
||||
{
|
||||
needsSet = true;
|
||||
DwarfAbbrevSection = ".section __DWARFA,__debug_abbrev,regular,debug";
|
||||
DwarfInfoSection = ".section __DWARFA,__debug_info,regular,debug";
|
||||
DwarfLineSection = ".section __DWARFA,__debug_line,regular,debug";
|
||||
DwarfAbbrevSection = ".section __DWARF,__debug_abbrev,regular,debug";
|
||||
DwarfInfoSection = ".section __DWARF,__debug_info,regular,debug";
|
||||
DwarfLineSection = ".section __DWARF,__debug_line,regular,debug";
|
||||
TextSection = ".text";
|
||||
DataSection = ".data";
|
||||
}
|
||||
};
|
||||
|
||||
@ -607,6 +609,9 @@ bool DarwinAsmPrinter::doFinalization(Module &M) {
|
||||
}
|
||||
}
|
||||
|
||||
// Emit initial debug information.
|
||||
DW.EndModule();
|
||||
|
||||
// Funny Darwin hack: This flag tells the linker that no global symbols
|
||||
// contain code that falls through to other global symbols (e.g. the obvious
|
||||
// implementation of multiple entry points). If this doesn't occur, the
|
||||
@ -614,9 +619,6 @@ bool DarwinAsmPrinter::doFinalization(Module &M) {
|
||||
// code that does this, it is always safe to set.
|
||||
O << "\t.subsections_via_symbols\n";
|
||||
|
||||
// Emit initial debug information.
|
||||
DW.EndModule();
|
||||
|
||||
AsmPrinter::doFinalization(M);
|
||||
return false; // success
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user