diff options
author | Jim Laskey <jlaskey@mac.com> | 2006-01-17 17:31:53 +0000 |
---|---|---|
committer | Jim Laskey <jlaskey@mac.com> | 2006-01-17 17:31:53 +0000 |
commit | 063e765345fd49df0f53b807e57ada7c2ded7e16 (patch) | |
tree | 851e46dbfed06121b4a50f55c467b376c4c25d6e | |
parent | 08a0464763a93be5f201b2d6d514732e810ef2ad (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.h | 446 | ||||
-rw-r--r-- | include/llvm/CodeGen/MachineDebugInfo.h | 144 | ||||
-rw-r--r-- | lib/CodeGen/DwarfWriter.cpp | 1344 | ||||
-rw-r--r-- | lib/CodeGen/MachineDebugInfo.cpp | 42 | ||||
-rw-r--r-- | lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 2 | ||||
-rw-r--r-- | lib/Target/PowerPC/PPCAsmPrinter.cpp | 14 |
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"; + case DW_TAG_shared_type: return "TAG_shared_type"; + case DW_TAG_lo_user: return "TAG_lo_user"; + case DW_TAG_hi_user: return "TAG_hi_user"; } - if (DwarfVerbose) { - O << "\t" - << Asm->CommentString - << " " - << Comment - << " " - << Value; + assert(0 && "Unknown Dwarf Tag"); + return ""; +} + +/// ChildrenString - Return the string for the specified children flag. +/// +static const char *ChildrenString(unsigned Children) { + switch(Children) { + case DW_CHILDREN_no: return "CHILDREN_no"; + case DW_CHILDREN_yes: return "CHILDREN_yes"; } - O << "\n"; + assert(0 && "Unknown Dwarf ChildrenFl |