aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJim Laskey <jlaskey@mac.com>2006-01-17 17:31:53 +0000
committerJim Laskey <jlaskey@mac.com>2006-01-17 17:31:53 +0000
commit063e765345fd49df0f53b807e57ada7c2ded7e16 (patch)
tree851e46dbfed06121b4a50f55c467b376c4c25d6e
parent08a0464763a93be5f201b2d6d514732e810ef2ad (diff)
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
-rw-r--r--include/llvm/CodeGen/DwarfWriter.h446
-rw-r--r--include/llvm/CodeGen/MachineDebugInfo.h144
-rw-r--r--lib/CodeGen/DwarfWriter.cpp1344
-rw-r--r--lib/CodeGen/MachineDebugInfo.cpp42
-rw-r--r--lib/CodeGen/SelectionDAG/LegalizeDAG.cpp2
-rw-r--r--lib/Target/PowerPC/PPCAsmPrinter.cpp14
6 files changed, 1787 insertions, 205 deletions
diff --git a/include/llvm/CodeGen/DwarfWriter.h b/include/llvm/CodeGen/DwarfWriter.h
index 1a7c5a5666..e178c91fbb 100644
--- a/include/llvm/CodeGen/DwarfWriter.h
+++ b/include/llvm/CodeGen/DwarfWriter.h
@@ -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;
@@ -454,8 +691,25 @@ 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:
+public:
+ /// getAddressSize - Return the size of a target address in bytes.
+ ///
+ unsigned getAddressSize() const { return AddressSize; }
+
+ /// PrintHex - Print a value as a hexidecimal value.
+ ///
+ void PrintHex(int Value) 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.
+ void EmitULEB128Bytes(unsigned Value) const;
- // 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")
- {}
+ /// EmitSLEB128Bytes - print an assembler byte data directive to compose a
+ /// signed leb128 value.
+ void EmitSLEB128Bytes(int Value) const;
- /// SetDebugInfo - Set DebugInfo at when it's know that pass manager
- /// has created it.
- void SetDebugInfo(MachineDebugInfo *di) { DebugInfo = di; }
+ /// 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);
- /// EmitHex - Emit a hexidecimal string to the output stream.
- ///
- void EmitHex(unsigned Value) const;
+ /// PrintSLEB128 - Print a series of hexidecimal values (separated by
+ /// commas) representing a signed leb128 value.
+ void PrintSLEB128(int Value) const;
- /// EmitComment - Emit a simple string comment.
+ /// 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 EmitComment(const char *Comment) const;
+ void EmitByte(int Value) const;
- /// EmitULEB128 - Emit a series of hexidecimal values (separated by commas)
- /// representing an unsigned leb128 value.
+ /// EmitShort - Emit a short directive and value.
///
- void EmitULEB128(unsigned Value) const;
+ void EmitShort(int Value) const;
- /// EmitSLEB128 - Emit a series of hexidecimal values (separated by commas)
- /// representing a signed leb128 value.
+ /// EmitLong - Emit a long directive and value.
///
- void EmitSLEB128(int Value) const;
+ void EmitLong(int Value) const;
- /// EmitLabelName - Emit label name for internal use by dwarf.
+ /// 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 EmitLabelName(const char *Tag, int Num) const;
+ 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.
+ /// EmitLabel - Emit location label for internal use by Dwarf.
///
- void EmitLabel(const char *Tag, int Num) const;
+ void EmitLabel(DWLabel Label) const {
+ EmitLabel(Label.Tag, Label.Number);
+ }
+ void EmitLabel(const char *Tag, unsigned Number) 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.)
+ /// 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 EmitULEB128Bytes(unsigned Value, const char *Comment) const;
+ void EmitInitial() 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.)
+ /// EmitDIE - Recusively Emits a debug information entry.
///
- void EmitSLEB128Bytes(int Value, const char *Comment) const;
+ void EmitDIE(DIE *Die) const;
- /// EmitInitial - Emit initial dwarf declarations.
+ /// SizeAndOffsetDie - Compute the size and offset of a DIE.
///
- void EmitInitial() const;
+ unsigned SizeAndOffsetDie(DIE *Die, unsigned Offset) const;
+
+ /// SizeAndOffsets - Compute the size and offset of all the DIEs.
+ ///
+ void SizeAndOffsets();
- /// ShouldEmitDwarf - Returns true if dwarf declarations should be made.
+ /// 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.
+ /// so the initial Dwarf headers are emitted.
bool ShouldEmitDwarf();
-
- /// BeginModule - Emit all dwarf sections that should come prior to the
+
+ 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
diff --git a/include/llvm/CodeGen/MachineDebugInfo.h b/include/llvm/CodeGen/MachineDebugInfo.h
index 039bdbc0d5..5846748e24 100644
--- a/include/llvm/CodeGen/MachineDebugInfo.h
+++ b/include/llvm/CodeGen/MachineDebugInfo.h
@@ -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; }
+ bool doInitialization();
+
- /// getNextUniqueID - Returns a unique number for labels used by debugger.
+ /// doFinalization - Tear down the debug state after completion of a module.
///
- unsigned getNextUniqueID() { return UniqueID++; }
+ bool doFinalization();
+
+ /// hasInfo - Returns true if debug info is present.
+ ///
+ // FIXME - need proper scheme to suppress debug output.
+ bool hasInfo() const { return !SourceFiles.empty(); }
/// 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();
+ /// 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();
}
- bool doInitialization();
- bool doFinalization();
+ /// 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));
+ }
- /// getUniqueSourceID - Register a source file with debug info. Returns an id.
- ///
- unsigned getUniqueSourceID(const std::string &fname,
- const std::string &dirname);
+ /// getDirectories - Return the UniqueVector of std::string representing
+ /// directories.
+ const UniqueVector<std::string> &getDirectories() const {
+ return Directories;
+ }
- /// getSourceFiles - Return a vector of files. Vector index + 1 equals id.
+ /// 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
diff --git a/lib/CodeGen/DwarfWriter.cpp b/lib/CodeGen/DwarfWriter.cpp
index b44b1aaa55..67a6464e16 100644
--- a/lib/CodeGen/DwarfWriter.cpp
+++ b/lib/CodeGen/DwarfWriter.cpp
@@ -13,6 +13,7 @@
#include "llvm/CodeGen/DwarfWriter.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/MachineDebugInfo.h"
#include "llvm/Support/CommandLine.h"
@@ -23,90 +24,776 @@ using namespace llvm;
static cl::opt<bool>
DwarfVerbose("dwarf-verbose", cl::Hidden,
- cl::desc("Add comments to dwarf directives."));
+ cl::desc("Add comments to Dwarf directives."));
-/// 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.)
+//===----------------------------------------------------------------------===//
+// Dwarf abbreviations used by this emitter.
+//
+
+static const unsigned char AbbrevTAG_compile_unit[] = {
+ DW_TAG_compile_unit, DW_CHILDREN_yes,
+ DW_AT_stmt_list, DW_FORM_data4,
+ DW_AT_high_pc, DW_FORM_addr,
+ DW_AT_low_pc, DW_FORM_addr,
+ DW_AT_producer, DW_FORM_string,
+ DW_AT_language, DW_FORM_data1,
+ DW_AT_name, DW_FORM_string,
+ DW_AT_comp_dir, DW_FORM_string,
+ 0, 0
+};
+
+static const unsigned char AbbrevTAG_subprogram[] = {
+ DW_TAG_subprogram, DW_CHILDREN_yes,
+ DW_AT_sibling, DW_FORM_ref4,
+ DW_AT_external, DW_FORM_flag,
+ DW_AT_name, DW_FORM_string,
+ DW_AT_decl_file, DW_FORM_data1,
+ DW_AT_decl_line, DW_FORM_data1,
+ DW_AT_prototyped, DW_FORM_flag,
+ DW_AT_type, DW_FORM_ref4,
+ DW_AT_low_pc, DW_FORM_addr,
+ DW_AT_high_pc, DW_FORM_addr,
+ DW_AT_frame_base, DW_FORM_block1,
+ 0, 0
+};
+
+static const unsigned char AbbrevTAG_formal_parameter[] = {
+ DW_TAG_formal_parameter, DW_CHILDREN_no,
+ DW_AT_name, DW_FORM_string,
+ DW_AT_decl_file, DW_FORM_data1,
+ DW_AT_decl_line, DW_FORM_data1,
+ DW_AT_type, DW_FORM_ref4,
+ DW_AT_location, DW_FORM_block1,
+ 0, 0
+};
+
+static const unsigned char AbbrevTAG_base_type[] = {
+ DW_TAG_base_type, DW_CHILDREN_no,
+ DW_AT_name, DW_FORM_string,
+ DW_AT_byte_size, DW_FORM_data1,
+ DW_AT_encoding, DW_FORM_data1,
+ 0, 0
+};
+
+static const unsigned char AbbrevTAG_pointer_type[] = {
+ DW_TAG_pointer_type, DW_CHILDREN_no,
+ DW_AT_byte_size, DW_FORM_data1,
+ DW_AT_type, DW_FORM_ref4,
+ 0, 0
+};
+
+static const unsigned char AbbrevTAG_array_type[] = {
+ DW_TAG_array_type, DW_CHILDREN_yes,
+ DW_AT_sibling, DW_FORM_ref4,
+ DW_AT_type, DW_FORM_ref4,
+ 0, 0
+};
+
+static const unsigned char AbbrevTAG_subrange_type[] = {
+ DW_TAG_subrange_type, DW_CHILDREN_no,
+ 0, 0
+};
+
+static const unsigned char AbbrevTAG_variable[] = {
+ DW_TAG_variable, DW_CHILDREN_no,
+ DW_AT_name, DW_FORM_string,
+ DW_AT_type, DW_FORM_ref4,
+ DW_AT_external, DW_FORM_flag,
+ DW_AT_artificial, DW_FORM_flag,
+ DW_AT_declaration, DW_FORM_flag,
+ 0, 0
+};
+
+//===----------------------------------------------------------------------===//
+
+/// TagString - Return the string for the specified tag.
///
-void DwarfWriter::EmitULEB128Bytes(unsigned Value, const char *Comment) const {
- if (hasLEB128) {
- O << "\t.uleb128\t"
- << Value;
- } else {
- O << Asm->Data8bitsDirective;
- EmitULEB128(Value);
+static const char *TagString(unsigned Tag) {
+ switch(Tag) {
+ case DW_TAG_array_type: return "TAG_array_type";
+ case DW_TAG_class_type: return "TAG_class_type";
+ case DW_TAG_entry_point: return "TAG_entry_point";
+ case DW_TAG_enumeration_type: return "TAG_enumeration_type";
+ case DW_TAG_formal_parameter: return "TAG_formal_parameter";
+ case DW_TAG_imported_declaration: return "TAG_imported_declaration";
+ case DW_TAG_label: return "TAG_label";
+ case DW_TAG_lexical_block: return "TAG_lexical_block";
+ case DW_TAG_member: return "TAG_member";
+ case DW_TAG_pointer_type: return "TAG_pointer_type";
+ case DW_TAG_reference_type: return "TAG_reference_type";
+ case DW_TAG_compile_unit: return "TAG_compile_unit";
+ case DW_TAG_string_type: return "TAG_string_type";
+ case DW_TAG_structure_type: return "TAG_structure_type";
+ case DW_TAG_subroutine_type: return "TAG_subroutine_type";
+ case DW_TAG_typedef: return "TAG_typedef";
+ case DW_TAG_union_type: return "TAG_union_type";
+ case DW_TAG_unspecified_parameters: return "TAG_unspecified_parameters";
+ case DW_TAG_variant: return "TAG_variant";
+ case DW_TAG_common_block: return "TAG_common_block";
+ case DW_TAG_common_inclusion: return "TAG_common_inclusion";
+ case DW_TAG_inheritance: return "TAG_inheritance";
+ case DW_TAG_inlined_subroutine: return "TAG_inlined_subroutine";
+ case DW_TAG_module: return "TAG_module";
+ case DW_TAG_ptr_to_member_type: return "TAG_ptr_to_member_type";
+ case DW_TAG_set_type: return "TAG_set_type";
+ case DW_TAG_subrange_type: return "TAG_subrange_type";
+ case DW_TAG_with_stmt: return "TAG_with_stmt";
+ case DW_TAG_access_declaration: return "TAG_access_declaration";
+ case DW_TAG_base_type: return "TAG_base_type";
+ case DW_TAG_catch_block: return "TAG_catch_block";
+ case DW_TAG_const_type: return "TAG_const_type";
+ case DW_TAG_constant: return "TAG_constant";
+ case DW_TAG_enumerator: return "TAG_enumerator";
+ case DW_TAG_file_type: return "TAG_file_type";
+ case DW_TAG_friend: return "TAG_friend";
+ case DW_TAG_namelist: return "TAG_namelist";
+ case DW_TAG_namelist_item: return "TAG_namelist_item";
+ case DW_TAG_packed_type: return "TAG_packed_type";
+ case DW_TAG_subprogram: return "TAG_subprogram";
+ case DW_TAG_template_type_parameter: return "TAG_template_type_parameter";
+ case DW_TAG_template_value_parameter: return "TAG_template_value_parameter";
+ case DW_TAG_thrown_type: return "TAG_thrown_type";
+ case DW_TAG_try_block: return "TAG_try_block";
+ case DW_TAG_variant_part: return "TAG_variant_part";
+ case DW_TAG_variable: return "TAG_variable";
+ case DW_TAG_volatile_type: return "TAG_volatile_type";
+ case DW_TAG_dwarf_procedure: return "TAG_dwarf_procedure";
+ case DW_TAG_restrict_type: return "TAG_restrict_type";
+ case DW_TAG_interface_type: return "TAG_interface_type";
+ case DW_TAG_namespace: return "TAG_namespace";
+ case DW_TAG_imported_module: return "TAG_imported_module";
+ case DW_TAG_unspecified_type: return "TAG_unspecified_type";
+ case DW_TAG_partial_unit: return "TAG_partial_unit";
+ case DW_TAG_imported_unit: return "TAG_imported_unit";
+ case DW_TAG_condition: return "TAG_condition";