Newer
Older
//===-- llvm/CodeGen/DwarfWriter.cpp - Dwarf Framework ----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by James M. Laskey and is distributed under the
// University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains support for writing dwarf debug info into asm files.
//
//===----------------------------------------------------------------------===//
#include "llvm/CodeGen/DwarfWriter.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Module.h"
#include "llvm/Type.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/MachineDebugInfo.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineLocation.h"
#include "llvm/Support/Dwarf.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Target/MRegisterInfo.h"
#include "llvm/Target/TargetMachine.h"
#include <iostream>
using namespace llvm;
static cl::opt<bool>
DwarfVerbose("dwarf-verbose", cl::Hidden,
cl::desc("Add comments to Dwarf directives."));
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// CompileUnit - This dwarf writer support class manages information associate
// with a source file.
class CompileUnit {
private:
CompileUnitDesc *Desc; // Compile unit debug descriptor.
unsigned ID; // File ID for source.
DIE *Die; // Compile unit debug information entry.
std::map<std::string, DIE *> Globals; // A map of globally visible named
// entities for this unit.
std::map<DebugInfoDesc *, DIE *> DescToDieMap;
// Tracks the mapping of unit level
// debug informaton descriptors to debug
// information entries.
public:
CompileUnit(CompileUnitDesc *CUD, unsigned I, DIE *D)
: Desc(CUD)
, ID(I)
, Die(D)
, Globals()
{}
~CompileUnit();
// Accessors.
CompileUnitDesc *getDesc() const { return Desc; }
unsigned getID() const { return ID; }
DIE* getDie() const { return Die; }
std::map<std::string, DIE *> &getGlobals() { return Globals; }
/// hasContent - Return true if this compile unit has something to write out.
///
bool hasContent() const;
/// AddGlobal - Add a new global entity to the compile unit.
///
void AddGlobal(const std::string &Name, DIE *Die);
/// getDieMapSlotFor - Returns the debug information entry map slot for the
/// specified debug descriptor.
DIE *&getDieMapSlotFor(DebugInfoDesc *DD) {
return DescToDieMap[DD];
}
//===----------------------------------------------------------------------===//
// 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)
{}
unsigned getAttribute() const { return Attribute; }
unsigned getForm() const { return Form; }
/// operator== - Used by DIEAbbrev to locate entry.
///
bool operator==(const DIEAbbrevData &DAD) const {
return Attribute == DAD.Attribute && Form == DAD.Form;
/// operator!= - Used by DIEAbbrev to locate entry.
///
bool operator!=(const DIEAbbrevData &DAD) const {
return Attribute != DAD.Attribute || Form != DAD.Form;
/// operator< - Used by DIEAbbrev to locate entry.
///
bool operator<(const DIEAbbrevData &DAD) const {
return Attribute < DAD.Attribute ||
(Attribute == DAD.Attribute && Form < DAD.Form);
//===----------------------------------------------------------------------===//
// DIEAbbrev - Dwarf abbreviation, describes the organization of a debug
// information object.
class DIEAbbrev {
private:
unsigned Tag; // Dwarf tag code.
unsigned ChildrenFlag; // Dwarf children flag.
std::vector<DIEAbbrevData> Data; // Raw data bytes for abbreviation.
public:
DIEAbbrev(unsigned T, unsigned C)
: Tag(T)
, ChildrenFlag(C)
, Data()
{}
~DIEAbbrev() {}
unsigned getTag() const { return Tag; }
unsigned getChildrenFlag() const { return ChildrenFlag; }
const std::vector<DIEAbbrevData> &getData() const { return Data; }
void setChildrenFlag(unsigned CF) { ChildrenFlag = CF; }
/// operator== - Used by UniqueVector to locate entry.
///
bool operator==(const DIEAbbrev &DA) const;
/// operator< - Used by UniqueVector to locate entry.
///
bool operator<(const DIEAbbrev &DA) const;
/// AddAttribute - Adds another set of attribute information to the
/// abbreviation.
void AddAttribute(unsigned Attribute, unsigned Form) {
Data.push_back(DIEAbbrevData(Attribute, Form));
/// AddFirstAttribute - Adds a set of attribute information to the front
/// of the abbreviation.
void AddFirstAttribute(unsigned Attribute, unsigned Form) {
Data.insert(Data.begin(), 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 DIEValue {
public:
enum {
isInteger,
isString,
isLabel,
isAsIsLabel,
isDelta,
};
unsigned Type; // Type of the value
DIEValue(unsigned T) : Type(T) {}
virtual ~DIEValue() {}
// Implement isa/cast/dyncast.
static bool classof(const DIEValue *) { return true; }
/// EmitValue - Emit value via the Dwarf writer.
///
virtual void EmitValue(const DwarfWriter &DW, unsigned Form) const = 0;
/// SizeOf - Return the size of a value in bytes.
///
virtual unsigned SizeOf(const DwarfWriter &DW, unsigned Form) const = 0;
};
//===----------------------------------------------------------------------===//
// DWInteger - An integer value DIE.
//
class DIEInteger : public DIEValue {
private:
uint64_t Integer;
public:
DIEInteger(uint64_t I) : DIEValue(isInteger), Integer(I) {}
// Implement isa/cast/dyncast.
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;
/// SizeOf - Determine size of integer value in bytes.
///
virtual unsigned SizeOf(const DwarfWriter &DW, unsigned Form) const;
};
//===----------------------------------------------------------------------===//
// DIEString - A string value DIE.
//
struct DIEString : public DIEValue {
const std::string String;
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 *S) { return S->Type == isString; }
/// EmitValue - Emit string value.
///
virtual void EmitValue(const DwarfWriter &DW, unsigned Form) const;
/// SizeOf - Determine size of string value in bytes.
///
virtual unsigned SizeOf(const DwarfWriter &DW, unsigned Form) const;
};
//===----------------------------------------------------------------------===//
// DIEDwarfLabel - A Dwarf internal label expression DIE.
//
struct DIEDwarfLabel : public DIEValue {
const DWLabel Label;
DIEDwarfLabel(const DWLabel &L) : DIEValue(isLabel), Label(L) {}
// Implement isa/cast/dyncast.
static bool classof(const DIEDwarfLabel *) { 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;
};
//===----------------------------------------------------------------------===//
// DIEObjectLabel - A label to an object in code or data.
//
struct DIEObjectLabel : public DIEValue {
const std::string Label;
DIEObjectLabel(const std::string &L) : DIEValue(isAsIsLabel), Label(L) {}
// Implement isa/cast/dyncast.
static bool classof(const DIEObjectLabel *) { return true; }
static bool classof(const DIEValue *L) { return L->Type == isAsIsLabel; }
/// EmitValue - Emit label value.
///
virtual void EmitValue(const DwarfWriter &DW, unsigned Form) const;
/// SizeOf - Determine size of label value in bytes.
///
virtual unsigned SizeOf(const DwarfWriter &DW, unsigned Form) const;
};
//===----------------------------------------------------------------------===//
// DIEDelta - A simple label difference DIE.
//
struct DIEDelta : public DIEValue {
const DWLabel LabelHi;
const DWLabel LabelLo;
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 *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 debug information entry offset.
///
virtual void EmitValue(const DwarfWriter &DW, unsigned Form) const;
/// SizeOf - Determine size of debug information entry in bytes.
///
virtual unsigned SizeOf(const DwarfWriter &DW, unsigned Form) const;
};
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
//===----------------------------------------------------------------------===//
// 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.
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.
public:
DIE(unsigned Tag);
~DIE();
unsigned getAbbrevID() const { return AbbrevID; }
unsigned getOffset() const { return Offset; }
unsigned getSize() const { return Size; }
const std::vector<DIE *> &getChildren() const { return Children; }
const std::vector<DIEValue *> &getValues() const { return Values; }
void setOffset(unsigned O) { Offset = O; }
void setSize(unsigned S) { Size = S; }
/// SiblingOffset - Return the offset of the debug information entry's
/// sibling.
unsigned SiblingOffset() const { return Offset + Size; }
/// AddSiblingOffset - Add a sibling offset field to the front of the DIE.
///
void AddSiblingOffset();
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
/// AddUInt - Add an unsigned integer attribute data and value.
///
void AddUInt(unsigned Attribute, unsigned Form, uint64_t Integer);
/// AddSInt - Add an signed integer attribute data and value.
///
void AddSInt(unsigned Attribute, unsigned Form, int64_t 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);
/// AddObjectLabel - Add a non-Dwarf label attribute data and value.
///
void AddObjectLabel(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);
/// 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.
///
void Complete(DwarfWriter &DW);
/// AddChild - Add a child to the DIE.
void AddChild(DIE *Child);
};
} // End of namespace llvm
//===----------------------------------------------------------------------===//
CompileUnit::~CompileUnit() {
delete Die;
}
/// hasContent - Return true if this compile unit has something to write out.
///
bool CompileUnit::hasContent() const {
return !Die->getChildren().empty();
}
/// AddGlobal - Add a new global entity to the compile unit.
///
void CompileUnit::AddGlobal(const std::string &Name, DIE *Die) {
Globals[Name] = Die;
}
//===----------------------------------------------------------------------===//
/// 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) {
if (Data[i] != DA.Data[i]) 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) {
if (Data[i] != DA.Data[i]) return Data[i] < DA.Data[i];
}
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 @"
<< " "
<< 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
//===----------------------------------------------------------------------===//
/// 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 {
switch (Form) {
case DW_FORM_ref1: // Fall thru
case DW_FORM_data1: DW.EmitInt8(Integer); break;
case DW_FORM_ref2: // Fall thru
case DW_FORM_data2: DW.EmitInt16(Integer); break;
case DW_FORM_ref4: // Fall thru
case DW_FORM_data4: DW.EmitInt32(Integer); break;
case DW_FORM_ref8: // Fall thru
case DW_FORM_data8: DW.EmitInt64(Integer); break;
case DW_FORM_udata: DW.EmitULEB128Bytes(Integer); break;
case DW_FORM_sdata: DW.EmitSLEB128Bytes(Integer); break;
default: assert(0 && "DIE Value form not supported yet"); break;
}
/// SizeOf - Determine size of integer value in bytes.
///
unsigned DIEInteger::SizeOf(const DwarfWriter &DW, unsigned Form) const {
switch (Form) {
case DW_FORM_flag: // Fall thru
case DW_FORM_ref1: // Fall thru
case DW_FORM_data1: return sizeof(int8_t);
case DW_FORM_ref2: // Fall thru
case DW_FORM_data2: return sizeof(int16_t);
case DW_FORM_ref4: // Fall thru
case DW_FORM_data4: return sizeof(int32_t);
case DW_FORM_ref8: // Fall thru
case DW_FORM_data8: return sizeof(int64_t);
case DW_FORM_udata: return DW.SizeULEB128(Integer);
case DW_FORM_sdata: return DW.SizeSLEB128(Integer);
default: assert(0 && "DIE Value form not supported yet"); break;
}
return 0;
}
//===----------------------------------------------------------------------===//
/// EmitValue - Emit string value.
///
void DIEString::EmitValue(const DwarfWriter &DW, unsigned Form) const {
DW.EmitString(String);
}
/// SizeOf - Determine size of string value in bytes.
///
unsigned DIEString::SizeOf(const DwarfWriter &DW, unsigned Form) const {
return String.size() + sizeof(char); // sizeof('\0');
}
//===----------------------------------------------------------------------===//
/// EmitValue - Emit label value.
///
void DIEDwarfLabel::EmitValue(const DwarfWriter &DW, unsigned Form) const {
DW.EmitReference(Label);
}
/// SizeOf - Determine size of label value in bytes.
///
unsigned DIEDwarfLabel::SizeOf(const DwarfWriter &DW, unsigned Form) const {
return DW.getAddressSize();
}
//===----------------------------------------------------------------------===//
/// EmitValue - Emit label value.
///
void DIEObjectLabel::EmitValue(const DwarfWriter &DW, unsigned Form) const {
DW.EmitReference(Label);
}
/// SizeOf - Determine size of label value in bytes.
///
unsigned DIEObjectLabel::SizeOf(const DwarfWriter &DW, unsigned Form) const {
}
//===----------------------------------------------------------------------===//
/// EmitValue - Emit delta value.
///
void DIEDelta::EmitValue(const DwarfWriter &DW, unsigned Form) const {
DW.EmitDifference(LabelHi, LabelLo);
}
/// SizeOf - Determine size of delta value in bytes.
///
unsigned DIEDelta::SizeOf(const DwarfWriter &DW, unsigned Form) const {
return DW.getAddressSize();
}
//===----------------------------------------------------------------------===//
/// EmitValue - Emit debug information entry offset.
///
void DIEntry::EmitValue(const DwarfWriter &DW, unsigned Form) const {
DW.EmitInt32(Entry->getOffset());
}
/// SizeOf - Determine size of debug information entry value in bytes.
///
unsigned DIEntry::SizeOf(const DwarfWriter &DW, unsigned Form) const {
return sizeof(int32_t);
}
//===----------------------------------------------------------------------===//
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
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)
, Offset(0)
, Size(0)
, 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];
}
}
/// AddSiblingOffset - Add a sibling offset field to the front of the DIE.
///
void DIE::AddSiblingOffset() {
DIEInteger *DI = new DIEInteger(0);
Values.insert(Values.begin(), DI);
Abbrev->AddFirstAttribute(DW_AT_sibling, DW_FORM_ref4);
}
/// AddUInt - Add an unsigned integer attribute data and value.
///
void DIE::AddUInt(unsigned Attribute, unsigned Form, uint64_t Integer) {
DIEInteger *DI = new DIEInteger(Integer);
Values.push_back(DI);
if (!Form) Form = DI->BestForm(false);
Abbrev->AddAttribute(Attribute, Form);
}
/// AddSInt - Add an signed integer attribute data and value.
///
void DIE::AddSInt(unsigned Attribute, unsigned Form, int64_t Integer) {
DIEInteger *DI = new DIEInteger(Integer);
Values.push_back(DI);
if (!Form) Form = DI->BestForm(true);
Abbrev->AddAttribute(Attribute, Form);
}
/// AddString - Add a std::string attribute data and value.
///
void DIE::AddString(unsigned Attribute, unsigned Form,
const std::string &String) {
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) {
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) {
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) {
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) {
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
/// 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) {
assert(Abbrev && "Adding children without an abbreviation");
Abbrev->setChildrenFlag(DW_CHILDREN_yes);
Children.push_back(Child);
}
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
/// PrintHex - Print a value as a hexidecimal value.
///
void DwarfWriter::PrintHex(int Value) const {
O << "0x" << std::hex << Value << std::dec;
}
/// 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 && !Comment.empty()) {
<< Asm->CommentString
/// EmitAlign - Print a align directive.
///
void DwarfWriter::EmitAlign(unsigned Alignment) const {
O << Asm->AlignDirective << Alignment << "\n";
}
/// EmitULEB128Bytes - Emit an assembler byte data directive to compose an
/// unsigned leb128 value.
void DwarfWriter::EmitULEB128Bytes(unsigned Value) const {
if (hasLEB128) {
O << "\t.uleb128\t"
<< Value;
} else {
O << Asm->Data8bitsDirective;
PrintULEB128(Value);
}
}
/// EmitSLEB128Bytes - Emit an assembler byte data directive to compose a
/// signed leb128 value.
void DwarfWriter::EmitSLEB128Bytes(int Value) const {
if (hasLEB128) {
O << "\t.sleb128\t"
<< Value;
} else {
O << Asm->Data8bitsDirective;
PrintSLEB128(Value);
}
}
/// PrintULEB128 - Print a series of hexidecimal values (separated by commas)
/// representing an unsigned leb128 value.
void DwarfWriter::PrintULEB128(unsigned Value) const {
do {
unsigned Byte = Value & 0x7f;