Added support for dwarf block data entries.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@26509 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Jim Laskey 2006-03-03 21:00:14 +00:00
parent 56879b2d96
commit b80af6f572

View File

@ -174,7 +174,8 @@ public:
isLabel,
isAsIsLabel,
isDelta,
isEntry
isEntry,
isBlock
};
unsigned Type; // Type of the value
@ -208,6 +209,10 @@ public:
static bool classof(const DIEInteger *) { return true; }
static bool classof(const DIEValue *I) { return I->Type == isInteger; }
/// BestForm - Choose the best form for integer.
///
unsigned BestForm(bool IsSigned);
/// EmitValue - Emit integer of appropriate size.
///
virtual void EmitValue(const DwarfWriter &DW, unsigned Form) const;
@ -316,15 +321,81 @@ struct DIEntry : public DIEValue {
static bool classof(const DIEntry *) { return true; }
static bool classof(const DIEValue *E) { return E->Type == isEntry; }
/// EmitValue - Emit delta value.
/// EmitValue - Emit die entry offset.
///
virtual void EmitValue(const DwarfWriter &DW, unsigned Form) const;
/// SizeOf - Determine size of delta value in bytes.
/// SizeOf - Determine size of die entry in bytes.
///
virtual unsigned SizeOf(const DwarfWriter &DW, unsigned Form) const;
};
//===----------------------------------------------------------------------===//
// DIEBlock - A block of values. Primarily used for location expressions.
//
struct DIEBlock : public DIEValue {
unsigned Size; // Size in bytes excluding size header.
std::vector<unsigned> Forms; // Data forms.
std::vector<DIEValue *> Values; // Block values.
DIEBlock()
: DIEValue(isBlock)
, Size(0)
, Forms()
, Values()
{}
~DIEBlock();
// Implement isa/cast/dyncast.
static bool classof(const DIEBlock *) { return true; }
static bool classof(const DIEValue *E) { return E->Type == isBlock; }
/// ComputeSize - calculate the size of the block.
///
unsigned ComputeSize(DwarfWriter &DW);
/// BestForm - Choose the best form for data.
///
unsigned BestForm();
/// EmitValue - Emit block data.
///
virtual void EmitValue(const DwarfWriter &DW, unsigned Form) const;
/// SizeOf - Determine size of block data in bytes.
///
virtual unsigned SizeOf(const DwarfWriter &DW, unsigned Form) const;
/// AddUInt - Add an unsigned integer value.
///
void AddUInt(unsigned Form, uint64_t Integer);
/// AddSInt - Add an signed integer value.
///
void AddSInt(unsigned Form, int64_t Integer);
/// AddString - Add a std::string value.
///
void AddString(unsigned Form, const std::string &String);
/// AddLabel - Add a Dwarf label value.
///
void AddLabel(unsigned Form, const DWLabel &Label);
/// AddObjectLabel - Add a non-Dwarf label value.
///
void AddObjectLabel(unsigned Form, const std::string &Label);
/// AddDelta - Add a label delta value.
///
void AddDelta(unsigned Form, const DWLabel &Hi, const DWLabel &Lo);
/// AddDIEntry - Add a DIE value.
///
void AddDIEntry(unsigned Form, DIE *Entry);
};
//===----------------------------------------------------------------------===//
// DIE - A structured debug information entry. Has an abbreviation which
// describes it's organization.
@ -381,10 +452,14 @@ public:
void AddDelta(unsigned Attribute, unsigned Form,
const DWLabel &Hi, const DWLabel &Lo);
/// AddDIEntry - Add a DIE attribute data and value.
/// AddDIEntry - Add a DIE attribute data and value.
///
void AddDIEntry(unsigned Attribute, unsigned Form, DIE *Entry);
/// AddBlock - Add block data.
///
void AddBlock(unsigned Attribute, unsigned Form, DIEBlock *Block);
/// Complete - Indicate that all attributes have been added and
/// ready to get an abbreviation ID.
///
@ -496,6 +571,21 @@ void DIEAbbrev::Emit(const DwarfWriter &DW) const {
//===----------------------------------------------------------------------===//
/// BestForm - Choose the best form for integer.
///
unsigned DIEInteger::BestForm(bool IsSigned) {
if (IsSigned) {
if ((char)Integer == (signed)Integer) return DW_FORM_data1;
if ((short)Integer == (signed)Integer) return DW_FORM_data2;
if ((int)Integer == (signed)Integer) return DW_FORM_data4;
} else {
if ((unsigned char)Integer == Integer) return DW_FORM_data1;
if ((unsigned short)Integer == Integer) return DW_FORM_data2;
if ((unsigned int)Integer == Integer) return DW_FORM_data4;
}
return DW_FORM_data8;
}
/// EmitValue - Emit integer of appropriate size.
///
void DIEInteger::EmitValue(const DwarfWriter &DW, unsigned Form) const {
@ -507,13 +597,6 @@ void DIEInteger::EmitValue(const DwarfWriter &DW, unsigned Form) const {
case DW_FORM_data8: DW.EmitInt64(Integer); break;
case DW_FORM_udata: DW.EmitULEB128Bytes(Integer); break;
case DW_FORM_sdata: DW.EmitSLEB128Bytes(Integer); break;
// FIXME - Punting on field offsets.
case DW_FORM_block1: {
DW.EmitInt8(1 + DW.SizeULEB128(Integer)); DW.EOL("Form1 Size");
DW.EmitInt8(DW_OP_plus_uconst); DW.EOL("DW_OP_plus_uconst");
DW.EmitULEB128Bytes(Integer);
break;
}
default: assert(0 && "DIE Value form not supported yet"); break;
}
}
@ -529,8 +612,6 @@ unsigned DIEInteger::SizeOf(const DwarfWriter &DW, unsigned Form) const {
case DW_FORM_data8: return sizeof(int64_t);
case DW_FORM_udata: return DW.SizeULEB128(Integer);
case DW_FORM_sdata: return DW.SizeSLEB128(Integer);
// FIXME - Punting on field offsets.
case DW_FORM_block1: return 2 + DW.SizeULEB128(Integer);
default: assert(0 && "DIE Value form not supported yet"); break;
}
return 0;
@ -569,19 +650,13 @@ unsigned DIEDwarfLabel::SizeOf(const DwarfWriter &DW, unsigned Form) const {
/// EmitValue - Emit label value.
///
void DIEObjectLabel::EmitValue(const DwarfWriter &DW, unsigned Form) const {
DW.EmitInt8(sizeof(int8_t) + DW.getAddressSize());
DW.EOL("DW_FORM_block1 length");
DW.EmitInt8(DW_OP_addr);
DW.EOL("DW_OP_addr");
DW.EmitReference(Label);
}
/// SizeOf - Determine size of label value in bytes.
///
unsigned DIEObjectLabel::SizeOf(const DwarfWriter &DW, unsigned Form) const {
return sizeof(int8_t) + sizeof(int8_t) + DW.getAddressSize();
return DW.getAddressSize();
}
//===----------------------------------------------------------------------===//
@ -599,13 +674,13 @@ unsigned DIEDelta::SizeOf(const DwarfWriter &DW, unsigned Form) const {
}
//===----------------------------------------------------------------------===//
/// EmitValue - Emit extry offset.
/// EmitValue - Emit die entry offset.
///
void DIEntry::EmitValue(const DwarfWriter &DW, unsigned Form) const {
DW.EmitInt32(Entry->getOffset());
}
/// SizeOf - Determine size of label value in bytes.
/// SizeOf - Determine size of die value in bytes.
///
unsigned DIEntry::SizeOf(const DwarfWriter &DW, unsigned Form) const {
return sizeof(int32_t);
@ -613,6 +688,115 @@ unsigned DIEntry::SizeOf(const DwarfWriter &DW, unsigned Form) const {
//===----------------------------------------------------------------------===//
DIEBlock::~DIEBlock() {
for (unsigned i = 0, N = Values.size(); i < N; ++i) {
delete Values[i];
}
}
/// ComputeSize - calculate the size of the block.
///
unsigned DIEBlock::ComputeSize(DwarfWriter &DW) {
Size = 0;
for (unsigned i = 0, N = Values.size(); i < N; ++i) {
Size += Values[i]->SizeOf(DW, Forms[i]);
}
return Size;
}
/// BestForm - Choose the best form for data.
///
unsigned DIEBlock::BestForm() {
if ((unsigned char)Size == Size) return DW_FORM_block1;
if ((unsigned short)Size == Size) return DW_FORM_block2;
if ((unsigned int)Size == Size) return DW_FORM_block4;
return DW_FORM_block;
}
/// EmitValue - Emit block data.
///
void DIEBlock::EmitValue(const DwarfWriter &DW, unsigned Form) const {
switch (Form) {
case DW_FORM_block1: DW.EmitInt8(Size); break;
case DW_FORM_block2: DW.EmitInt16(Size); break;
case DW_FORM_block4: DW.EmitInt32(Size); break;
case DW_FORM_block: DW.EmitULEB128Bytes(Size); break;
default: assert(0 && "Improper form for block"); break;
}
for (unsigned i = 0, N = Values.size(); i < N; ++i) {
DW.EOL("");
Values[i]->EmitValue(DW, Forms[i]);
}
}
/// SizeOf - Determine size of block data in bytes.
///
unsigned DIEBlock::SizeOf(const DwarfWriter &DW, unsigned Form) const {
switch (Form) {
case DW_FORM_block1: return Size + sizeof(int8_t);
case DW_FORM_block2: return Size + sizeof(int16_t);
case DW_FORM_block4: return Size + sizeof(int32_t);
case DW_FORM_block: return Size + DW.SizeULEB128(Size);
default: assert(0 && "Improper form for block"); break;
}
return 0;
}
/// AddUInt - Add an unsigned integer value.
///
void DIEBlock::AddUInt(unsigned Form, uint64_t Integer) {
DIEInteger *DI = new DIEInteger(Integer);
Values.push_back(DI);
if (Form == 0) Form = DI->BestForm(false);
Forms.push_back(Form);
}
/// AddSInt - Add an signed integer value.
///
void DIEBlock::AddSInt(unsigned Form, int64_t Integer) {
DIEInteger *DI = new DIEInteger(Integer);
Values.push_back(DI);
if (Form == 0) Form = DI->BestForm(true);
Forms.push_back(Form);
}
/// AddString - Add a std::string value.
///
void DIEBlock::AddString(unsigned Form, const std::string &String) {
Values.push_back(new DIEString(String));
Forms.push_back(Form);
}
/// AddLabel - Add a Dwarf label value.
///
void DIEBlock::AddLabel(unsigned Form, const DWLabel &Label) {
Values.push_back(new DIEDwarfLabel(Label));
Forms.push_back(Form);
}
/// AddObjectLabel - Add a non-Dwarf label value.
///
void DIEBlock::AddObjectLabel(unsigned Form, const std::string &Label) {
Values.push_back(new DIEObjectLabel(Label));
Forms.push_back(Form);
}
/// AddDelta - Add a label delta value.
///
void DIEBlock::AddDelta(unsigned Form, const DWLabel &Hi, const DWLabel &Lo) {
Values.push_back(new DIEDelta(Hi, Lo));
Forms.push_back(Form);
}
/// AddDIEntry - Add a DIE value.
///
void DIEBlock::AddDIEntry(unsigned Form, DIE *Entry) {
Values.push_back(new DIEntry(Entry));
Forms.push_back(Form);
}
//===----------------------------------------------------------------------===//
DIE::DIE(unsigned Tag)
: Abbrev(new DIEAbbrev(Tag, DW_CHILDREN_no))
, AbbrevID(0)
@ -637,67 +821,67 @@ DIE::~DIE() {
/// AddUInt - Add an unsigned integer attribute data and value.
///
void DIE::AddUInt(unsigned Attribute, unsigned Form, uint64_t Integer) {
if (Form == 0) {
if ((unsigned char)Integer == Integer) Form = DW_FORM_data1;
else if ((unsigned short)Integer == Integer) Form = DW_FORM_data2;
else if ((unsigned int)Integer == Integer) Form = DW_FORM_data4;
else Form = DW_FORM_data8;
}
DIEInteger *DI = new DIEInteger(Integer);
Values.push_back(DI);
if (!Form) Form = DI->BestForm(false);
Abbrev->AddAttribute(Attribute, Form);
Values.push_back(new DIEInteger(Integer));
}
/// AddSInt - Add an signed integer attribute data and value.
///
void DIE::AddSInt(unsigned Attribute, unsigned Form, int64_t Integer) {
if (Form == 0) {
if ((char)Integer == Integer) Form = DW_FORM_data1;
else if ((short)Integer == Integer) Form = DW_FORM_data2;
else if ((int)Integer == Integer) Form = DW_FORM_data4;
else Form = DW_FORM_data8;
}
DIEInteger *DI = new DIEInteger(Integer);
Values.push_back(DI);
if (!Form) Form = DI->BestForm(true);
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));
Abbrev->AddAttribute(Attribute, Form);
}
/// 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 DIEDwarfLabel(Label));
Abbrev->AddAttribute(Attribute, Form);
}
/// AddObjectLabel - Add an non-Dwarf label attribute data and value.
///
void DIE::AddObjectLabel(unsigned Attribute, unsigned Form,
const std::string &Label) {
Abbrev->AddAttribute(Attribute, Form);
Values.push_back(new DIEObjectLabel(Label));
Abbrev->AddAttribute(Attribute, Form);
}
/// 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));
Abbrev->AddAttribute(Attribute, Form);
}
/// AddDIEntry - Add a DIE attribute data and value.
///
void DIE::AddDIEntry(unsigned Attribute,
unsigned Form, DIE *Entry) {
Abbrev->AddAttribute(Attribute, Form);
void DIE::AddDIEntry(unsigned Attribute, unsigned Form, DIE *Entry) {
Values.push_back(new DIEntry(Entry));
Abbrev->AddAttribute(Attribute, Form);
}
/// AddBlock - Add block data.
///
void DIE::AddBlock(unsigned Attribute, unsigned Form, DIEBlock *Block) {
assert(Block->Size && "Block size has not been computed");
Values.push_back(Block);
if (!Form) Form = Block->BestForm();
Abbrev->AddAttribute(Attribute, Form);
}
/// Complete - Indicate that all attributes have been added and ready to get an
@ -731,7 +915,7 @@ void DwarfWriter::PrintHex(int Value) const {
/// EOL - Print a newline character to asm stream. If a comment is present
/// then it will be printed first. Comments should not contain '\n'.
void DwarfWriter::EOL(const std::string &Comment) const {
if (DwarfVerbose) {
if (DwarfVerbose && !Comment.empty()) {
O << "\t"
<< Asm->CommentString
<< " "
@ -1134,13 +1318,18 @@ DIE *DwarfWriter::NewType(DIE *Context, TypeDesc *TyDesc) {
// Add elements to structure type.
for(unsigned i = 0, N = Elements.size(); i < N; ++i) {
DerivedTypeDesc *MemberDesc = cast<DerivedTypeDesc>(Elements[i]);
// Extract the basic information.
const std::string &Name = MemberDesc->getName();
unsigned Line = MemberDesc->getLine();
TypeDesc *MemTy = MemberDesc->getFromType();
uint64_t Size = MemberDesc->getSize();
uint64_t Offset = MemberDesc->getOffset();
// Construct member die.
DIE *Member = new DIE(DW_TAG_member);
// Add details.
if (!Name.empty()) Member->AddString(DW_AT_name, DW_FORM_string, Name);
if (CompileUnitDesc *File = MemberDesc->getFile()) {
CompileUnit *FileUnit = FindCompileUnit(File);
@ -1149,13 +1338,19 @@ DIE *DwarfWriter::NewType(DIE *Context, TypeDesc *TyDesc) {
Member->AddUInt(DW_AT_decl_file, 0, FileID);
Member->AddUInt(DW_AT_decl_line, 0, Line);
}
if (TypeDesc *FromTy = MemberDesc->getFromType()) {
Member->AddDIEntry(DW_AT_type, DW_FORM_ref4,
NewType(Context, FromTy));
}
// FIXME - Punt on the Address.
Member->AddUInt(DW_AT_data_member_location, DW_FORM_block1,
Offset >> 3);
// Add computation for offset.
DIEBlock *Block = new DIEBlock();
Block->AddUInt(DW_FORM_data1, DW_OP_plus_uconst);
Block->AddUInt(DW_FORM_udata, Offset >> 3);
Block->ComputeSize(*this);
Member->AddBlock(DW_AT_data_member_location, 0, Block);
Ty->AddChild(Member);
}
break;
@ -1263,8 +1458,12 @@ DIE *DwarfWriter::NewGlobalVariable(GlobalVariableDesc *GVD) {
VariableDie->AddUInt (DW_AT_decl_line, 0, Line);
VariableDie->AddDIEntry (DW_AT_type, DW_FORM_ref4, Type);
VariableDie->AddUInt (DW_AT_external, DW_FORM_flag, 1);
// FIXME - needs to be a proper expression.
VariableDie->AddObjectLabel(DW_AT_location, DW_FORM_block1, MangledName);
DIEBlock *Block = new DIEBlock();
Block->AddUInt(DW_FORM_data1, DW_OP_addr);
Block->AddObjectLabel(DW_FORM_udata, MangledName);
Block->ComputeSize(*this);
VariableDie->AddBlock(DW_AT_location, 0, Block);
// Add to map.
Slot = VariableDie;