Crude Dwarf global variable debugging.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@25569 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Jim Laskey 2006-01-24 00:49:18 +00:00
parent 42a162ed80
commit 52060a0e71
3 changed files with 300 additions and 169 deletions

View File

@ -445,13 +445,17 @@ namespace llvm {
class DwarfWriter; class DwarfWriter;
class DWContext; class DWContext;
class MachineDebugInfo; class MachineDebugInfo;
class MachineFunction;
class Module;
class Type;
//===--------------------------------------------------------------------===// //===--------------------------------------------------------------------===//
// DWLabel - Labels are used to track locations in the assembler file. // 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 // 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 of label (Ex. location) and number is a value unique in that
// category. // category.
struct DWLabel { class DWLabel {
public:
const char *Tag; // Label category tag. Should always be const char *Tag; // Label category tag. Should always be
// a staticly declared C string. // a staticly declared C string.
unsigned Number; // Unique number. unsigned Number; // Unique number.
@ -620,15 +624,15 @@ namespace llvm {
}; };
//===--------------------------------------------------------------------===// //===--------------------------------------------------------------------===//
// DIELabel - A simple label expression DIE. // DIEDwarfLabel - A Dwarf internal label expression DIE.
// //
struct DIELabel : public DIEValue { struct DIEDwarfLabel : public DIEValue {
const DWLabel Label; const DWLabel Label;
DIELabel(const DWLabel &L) : DIEValue(isLabel), Label(L) {} DIEDwarfLabel(const DWLabel &L) : DIEValue(isLabel), Label(L) {}
// Implement isa/cast/dyncast. // Implement isa/cast/dyncast.
static bool classof(const DIELabel *) { return true; } static bool classof(const DIEDwarfLabel *) { return true; }
static bool classof(const DIEValue *L) { return L->Type == isLabel; } static bool classof(const DIEValue *L) { return L->Type == isLabel; }
/// EmitValue - Emit label value. /// EmitValue - Emit label value.
@ -642,15 +646,15 @@ namespace llvm {
//===--------------------------------------------------------------------===// //===--------------------------------------------------------------------===//
// DIEAsIsLabel - An exact name of a label. // DIEObjectLabel - A label to an object in code or data.
// //
struct DIEAsIsLabel : public DIEValue { struct DIEObjectLabel : public DIEValue {
const std::string Label; const std::string Label;
DIEAsIsLabel(const std::string &L) : DIEValue(isAsIsLabel), Label(L) {} DIEObjectLabel(const std::string &L) : DIEValue(isAsIsLabel), Label(L) {}
// Implement isa/cast/dyncast. // Implement isa/cast/dyncast.
static bool classof(const DIEAsIsLabel *) { return true; } static bool classof(const DIEObjectLabel *) { return true; }
static bool classof(const DIEValue *L) { return L->Type == isAsIsLabel; } static bool classof(const DIEValue *L) { return L->Type == isAsIsLabel; }
/// EmitValue - Emit label value. /// EmitValue - Emit label value.
@ -752,10 +756,10 @@ namespace llvm {
/// ///
void AddLabel(unsigned Attribute, unsigned Form, const DWLabel &Label); void AddLabel(unsigned Attribute, unsigned Form, const DWLabel &Label);
/// AddAsIsLabel - Add a non-Dwarf label attribute data and value. /// AddObjectLabel - Add a non-Dwarf label attribute data and value.
/// ///
void AddAsIsLabel(unsigned Attribute, unsigned Form, void AddObjectLabel(unsigned Attribute, unsigned Form,
const std::string &Label); const std::string &Label);
/// AddDelta - Add a label delta attribute data and value. /// AddDelta - Add a label delta attribute data and value.
/// ///
@ -781,13 +785,15 @@ namespace llvm {
class DWContext { class DWContext {
private: private:
DwarfWriter &DW; // DwarfWriter for global information. DwarfWriter &DW; // DwarfWriter for global information.
DWContext *Parent; // Next context level searched.
DIE *Owner; // Owning debug information entry. DIE *Owner; // Owning debug information entry.
std::map<std::string, DIE*> Types; // Named types in context. std::map<const Type *, DIE*> Types; // Named types in context.
std::map<std::string, DIE*> Variables;// Named variables in context. std::map<std::string, DIE*> Variables;// Named variables in context.
public: public:
DWContext(DwarfWriter &D, DIE *O) DWContext(DwarfWriter &D, DWContext *P, DIE *O)
: DW(D) : DW(D)
, Parent(P)
, Owner(O) , Owner(O)
, Types() , Types()
, Variables() , Variables()
@ -796,16 +802,15 @@ namespace llvm {
} }
~DWContext() {} ~DWContext() {}
/// NewBasicType - Creates a new basic type, if necessary, then adds in the /// NewBasicType - Creates a new basic type, if necessary, then adds to the
/// context and owner. /// context and owner.
DIE *NewBasicType(const std::string &Name, unsigned Size, DIE *NewBasicType(const Type *Ty, unsigned Size, unsigned Align);
unsigned Encoding);
/// NewVariable - Creates a basic variable, if necessary, then adds in the /// NewVariable - Creates a basic variable, if necessary, then adds to the
/// context and owner. /// context and owner.
DIE *NewVariable(const std::string &Name, DIE *NewGlobalVariable(const std::string &Name,
unsigned SourceFileID, unsigned Line, const std::string &MangledName,
DIE *Type, bool IsExternal); DIE *Type);
}; };
//===--------------------------------------------------------------------===// //===--------------------------------------------------------------------===//
@ -1039,6 +1044,14 @@ public:
/// NewGlobalEntity - Make the entity visible globally using the given name. /// NewGlobalEntity - Make the entity visible globally using the given name.
/// ///
void NewGlobalEntity(const std::string &Name, DIE *Entity); void NewGlobalEntity(const std::string &Name, DIE *Entity);
/// NewGlobalVariable - Add a new global variable DIE to the context.
///
void NewGlobalVariable(DWContext *Context,
const std::string &Name,
const std::string &MangledName,
const Type *Ty,
unsigned Size, unsigned Align);
private: private:
/// NewCompileUnit - Create new compile unit information. /// NewCompileUnit - Create new compile unit information.
@ -1106,39 +1119,47 @@ private:
/// ///
void EmitDebugMacInfo(); void EmitDebugMacInfo();
/// ConstructCompileUnitDIEs - Create a compile unit DIE for each source and
/// header file.
void ConstructCompileUnitDIEs();
/// ConstructGlobalDIEs - Create DIEs for each of the externally visible global
/// variables.
void ConstructGlobalDIEs(Module &M);
/// ShouldEmitDwarf - Returns true if Dwarf declarations should be made. /// ShouldEmitDwarf - Returns true if Dwarf declarations should be made.
/// When called it also checks to see if debug info is newly available. if /// 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(); bool ShouldEmitDwarf();
public: public:
DwarfWriter(std::ostream &o, AsmPrinter *ap); DwarfWriter(std::ostream &OS, AsmPrinter *A);
virtual ~DwarfWriter(); virtual ~DwarfWriter();
/// SetDebugInfo - Set DebugInfo when it's known that pass manager has /// SetDebugInfo - Set DebugInfo when it's known that pass manager has
/// created it. Set by the target AsmPrinter. /// created it. Set by the target AsmPrinter.
void SetDebugInfo(MachineDebugInfo *di) { DebugInfo = di; } void SetDebugInfo(MachineDebugInfo *DI) { DebugInfo = DI; }
//===------------------------------------------------------------------===// //===------------------------------------------------------------------===//
// Main entry points. // Main entry points.
// //
/// BeginModule - Emit all Dwarf sections that should come prior to the /// BeginModule - Emit all Dwarf sections that should come prior to the
/// content. /// content.
void BeginModule(); void BeginModule(Module &M);
/// EndModule - Emit all Dwarf sections that should come after the content. /// EndModule - Emit all Dwarf sections that should come after the content.
/// ///
void EndModule(); void EndModule(Module &M);
/// BeginFunction - Gather pre-function debug information. /// BeginFunction - Gather pre-function debug information.
/// ///
void BeginFunction(); void BeginFunction(MachineFunction &MF);
/// EndFunction - Gather and emit post-function debug information. /// EndFunction - Gather and emit post-function debug information.
/// ///
void EndFunction(); void EndFunction(MachineFunction &MF);
}; };
} // end llvm namespace } // end llvm namespace

View File

@ -14,9 +14,13 @@
#include "llvm/CodeGen/DwarfWriter.h" #include "llvm/CodeGen/DwarfWriter.h"
#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringExtras.h"
#include "llvm/Module.h"
#include "llvm/Type.h"
#include "llvm/CodeGen/AsmPrinter.h" #include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/MachineDebugInfo.h" #include "llvm/CodeGen/MachineDebugInfo.h"
#include "llvm/Support/CommandLine.h" #include "llvm/Support/CommandLine.h"
#include "llvm/Support/Mangler.h"
#include "llvm/Target/TargetMachine.h"
#include <iostream> #include <iostream>
@ -588,7 +592,7 @@ bool DIEAbbrev::operator==(const DIEAbbrev &DA) const {
if (ChildrenFlag != DA.ChildrenFlag) return false; if (ChildrenFlag != DA.ChildrenFlag) return false;
if (Data.size() != DA.Data.size()) return false; if (Data.size() != DA.Data.size()) return false;
for (unsigned i = 0, N = Data.size(); i < N; i++) { for (unsigned i = 0, N = Data.size(); i < N; ++i) {
if (Data[i] != DA.Data[i]) return false; if (Data[i] != DA.Data[i]) return false;
} }
@ -602,7 +606,7 @@ bool DIEAbbrev::operator<(const DIEAbbrev &DA) const {
if (ChildrenFlag != DA.ChildrenFlag) return ChildrenFlag < DA.ChildrenFlag; if (ChildrenFlag != DA.ChildrenFlag) return ChildrenFlag < DA.ChildrenFlag;
if (Data.size() != DA.Data.size()) return Data.size() < DA.Data.size(); if (Data.size() != DA.Data.size()) return Data.size() < DA.Data.size();
for (unsigned i = 0, N = Data.size(); i < N; i++) { for (unsigned i = 0, N = Data.size(); i < N; ++i) {
if (Data[i] != DA.Data[i]) return Data[i] < DA.Data[i]; if (Data[i] != DA.Data[i]) return Data[i] < DA.Data[i];
} }
@ -621,7 +625,7 @@ void DIEAbbrev::Emit(const DwarfWriter &DW) const {
DW.EOL(ChildrenString(ChildrenFlag)); DW.EOL(ChildrenString(ChildrenFlag));
// For each attribute description. // For each attribute description.
for (unsigned i = 0, N = Data.size(); i < N; i++) { for (unsigned i = 0, N = Data.size(); i < N; ++i) {
const DIEAbbrevData &AttrData = Data[i]; const DIEAbbrevData &AttrData = Data[i];
// Emit attribute type. // Emit attribute type.
@ -648,7 +652,7 @@ void DIEAbbrev::Emit(const DwarfWriter &DW) const {
<< ChildrenString(ChildrenFlag) << ChildrenString(ChildrenFlag)
<< "\n"; << "\n";
for (unsigned i = 0, N = Data.size(); i < N; i++) { for (unsigned i = 0, N = Data.size(); i < N; ++i) {
O << " " O << " "
<< AttributeString(Data[i].getAttribute()) << AttributeString(Data[i].getAttribute())
<< " " << " "
@ -708,13 +712,13 @@ unsigned DIEString::SizeOf(const DwarfWriter &DW, unsigned Form) const {
/// EmitValue - Emit label value. /// EmitValue - Emit label value.
/// ///
void DIELabel::EmitValue(const DwarfWriter &DW, unsigned Form) const { void DIEDwarfLabel::EmitValue(const DwarfWriter &DW, unsigned Form) const {
DW.EmitReference(Label); DW.EmitReference(Label);
} }
/// SizeOf - Determine size of label value in bytes. /// SizeOf - Determine size of label value in bytes.
/// ///
unsigned DIELabel::SizeOf(const DwarfWriter &DW, unsigned Form) const { unsigned DIEDwarfLabel::SizeOf(const DwarfWriter &DW, unsigned Form) const {
return DW.getAddressSize(); return DW.getAddressSize();
} }
@ -722,14 +726,20 @@ unsigned DIELabel::SizeOf(const DwarfWriter &DW, unsigned Form) const {
/// EmitValue - Emit label value. /// EmitValue - Emit label value.
/// ///
void DIEAsIsLabel::EmitValue(const DwarfWriter &DW, unsigned Form) const { void DIEObjectLabel::EmitValue(const DwarfWriter &DW, unsigned Form) const {
DW.EmitByte(sizeof(int8_t) + DW.getAddressSize());
DW.EOL("DW_FORM_block1 length");
DW.EmitByte(DW_OP_addr);
DW.EOL("DW_OP_addr");
DW.EmitReference(Label); DW.EmitReference(Label);
} }
/// SizeOf - Determine size of label value in bytes. /// SizeOf - Determine size of label value in bytes.
/// ///
unsigned DIEAsIsLabel::SizeOf(const DwarfWriter &DW, unsigned Form) const { unsigned DIEObjectLabel::SizeOf(const DwarfWriter &DW, unsigned Form) const {
return DW.getAddressSize(); return sizeof(int8_t) + sizeof(int8_t) + DW.getAddressSize();
} }
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
@ -774,11 +784,11 @@ DIE::DIE(unsigned Tag, unsigned ChildrenFlag)
DIE::~DIE() { DIE::~DIE() {
if (Abbrev) delete Abbrev; if (Abbrev) delete Abbrev;
for (unsigned i = 0, N = Children.size(); i < N; i++) { for (unsigned i = 0, N = Children.size(); i < N; ++i) {
delete Children[i]; delete Children[i];
} }
for (unsigned j = 0, M = Values.size(); j < M; j++) { for (unsigned j = 0, M = Values.size(); j < M; ++j) {
delete Values[j]; delete Values[j];
} }
@ -817,15 +827,15 @@ void DIE::AddString(unsigned Attribute, unsigned Form,
void DIE::AddLabel(unsigned Attribute, unsigned Form, void DIE::AddLabel(unsigned Attribute, unsigned Form,
const DWLabel &Label) { const DWLabel &Label) {
Abbrev->AddAttribute(Attribute, Form); Abbrev->AddAttribute(Attribute, Form);
Values.push_back(new DIELabel(Label)); Values.push_back(new DIEDwarfLabel(Label));
} }
/// AddAsIsLabel - Add an non-Dwarf label attribute data and value. /// AddObjectLabel - Add an non-Dwarf label attribute data and value.
/// ///
void DIE::AddAsIsLabel(unsigned Attribute, unsigned Form, void DIE::AddObjectLabel(unsigned Attribute, unsigned Form,
const std::string &Label) { const std::string &Label) {
Abbrev->AddAttribute(Attribute, Form); Abbrev->AddAttribute(Attribute, Form);
Values.push_back(new DIEAsIsLabel(Label)); Values.push_back(new DIEObjectLabel(Label));
} }
/// AddDelta - Add a label delta attribute data and value. /// AddDelta - Add a label delta attribute data and value.
@ -860,67 +870,112 @@ void DIE::AddChild(DIE *Child) {
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
/// NewBasicType - Creates a new basic type if necessary, then adds in the /// NewBasicType - Creates a new basic type if necessary, then adds to the
/// context and owner. /// context and owner.
DIE *DWContext::NewBasicType(const std::string &Name, unsigned Size, DIE *DWContext::NewBasicType(const Type *Ty, unsigned Size, unsigned Align) {
unsigned Encoding) { DIE *TypeDie = Types[Ty];
// FIXME - Just a prototype.
DIE *Type = Types[Name]; char *Name;
unsigned Encoding;
// If first occurance of type. // If first occurance of type.
if (!Type) { if (!TypeDie) {
const char *Name;
unsigned Encoding = 0;
switch (Ty->getTypeID()) {
case Type::UByteTyID:
Name = "unsigned char";
Encoding = DW_ATE_unsigned_char;
break;
case Type::SByteTyID:
Name = "char";
Encoding = DW_ATE_signed_char;
break;
case Type::UShortTyID:
Name = "unsigned short";
Encoding = DW_ATE_unsigned;
break;
case Type::ShortTyID:
Name = "short";
Encoding = DW_ATE_signed;
break;
case Type::UIntTyID:
Name = "unsigned int";
Encoding = DW_ATE_unsigned;
break;
case Type::IntTyID:
Name = "int";
Encoding = DW_ATE_signed;
break;
case Type::ULongTyID:
Name = "unsigned long long";
Encoding = DW_ATE_unsigned;
break;
case Type::LongTyID:
Name = "long long";
Encoding = DW_ATE_signed;
break;
case Type::FloatTyID:
Name = "float";
Encoding = DW_ATE_float;
break;
case Type::DoubleTyID:
Name = "float";
Encoding = DW_ATE_float;
break;
default:
// FIXME - handle more complex types.
Name = "unknown";
Encoding = DW_ATE_address;
break;
}
// construct the type DIE. // construct the type DIE.
Type = new DIE(DW_TAG_base_type, DW_CHILDREN_no); TypeDie = new DIE(DW_TAG_base_type, DW_CHILDREN_no);
Type->AddString(DW_AT_name, DW_FORM_string, Name); TypeDie->AddString(DW_AT_name, DW_FORM_string, Name);
Type->AddInt (DW_AT_byte_size, DW_FORM_data1, Size); TypeDie->AddInt (DW_AT_byte_size, DW_FORM_data1, Size);
Type->AddInt (DW_AT_encoding, DW_FORM_data1, Encoding); TypeDie->AddInt (DW_AT_encoding, DW_FORM_data1, Encoding);
Type->Complete(DW); TypeDie->Complete(DW);
// Add to context owner. // Add to context owner.
Owner->AddChild(Type); Owner->AddChild(TypeDie);
// Add to map. // Add to map.
Types[Name] = Type; Types[Ty] = TypeDie;
} }
return Type; return TypeDie;
} }
/// NewVariable - Creates a basic variable, if necessary, then adds in the /// NewGlobalVariable - Creates a global variable, if necessary, then adds in
/// context and owner. /// the context and owner.
DIE *DWContext::NewVariable(const std::string &Name, DIE *DWContext::NewGlobalVariable(const std::string &Name,
unsigned SourceFileID, unsigned Line, const std::string &MangledName,
DIE *Type, bool IsExternal) { DIE *Type) {
// FIXME - Just a prototype. DIE *VariableDie = Variables[MangledName];
DIE *Variable = Variables[Name];
// If first occurance of variable. // If first occurance of variable.
if (!Variable) { if (!VariableDie) {
assert(IsExternal && "Internal variables not handled yet"); // FIXME - need source file name line number.
Variable = new DIE(DW_TAG_variable, DW_CHILDREN_no); VariableDie = new DIE(DW_TAG_variable, DW_CHILDREN_no);
Variable->AddString (DW_AT_name, DW_FORM_string, Name); VariableDie->AddString (DW_AT_name, DW_FORM_string, Name);
Variable->AddInt (DW_AT_decl_file, 0, SourceFileID); VariableDie->AddInt (DW_AT_decl_file, 0, 0);
Variable->AddInt (DW_AT_decl_line, 0, Line); VariableDie->AddInt (DW_AT_decl_line, 0, 0);
Variable->AddDIEntry (DW_AT_type, DW_FORM_ref4, Type); VariableDie->AddDIEntry (DW_AT_type, DW_FORM_ref4, Type);
Variable->AddInt (DW_AT_external, DW_FORM_flag, (int)IsExternal); VariableDie->AddInt (DW_AT_external, DW_FORM_flag, 1);
// FIXME - needs to be an expression. // FIXME - needs to be a proper expression.
Variable->AddAsIsLabel(DW_AT_location, DW_FORM_block1, VariableDie->AddObjectLabel(DW_AT_location, DW_FORM_block1, MangledName);
std::string("_")+Name+".b"); VariableDie->Complete(DW);
Variable->Complete(DW);
// Add to context owner. // Add to context owner.
Owner->AddChild(Variable); Owner->AddChild(VariableDie);
// Add to map. // Add to map.
Variables[Name] = Variable; Variables[MangledName] = VariableDie;
// If external add to visible names.
if (IsExternal) {
DW.NewGlobalEntity(Name, Variable);
}
} }
return Variable; return VariableDie;
} }
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
@ -1048,7 +1103,7 @@ void DwarfWriter::EmitLong(int Value) const {
void DwarfWriter::EmitString(const std::string &String) const { void DwarfWriter::EmitString(const std::string &String) const {
O << Asm->AsciiDirective O << Asm->AsciiDirective
<< "\""; << "\"";
for (unsigned i = 0, N = String.size(); i < N; i++) { for (unsigned i = 0, N = String.size(); i < N; ++i) {
unsigned char C = String[i]; unsigned char C = String[i];
if (!isascii(C) || iscntrl(C)) { if (!isascii(C) || iscntrl(C)) {
@ -1134,7 +1189,7 @@ void DwarfWriter::EmitDifference(const char *TagHi, unsigned NumberHi,
PrintLabelName("set", SetCounter); PrintLabelName("set", SetCounter);
SetCounter++; ++SetCounter;
} else { } else {
if (AddressSize == sizeof(int32_t)) if (AddressSize == sizeof(int32_t))
O << Asm->Data32bitsDirective; O << Asm->Data32bitsDirective;
@ -1163,17 +1218,30 @@ DWLabel DwarfWriter::NewString(const std::string &String) {
/// NewGlobalType - Make the type visible globally using the given name. /// NewGlobalType - Make the type visible globally using the given name.
/// ///
void DwarfWriter::NewGlobalType(const std::string &Name, DIE *Type) { void DwarfWriter::NewGlobalType(const std::string &Name, DIE *Type) {
// FIXME - check for duplication. assert(!GlobalTypes[Name] && "Duplicate global type");
GlobalTypes[Name] = Type; GlobalTypes[Name] = Type;
} }
/// NewGlobalEntity - Make the entity visible globally using the given name. /// NewGlobalEntity - Make the entity visible globally using the given name.
/// ///
void DwarfWriter::NewGlobalEntity(const std::string &Name, DIE *Entity) { void DwarfWriter::NewGlobalEntity(const std::string &Name, DIE *Entity) {
// FIXME - check for duplication. assert(!GlobalEntities[Name] && "Duplicate global variable or function");
GlobalEntities[Name] = Entity; GlobalEntities[Name] = Entity;
} }
/// NewGlobalVariable - Add a new global variable DIE to the context.
///
void DwarfWriter::NewGlobalVariable(DWContext *Context,
const std::string &Name,
const std::string &MangledName,
const Type *Ty,
unsigned Size, unsigned Align) {
// Get the DIE type for the global.
DIE *Type = Context->NewBasicType(Ty, Size, Align);
DIE *Variable = Context->NewGlobalVariable(Name, MangledName, Type);
NewGlobalEntity(Name, Variable);
}
/// NewCompileUnit - Create new compile unit information. /// NewCompileUnit - Create new compile unit information.
/// ///
DIE *DwarfWriter::NewCompileUnit(const std::string &Directory, DIE *DwarfWriter::NewCompileUnit(const std::string &Directory,
@ -1225,6 +1293,7 @@ void DwarfWriter::EmitDIE(DIE *Die) const {
EmitULEB128Bytes(AbbrevID); EmitULEB128Bytes(AbbrevID);
EOL(std::string("Abbrev [" + EOL(std::string("Abbrev [" +
utostr(AbbrevID) + utostr(AbbrevID) +
"] " +
TagString(Abbrev.getTag())) + TagString(Abbrev.getTag())) +
" "); " ");
@ -1232,7 +1301,7 @@ void DwarfWriter::EmitDIE(DIE *Die) const {
const std::vector<DIEAbbrevData> &AbbrevData = Abbrev.getData(); const std::vector<DIEAbbrevData> &AbbrevData = Abbrev.getData();
// Emit the DIE attribute values. // Emit the DIE attribute values.
for (unsigned i = 0, N = Values.size(); i < N; i++) { for (unsigned i = 0, N = Values.size(); i < N; ++i) {
unsigned Attr = AbbrevData[i].getAttribute(); unsigned Attr = AbbrevData[i].getAttribute();
unsigned Form = AbbrevData[i].getForm(); unsigned Form = AbbrevData[i].getForm();
assert(Form && "Too many attributes for DIE (check abbreviation)"); assert(Form && "Too many attributes for DIE (check abbreviation)");
@ -1256,7 +1325,7 @@ void DwarfWriter::EmitDIE(DIE *Die) const {
if (Abbrev.getChildrenFlag() == DW_CHILDREN_yes) { if (Abbrev.getChildrenFlag() == DW_CHILDREN_yes) {
const std::vector<DIE *> &Children = Die->getChildren(); const std::vector<DIE *> &Children = Die->getChildren();
for (unsigned j = 0, M = Children.size(); j < M; j++) { for (unsigned j = 0, M = Children.size(); j < M; ++j) {
// FIXME - handle sibling offsets. // FIXME - handle sibling offsets.
// FIXME - handle all DIE types. // FIXME - handle all DIE types.
EmitDIE(Children[j]); EmitDIE(Children[j]);
@ -1283,7 +1352,7 @@ unsigned DwarfWriter::SizeAndOffsetDie(DIE *Die, unsigned Offset) const {
const std::vector<DIEAbbrevData> &AbbrevData = Abbrev.getData(); const std::vector<DIEAbbrevData> &AbbrevData = Abbrev.getData();
// Emit the DIE attribute values. // Emit the DIE attribute values.
for (unsigned i = 0, N = Values.size(); i < N; i++) { for (unsigned i = 0, N = Values.size(); i < N; ++i) {
// Size attribute value. // Size attribute value.
Offset += Values[i]->SizeOf(*this, AbbrevData[i].getForm()); Offset += Values[i]->SizeOf(*this, AbbrevData[i].getForm());
} }
@ -1292,7 +1361,7 @@ unsigned DwarfWriter::SizeAndOffsetDie(DIE *Die, unsigned Offset) const {
if (Abbrev.getChildrenFlag() == DW_CHILDREN_yes) { if (Abbrev.getChildrenFlag() == DW_CHILDREN_yes) {
const std::vector<DIE *> &Children = Die->getChildren(); const std::vector<DIE *> &Children = Die->getChildren();
for (unsigned j = 0, M = Children.size(); j < M; j++) { for (unsigned j = 0, M = Children.size(); j < M; ++j) {
// FIXME - handle sibling offsets. // FIXME - handle sibling offsets.
// FIXME - handle all DIE types. // FIXME - handle all DIE types.
Offset = SizeAndOffsetDie(Children[j], Offset); Offset = SizeAndOffsetDie(Children[j], Offset);
@ -1316,7 +1385,7 @@ void DwarfWriter::SizeAndOffsets() {
sizeof(int8_t); // Pointer Size (in bytes) sizeof(int8_t); // Pointer Size (in bytes)
// Process each compile unit. // Process each compile unit.
for (unsigned i = 0, N = CompileUnits.size(); i < N; i++) { for (unsigned i = 0, N = CompileUnits.size(); i < N; ++i) {
Offset = SizeAndOffsetDie(CompileUnits[i], Offset); Offset = SizeAndOffsetDie(CompileUnits[i], Offset);
} }
} }
@ -1348,7 +1417,7 @@ void DwarfWriter::EmitDebugInfo() const {
EmitByte(AddressSize); EOL("Address Size (in bytes)"); EmitByte(AddressSize); EOL("Address Size (in bytes)");
// Process each compile unit. // Process each compile unit.
for (unsigned i = 0; i < N; i++) { for (unsigned i = 0; i < N; ++i) {
EmitDIE(CompileUnits[i]); EmitDIE(CompileUnits[i]);
} }
@ -1368,7 +1437,7 @@ void DwarfWriter::EmitAbbreviations() const {
// For each abbrevation. // For each abbrevation.
for (unsigned AbbrevID = 1, NAID = Abbreviations.size(); for (unsigned AbbrevID = 1, NAID = Abbreviations.size();
AbbrevID <= NAID; AbbrevID++) { AbbrevID <= NAID; ++AbbrevID) {
// Get abbreviation data // Get abbreviation data
const DIEAbbrev &Abbrev = Abbreviations[AbbrevID]; const DIEAbbrev &Abbrev = Abbreviations[AbbrevID];
@ -1432,14 +1501,14 @@ void DwarfWriter::EmitDebugLines() const {
// Emit directories. // Emit directories.
for (unsigned DirectoryID = 1, NDID = Directories.size(); for (unsigned DirectoryID = 1, NDID = Directories.size();
DirectoryID <= NDID; DirectoryID++) { DirectoryID <= NDID; ++DirectoryID) {
EmitString(Directories[DirectoryID]); EOL("Directory"); EmitString(Directories[DirectoryID]); EOL("Directory");
} }
EmitByte(0); EOL("End of directories"); EmitByte(0); EOL("End of directories");
// Emit files. // Emit files.
for (unsigned SourceID = 1, NSID = SourceFiles.size(); for (unsigned SourceID = 1, NSID = SourceFiles.size();
SourceID <= NSID; SourceID++) { SourceID <= NSID; ++SourceID) {
const SourceFileInfo &SourceFile = SourceFiles[SourceID]; const SourceFileInfo &SourceFile = SourceFiles[SourceID];
EmitString(SourceFile.getName()); EOL("Source"); EmitString(SourceFile.getName()); EOL("Source");
EmitULEB128Bytes(SourceFile.getDirectoryID()); EOL("Directory #"); EmitULEB128Bytes(SourceFile.getDirectoryID()); EOL("Directory #");
@ -1458,7 +1527,7 @@ void DwarfWriter::EmitDebugLines() const {
unsigned Line = 1; unsigned Line = 1;
// Construct rows of the address, source, line, column matrix. // Construct rows of the address, source, line, column matrix.
for (unsigned i = 0, N = LineInfos.size(); i < N; i++) { for (unsigned i = 0, N = LineInfos.size(); i < N; ++i) {
SourceLineInfo *LineInfo = LineInfos[i]; SourceLineInfo *LineInfo = LineInfos[i];
// Define the line address. // Define the line address.
@ -1533,11 +1602,11 @@ void DwarfWriter::EmitDebugPubNames() {
EmitDifference("info_end", 0, "info_begin", 0); EmitDifference("info_end", 0, "info_begin", 0);
EOL("Compilation Unit Length"); EOL("Compilation Unit Length");
for (std::map<std::string, DIE *>::iterator G = GlobalTypes.begin(), for (std::map<std::string, DIE *>::iterator GI = GlobalEntities.begin(),
GE = GlobalTypes.begin(); GE = GlobalEntities.end();
G != GE; G++) { GI != GE; ++GI) {
const std::string &Name = (*G).first; const std::string &Name = GI->first;
DIE * Entity = (*G).second; DIE * Entity = GI->second;
EmitLong(Entity->getOffset()); EOL("DIE offset"); EmitLong(Entity->getOffset()); EOL("DIE offset");
EmitString(Name); EOL("External Name"); EmitString(Name); EOL("External Name");
@ -1569,7 +1638,7 @@ void DwarfWriter::EmitDebugStr() {
// For each of strings in teh string pool. // For each of strings in teh string pool.
for (unsigned StringID = 1, N = StringPool.size(); for (unsigned StringID = 1, N = StringPool.size();
StringID <= N; StringID++) { StringID <= N; ++StringID) {
// Emit a label for reference from debug information entries. // Emit a label for reference from debug information entries.
EmitLabel("string", StringID); EmitLabel("string", StringID);
// Emit the string itself. // Emit the string itself.
@ -1630,6 +1699,63 @@ void DwarfWriter::EmitDebugMacInfo() {
Asm->SwitchSection(DwarfMacInfoSection, 0); Asm->SwitchSection(DwarfMacInfoSection, 0);
} }
/// ConstructCompileUnitDIEs - Create a compile unit DIE for each source and
/// header file.
void DwarfWriter::ConstructCompileUnitDIEs() {
// Get directory and source information.
const UniqueVector<std::string> &Directories = DebugInfo->getDirectories();
const UniqueVector<SourceFileInfo> &SourceFiles = DebugInfo->getSourceFiles();
// Construct compile unit DIEs for each source.
for (unsigned SourceID = 1, NSID = SourceFiles.size();
SourceID <= NSID; ++SourceID) {
const SourceFileInfo &SourceFile = SourceFiles[SourceID];
const std::string &Directory = Directories[SourceFile.getDirectoryID()];
const std::string &SourceName = SourceFile.getName();
DIE *Unit = NewCompileUnit(Directory, SourceName);
DWContext *Context = new DWContext(*this, NULL, Unit);
CompileUnits.push_back(Unit);
}
}
/// ConstructGlobalDIEs - Create DIEs for each of the externally visible global
/// variables.
void DwarfWriter::ConstructGlobalDIEs(Module &M) {
const TargetData &TD = Asm->TM.getTargetData();
// Iterate throu each of the globals.
for (Module::const_global_iterator GI = M.global_begin(), GE = M.global_end();
GI != GE; ++GI) {
if (!GI->hasInitializer()) continue; // External global require no code
// Check to see if this is a special global used by LLVM, if so, emit it.
if (GI->hasAppendingLinkage() && (GI->getName() == "llvm.global_ctors" ||
GI->getName() == "llvm.global_dtors"))
continue;
std::string Name = Asm->Mang->getValueName(GI);
Constant *C = GI->getInitializer();
const Type *Ty = C->getType();
unsigned Size = TD.getTypeSize(Ty);
unsigned Align = TD.getTypeAlignmentShift(Ty);
if (C->isNullValue() && /* FIXME: Verify correct */
(GI->hasInternalLinkage() || GI->hasWeakLinkage() ||
GI->hasLinkOnceLinkage())) {
if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
}
/// FIXME - Get correct compile unit context.
assert(CompileUnits.size() && "No compile units");
DWContext *Context = CompileUnits[0]->getContext();
/// Create new global.
NewGlobalVariable(Context, GI->getName(), Name, Ty, Size, Align);
}
}
/// ShouldEmitDwarf - Determine if Dwarf declarations should be made. /// ShouldEmitDwarf - Determine if Dwarf declarations should be made.
/// ///
bool DwarfWriter::ShouldEmitDwarf() { bool DwarfWriter::ShouldEmitDwarf() {
@ -1649,52 +1775,52 @@ bool DwarfWriter::ShouldEmitDwarf() {
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// Main entry points. // Main entry points.
// //
DwarfWriter::DwarfWriter(std::ostream &o, AsmPrinter *ap) DwarfWriter::DwarfWriter(std::ostream &OS, AsmPrinter *A)
: O(o) : O(OS)
, Asm(ap) , Asm(A)
, DebugInfo(NULL) , DebugInfo(NULL)
, didInitial(false) , didInitial(false)
, CompileUnits() , CompileUnits()
, Abbreviations() , Abbreviations()
, GlobalTypes() , GlobalTypes()
, GlobalEntities() , GlobalEntities()
, StringPool() , StringPool()
, AddressSize(sizeof(int32_t)) , AddressSize(sizeof(int32_t))
, hasLEB128(false) , hasLEB128(false)
, hasDotLoc(false) , hasDotLoc(false)
, hasDotFile(false) , hasDotFile(false)
, needsSet(false) , needsSet(false)
, DwarfAbbrevSection(".debug_abbrev") , DwarfAbbrevSection(".debug_abbrev")
, DwarfInfoSection(".debug_info") , DwarfInfoSection(".debug_info")
, DwarfLineSection(".debug_line") , DwarfLineSection(".debug_line")
, DwarfFrameSection(".debug_frame") , DwarfFrameSection(".debug_frame")
, DwarfPubNamesSection(".debug_pubnames") , DwarfPubNamesSection(".debug_pubnames")
, DwarfPubTypesSection(".debug_pubtypes") , DwarfPubTypesSection(".debug_pubtypes")
, DwarfStrSection(".debug_str") , DwarfStrSection(".debug_str")
, DwarfLocSection(".debug_loc") , DwarfLocSection(".debug_loc")
, DwarfARangesSection(".debug_aranges") , DwarfARangesSection(".debug_aranges")
, DwarfRangesSection(".debug_ranges") , DwarfRangesSection(".debug_ranges")
, DwarfMacInfoSection(".debug_macinfo") , DwarfMacInfoSection(".debug_macinfo")
, TextSection(".text") , TextSection(".text")
, DataSection(".data") , DataSection(".data")
{} {}
DwarfWriter::~DwarfWriter() { DwarfWriter::~DwarfWriter() {
for (unsigned i = 0, N = CompileUnits.size(); i < N; i++) { for (unsigned i = 0, N = CompileUnits.size(); i < N; ++i) {
delete CompileUnits[i]; delete CompileUnits[i];
}
} }
}
/// BeginModule - Emit all Dwarf sections that should come prior to the content. /// BeginModule - Emit all Dwarf sections that should come prior to the content.
/// ///
void DwarfWriter::BeginModule() { void DwarfWriter::BeginModule(Module &M) {
if (!ShouldEmitDwarf()) return; if (!ShouldEmitDwarf()) return;
EOL("Dwarf Begin Module"); EOL("Dwarf Begin Module");
} }
/// EndModule - Emit all Dwarf sections that should come after the content. /// EndModule - Emit all Dwarf sections that should come after the content.
/// ///
void DwarfWriter::EndModule() { void DwarfWriter::EndModule(Module &M) {
if (!ShouldEmitDwarf()) return; if (!ShouldEmitDwarf()) return;
EOL("Dwarf End Module"); EOL("Dwarf End Module");
@ -1704,27 +1830,11 @@ void DwarfWriter::EndModule() {
Asm->SwitchSection(DataSection, 0); Asm->SwitchSection(DataSection, 0);
EmitLabel("data_end", 0); EmitLabel("data_end", 0);
// Get directory and source information. // Create all the compile unit DIEs.
const UniqueVector<std::string> &Directories = DebugInfo->getDirectories(); ConstructCompileUnitDIEs();
const UniqueVector<SourceFileInfo> &SourceFiles = DebugInfo->getSourceFiles();
// Create DIEs for each of the externally visible global variables.
// Construct compile unit DIEs for each source. ConstructGlobalDIEs(M);
for (unsigned SourceID = 1, NSID = SourceFiles.size();
SourceID <= NSID; SourceID++) {
const SourceFileInfo &SourceFile = SourceFiles[SourceID];
const std::string &Directory = Directories[SourceFile.getDirectoryID()];
const std::string &SourceName = SourceFile.getName();
DIE *Unit = NewCompileUnit(Directory, SourceName);
#if 0
// FIXME - just testing.
DWContext *Context = new DWContext(*this, Unit);
DIE *TypeInt = Context->NewBasicType("int", sizeof(int32_t), DW_ATE_signed);
Context->NewVariable("MyGlobal", SourceID, 1, TypeInt, true);
#endif
CompileUnits.push_back(Unit);
}
// Compute DIE offsets and sizes. // Compute DIE offsets and sizes.
SizeAndOffsets(); SizeAndOffsets();
@ -1765,14 +1875,14 @@ void DwarfWriter::EndModule() {
/// BeginFunction - Gather pre-function debug information. /// BeginFunction - Gather pre-function debug information.
/// ///
void DwarfWriter::BeginFunction() { void DwarfWriter::BeginFunction(MachineFunction &MF) {
if (!ShouldEmitDwarf()) return; if (!ShouldEmitDwarf()) return;
EOL("Dwarf Begin Function"); EOL("Dwarf Begin Function");
} }
/// EndFunction - Gather and emit post-function debug information. /// EndFunction - Gather and emit post-function debug information.
/// ///
void DwarfWriter::EndFunction() { void DwarfWriter::EndFunction(MachineFunction &MF) {
if (!ShouldEmitDwarf()) return; if (!ShouldEmitDwarf()) return;
EOL("Dwarf End Function"); EOL("Dwarf End Function");
} }

View File

@ -438,7 +438,7 @@ bool DarwinAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
O << "\n\n"; O << "\n\n";
// Emit pre-function debug information. // Emit pre-function debug information.
DW.BeginFunction(); DW.BeginFunction(MF);
// Print out constants referenced by the function // Print out constants referenced by the function
EmitConstantPool(MF.getConstantPool()); EmitConstantPool(MF.getConstantPool());
@ -486,7 +486,7 @@ bool DarwinAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
} }
// Emit post-function debug information. // Emit post-function debug information.
DW.EndFunction(); DW.EndFunction(MF);
// We didn't modify anything. // We didn't modify anything.
return false; return false;
@ -502,7 +502,7 @@ bool DarwinAsmPrinter::doInitialization(Module &M) {
Mang->setUseQuotes(true); Mang->setUseQuotes(true);
// Emit initial debug information. // Emit initial debug information.
DW.BeginModule(); DW.BeginModule(M);
return false; return false;
} }
@ -619,7 +619,7 @@ bool DarwinAsmPrinter::doFinalization(Module &M) {
} }
// Emit initial debug information. // Emit initial debug information.
DW.EndModule(); DW.EndModule(M);
// Funny Darwin hack: This flag tells the linker that no global symbols // Funny Darwin hack: This flag tells the linker that no global symbols
// contain code that falls through to other global symbols (e.g. the obvious // contain code that falls through to other global symbols (e.g. the obvious