aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/AsmPrinter/DwarfWriter.cpp
diff options
context:
space:
mode:
authorBill Wendling <isanbard@gmail.com>2009-05-15 09:23:25 +0000
committerBill Wendling <isanbard@gmail.com>2009-05-15 09:23:25 +0000
commit0310d768a1e267935729fdeee0d677ebf7095cb3 (patch)
tree19d839ff2d8c785021cfa8689cd5ebd4c5861d40 /lib/CodeGen/AsmPrinter/DwarfWriter.cpp
parentca37b511fa1e542c936402c0023455fd9a444e76 (diff)
Split out the DwarfDebug module from the DwarfWriter module.
Again, no intendtional functionality change. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@71854 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/AsmPrinter/DwarfWriter.cpp')
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfWriter.cpp2798
1 files changed, 2 insertions, 2796 deletions
diff --git a/lib/CodeGen/AsmPrinter/DwarfWriter.cpp b/lib/CodeGen/AsmPrinter/DwarfWriter.cpp
index 71f73a59f5..483ee559ff 100644
--- a/lib/CodeGen/AsmPrinter/DwarfWriter.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfWriter.cpp
@@ -12,2810 +12,16 @@
//===----------------------------------------------------------------------===//
#include "llvm/CodeGen/DwarfWriter.h"
-#include "DIE.h"
+#include "DwarfDebug.h"
#include "DwarfException.h"
-#include "DwarfPrinter.h"
-#include "llvm/Module.h"
-#include "llvm/DerivedTypes.h"
-#include "llvm/Constants.h"
-#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
-#include "llvm/CodeGen/MachineFrameInfo.h"
-#include "llvm/CodeGen/MachineLocation.h"
-#include "llvm/Analysis/DebugInfo.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/Dwarf.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/DataTypes.h"
-#include "llvm/Support/Mangler.h"
-#include "llvm/Support/Timer.h"
-#include "llvm/Support/raw_ostream.h"
-#include "llvm/System/Path.h"
-#include "llvm/Target/TargetAsmInfo.h"
-#include "llvm/Target/TargetRegisterInfo.h"
-#include "llvm/Target/TargetData.h"
-#include "llvm/Target/TargetFrameInfo.h"
-#include "llvm/Target/TargetInstrInfo.h"
-#include "llvm/Target/TargetMachine.h"
-#include "llvm/Target/TargetOptions.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/FoldingSet.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/StringMap.h"
-#include <ostream>
-#include <string>
+
using namespace llvm;
-using namespace llvm::dwarf;
static RegisterPass<DwarfWriter>
X("dwarfwriter", "DWARF Information Writer");
char DwarfWriter::ID = 0;
-static TimerGroup &getDwarfTimerGroup() {
- static TimerGroup DwarfTimerGroup("Dwarf Exception and Debugging");
- return DwarfTimerGroup;
-}
-
-namespace llvm {
-
-//===----------------------------------------------------------------------===//
-
-/// Configuration values for initial hash set sizes (log2).
-///
-static const unsigned InitDiesSetSize = 9; // log2(512)
-static const unsigned InitAbbreviationsSetSize = 9; // log2(512)
-static const unsigned InitValuesSetSize = 9; // log2(512)
-
-//===----------------------------------------------------------------------===//
-/// CompileUnit - This dwarf writer support class manages information associate
-/// with a source file.
-class VISIBILITY_HIDDEN CompileUnit {
- /// ID - File identifier for source.
- ///
- unsigned ID;
-
- /// Die - Compile unit debug information entry.
- ///
- DIE *Die;
-
- /// GVToDieMap - Tracks the mapping of unit level debug informaton
- /// variables to debug information entries.
- std::map<GlobalVariable *, DIE *> GVToDieMap;
-
- /// GVToDIEEntryMap - Tracks the mapping of unit level debug informaton
- /// descriptors to debug information entries using a DIEEntry proxy.
- std::map<GlobalVariable *, DIEEntry *> GVToDIEEntryMap;
-
- /// Globals - A map of globally visible named entities for this unit.
- ///
- StringMap<DIE*> Globals;
-
- /// DiesSet - Used to uniquely define dies within the compile unit.
- ///
- FoldingSet<DIE> DiesSet;
-public:
- CompileUnit(unsigned I, DIE *D)
- : ID(I), Die(D), GVToDieMap(),
- GVToDIEEntryMap(), Globals(), DiesSet(InitDiesSetSize)
- {}
-
- ~CompileUnit() {
- delete Die;
- }
-
- // Accessors.
- unsigned getID() const { return ID; }
- DIE* getDie() const { return Die; }
- StringMap<DIE*> &getGlobals() { return Globals; }
-
- /// hasContent - Return true if this compile unit has something to write out.
- ///
- bool hasContent() const {
- return !Die->getChildren().empty();
- }
-
- /// AddGlobal - Add a new global entity to the compile unit.
- ///
- void AddGlobal(const std::string &Name, DIE *Die) {
- Globals[Name] = Die;
- }
-
- /// getDieMapSlotFor - Returns the debug information entry map slot for the
- /// specified debug variable.
- DIE *&getDieMapSlotFor(GlobalVariable *GV) {
- return GVToDieMap[GV];
- }
-
- /// getDIEEntrySlotFor - Returns the debug information entry proxy slot for the
- /// specified debug variable.
- DIEEntry *&getDIEEntrySlotFor(GlobalVariable *GV) {
- return GVToDIEEntryMap[GV];
- }
-
- /// AddDie - Adds or interns the DIE to the compile unit.
- ///
- DIE *AddDie(DIE &Buffer) {
- FoldingSetNodeID ID;
- Buffer.Profile(ID);
- void *Where;
- DIE *Die = DiesSet.FindNodeOrInsertPos(ID, Where);
-
- if (!Die) {
- Die = new DIE(Buffer);
- DiesSet.InsertNode(Die, Where);
- this->Die->AddChild(Die);
- Buffer.Detach();
- }
-
- return Die;
- }
-};
-
-//===----------------------------------------------------------------------===//
-/// SrcLineInfo - This class is used to record source line correspondence.
-///
-class VISIBILITY_HIDDEN SrcLineInfo {
- unsigned Line; // Source line number.
- unsigned Column; // Source column.
- unsigned SourceID; // Source ID number.
- unsigned LabelID; // Label in code ID number.
-public:
- SrcLineInfo(unsigned L, unsigned C, unsigned S, unsigned I)
- : Line(L), Column(C), SourceID(S), LabelID(I) {}
-
- // Accessors
- unsigned getLine() const { return Line; }
- unsigned getColumn() const { return Column; }
- unsigned getSourceID() const { return SourceID; }
- unsigned getLabelID() const { return LabelID; }
-};
-
-//===----------------------------------------------------------------------===//
-/// DbgVariable - This class is used to track local variable information.
-///
-class VISIBILITY_HIDDEN DbgVariable {
- DIVariable Var; // Variable Descriptor.
- unsigned FrameIndex; // Variable frame index.
-public:
- DbgVariable(DIVariable V, unsigned I) : Var(V), FrameIndex(I) {}
-
- // Accessors.
- DIVariable getVariable() const { return Var; }
- unsigned getFrameIndex() const { return FrameIndex; }
-};
-
-//===----------------------------------------------------------------------===//
-/// DbgScope - This class is used to track scope information.
-///
-class DbgConcreteScope;
-class VISIBILITY_HIDDEN DbgScope {
- DbgScope *Parent; // Parent to this scope.
- DIDescriptor Desc; // Debug info descriptor for scope.
- // Either subprogram or block.
- unsigned StartLabelID; // Label ID of the beginning of scope.
- unsigned EndLabelID; // Label ID of the end of scope.
- SmallVector<DbgScope *, 4> Scopes; // Scopes defined in scope.
- SmallVector<DbgVariable *, 8> Variables;// Variables declared in scope.
- SmallVector<DbgConcreteScope *, 8> ConcreteInsts;// Concrete insts of funcs.
-public:
- DbgScope(DbgScope *P, DIDescriptor D)
- : Parent(P), Desc(D), StartLabelID(0), EndLabelID(0) {}
- virtual ~DbgScope();
-
- // Accessors.
- DbgScope *getParent() const { return Parent; }
- DIDescriptor getDesc() const { return Desc; }
- unsigned getStartLabelID() const { return StartLabelID; }
- unsigned getEndLabelID() const { return EndLabelID; }
- SmallVector<DbgScope *, 4> &getScopes() { return Scopes; }
- SmallVector<DbgVariable *, 8> &getVariables() { return Variables; }
- SmallVector<DbgConcreteScope*,8> &getConcreteInsts() { return ConcreteInsts; }
- void setStartLabelID(unsigned S) { StartLabelID = S; }
- void setEndLabelID(unsigned E) { EndLabelID = E; }
-
- /// AddScope - Add a scope to the scope.
- ///
- void AddScope(DbgScope *S) { Scopes.push_back(S); }
-
- /// AddVariable - Add a variable to the scope.
- ///
- void AddVariable(DbgVariable *V) { Variables.push_back(V); }
-
- /// AddConcreteInst - Add a concrete instance to the scope.
- ///
- void AddConcreteInst(DbgConcreteScope *C) { ConcreteInsts.push_back(C); }
-
-#ifndef NDEBUG
- void dump() const;
-#endif
-};
-
-#ifndef NDEBUG
-void DbgScope::dump() const {
- static unsigned IndentLevel = 0;
- std::string Indent(IndentLevel, ' ');
-
- cerr << Indent; Desc.dump();
- cerr << " [" << StartLabelID << ", " << EndLabelID << "]\n";
-
- IndentLevel += 2;
-
- for (unsigned i = 0, e = Scopes.size(); i != e; ++i)
- if (Scopes[i] != this)
- Scopes[i]->dump();
-
- IndentLevel -= 2;
-}
-#endif
-
-//===----------------------------------------------------------------------===//
-/// DbgConcreteScope - This class is used to track a scope that holds concrete
-/// instance information.
-///
-class VISIBILITY_HIDDEN DbgConcreteScope : public DbgScope {
- CompileUnit *Unit;
- DIE *Die; // Debug info for this concrete scope.
-public:
- DbgConcreteScope(DIDescriptor D) : DbgScope(NULL, D) {}
-
- // Accessors.
- DIE *getDie() const { return Die; }
- void setDie(DIE *D) { Die = D; }
-};
-
-DbgScope::~DbgScope() {
- for (unsigned i = 0, N = Scopes.size(); i < N; ++i)
- delete Scopes[i];
- for (unsigned j = 0, M = Variables.size(); j < M; ++j)
- delete Variables[j];
- for (unsigned k = 0, O = ConcreteInsts.size(); k < O; ++k)
- delete ConcreteInsts[k];
-}
-
-//===----------------------------------------------------------------------===//
-/// DwarfDebug - Emits Dwarf debug directives.
-///
-class VISIBILITY_HIDDEN DwarfDebug : public Dwarf {
- //===--------------------------------------------------------------------===//
- // Attributes used to construct specific Dwarf sections.
- //
-
- /// CompileUnitMap - A map of global variables representing compile units to
- /// compile units.
- DenseMap<Value *, CompileUnit *> CompileUnitMap;
-
- /// CompileUnits - All the compile units in this module.
- ///
- SmallVector<CompileUnit *, 8> CompileUnits;
-
- /// MainCU - Some platform prefers one compile unit per .o file. In such
- /// cases, all dies are inserted in MainCU.
- CompileUnit *MainCU;
-
- /// AbbreviationsSet - Used to uniquely define abbreviations.
- ///
- FoldingSet<DIEAbbrev> AbbreviationsSet;
-
- /// Abbreviations - A list of all the unique abbreviations in use.
- ///
- std::vector<DIEAbbrev *> Abbreviations;
-
- /// DirectoryIdMap - Directory name to directory id map.
- ///
- StringMap<unsigned> DirectoryIdMap;
-
- /// DirectoryNames - A list of directory names.
- SmallVector<std::string, 8> DirectoryNames;
-
- /// SourceFileIdMap - Source file name to source file id map.
- ///
- StringMap<unsigned> SourceFileIdMap;
-
- /// SourceFileNames - A list of source file names.
- SmallVector<std::string, 8> SourceFileNames;
-
- /// SourceIdMap - Source id map, i.e. pair of directory id and source file
- /// id mapped to a unique id.
- DenseMap<std::pair<unsigned, unsigned>, unsigned> SourceIdMap;
-
- /// SourceIds - Reverse map from source id to directory id + file id pair.
- ///
- SmallVector<std::pair<unsigned, unsigned>, 8> SourceIds;
-
- /// Lines - List of of source line correspondence.
- std::vector<SrcLineInfo> Lines;
-
- /// ValuesSet - Used to uniquely define values.
- ///
- FoldingSet<DIEValue> ValuesSet;
-
- /// Values - A list of all the unique values in use.
- ///
- std::vector<DIEValue *> Values;
-
- /// StringPool - A UniqueVector of strings used by indirect references.
- ///
- UniqueVector<std::string> StringPool;
-
- /// SectionMap - Provides a unique id per text section.
- ///
- UniqueVector<const Section*> SectionMap;
-
- /// SectionSourceLines - Tracks line numbers per text section.
- ///
- std::vector<std::vector<SrcLineInfo> > SectionSourceLines;
-
- /// didInitial - Flag to indicate if initial emission has been done.
- ///
- bool didInitial;
-
- /// shouldEmit - Flag to indicate if debug information should be emitted.
- ///
- bool shouldEmit;
-
- // FunctionDbgScope - Top level scope for the current function.
- //
- DbgScope *FunctionDbgScope;
-
- /// DbgScopeMap - Tracks the scopes in the current function.
- DenseMap<GlobalVariable *, DbgScope *> DbgScopeMap;
-
- /// DbgAbstractScopeMap - Tracks abstract instance scopes in the current
- /// function.
- DenseMap<GlobalVariable *, DbgScope *> DbgAbstractScopeMap;
-
- /// DbgConcreteScopeMap - Tracks concrete instance scopes in the current
- /// function.
- DenseMap<GlobalVariable *,
- SmallVector<DbgScope *, 8> > DbgConcreteScopeMap;
-
- /// InlineInfo - Keep track of inlined functions and their location. This
- /// information is used to populate debug_inlined section.
- DenseMap<GlobalVariable *, SmallVector<unsigned, 4> > InlineInfo;
-
- /// InlinedVariableScopes - Scopes information for the inlined subroutine
- /// variables.
- DenseMap<const MachineInstr *, DbgScope *> InlinedVariableScopes;
-
- /// AbstractInstanceRootMap - Map of abstract instance roots of inlined
- /// functions. These are subroutine entries that contain a DW_AT_inline
- /// attribute.
- DenseMap<const GlobalVariable *, DbgScope *> AbstractInstanceRootMap;
-
- /// AbstractInstanceRootList - List of abstract instance roots of inlined
- /// functions. These are subroutine entries that contain a DW_AT_inline
- /// attribute.
- SmallVector<DbgScope *, 32> AbstractInstanceRootList;
-
- /// LexicalScopeStack - A stack of lexical scopes. The top one is the current
- /// scope.
- SmallVector<DbgScope *, 16> LexicalScopeStack;
-
- /// CompileUnitOffsets - A vector of the offsets of the compile units. This is
- /// used when calculating the "origin" of a concrete instance of an inlined
- /// function.
- DenseMap<CompileUnit *, unsigned> CompileUnitOffsets;
-
- /// DebugTimer - Timer for the Dwarf debug writer.
- Timer *DebugTimer;
-
- struct FunctionDebugFrameInfo {
- unsigned Number;
- std::vector<MachineMove> Moves;
-
- FunctionDebugFrameInfo(unsigned Num, const std::vector<MachineMove> &M):
- Number(Num), Moves(M) { }
- };
-
- std::vector<FunctionDebugFrameInfo> DebugFrames;
-
-private:
- /// getSourceDirectoryAndFileIds - Return the directory and file ids that
- /// maps to the source id. Source id starts at 1.
- std::pair<unsigned, unsigned>
- getSourceDirectoryAndFileIds(unsigned SId) const {
- return SourceIds[SId-1];
- }
-
- /// getNumSourceDirectories - Return the number of source directories in the
- /// debug info.
- unsigned getNumSourceDirectories() const {
- return DirectoryNames.size();
- }
-
- /// getSourceDirectoryName - Return the name of the directory corresponding
- /// to the id.
- const std::string &getSourceDirectoryName(unsigned Id) const {
- return DirectoryNames[Id - 1];
- }
-
- /// getSourceFileName - Return the name of the source file corresponding
- /// to the id.
- const std::string &getSourceFileName(unsigned Id) const {
- return SourceFileNames[Id - 1];
- }
-
- /// getNumSourceIds - Return the number of unique source ids.
- unsigned getNumSourceIds() const {
- return SourceIds.size();
- }
-
- /// AssignAbbrevNumber - Define a unique number for the abbreviation.
- ///
- void AssignAbbrevNumber(DIEAbbrev &Abbrev) {
- // Profile the node so that we can make it unique.
- FoldingSetNodeID ID;
- Abbrev.Profile(ID);
-
- // Check the set for priors.
- DIEAbbrev *InSet = AbbreviationsSet.GetOrInsertNode(&Abbrev);
-
- // If it's newly added.
- if (InSet == &Abbrev) {
- // Add to abbreviation list.
- Abbreviations.push_back(&Abbrev);
- // Assign the vector position + 1 as its number.
- Abbrev.setNumber(Abbreviations.size());
- } else {
- // Assign existing abbreviation number.
- Abbrev.setNumber(InSet->getNumber());
- }
- }
-
- /// NewString - Add a string to the constant pool and returns a label.
- ///
- DWLabel NewString(const std::string &String) {
- unsigned StringID = StringPool.insert(String);
- return DWLabel("string", StringID);
- }
-
- /// NewDIEEntry - Creates a new DIEEntry to be a proxy for a debug information
- /// entry.
- DIEEntry *NewDIEEntry(DIE *Entry = NULL) {
- DIEEntry *Value;
-
- if (Entry) {
- FoldingSetNodeID ID;
- DIEEntry::Profile(ID, Entry);
- void *Where;
- Value = static_cast<DIEEntry *>(ValuesSet.FindNodeOrInsertPos(ID, Where));
-
- if (Value) return Value;
-
- Value = new DIEEntry(Entry);
- ValuesSet.InsertNode(Value, Where);
- } else {
- Value = new DIEEntry(Entry);
- }
-
- Values.push_back(Value);
- return Value;
- }
-
- /// SetDIEEntry - Set a DIEEntry once the debug information entry is defined.
- ///
- void SetDIEEntry(DIEEntry *Value, DIE *Entry) {
- Value->setEntry(Entry);
- // Add to values set if not already there. If it is, we merely have a
- // duplicate in the values list (no harm.)
- ValuesSet.GetOrInsertNode(Value);
- }
-
- /// AddUInt - Add an unsigned integer attribute data and value.
- ///
- void AddUInt(DIE *Die, unsigned Attribute, unsigned Form, uint64_t Integer) {
- if (!Form) Form = DIEInteger::BestForm(false, Integer);
-
- FoldingSetNodeID ID;
- DIEInteger::Profile(ID, Integer);
- void *Where;
- DIEValue *Value = ValuesSet.FindNodeOrInsertPos(ID, Where);
- if (!Value) {
- Value = new DIEInteger(Integer);
- ValuesSet.InsertNode(Value, Where);
- Values.push_back(Value);
- }
-
- Die->AddValue(Attribute, Form, Value);
- }
-
- /// AddSInt - Add an signed integer attribute data and value.
- ///
- void AddSInt(DIE *Die, unsigned Attribute, unsigned Form, int64_t Integer) {
- if (!Form) Form = DIEInteger::BestForm(true, Integer);
-
- FoldingSetNodeID ID;
- DIEInteger::Profile(ID, (uint64_t)Integer);
- void *Where;
- DIEValue *Value = ValuesSet.FindNodeOrInsertPos(ID, Where);
- if (!Value) {
- Value = new DIEInteger(Integer);
- ValuesSet.InsertNode(Value, Where);
- Values.push_back(Value);
- }
-
- Die->AddValue(Attribute, Form, Value);
- }
-
- /// AddString - Add a string attribute data and value.
- ///
- void AddString(DIE *Die, unsigned Attribute, unsigned Form,
- const std::string &String) {
- FoldingSetNodeID ID;
- DIEString::Profile(ID, String);
- void *Where;
- DIEValue *Value = ValuesSet.FindNodeOrInsertPos(ID, Where);
- if (!Value) {
- Value = new DIEString(String);
- ValuesSet.InsertNode(Value, Where);
- Values.push_back(Value);
- }
-
- Die->AddValue(Attribute, Form, Value);
- }
-
- /// AddLabel - Add a Dwarf label attribute data and value.
- ///
- void AddLabel(DIE *Die, unsigned Attribute, unsigned Form,
- const DWLabel &Label) {
- FoldingSetNodeID ID;
- DIEDwarfLabel::Profile(ID, Label);
- void *Where;
- DIEValue *Value = ValuesSet.FindNodeOrInsertPos(ID, Where);
- if (!Value) {
- Value = new DIEDwarfLabel(Label);
- ValuesSet.InsertNode(Value, Where);
- Values.push_back(Value);
- }
-
- Die->AddValue(Attribute, Form, Value);
- }
-
- /// AddObjectLabel - Add an non-Dwarf label attribute data and value.
- ///
- void AddObjectLabel(DIE *Die, unsigned Attribute, unsigned Form,
- const std::string &Label) {
- FoldingSetNodeID ID;
- DIEObjectLabel::Profile(ID, Label);
- void *Where;
- DIEValue *Value = ValuesSet.FindNodeOrInsertPos(ID, Where);
- if (!Value) {
- Value = new DIEObjectLabel(Label);
- ValuesSet.InsertNode(Value, Where);
- Values.push_back(Value);
- }
-
- Die->AddValue(Attribute, Form, Value);
- }
-
- /// AddSectionOffset - Add a section offset label attribute data and value.
- ///
- void AddSectionOffset(DIE *Die, unsigned Attribute, unsigned Form,
- const DWLabel &Label, const DWLabel &Section,
- bool isEH = false, bool useSet = true) {
- FoldingSetNodeID ID;
- DIESectionOffset::Profile(ID, Label, Section);
- void *Where;
- DIEValue *Value = ValuesSet.FindNodeOrInsertPos(ID, Where);
- if (!Value) {
- Value = new DIESectionOffset(Label, Section, isEH, useSet);
- ValuesSet.InsertNode(Value, Where);
- Values.push_back(Value);
- }
-
- Die->AddValue(Attribute, Form, Value);
- }
-
- /// AddDelta - Add a label delta attribute data and value.
- ///
- void AddDelta(DIE *Die, unsigned Attribute, unsigned Form,
- const DWLabel &Hi, const DWLabel &Lo) {
- FoldingSetNodeID ID;
- DIEDelta::Profile(ID, Hi, Lo);
- void *Where;
- DIEValue *Value = ValuesSet.FindNodeOrInsertPos(ID, Where);
- if (!Value) {
- Value = new DIEDelta(Hi, Lo);
- ValuesSet.InsertNode(Value, Where);
- Values.push_back(Value);
- }
-
- Die->AddValue(Attribute, Form, Value);
- }
-
- /// AddDIEEntry - Add a DIE attribute data and value.
- ///
- void AddDIEEntry(DIE *Die, unsigned Attribute, unsigned Form, DIE *Entry) {
- Die->AddValue(Attribute, Form, NewDIEEntry(Entry));
- }
-
- /// AddBlock - Add block data.
- ///
- void AddBlock(DIE *Die, unsigned Attribute, unsigned Form, DIEBlock *Block) {
- Block->ComputeSize(TD);
- FoldingSetNodeID ID;
- Block->Profile(ID);
- void *Where;
- DIEValue *Value = ValuesSet.FindNodeOrInsertPos(ID, Where);
- if (!Value) {
- Value = Block;
- ValuesSet.InsertNode(Value, Where);
- Values.push_back(Value);
- } else {
- // Already exists, reuse the previous one.
- delete Block;
- Block = cast<DIEBlock>(Value);
- }
-
- Die->AddValue(Attribute, Block->BestForm(), Value);
- }
-
- /// AddSourceLine - Add location information to specified debug information
- /// entry.
- void AddSourceLine(DIE *Die, const DIVariable *V) {
- // If there is no compile unit specified, don't add a line #.
- if (V->getCompileUnit().isNull())
- return;
-
- unsigned Line = V->getLineNumber();
- unsigned FileID = FindCompileUnit(V->getCompileUnit()).getID();
- assert(FileID && "Invalid file id");
- AddUInt(Die, DW_AT_decl_file, 0, FileID);
- AddUInt(Die, DW_AT_decl_line, 0, Line);
- }
-
- /// AddSourceLine - Add location information to specified debug information
- /// entry.
- void AddSourceLine(DIE *Die, const DIGlobal *G) {
- // If there is no compile unit specified, don't add a line #.
- if (G->getCompileUnit().isNull())
- return;
- unsigned Line = G->getLineNumber();
- unsigned FileID = FindCompileUnit(G->getCompileUnit()).getID();
- assert(FileID && "Invalid file id");
- AddUInt(Die, DW_AT_decl_file, 0, FileID);
- AddUInt(Die, DW_AT_decl_line, 0, Line);
- }
-
- void AddSourceLine(DIE *Die, const DIType *Ty) {
- // If there is no compile unit specified, don't add a line #.
- DICompileUnit CU = Ty->getCompileUnit();
- if (CU.isNull())
- return;
-
- unsigned Line = Ty->getLineNumber();
- unsigned FileID = FindCompileUnit(CU).getID();
- assert(FileID && "Invalid file id");
- AddUInt(Die, DW_AT_decl_file, 0, FileID);
- AddUInt(Die, DW_AT_decl_line, 0, Line);
- }
-
- /// AddAddress - Add an address attribute to a die based on the location
- /// provided.
- void AddAddress(DIE *Die, unsigned Attribute,
- const MachineLocation &Location) {
- unsigned Reg = RI->getDwarfRegNum(Location.getReg(), false);
- DIEBlock *Block = new DIEBlock();
-
- if (Location.isReg()) {
- if (Reg < 32) {
- AddUInt(Block, 0, DW_FORM_data1, DW_OP_reg0 + Reg);
- } else {
- AddUInt(Block, 0, DW_FORM_data1, DW_OP_regx);
- AddUInt(Block, 0, DW_FORM_udata, Reg);
- }
- } else {
- if (Reg < 32) {
- AddUInt(Block, 0, DW_FORM_data1, DW_OP_breg0 + Reg);
- } else {
- AddUInt(Block, 0, DW_FORM_data1, DW_OP_bregx);
- AddUInt(Block, 0, DW_FORM_udata, Reg);
- }
- AddUInt(Block, 0, DW_FORM_sdata, Location.getOffset());
- }
-
- AddBlock(Die, Attribute, 0, Block);
- }
-
- /// AddType - Add a new type attribute to the specified entity.
- void AddType(CompileUnit *DW_Unit, DIE *Entity, DIType Ty) {
- if (Ty.isNull())
- return;
-
- // Check for pre-existence.
- DIEEntry *&Slot = DW_Unit->getDIEEntrySlotFor(Ty.getGV());
- // If it exists then use the existing value.
- if (Slot) {
- Entity->AddValue(DW_AT_type, DW_FORM_ref4, Slot);
- return;
- }
-
- // Set up proxy.
- Slot = NewDIEEntry();
-
- // Construct type.
- DIE Buffer(DW_TAG_base_type);
- if (Ty.isBasicType(Ty.getTag()))
- ConstructTypeDIE(DW_Unit, Buffer, DIBasicType(Ty.getGV()));
- else if (Ty.isDerivedType(Ty.getTag()))
- ConstructTypeDIE(DW_Unit, Buffer, DIDerivedType(Ty.getGV()));
- else {
- assert(Ty.isCompositeType(Ty.getTag()) && "Unknown kind of DIType");
- ConstructTypeDIE(DW_Unit, Buffer, DICompositeType(Ty.getGV()));
- }
-
- // Add debug information entry to entity and appropriate context.
- DIE *Die = NULL;
- DIDescriptor Context = Ty.getContext();
- if (!Context.isNull())
- Die = DW_Unit->getDieMapSlotFor(Context.getGV());
-
- if (Die) {
- DIE *Child = new DIE(Buffer);
- Die->AddChild(Child);
- Buffer.Detach();
- SetDIEEntry(Slot, Child);
- } else {
- Die = DW_Unit->AddDie(Buffer);
- SetDIEEntry(Slot, Die);
- }
-
- Entity->AddValue(DW_AT_type, DW_FORM_ref4, Slot);
- }
-
- /// ConstructTypeDIE - Construct basic type die from DIBasicType.
- void ConstructTypeDIE(CompileUnit *DW_Unit, DIE &Buffer,
- DIBasicType BTy) {
-
- // Get core information.
- std::string Name;
- BTy.getName(Name);
- Buffer.setTag(DW_TAG_base_type);
- AddUInt(&Buffer, DW_AT_encoding, DW_FORM_data1, BTy.getEncoding());
- // Add name if not anonymous or intermediate type.
- if (!Name.empty())
- AddString(&Buffer, DW_AT_name, DW_FORM_string, Name);
- uint64_t Size = BTy.getSizeInBits() >> 3;
- AddUInt(&Buffer, DW_AT_byte_size, 0, Size);
- }
-
- /// ConstructTypeDIE - Construct derived type die from DIDerivedType.
- void ConstructTypeDIE(CompileUnit *DW_Unit, DIE &Buffer,
- DIDerivedType DTy) {
-
- // Get core information.
- std::string Name;
- DTy.getName(Name);
- uint64_t Size = DTy.getSizeInBits() >> 3;
- unsigned Tag = DTy.getTag();
-
- // FIXME - Workaround for templates.
- if (Tag == DW_TAG_inheritance) Tag = DW_TAG_reference_type;
-
- Buffer.setTag(Tag);
-
- // Map to main type, void will not have a type.
- DIType FromTy = DTy.getTypeDerivedFrom();
- AddType(DW_Unit, &Buffer, FromTy);
-
- // Add name if not anonymous or intermediate type.
- if (!Name.empty())
- AddString(&Buffer, DW_AT_name, DW_FORM_string, Name);
-
- // Add size if non-zero (derived types might be zero-sized.)
- if (Size)
- AddUInt(&Buffer, DW_AT_byte_size, 0, Size);
-
- // Add source line info if available and TyDesc is not a forward
- // declaration.
- if (!DTy.isForwardDecl())
- AddSourceLine(&Buffer, &DTy);
- }
-
- /// ConstructTypeDIE - Construct type DIE from DICompositeType.
- void ConstructTypeDIE(CompileUnit *DW_Unit, DIE &Buffer,
- DICompositeType CTy) {
- // Get core information.
- std::string Name;
- CTy.getName(Name);
-
- uint64_t Size = CTy.getSizeInBits() >> 3;
- unsigned Tag = CTy.getTag();
- Buffer.setTag(Tag);
-
- switch (Tag) {
- case DW_TAG_vector_type:
- case DW_TAG_array_type:
- ConstructArrayTypeDIE(DW_Unit, Buffer, &CTy);
- break;
- case DW_TAG_enumeration_type:
- {
- DIArray Elements = CTy.getTypeArray();
- // Add enumerators to enumeration type.
- for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) {
- DIE *ElemDie = NULL;
- DIEnumerator Enum(Elements.getElement(i).getGV());
- ElemDie = ConstructEnumTypeDIE(DW_Unit, &Enum);
- Buffer.AddChild(ElemDie);
- }
- }
- break;
- case DW_TAG_subroutine_type:
- {
- // Add return type.
- DIArray Elements = CTy.getTypeArray();
- DIDescriptor RTy = Elements.getElement(0);
- AddType(DW_Unit, &Buffer, DIType(RTy.getGV()));
-
- // Add prototype flag.
- AddUInt(&Buffer, DW_AT_prototyped, DW_FORM_flag, 1);
-
- // Add arguments.
- for (unsigned i = 1, N = Elements.getNumElements(); i < N; ++i) {
- DIE *Arg = new DIE(DW_TAG_formal_parameter);
- DIDescriptor Ty = Elements.getElement(i);
- AddType(DW_Unit, Arg, DIType(Ty.getGV()));
- Buffer.AddChild(Arg);
- }
- }
- break;
- case DW_TAG_structure_type:
- case DW_TAG_union_type:
- case DW_TAG_class_type:
- {
- // Add elements to structure type.
- DIArray Elements = CTy.getTypeArray();
-
- // A forward struct declared type may not have elements available.
- if (Elements.isNull())
- break;
-
- // Add elements to structure type.
- for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) {
- DIDescriptor Element = Elements.getElement(i);
- DIE *ElemDie = NULL;
- if (Element.getTag() == dwarf::DW_TAG_subprogram)
- ElemDie = CreateSubprogramDIE(DW_Unit,
- DISubprogram(Element.getGV()));
- else if (Element.getTag() == dwarf::DW_TAG_variable) // ??
- ElemDie = CreateGlobalVariableDIE(DW_Unit,
- DIGlobalVariable(Element.getGV()));
- else
- ElemDie = CreateMemberDIE(DW_Unit,
- DIDerivedType(Element.getGV()));
- Buffer.AddChild(ElemDie);
- }
-
- // FIXME: We'd like an API to register additional attributes for the
- // frontend to use while synthesizing, and then we'd use that api in
- // clang instead of this.
- if (Name == "__block_literal_generic")
- AddUInt(&Buffer, DW_AT_APPLE_block, DW_FORM_flag, 1);
-
- unsigned RLang = CTy.getRunTimeLang();
- if (RLang)
- AddUInt(&Buffer, DW_AT_APPLE_runtime_class, DW_FORM_data1, RLang);
- }
- break;
- default:
- break;
- }
-
- // Add name if not anonymous or intermediate type.
- if (!Name.empty())
- AddString(&Buffer, DW_AT_name, DW_FORM_string, Name);
-
- if (Tag == DW_TAG_enumeration_type || Tag == DW_TAG_structure_type
- || Tag == DW_TAG_union_type) {
- // Add size if non-zero (derived types might be zero-sized.)
- if (Size)
- AddUInt(&Buffer, DW_AT_byte_size, 0, Size);
- else {
- // Add zero size if it is not a forward declaration.
- if (CTy.isForwardDecl())
- AddUInt(&Buffer, DW_AT_declaration, DW_FORM_flag, 1);
- else
- AddUInt(&Buffer, DW_AT_byte_size, 0, 0);
- }
-
- // Add source line info if available.
- if (!CTy.isForwardDecl())
- AddSourceLine(&Buffer, &CTy);
- }
- }
-
- /// ConstructSubrangeDIE - Construct subrange DIE from DISubrange.
- void ConstructSubrangeDIE(DIE &Buffer, DISubrange SR, DIE *IndexTy) {
- int64_t L = SR.getLo();
- int64_t H = SR.getHi();
- DIE *DW_Subrange = new DIE(DW_TAG_subrange_type);
- if (L != H) {
- AddDIEEntry(DW_Subrange, DW_AT_type, DW_FORM_ref4, IndexTy);
- if (L)
- AddSInt(DW_Subrange, DW_AT_lower_bound, 0, L);
- AddSInt(DW_Subrange, DW_AT_upper_bound, 0, H);
- }
- Buffer.AddChild(DW_Subrange);
- }
-
- /// ConstructArrayTypeDIE - Construct array type DIE from DICompositeType.
- void ConstructArrayTypeDIE(CompileUnit *DW_Unit, DIE &Buffer,
- DICompositeType *CTy) {
- Buffer.setTag(DW_TAG_array_type);
- if (CTy->getTag() == DW_TAG_vector_type)
- AddUInt(&Buffer, DW_AT_GNU_vector, DW_FORM_flag, 1);
-
- // Emit derived type.
- AddType(DW_Unit, &Buffer, CTy->getTypeDerivedFrom());
- DIArray Elements = CTy->getTypeArray();
-
- // Construct an anonymous type for index type.
- DIE IdxBuffer(DW_TAG_base_type);
- AddUInt(&IdxBuffer, DW_AT_byte_size, 0, sizeof(int32_t));
- AddUInt(&IdxBuffer, DW_AT_encoding, DW_FORM_data1, DW_ATE_signed);
- DIE *IndexTy = DW_Unit->AddDie(IdxBuffer);
-
- // Add subranges to array type.
- for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) {
- DIDescriptor Element = Elements.getElement(i);
- if (Element.getTag() == dwarf::DW_TAG_subrange_type)
- ConstructSubrangeDIE(Buffer, DISubrange(Element.getGV()), IndexTy);
- }
- }
-
- /// ConstructEnumTypeDIE - Construct enum type DIE from DIEnumerator.
- DIE *ConstructEnumTypeDIE(CompileUnit *DW_Unit, DIEnumerator *ETy) {
-
- DIE *Enumerator = new DIE(DW_TAG_enumerator);
- std::string Name;
- ETy->getName(Name);
- AddString(Enumerator, DW_AT_name, DW_FORM_string, Name);
- int64_t Value = ETy->getEnumValue();
- AddSInt(Enumerator, DW_AT_const_value, DW_FORM_sdata, Value);
- return Enumerator;
- }
-
- /// CreateGlobalVariableDIE - Create new DIE using GV.
- DIE *CreateGlobalVariableDIE(CompileUnit *DW_Unit, const DIGlobalVariable &GV)
- {
- DIE *GVDie = new DIE(DW_TAG_variable);
- std::string Name;
- GV.getDisplayName(Name);
- AddString(GVDie, DW_AT_name, DW_FORM_string, Name);
- std::string LinkageName;
- GV.getLinkageName(LinkageName);
- if (!LinkageName.empty())
- AddString(GVDie, DW_AT_MIPS_linkage_name, DW_FORM_string, LinkageName);
- AddType(DW_Unit, GVDie, GV.getType());
- if (!GV.isLocalToUnit())
- AddUInt(GVDie, DW_AT_external, DW_FORM_flag, 1);
- AddSourceLine(GVDie, &GV);
- return GVDie;
- }
-
- /// CreateMemberDIE - Create new member DIE.
- DIE *CreateMemberDIE(CompileUnit *DW_Unit, const DIDerivedType &DT) {
- DIE *MemberDie = new DIE(DT.getTag());
- std::string Name;
- DT.getName(Name);
- if (!Name.empty())
- AddString(MemberDie, DW_AT_name, DW_FORM_string, Name);
-
- AddType(DW_Unit, MemberDie, DT.getTypeDerivedFrom());
-
- AddSourceLine(MemberDie, &DT);
-
- uint64_t Size = DT.getSizeInBits();
- uint64_t FieldSize = DT.getOriginalTypeSize();
-
- if (Size != FieldSize) {
- // Handle bitfield.
- AddUInt(MemberDie, DW_AT_byte_size, 0, DT.getOriginalTypeSize() >> 3);
- AddUInt(MemberDie, DW_AT_bit_size, 0, DT.getSizeInBits());
-
- uint64_t Offset = DT.getOffsetInBits();
- uint64_t FieldOffset = Offset;
- uint64_t AlignMask = ~(DT.getAlignInBits() - 1);
- uint64_t HiMark = (Offset + FieldSize) & AlignMask;
- FieldOffset = (HiMark - FieldSize);
- Offset -= FieldOffset;
- // Maybe we need to work from the other end.
- if (TD->isLittleEndian()) Offset = FieldSize - (Offset + Size);
- AddUInt(MemberDie, DW_AT_bit_offset, 0, Offset);
- }
- DIEBlock *Block = new DIEBlock();
- AddUInt(Block, 0, DW_FORM_data1, DW_OP_plus_uconst);