#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DIE_H
#define LLVM_LIB_CODEGEN_ASMPRINTER_DIE_H
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Dwarf.h"
#include <vector>
namespace llvm {
class AsmPrinter;
class MCExpr;
class MCSymbol;
class raw_ostream;
class DwarfTypeUnit;
class DIEAbbrevData {
dwarf::Attribute Attribute;
dwarf::Form Form;
public:
DIEAbbrevData(dwarf::Attribute A, dwarf::Form F) : Attribute(A), Form(F) {}
dwarf::Attribute getAttribute() const { return Attribute; }
dwarf::Form getForm() const { return Form; }
void Profile(FoldingSetNodeID &ID) const;
};
class DIEAbbrev : public FoldingSetNode {
unsigned Number;
dwarf::Tag Tag;
bool Children;
SmallVector<DIEAbbrevData, 12> Data;
public:
DIEAbbrev(dwarf::Tag T, bool C) : Tag(T), Children(C), Data() {}
dwarf::Tag getTag() const { return Tag; }
unsigned getNumber() const { return Number; }
bool hasChildren() const { return Children; }
const SmallVectorImpl<DIEAbbrevData> &getData() const { return Data; }
void setChildrenFlag(bool hasChild) { Children = hasChild; }
void setNumber(unsigned N) { Number = N; }
void AddAttribute(dwarf::Attribute Attribute, dwarf::Form Form) {
Data.push_back(DIEAbbrevData(Attribute, Form));
}
void Profile(FoldingSetNodeID &ID) const;
void Emit(AsmPrinter *AP) const;
#ifndef NDEBUG
void print(raw_ostream &O);
void dump();
#endif
};
class DIEValue;
class DIE {
protected:
unsigned Offset;
unsigned Size;
DIEAbbrev Abbrev;
std::vector<std::unique_ptr<DIE>> Children;
DIE *Parent;
SmallVector<DIEValue *, 12> Values;
protected:
DIE()
: Offset(0), Size(0), Abbrev((dwarf::Tag)0, dwarf::DW_CHILDREN_no),
Parent(nullptr) {}
public:
explicit DIE(dwarf::Tag Tag)
: Offset(0), Size(0), Abbrev((dwarf::Tag)Tag, dwarf::DW_CHILDREN_no),
Parent(nullptr) {}
DIEAbbrev &getAbbrev() { return Abbrev; }
const DIEAbbrev &getAbbrev() const { return Abbrev; }
unsigned getAbbrevNumber() const { return Abbrev.getNumber(); }
dwarf::Tag getTag() const { return Abbrev.getTag(); }
unsigned getOffset() const { return Offset; }
unsigned getSize() const { return Size; }
const std::vector<std::unique_ptr<DIE>> &getChildren() const {
return Children;
}
const SmallVectorImpl<DIEValue *> &getValues() const { return Values; }
DIE *getParent() const { return Parent; }
const DIE *getUnit() const;
const DIE *getUnitOrNull() const;
void setOffset(unsigned O) { Offset = O; }
void setSize(unsigned S) { Size = S; }
void addValue(dwarf::Attribute Attribute, dwarf::Form Form, DIEValue *Value) {
Abbrev.AddAttribute(Attribute, Form);
Values.push_back(Value);
}
void addChild(std::unique_ptr<DIE> Child) {
assert(!Child->getParent());
Abbrev.setChildrenFlag(dwarf::DW_CHILDREN_yes);
Child->Parent = this;
Children.push_back(std::move(Child));
}
DIEValue *findAttribute(dwarf::Attribute Attribute) const;
#ifndef NDEBUG
void print(raw_ostream &O, unsigned IndentCount = 0) const;
void dump();
#endif
};
class DIEValue {
virtual void anchor();
public:
enum Type {
isInteger,
isString,
isExpr,
isLabel,
isDelta,
isEntry,
isTypeSignature,
isBlock,
isLoc,
isLocList,
};
protected:
Type Ty;
explicit DIEValue(Type T) : Ty(T) {}
virtual ~DIEValue() {}
public:
Type getType() const { return Ty; }
virtual void EmitValue(AsmPrinter *AP, dwarf::Form Form) const = 0;
virtual unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const = 0;
#ifndef NDEBUG
virtual void print(raw_ostream &O) const = 0;
void dump() const;
#endif
};
class DIEInteger : public DIEValue {
uint64_t Integer;
public:
explicit DIEInteger(uint64_t I) : DIEValue(isInteger), Integer(I) {}
static dwarf::Form BestForm(bool IsSigned, uint64_t Int) {
if (IsSigned) {
const int64_t SignedInt = Int;
if ((char)Int == SignedInt)
return dwarf::DW_FORM_data1;
if ((short)Int == SignedInt)
return dwarf::DW_FORM_data2;
if ((int)Int == SignedInt)
return dwarf::DW_FORM_data4;
} else {
if ((unsigned char)Int == Int)
return dwarf::DW_FORM_data1;
if ((unsigned short)Int == Int)
return dwarf::DW_FORM_data2;
if ((unsigned int)Int == Int)
return dwarf::DW_FORM_data4;
}
return dwarf::DW_FORM_data8;
}
void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override;
uint64_t getValue() const { return Integer; }
unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override;
static bool classof(const DIEValue *I) { return I->getType() == isInteger; }
#ifndef NDEBUG
void print(raw_ostream &O) const override;
#endif
};
class DIEExpr : public DIEValue {
const MCExpr *Expr;
public:
explicit DIEExpr(const MCExpr *E) : DIEValue(isExpr), Expr(E) {}
void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override;
const MCExpr *getValue() const { return Expr; }
unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override;
static bool classof(const DIEValue *E) { return E->getType() == isExpr; }
#ifndef NDEBUG
void print(raw_ostream &O) const override;
#endif
};
class DIELabel : public DIEValue {
const MCSymbol *Label;
public:
explicit DIELabel(const MCSymbol *L) : DIEValue(isLabel), Label(L) {}
void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override;
const MCSymbol *getValue() const { return Label; }
unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override;
static bool classof(const DIEValue *L) { return L->getType() == isLabel; }
#ifndef NDEBUG
void print(raw_ostream &O) const override;
#endif
};
class DIEDelta : public DIEValue {
const MCSymbol *LabelHi;
const MCSymbol *LabelLo;
public:
DIEDelta(const MCSymbol *Hi, const MCSymbol *Lo)
: DIEValue(isDelta), LabelHi(Hi), LabelLo(Lo) {}
void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override;
unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override;
static bool classof(const DIEValue *D) { return D->getType() == isDelta; }
#ifndef NDEBUG
void print(raw_ostream &O) const override;
#endif
};
class DIEString : public DIEValue {
const DIEValue *Access;
const StringRef Str;
public:
DIEString(const DIEValue *Acc, const StringRef S)
: DIEValue(isString), Access(Acc), Str(S) {}
StringRef getString() const { return Str; }
void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override;
unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override;
static bool classof(const DIEValue *D) { return D->getType() == isString; }
#ifndef NDEBUG
void print(raw_ostream &O) const override;
#endif
};
class DIEEntry : public DIEValue {
DIE &Entry;
public:
explicit DIEEntry(DIE &E) : DIEValue(isEntry), Entry(E) {
}
DIE &getEntry() const { return Entry; }
void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override;
unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override {
return Form == dwarf::DW_FORM_ref_addr ? getRefAddrSize(AP)
: sizeof(int32_t);
}
static unsigned getRefAddrSize(AsmPrinter *AP);
static bool classof(const DIEValue *E) { return E->getType() == isEntry; }
#ifndef NDEBUG
void print(raw_ostream &O) const override;
#endif
};
class DIETypeSignature : public DIEValue {
const DwarfTypeUnit &Unit;
public:
explicit DIETypeSignature(const DwarfTypeUnit &Unit)
: DIEValue(isTypeSignature), Unit(Unit) {}
void EmitValue(AsmPrinter *Asm, dwarf::Form Form) const override;
unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override {
assert(Form == dwarf::DW_FORM_ref_sig8);
return 8;
}
static bool classof(const DIEValue *E) {
return E->getType() == isTypeSignature;
}
#ifndef NDEBUG
void print(raw_ostream &O) const override;
void dump() const;
#endif
};
class DIELoc : public DIEValue, public DIE {
mutable unsigned Size; public:
DIELoc() : DIEValue(isLoc), Size(0) {}
unsigned ComputeSize(AsmPrinter *AP) const;
dwarf::Form BestForm(unsigned DwarfVersion) const {
if ((unsigned char)Size == Size)
return dwarf::DW_FORM_block1;
if ((unsigned short)Size == Size)
return dwarf::DW_FORM_block2;
if ((unsigned int)Size == Size)
return dwarf::DW_FORM_block4;
return dwarf::DW_FORM_block;
}
void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override;
unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override;
static bool classof(const DIEValue *E) { return E->getType() == isLoc; }
#ifndef NDEBUG
void print(raw_ostream &O) const override;
#endif
};
class DIEBlock : public DIEValue, public DIE {
mutable unsigned Size; public:
DIEBlock() : DIEValue(isBlock), Size(0) {}
unsigned ComputeSize(AsmPrinter *AP) const;
dwarf::Form BestForm() const {
if ((unsigned char)Size == Size)
return dwarf::DW_FORM_block1;
if ((unsigned short)Size == Size)
return dwarf::DW_FORM_block2;
if ((unsigned int)Size == Size)
return dwarf::DW_FORM_block4;
return dwarf::DW_FORM_block;
}
void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override;
unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override;
static bool classof(const DIEValue *E) { return E->getType() == isBlock; }
#ifndef NDEBUG
void print(raw_ostream &O) const override;
#endif
};
class DIELocList : public DIEValue {
size_t Index;
public:
DIELocList(size_t I) : DIEValue(isLocList), Index(I) {}
size_t getValue() const { return Index; }
void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override;
unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override;
static bool classof(const DIEValue *E) { return E->getType() == isLocList; }
#ifndef NDEBUG
void print(raw_ostream &O) const override;
#endif
};
}
#endif