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/Support/Dwarf.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Mangler.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."));
//===----------------------------------------------------------------------===//
// Forward declarations.
//
class CompileUnit;
class DIE;
//===----------------------------------------------------------------------===//
// CompileUnit - This dwarf writer support class manages information associate
// with a source file.
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
class CompileUnit {
private:
CompileUnitDesc *Desc; // Compile unit debug descriptor.
unsigned ID; // File ID for source.
DIE *Die; // Compile unit die.
std::map<std::string, DIE *> Globals; // A map of globally visible named
// entities for this unit.
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);
};
//===----------------------------------------------------------------------===//
// 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));
/// 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 die entry offset.
///
virtual void EmitValue(const DwarfWriter &DW, unsigned Form) const;
/// SizeOf - Determine size of die entry in bytes.
///
virtual unsigned SizeOf(const DwarfWriter &DW, unsigned Form) const;
};
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
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
//===----------------------------------------------------------------------===//
// 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();
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
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; }
/// 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_data1: DW.EmitInt8(Integer); break;
case DW_FORM_data2: DW.EmitInt16(Integer); break;
case DW_FORM_data4: DW.EmitInt32(Integer); break;
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_data1: return sizeof(int8_t);
case DW_FORM_data2: return sizeof(int16_t);
case DW_FORM_data4: return sizeof(int32_t);
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 die entry offset.
///
void DIEntry::EmitValue(const DwarfWriter &DW, unsigned Form) const {
DW.EmitInt32(Entry->getOffset());
}
/// SizeOf - Determine size of die value in bytes.
///
unsigned DIEntry::SizeOf(const DwarfWriter &DW, unsigned Form) const {
return sizeof(int32_t);
}
//===----------------------------------------------------------------------===//
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
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
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];
}
}
/// 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
/// 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;
Value >>= 7;
if (Value) Byte |= 0x80;
PrintHex(Byte);
if (Value) O << ", ";
} while (Value);
}
/// SizeULEB128 - Compute the number of bytes required for an unsigned leb128
/// value.
unsigned DwarfWriter::SizeULEB128(unsigned Value) {
unsigned Size = 0;
do {
Value >>= 7;
Size += sizeof(int8_t);
} while (Value);
return Size;
}
/// PrintSLEB128 - Print a series of hexidecimal values (separated by commas)
/// representing a signed leb128 value.
void DwarfWriter::PrintSLEB128(int Value) const {
int Sign = Value >> (8 * sizeof(Value) - 1);
bool IsMore;
do {
unsigned Byte = Value & 0x7f;
Value >>= 7;
IsMore = Value != Sign || ((Byte ^ Sign) & 0x40) != 0;
if (IsMore) Byte |= 0x80;
PrintHex(Byte);
if (IsMore) O << ", ";
} while (IsMore);
}
/// SizeSLEB128 - Compute the number of bytes required for a signed leb128
/// value.
unsigned DwarfWriter::SizeSLEB128(int Value) {
unsigned Size = 0;
int Sign = Value >> (8 * sizeof(Value) - 1);
bool IsMore;
do {
unsigned Byte = Value & 0x7f;
Value >>= 7;
IsMore = Value != Sign || ((Byte ^ Sign) & 0x40) != 0;