aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llvm/CodeGen/DwarfWriter.h325
-rw-r--r--lib/CodeGen/DwarfWriter.cpp582
2 files changed, 658 insertions, 249 deletions
diff --git a/include/llvm/CodeGen/DwarfWriter.h b/include/llvm/CodeGen/DwarfWriter.h
index c371783a55..8c0bcb9ec5 100644
--- a/include/llvm/CodeGen/DwarfWriter.h
+++ b/include/llvm/CodeGen/DwarfWriter.h
@@ -438,6 +438,15 @@ namespace llvm {
};
//===--------------------------------------------------------------------===//
+ // Forward declarations.
+ //
+ class AsmPrinter;
+ class DIE;
+ class DwarfWriter;
+ class DWContext;
+ class MachineDebugInfo;
+
+ //===--------------------------------------------------------------------===//
// 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
@@ -445,57 +454,89 @@ namespace llvm {
struct DWLabel {
const char *Tag; // Label category tag. Should always be
// a staticly declared C string.
- unsigned Number; // Unique number
+ unsigned Number; // Unique number.
- DWLabel() : Tag(NULL), Number(0) {}
DWLabel(const char *T, unsigned N) : Tag(T), Number(N) {}
};
-
+
+ //===--------------------------------------------------------------------===//
+ // DIEAbbrevData - Dwarf abbreviation data, describes the one attribute of a
+ // Dwarf abbreviation.
+ class DIEAbbrevData {
+ private:
+ unsigned Attribute; // Dwarf attribute code.
+ unsigned Form; // Dwarf form code.
+
+ public:
+ DIEAbbrevData(unsigned A, unsigned F)
+ : Attribute(A)
+ , Form(F)
+ {}
+
+ // Accessors
+ unsigned getAttribute() const { return Attribute; }
+ unsigned getForm() const { return Form; }
+ };
+
//===--------------------------------------------------------------------===//
// 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.
+ unsigned Tag; // Dwarf tag code.
+ unsigned ChildrenFlag; // Dwarf children flag.
+ std::vector<DIEAbbrevData> Data; // Raw data bytes for abbreviation.
public:
- DIEAbbrev(const unsigned char *D)
- : Data(D)
+ DIEAbbrev(unsigned T, unsigned C)
+ : Tag(T)
+ , ChildrenFlag(C)
+ , Data()
{}
+ ~DIEAbbrev() {}
+ // Accessors
+ unsigned getTag() const { return Tag; }
+ unsigned getChildrenFlag() const { return ChildrenFlag; }
+ const std::vector<DIEAbbrevData> &getData() const { return Data; }
+
/// operator== - Used by UniqueVector to locate entry.
///
- bool operator==(const DIEAbbrev &DA) const {
- return Data == DA.Data;
- }
+ bool operator==(const DIEAbbrev &DA) const;
/// operator< - Used by UniqueVector to locate entry.
///
- bool operator<(const DIEAbbrev &DA) const {
- return Data < DA.Data;
- }
+ bool operator<(const DIEAbbrev &DA) const;
- // 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]; }
+ /// AddAttribute - Adds another set of attribute information to the
+ /// abbreviation.
+ void AddAttribute(unsigned Attribute, unsigned Form) {
+ Data.push_back(DIEAbbrevData(Attribute, Form));
+ }
+
+ /// Emit - Print the abbreviation using the specified Dwarf writer.
+ ///
+ void Emit(const DwarfWriter &DW) const;
+
+#ifndef NDEBUG
+ void print(std::ostream &O);
+ void dump();
+#endif
};
//===--------------------------------------------------------------------===//
// DIEValue - A debug information entry value.
//
- class DwarfWriter;
class DIEValue {
public:
enum {
isInteger,
isString,
isLabel,
- isDelta
+ isAsIsLabel,
+ isDelta,
+ isEntry
};
unsigned Type; // Type of the value
@@ -520,14 +561,14 @@ namespace llvm {
//
class DIEInteger : public DIEValue {
private:
- int Value;
+ int Integer;
public:
- DIEInteger(int V) : DIEValue(isInteger), Value(V) {}
+ DIEInteger(int I) : DIEValue(isInteger), Integer(I) {}
// Implement isa/cast/dyncast.
static bool classof(const DIEInteger *) { return true; }
- static bool classof(const DIEValue *V) { return V->Type == isInteger; }
+ static bool classof(const DIEValue *I) { return I->Type == isInteger; }
/// EmitValue - Emit integer of appropriate size.
///
@@ -542,13 +583,13 @@ namespace llvm {
// DIEString - A string value DIE.
//
struct DIEString : public DIEValue {
- const std::string Value;
+ const std::string String;
- DIEString(const std::string &V) : DIEValue(isString), Value(V) {}
+ DIEString(const std::string &S) : DIEValue(isString), String(S) {}
// Implement isa/cast/dyncast.
static bool classof(const DIEString *) { return true; }
- static bool classof(const DIEValue *V) { return V->Type == isString; }
+ static bool classof(const DIEValue *S) { return S->Type == isString; }
/// EmitValue - Emit string value.
///
@@ -563,13 +604,35 @@ namespace llvm {
// DIELabel - A simple label expression DIE.
//
struct DIELabel : public DIEValue {
- const DWLabel Value;
+ const DWLabel Label;
+
+ DIELabel(const DWLabel &L) : DIEValue(isLabel), Label(L) {}
+
+ // Implement isa/cast/dyncast.
+ static bool classof(const DIELabel *) { return true; }
+ static bool classof(const DIEValue *L) { return L->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;
+ };
+
+
+ //===--------------------------------------------------------------------===//
+ // DIEAsIsLabel - An exact name of a label.
+ //
+ struct DIEAsIsLabel : public DIEValue {
+ const std::string Label;
- DIELabel(const DWLabel &V) : DIEValue(isLabel), Value(V) {}
+ DIEAsIsLabel(const std::string &L) : DIEValue(isAsIsLabel), Label(L) {}
// Implement isa/cast/dyncast.
- static bool classof(const DWLabel *) { return true; }
- static bool classof(const DIEValue *V) { return V->Type == isLabel; }
+ static bool classof(const DIEAsIsLabel *) { return true; }
+ static bool classof(const DIEValue *L) { return L->Type == isAsIsLabel; }
/// EmitValue - Emit label value.
///
@@ -584,15 +647,36 @@ namespace llvm {
// DIEDelta - A simple label difference DIE.
//
struct DIEDelta : public DIEValue {
- const DWLabel Value1;
- const DWLabel Value2;
+ const DWLabel LabelHi;
+ const DWLabel LabelLo;
- DIEDelta(const DWLabel &V1, const DWLabel &V2)
- : DIEValue(isDelta), Value1(V1), Value2(V2) {}
+ DIEDelta(const DWLabel &Hi, const DWLabel &Lo)
+ : DIEValue(isDelta), LabelHi(Hi), LabelLo(Lo) {}
// Implement isa/cast/dyncast.
static bool classof(const DIEDelta *) { return true; }
- static bool classof(const DIEValue *V) { return V->Type == isDelta; }
+ static bool classof(const DIEValue *D) { return D->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;
+ };
+
+ //===--------------------------------------------------------------------===//
+ // DIEntry - A pointer to a debug information entry.
+ //
+ struct DIEntry : public DIEValue {
+ DIE *Entry;
+
+ DIEntry(DIE *E) : DIEValue(isEntry), Entry(E) {}
+
+ // Implement isa/cast/dyncast.
+ static bool classof(const DIEntry *) { return true; }
+ static bool classof(const DIEValue *E) { return E->Type == isEntry; }
/// EmitValue - Emit delta value.
///
@@ -608,70 +692,106 @@ namespace llvm {
// describes it's organization.
class DIE {
private:
+ DIEAbbrev *Abbrev; // Temporary buffer for abbreviation.
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
+ unsigned Offset; // Offset in debug info section.
+ unsigned Size; // Size of instance + children.
+ DWContext *Context; // Context for types and values.
+ std::vector<DIE *> Children; // Children DIEs.
+ std::vector<DIEValue *> Values; // Attributes values.
public:
- DIE(unsigned AbbrevID)
- : AbbrevID(AbbrevID)
- , Offset(0)
- , Size(0)
- , Children()
- , Values()
- {}
- ~DIE() {
- for (unsigned i = 0, N = Children.size(); i < N; i++) {
- delete Children[i];
- }
-
- for (unsigned j = 0, M = Children.size(); j < M; j++) {
- delete Children[j];
- }
- }
+ DIE(unsigned Tag, unsigned ChildrenFlag);
+ ~DIE();
// Accessors
- unsigned getAbbrevID() const { return AbbrevID; }
- unsigned getOffset() const { return Offset; }
- unsigned getSize() const { return Size; }
+ unsigned getAbbrevID() const { return AbbrevID; }
+ unsigned getOffset() const { return Offset; }
+ unsigned getSize() const { return Size; }
+ DWContext *getContext() const { return Context; }
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));
- }
+ void setContext(DWContext *C) { Context = C; }
/// SiblingOffset - Return the offset of the debug information entry's
/// sibling.
unsigned SiblingOffset() const { return Offset + Size; }
- };
- //===--------------------------------------------------------------------===//
- // Forward declarations.
- //
- class AsmPrinter;
- class MachineDebugInfo;
+ /// AddInt - Add a simple integer attribute data and value.
+ ///
+ void AddInt(unsigned Attribute, unsigned Form, int Integer);
+
+ /// AddString - Add a std::string attribute data and value.
+ ///
+ void AddString(unsigned Attribute, unsigned Form,
+ const std::string &String);
+
+ /// AddLabel - Add a Dwarf label attribute data and value.
+ ///
+ void AddLabel(unsigned Attribute, unsigned Form, const DWLabel &Label);
+
+ /// AddAsIsLabel - Add a non-Dwarf label attribute data and value.
+ ///
+ void AddAsIsLabel(unsigned Attribute, unsigned Form,
+ const std::string &Label);
+
+ /// AddDelta - Add a label delta attribute data and value.
+ ///
+ void AddDelta(unsigned Attribute, unsigned Form,
+ const DWLabel &Hi, const DWLabel &Lo);
+
+ /// AddDIEntry - Add a DIE attribute data and value.
+ ///
+ void AddDIEntry(unsigned Attribute, unsigned Form, DIE *Entry);
+
+ /// Complete - Indicate that all attributes have been added and
+ /// ready to get an abbreviation ID.
+ ///
+ void Complete(DwarfWriter &DW);
+
+ /// AddChild - Add a child to the DIE.
+ void AddChild(DIE *Child);
+ };
//===--------------------------------------------------------------------===//
- // DwarfWriter - emits Dwarf debug and exception handling directives.
+ /// DWContext - Name context for types and values.
+ ///
+ class DWContext {
+ private:
+ DwarfWriter &DW; // DwarfWriter for global information.
+ DIE *Owner; // Owning debug information entry.
+ std::map<std::string, DIE*> Types; // Named types in context.
+ std::map<std::string, DIE*> Variables;// Named variables in context.
+
+ public:
+ DWContext(DwarfWriter &D, DIE *O)
+ : DW(D)
+ , Owner(O)
+ , Types()
+ , Variables()
+ {
+ Owner->setContext(this);
+ }
+ ~DWContext() {}
+
+ /// NewBasicType - Creates a new basic type, if necessary, then adds in the
+ /// context and owner.
+ DIE *NewBasicType(const std::string &Name, unsigned Size,
+ unsigned Encoding);
+
+ /// NewVariable - Creates a basic variable, if necessary, then adds in the
+ /// context and owner.
+ DIE *NewVariable(const std::string &Name,
+ unsigned SourceFileID, unsigned Line,
+ DIE *Type, bool IsExternal);
+ };
+
+ //===--------------------------------------------------------------------===//
+ // DwarfWriter - Emits Dwarf debug and exception handling directives.
//
class DwarfWriter {
-
protected:
//===------------------------------------------------------------------===//
@@ -707,6 +827,18 @@ namespace llvm {
///
UniqueVector<DIEAbbrev> Abbreviations;
+ /// GlobalTypes - A map of globally visible named types.
+ ///
+ std::map<std::string, DIE *> GlobalTypes;
+
+ /// GlobalEntities - A map of globally visible named entities.
+ ///
+ std::map<std::string, DIE *> GlobalEntities;
+
+ /// StringPool - A UniqueVector of strings used by indirect references.
+ ///
+ UniqueVector<std::string> StringPool;
+
//===------------------------------------------------------------------===//
// Properties to be set by the derived class ctor, used to configure the
// Dwarf writer.
@@ -861,21 +993,34 @@ public:
EmitReference(Label.Tag, Label.Number);
}
void EmitReference(const char *Tag, unsigned Number) const;
+ void EmitReference(const std::string Name) 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(DWLabel LabelHi, DWLabel LabelLo) const {
+ EmitDifference(LabelHi.Tag, LabelHi.Number, LabelLo.Tag, LabelLo.Number);
}
- void EmitDifference(const char *Tag1, unsigned Number1,
- const char *Tag2, unsigned Number2) const;
+ void EmitDifference(const char *TagHi, unsigned NumberHi,
+ const char *TagLo, unsigned NumberLo) const;
-private:
- /// NewDIE - Construct a new structured debug information entry.
+ /// NewAbbreviation - Add the abbreviation to the Abbreviation vector.
///
- DIE *NewDIE(const unsigned char *AbbrevData);
+ unsigned NewAbbreviation(DIEAbbrev *Abbrev);
+
+ /// NewString - Add a string to the constant pool and returns a label.
+ ///
+ DWLabel NewString(const std::string &String);
+
+ /// NewGlobalType - Make the type visible globally using the given name.
+ ///
+ void NewGlobalType(const std::string &Name, DIE *Type);
+
+ /// NewGlobalEntity - Make the entity visible globally using the given name.
+ ///
+ void NewGlobalEntity(const std::string &Name, DIE *Entity);
+private:
/// NewCompileUnit - Create new compile unit information.
///
DIE *NewCompileUnit(const std::string &Directory,
@@ -956,7 +1101,7 @@ private:
void SetDebugInfo(MachineDebugInfo *di) { DebugInfo = di; }
//===------------------------------------------------------------------===//
- // Main enties.
+ // Main entry points.
//
/// BeginModule - Emit all Dwarf sections that should come prior to the
diff --git a/lib/CodeGen/DwarfWriter.cpp b/lib/CodeGen/DwarfWriter.cpp
index 824e94fc26..a90a13a076 100644
--- a/lib/CodeGen/DwarfWriter.cpp
+++ b/lib/CodeGen/DwarfWriter.cpp
@@ -27,84 +27,6 @@ DwarfVerbose("dwarf-verbose", cl::Hidden,
cl::desc("Add comments to Dwarf directives."));
//===----------------------------------------------------------------------===//
-// 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.
///
@@ -659,13 +581,102 @@ static const char *CallFrameString(unsigned Encoding) {
//===----------------------------------------------------------------------===//
+/// operator== - Used by UniqueVector to locate entry.
+///
+bool DIEAbbrev::operator==(const DIEAbbrev &DA) const {
+ if (Tag != DA.Tag) return false;
+ if (ChildrenFlag != DA.ChildrenFlag) return false;
+ if (Data.size() != DA.Data.size()) return false;
+
+ for (unsigned i = 0, N = Data.size(); i < N; i++) {
+ const DIEAbbrevData &AttrData = Data[i];
+ const DIEAbbrevData &DAAttrData = Data[i];
+ if (AttrData.getAttribute() != DAAttrData.getAttribute()) return false;
+ if (AttrData.getForm() != DAAttrData.getForm()) return false;
+ }
+
+ return true;
+}
+
+/// operator< - Used by UniqueVector to locate entry.
+///
+bool DIEAbbrev::operator<(const DIEAbbrev &DA) const {
+ if (Tag != DA.Tag) return Tag < DA.Tag;
+ if (ChildrenFlag != DA.ChildrenFlag) return ChildrenFlag < DA.ChildrenFlag;
+ if (Data.size() != DA.Data.size()) return Data.size() < DA.Data.size();
+
+ for (unsigned i = 0, N = Data.size(); i < N; i++) {
+ const DIEAbbrevData &AttrData = Data[i];
+ const DIEAbbrevData &DAAttrData = DA.Data[i];
+ if (AttrData.getAttribute() != DAAttrData.getAttribute())
+ return AttrData.getAttribute() < DAAttrData.getAttribute();
+ if (AttrData.getForm() != DAAttrData.getForm())
+ return AttrData.getForm() < DAAttrData.getForm();
+ }
+
+ return false;
+}
+
+/// Emit - Print the abbreviation using the specified Dwarf writer.
+///
+void DIEAbbrev::Emit(const DwarfWriter &DW) const {
+ // Emit its Dwarf tag type.
+ DW.EmitULEB128Bytes(Tag);
+ DW.EOL(TagString(Tag));
+
+ // Emit whether it has children DIEs.
+ DW.EmitULEB128Bytes(ChildrenFlag);
+ DW.EOL(ChildrenString(ChildrenFlag));
+
+ // For each attribute description.
+ for (unsigned i = 0, N = Data.size(); i < N; i++) {
+ const DIEAbbrevData &AttrData = Data[i];
+
+ // Emit attribute type.
+ DW.EmitULEB128Bytes(AttrData.getAttribute());
+ DW.EOL(AttributeString(AttrData.getAttribute()));
+
+ // Emit form type.
+ DW.EmitULEB128Bytes(AttrData.getForm());
+ DW.EOL(FormEncodingString(AttrData.getForm()));
+ }
+
+ // Mark end of abbreviation.
+ DW.EmitULEB128Bytes(0); DW.EOL("EOM(1)");
+ DW.EmitULEB128Bytes(0); DW.EOL("EOM(2)");
+}
+
+#ifndef NDEBUG
+ void DIEAbbrev::print(std::ostream &O) {
+ O << "Abbreviation @"
+ << std::hex << (unsigned)this << std::dec
+ << " "
+ << TagString(Tag)
+ << " "
+ << ChildrenString(ChildrenFlag)
+ << "\n";
+
+ for (unsigned i = 0, N = Data.size(); i < N; i++) {
+ O << " "
+ << AttributeString(Data[i].getAttribute())
+ << " "
+ << FormEncodingString(Data[i].getForm())
+ << "\n";
+ }
+ }
+ void DIEAbbrev::dump() { print(std::cerr); }
+#endif
+
+//===----------------------------------------------------------------------===//
+
/// EmitValue - Emit integer of appropriate size.
///
void DIEInteger::EmitValue(const DwarfWriter &DW, unsigned Form) const {
switch (Form) {
- case DW_FORM_data1: DW.EmitByte(Value); break;
- case DW_FORM_data2: DW.EmitShort(Value); break;
- case DW_FORM_data4: DW.EmitLong(Value); break;
+ case DW_FORM_data1: // Fall thru
+ case DW_FORM_flag: DW.EmitByte(Integer); break;
+ case DW_FORM_data2: DW.EmitShort(Integer); break;
+ case DW_FORM_data4: DW.EmitLong(Integer); break;
default: assert(0 && "DIE Value form not supported yet"); break;
}
}
@@ -674,6 +685,7 @@ void DIEInteger::EmitValue(const DwarfWriter &DW, unsigned Form) const {
///
unsigned DIEInteger::SizeOf(const DwarfWriter &DW, unsigned Form) const {
switch (Form) {
+ case DW_FORM_flag: // Fall thru
case DW_FORM_data1: return sizeof(int8_t);
case DW_FORM_data2: return sizeof(int16_t);
case DW_FORM_data4: return sizeof(int32_t);
@@ -687,13 +699,13 @@ unsigned DIEInteger::SizeOf(const DwarfWriter &DW, unsigned Form) const {
/// EmitValue - Emit string value.
///
void DIEString::EmitValue(const DwarfWriter &DW, unsigned Form) const {
- DW.EmitString(Value);
+ DW.EmitString(String);
}
/// SizeOf - Determine size of string value in bytes.
///
unsigned DIEString::SizeOf(const DwarfWriter &DW, unsigned Form) const {
- return Value.size() + sizeof(int8_t);
+ return String.size() + sizeof('\0');
}
//===----------------------------------------------------------------------===//
@@ -701,7 +713,7 @@ unsigned DIEString::SizeOf(const DwarfWriter &DW, unsigned Form) const {
/// EmitValue - Emit label value.
///
void DIELabel::EmitValue(const DwarfWriter &DW, unsigned Form) const {
- DW.EmitReference(Value);
+ DW.EmitReference(Label);
}
/// SizeOf - Determine size of label value in bytes.
@@ -712,10 +724,24 @@ unsigned DIELabel::SizeOf(const DwarfWriter &DW, unsigned Form) const {
//===----------------------------------------------------------------------===//
+/// EmitValue - Emit label value.
+///
+void DIEAsIsLabel::EmitValue(const DwarfWriter &DW, unsigned Form) const {
+ DW.EmitReference(Label);
+}
+
+/// SizeOf - Determine size of label value in bytes.
+///
+unsigned DIEAsIsLabel::SizeOf(const DwarfWriter &DW, unsigned Form) const {
+ return DW.getAddressSize();
+}
+
+//===----------------------------------------------------------------------===//
+
/// EmitValue - Emit delta value.
///
void DIEDelta::EmitValue(const DwarfWriter &DW, unsigned Form) const {
- DW.EmitDifference(Value1, Value2);
+ DW.EmitDifference(LabelHi, LabelLo);
}
/// SizeOf - Determine size of delta value in bytes.
@@ -725,6 +751,171 @@ unsigned DIEDelta::SizeOf(const DwarfWriter &DW, unsigned Form) const {
}
//===----------------------------------------------------------------------===//
+/// EmitValue - Emit extry offset.
+///
+void DIEntry::EmitValue(const DwarfWriter &DW, unsigned Form) const {
+ DW.EmitLong(Entry->getOffset());
+}
+
+/// SizeOf - Determine size of label value in bytes.
+///
+unsigned DIEntry::SizeOf(const DwarfWriter &DW, unsigned Form) const {
+ return sizeof(int32_t);
+}
+
+//===----------------------------------------------------------------------===//
+
+DIE::DIE(unsigned Tag, unsigned ChildrenFlag)
+: Abbrev(new DIEAbbrev(Tag, ChildrenFlag))
+, AbbrevID(0)
+, Offset(0)
+, Size(0)
+, Context(NULL)
+, Children()
+, Values()
+{}
+
+DIE::~DIE() {
+ if (Abbrev) delete Abbrev;
+
+ for (unsigned i = 0, N = Children.size(); i < N; i++) {
+ delete Children[i];
+ }
+
+ for (unsigned j = 0, M = Values.size(); j < M; j++) {
+ delete Values[j];
+ }
+
+ if (Context) delete Context;
+}
+
+/// AddInt - Add a simple integer attribute data and value.
+///
+void DIE::AddInt(unsigned Attribute, unsigned Form,
+ int Integer) {
+ Abbrev->AddAttribute(Attribute, Form);
+ Values.push_back(new DIEInteger(Integer));
+}
+
+/// AddString - Add a std::string attribute data and value.
+///
+void DIE::AddString(unsigned Attribute, unsigned Form,
+ const std::string &String) {
+ Abbrev->AddAttribute(Attribute, Form);
+ Values.push_back(new DIEString(String));
+}
+
+/// AddLabel - Add a Dwarf label attribute data and value.
+///
+void DIE::AddLabel(unsigned Attribute, unsigned Form,
+ const DWLabel &Label) {
+ Abbrev->AddAttribute(Attribute, Form);
+ Values.push_back(new DIELabel(Label));
+}
+
+/// AddAsIsLabel - Add an non-Dwarf label attribute data and value.
+///
+void DIE::AddAsIsLabel(unsigned Attribute, unsigned Form,
+ const std::string &Label) {
+ Abbrev->AddAttribute(Attribute, Form);
+ Values.push_back(new DIEAsIsLabel(Label));
+}
+
+/// AddDelta - Add a label delta attribute data and value.
+///
+void DIE::AddDelta(unsigned Attribute, unsigned Form,
+ const DWLabel &Hi, const DWLabel &Lo) {
+ Abbrev->AddAttribute(Attribute, Form);
+ Values.push_back(new DIEDelta(Hi, Lo));
+}
+
+/// AddDIEntry - Add a DIE attribute data and value.
+///
+void DIE::AddDIEntry(unsigned Attribute,
+ unsigned Form, DIE *Entry) {
+ Abbrev->AddAttribute(Attribute, Form);
+ Values.push_back(new DIEntry(Entry));
+}
+
+/// Complete - Indicate that all attributes have been added and ready to get an
+/// abbreviation ID.
+void DIE::Complete(DwarfWriter &DW) {
+ AbbrevID = DW.NewAbbreviation(Abbrev);
+ delete Abbrev;
+ Abbrev = NULL;
+}
+
+/// AddChild - Add a child to the DIE.
+///
+void DIE::AddChild(DIE *Child) {
+ Children.push_back(Child);
+}
+
+//===----------------------------------------------------------------------===//
+
+/// NewBasicType - Creates a new basic type if necessary, then adds in the
+/// context and owner.
+DIE *DWContext::NewBasicType(const std::string &Name, unsigned Size,
+ unsigned Encoding) {
+ // FIXME - Just a prototype.
+ DIE *Type = Types[Name];
+
+ // If first occurance of type.
+ if (!Type) {
+ // construct the type DIE.
+ Type = new DIE(DW_TAG_base_type, DW_CHILDREN_no);
+ Type->AddString(DW_AT_name, DW_FORM_string, Name);
+ Type->AddInt (DW_AT_byte_size, DW_FORM_data1, Size);
+ Type->AddInt (DW_AT_encoding, DW_FORM_data1, Encoding);
+ Type->Complete(DW);
+
+ // Add to context owner.
+ Owner->AddChild(Type);
+
+ // Add to map.
+ Types[Name] = Type;
+ }
+
+ return Type;
+}
+
+/// NewVariable - Creates a basic variable, if necessary, then adds in the
+/// context and owner.
+DIE *DWContext::NewVariable(const std::string &Name,
+ unsigned SourceFileID, unsigned Line,
+ DIE *Type, bool IsExternal) {
+ // FIXME - Just a prototype.
+ DIE *Variable = Variables[Name];
+
+ // If first occurance of variable.
+ if (!Variable) {
+ assert(IsExternal && "Internal variables not handled yet");
+ Variable = new DIE(DW_TAG_variable, DW_CHILDREN_no);
+ Variable->AddString (DW_AT_name, DW_FORM_string, Name);
+ Variable->AddInt (DW_AT_decl_file, DW_FORM_data1, SourceFileID);
+ Variable->AddInt (DW_AT_decl_line, DW_FORM_data1, Line);
+ Variable->AddDIEntry (DW_AT_type, DW_FORM_ref4, Type);
+ Variable->AddInt (DW_AT_external, DW_FORM_flag, (int)IsExternal);
+ Variable->AddAsIsLabel(DW_AT_location, DW_FORM_block1,
+ std::string("_")+Name+".b");
+ Variable->Complete(DW);
+
+ // Add to context owner.
+ Owner->AddChild(Variable);
+
+ // Add to map.
+ Variables[Name] = Variable;
+
+ // If external add to visible names.
+ if (IsExternal) {
+ DW.NewGlobalEntity(Name, Variable);
+ }
+ }
+
+ return Variable;
+}
+
+//===----------------------------------------------------------------------===//
/// PrintHex - Print a value as a hexidecimal value.
///
@@ -903,20 +1094,29 @@ void DwarfWriter::EmitReference(const char *Tag, unsigned Number) const {
PrintLabelName(Tag, Number);
}
+void DwarfWriter::EmitReference(const std::string Name) const {
+ if (AddressSize == 4)
+ O << Asm->Data32bitsDirective;
+ else
+ O << Asm->Data64bitsDirective;
+
+ O << Name;
+}
/// EmitDifference - Emit an label difference as sizeof(pointer) value. Some
/// assemblers do not accept absolute expressions with data directives, so there
/// is an option (needsSet) to use an intermediary 'set' expression.
-void DwarfWriter::EmitDifference(const char *Tag1, unsigned Number1,
- const char *Tag2, unsigned Number2) const {
+void DwarfWriter::EmitDifference(const char *TagHi, unsigned NumberHi,
+ const char *TagLo, unsigned NumberLo) const {
if (needsSet) {
static unsigned SetCounter = 0;
+
O << "\t.set\t";
PrintLabelName("set", SetCounter);
O << ",";
- PrintLabelName(Tag1, Number1);
+ PrintLabelName(TagHi, NumberHi);
O << "-";
- PrintLabelName(Tag2, Number2);
+ PrintLabelName(TagLo, NumberLo);
O << "\n";
if (AddressSize == sizeof(int32_t))
@@ -933,40 +1133,58 @@ void DwarfWriter::EmitDifference(const char *Tag1, unsigned Number1,
else
O << Asm->Data64bitsDirective;
- PrintLabelName(Tag1, Number1);
+ PrintLabelName(TagHi, NumberHi);
O << "-";
- PrintLabelName(Tag2, Number2);
+ PrintLabelName(TagLo, NumberLo);
}
}
-/// NewDIE - Construct a new structured debug information entry.
+/// NewAbbreviation - Add the abbreviation to the Abbreviation vector.
///
-DIE *DwarfWriter::NewDIE(const unsigned char *AbbrevData) {
- // Get the abbreviation ID.
- unsigned AbbrevID = Abbreviations.insert(DIEAbbrev(AbbrevData));
- // Allocate new new structured DIE.
- DIE *Die = new DIE(AbbrevID);
- // Return structured DIE.
- return Die;
+unsigned DwarfWriter::NewAbbreviation(DIEAbbrev *Abbrev) {
+ return Abbreviations.insert(*Abbrev);
+}
+
+/// NewString - Add a string to the constant pool and returns a label.
+///
+DWLabel DwarfWriter::NewString(const std::string &String) {
+ unsigned StringID = StringPool.insert(String);
+ return DWLabel("string", StringID);
+}
+
+/// NewGlobalType - Make the type visible globally using the given name.
+///
+void DwarfWriter::NewGlobalType(const std::string &Name, DIE *Type) {
+ // FIXME - check for duplication.
+ GlobalTypes[Name] = Type;
+}
+
+/// NewGlobalEntity - Make the entity visible globally using the given name.
+///
+void DwarfWriter::NewGlobalEntity(const std::string &Name, DIE *Entity) {
+ // FIXME - check for duplication.
+ GlobalEntities[Name] = Entity;
}
/// NewCompileUnit - Create new compile unit information.
///
DIE *DwarfWriter::NewCompileUnit(const std::string &Directory,
const std::string &SourceName) {
- DIE *Die = NewDIE(AbbrevTAG_compile_unit);
+ DIE *Unit = new DIE(DW_TAG_compile_unit, DW_CHILDREN_yes);
// FIXME - use the correct line set.
- Die->AddValue(DWLabel("line", 0));
- Die->AddValue(DWLabel("text_end", 0));
- Die->AddValue(DWLabel("text_begin", 0));
+ Unit->AddLabel (DW_AT_stmt_list, DW_FORM_data4, DWLabel("line", 0));
+ Unit->AddLabel (DW_AT_high_pc, DW_FORM_addr, DWLabel("text_end", 0));
+ Unit->AddLabel (DW_AT_low_pc, DW_FORM_addr, DWLabel("text_begin", 0));
// FIXME - The producer needs to be in this form, but should come from
// an appropriate source.
- Die->AddValue("llvm 3.4.x (LLVM Research Group)");
- Die->AddValue(DW_LANG_C89);
- Die->AddValue(SourceName);
- Die->AddValue(Directory);
+ Unit->AddString(DW_AT_producer, DW_FORM_string,
+ "llvm 3.4.x (LLVM Research Group)");
+ Unit->AddInt (DW_AT_language, DW_FORM_data1, DW_LANG_C89);
+ Unit->AddString(DW_AT_name, DW_FORM_string, SourceName);
+ Unit->AddString(DW_AT_comp_dir, DW_FORM_string, Directory);
+ Unit->Complete(*this);
- return Die;
+ return Unit;
}
/// EmitInitial - Emit initial Dwarf declarations. This is necessar