mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-28 22:20:37 +00:00
Split out the Dwarf writer stuff into separate files. This is a much more
logical/sane approach to organizing all of the stuff that goes into writing out DWARF information. Honestly? even this is too complex for what it's supposed to be doing. Trivia: It *looks* like there would be functionality changes, however there aren't! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@71821 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
5f00b0c5b6
commit
88423eecd0
518
lib/CodeGen/AsmPrinter/DIE.cpp
Normal file
518
lib/CodeGen/AsmPrinter/DIE.cpp
Normal file
@ -0,0 +1,518 @@
|
||||
//===--- lib/CodeGen/DIE.cpp - DWARF Info Entries -------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Data structures for DWARF info entries.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "DIE.h"
|
||||
#include "DwarfPrinter.h"
|
||||
#include "llvm/CodeGen/AsmPrinter.h"
|
||||
#include "llvm/Target/TargetAsmInfo.h"
|
||||
#include "llvm/Target/TargetData.h"
|
||||
#include <ostream>
|
||||
using namespace llvm;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// DIEAbbrevData Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// Profile - Used to gather unique data for the abbreviation folding set.
|
||||
///
|
||||
void DIEAbbrevData::Profile(FoldingSetNodeID &ID) const {
|
||||
ID.AddInteger(Attribute);
|
||||
ID.AddInteger(Form);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// DIEAbbrev Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// Profile - Used to gather unique data for the abbreviation folding set.
|
||||
///
|
||||
void DIEAbbrev::Profile(FoldingSetNodeID &ID) const {
|
||||
ID.AddInteger(Tag);
|
||||
ID.AddInteger(ChildrenFlag);
|
||||
|
||||
// For each attribute description.
|
||||
for (unsigned i = 0, N = Data.size(); i < N; ++i)
|
||||
Data[i].Profile(ID);
|
||||
}
|
||||
|
||||
/// Emit - Print the abbreviation using the specified asm printer.
|
||||
///
|
||||
void DIEAbbrev::Emit(const AsmPrinter *Asm) const {
|
||||
// Emit its Dwarf tag type.
|
||||
Asm->EmitULEB128Bytes(Tag);
|
||||
Asm->EOL(dwarf::TagString(Tag));
|
||||
|
||||
// Emit whether it has children DIEs.
|
||||
Asm->EmitULEB128Bytes(ChildrenFlag);
|
||||
Asm->EOL(dwarf::ChildrenString(ChildrenFlag));
|
||||
|
||||
// For each attribute description.
|
||||
for (unsigned i = 0, N = Data.size(); i < N; ++i) {
|
||||
const DIEAbbrevData &AttrData = Data[i];
|
||||
|
||||
// Emit attribute type.
|
||||
Asm->EmitULEB128Bytes(AttrData.getAttribute());
|
||||
Asm->EOL(dwarf::AttributeString(AttrData.getAttribute()));
|
||||
|
||||
// Emit form type.
|
||||
Asm->EmitULEB128Bytes(AttrData.getForm());
|
||||
Asm->EOL(dwarf::FormEncodingString(AttrData.getForm()));
|
||||
}
|
||||
|
||||
// Mark end of abbreviation.
|
||||
Asm->EmitULEB128Bytes(0); Asm->EOL("EOM(1)");
|
||||
Asm->EmitULEB128Bytes(0); Asm->EOL("EOM(2)");
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
void DIEAbbrev::print(std::ostream &O) {
|
||||
O << "Abbreviation @"
|
||||
<< std::hex << (intptr_t)this << std::dec
|
||||
<< " "
|
||||
<< dwarf::TagString(Tag)
|
||||
<< " "
|
||||
<< dwarf::ChildrenString(ChildrenFlag)
|
||||
<< "\n";
|
||||
|
||||
for (unsigned i = 0, N = Data.size(); i < N; ++i) {
|
||||
O << " "
|
||||
<< dwarf::AttributeString(Data[i].getAttribute())
|
||||
<< " "
|
||||
<< dwarf::FormEncodingString(Data[i].getForm())
|
||||
<< "\n";
|
||||
}
|
||||
}
|
||||
void DIEAbbrev::dump() { print(cerr); }
|
||||
#endif
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// DIE Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
DIE::~DIE() {
|
||||
for (unsigned i = 0, N = Children.size(); i < N; ++i)
|
||||
delete Children[i];
|
||||
}
|
||||
|
||||
/// 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(dwarf::DW_AT_sibling, dwarf::DW_FORM_ref4);
|
||||
}
|
||||
|
||||
/// Profile - Used to gather unique data for the value folding set.
|
||||
///
|
||||
void DIE::Profile(FoldingSetNodeID &ID) {
|
||||
Abbrev.Profile(ID);
|
||||
|
||||
for (unsigned i = 0, N = Children.size(); i < N; ++i)
|
||||
ID.AddPointer(Children[i]);
|
||||
|
||||
for (unsigned j = 0, M = Values.size(); j < M; ++j)
|
||||
ID.AddPointer(Values[j]);
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
void DIE::print(std::ostream &O, unsigned IncIndent) {
|
||||
static unsigned IndentCount = 0;
|
||||
IndentCount += IncIndent;
|
||||
const std::string Indent(IndentCount, ' ');
|
||||
bool isBlock = Abbrev.getTag() == 0;
|
||||
|
||||
if (!isBlock) {
|
||||
O << Indent
|
||||
<< "Die: "
|
||||
<< "0x" << std::hex << (intptr_t)this << std::dec
|
||||
<< ", Offset: " << Offset
|
||||
<< ", Size: " << Size
|
||||
<< "\n";
|
||||
|
||||
O << Indent
|
||||
<< dwarf::TagString(Abbrev.getTag())
|
||||
<< " "
|
||||
<< dwarf::ChildrenString(Abbrev.getChildrenFlag());
|
||||
} else {
|
||||
O << "Size: " << Size;
|
||||
}
|
||||
O << "\n";
|
||||
|
||||
const SmallVector<DIEAbbrevData, 8> &Data = Abbrev.getData();
|
||||
|
||||
IndentCount += 2;
|
||||
for (unsigned i = 0, N = Data.size(); i < N; ++i) {
|
||||
O << Indent;
|
||||
|
||||
if (!isBlock)
|
||||
O << dwarf::AttributeString(Data[i].getAttribute());
|
||||
else
|
||||
O << "Blk[" << i << "]";
|
||||
|
||||
O << " "
|
||||
<< dwarf::FormEncodingString(Data[i].getForm())
|
||||
<< " ";
|
||||
Values[i]->print(O);
|
||||
O << "\n";
|
||||
}
|
||||
IndentCount -= 2;
|
||||
|
||||
for (unsigned j = 0, M = Children.size(); j < M; ++j) {
|
||||
Children[j]->print(O, 4);
|
||||
}
|
||||
|
||||
if (!isBlock) O << "\n";
|
||||
IndentCount -= IncIndent;
|
||||
}
|
||||
|
||||
void DIE::dump() {
|
||||
print(cerr);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef NDEBUG
|
||||
void DIEValue::dump() {
|
||||
print(cerr);
|
||||
}
|
||||
#endif
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// DIEInteger Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// EmitValue - Emit integer of appropriate size.
|
||||
///
|
||||
void DIEInteger::EmitValue(Dwarf *D, unsigned Form) const {
|
||||
const AsmPrinter *Asm = D->getAsm();
|
||||
switch (Form) {
|
||||
case dwarf::DW_FORM_flag: // Fall thru
|
||||
case dwarf::DW_FORM_ref1: // Fall thru
|
||||
case dwarf::DW_FORM_data1: Asm->EmitInt8(Integer); break;
|
||||
case dwarf::DW_FORM_ref2: // Fall thru
|
||||
case dwarf::DW_FORM_data2: Asm->EmitInt16(Integer); break;
|
||||
case dwarf::DW_FORM_ref4: // Fall thru
|
||||
case dwarf::DW_FORM_data4: Asm->EmitInt32(Integer); break;
|
||||
case dwarf::DW_FORM_ref8: // Fall thru
|
||||
case dwarf::DW_FORM_data8: Asm->EmitInt64(Integer); break;
|
||||
case dwarf::DW_FORM_udata: Asm->EmitULEB128Bytes(Integer); break;
|
||||
case dwarf::DW_FORM_sdata: Asm->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 TargetData *TD, unsigned Form) const {
|
||||
switch (Form) {
|
||||
case dwarf::DW_FORM_flag: // Fall thru
|
||||
case dwarf::DW_FORM_ref1: // Fall thru
|
||||
case dwarf::DW_FORM_data1: return sizeof(int8_t);
|
||||
case dwarf::DW_FORM_ref2: // Fall thru
|
||||
case dwarf::DW_FORM_data2: return sizeof(int16_t);
|
||||
case dwarf::DW_FORM_ref4: // Fall thru
|
||||
case dwarf::DW_FORM_data4: return sizeof(int32_t);
|
||||
case dwarf::DW_FORM_ref8: // Fall thru
|
||||
case dwarf::DW_FORM_data8: return sizeof(int64_t);
|
||||
case dwarf::DW_FORM_udata: return TargetAsmInfo::getULEB128Size(Integer);
|
||||
case dwarf::DW_FORM_sdata: return TargetAsmInfo::getSLEB128Size(Integer);
|
||||
default: assert(0 && "DIE Value form not supported yet"); break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// Profile - Used to gather unique data for the value folding set.
|
||||
///
|
||||
void DIEInteger::Profile(FoldingSetNodeID &ID, unsigned Int) {
|
||||
ID.AddInteger(isInteger);
|
||||
ID.AddInteger(Int);
|
||||
}
|
||||
void DIEInteger::Profile(FoldingSetNodeID &ID) {
|
||||
Profile(ID, Integer);
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
void DIEInteger::print(std::ostream &O) {
|
||||
O << "Int: " << (int64_t)Integer
|
||||
<< " 0x" << std::hex << Integer << std::dec;
|
||||
}
|
||||
#endif
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// DIEString Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// EmitValue - Emit string value.
|
||||
///
|
||||
void DIEString::EmitValue(Dwarf *D, unsigned Form) const {
|
||||
D->getAsm()->EmitString(Str);
|
||||
}
|
||||
|
||||
/// Profile - Used to gather unique data for the value folding set.
|
||||
///
|
||||
void DIEString::Profile(FoldingSetNodeID &ID, const std::string &Str) {
|
||||
ID.AddInteger(isString);
|
||||
ID.AddString(Str);
|
||||
}
|
||||
void DIEString::Profile(FoldingSetNodeID &ID) {
|
||||
Profile(ID, Str);
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
void DIEString::print(std::ostream &O) {
|
||||
O << "Str: \"" << Str << "\"";
|
||||
}
|
||||
#endif
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// DIEDwarfLabel Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// EmitValue - Emit label value.
|
||||
///
|
||||
void DIEDwarfLabel::EmitValue(Dwarf *D, unsigned Form) const {
|
||||
bool IsSmall = Form == dwarf::DW_FORM_data4;
|
||||
D->EmitReference(Label, false, IsSmall);
|
||||
}
|
||||
|
||||
/// SizeOf - Determine size of label value in bytes.
|
||||
///
|
||||
unsigned DIEDwarfLabel::SizeOf(const TargetData *TD, unsigned Form) const {
|
||||
if (Form == dwarf::DW_FORM_data4) return 4;
|
||||
return TD->getPointerSize();
|
||||
}
|
||||
|
||||
/// Profile - Used to gather unique data for the value folding set.
|
||||
///
|
||||
void DIEDwarfLabel::Profile(FoldingSetNodeID &ID, const DWLabel &Label) {
|
||||
ID.AddInteger(isLabel);
|
||||
Label.Profile(ID);
|
||||
}
|
||||
void DIEDwarfLabel::Profile(FoldingSetNodeID &ID) {
|
||||
Profile(ID, Label);
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
void DIEDwarfLabel::print(std::ostream &O) {
|
||||
O << "Lbl: ";
|
||||
Label.print(O);
|
||||
}
|
||||
#endif
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// DIEObjectLabel Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// EmitValue - Emit label value.
|
||||
///
|
||||
void DIEObjectLabel::EmitValue(Dwarf *D, unsigned Form) const {
|
||||
bool IsSmall = Form == dwarf::DW_FORM_data4;
|
||||
D->EmitReference(Label, false, IsSmall);
|
||||
}
|
||||
|
||||
/// SizeOf - Determine size of label value in bytes.
|
||||
///
|
||||
unsigned DIEObjectLabel::SizeOf(const TargetData *TD, unsigned Form) const {
|
||||
if (Form == dwarf::DW_FORM_data4) return 4;
|
||||
return TD->getPointerSize();
|
||||
}
|
||||
|
||||
/// Profile - Used to gather unique data for the value folding set.
|
||||
///
|
||||
void DIEObjectLabel::Profile(FoldingSetNodeID &ID, const std::string &Label) {
|
||||
ID.AddInteger(isAsIsLabel);
|
||||
ID.AddString(Label);
|
||||
}
|
||||
void DIEObjectLabel::Profile(FoldingSetNodeID &ID) {
|
||||
Profile(ID, Label.c_str());
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
void DIEObjectLabel::print(std::ostream &O) {
|
||||
O << "Obj: " << Label;
|
||||
}
|
||||
#endif
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// DIESectionOffset Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// EmitValue - Emit delta value.
|
||||
///
|
||||
void DIESectionOffset::EmitValue(Dwarf *D, unsigned Form) const {
|
||||
bool IsSmall = Form == dwarf::DW_FORM_data4;
|
||||
D->EmitSectionOffset(Label.getTag(), Section.getTag(),
|
||||
Label.getNumber(), Section.getNumber(),
|
||||
IsSmall, IsEH, UseSet);
|
||||
}
|
||||
|
||||
/// SizeOf - Determine size of delta value in bytes.
|
||||
///
|
||||
unsigned DIESectionOffset::SizeOf(const TargetData *TD, unsigned Form) const {
|
||||
if (Form == dwarf::DW_FORM_data4) return 4;
|
||||
return TD->getPointerSize();
|
||||
}
|
||||
|
||||
/// Profile - Used to gather unique data for the value folding set.
|
||||
///
|
||||
void DIESectionOffset::Profile(FoldingSetNodeID &ID, const DWLabel &Label,
|
||||
const DWLabel &Section) {
|
||||
ID.AddInteger(isSectionOffset);
|
||||
Label.Profile(ID);
|
||||
Section.Profile(ID);
|
||||
// IsEH and UseSet are specific to the Label/Section that we will emit the
|
||||
// offset for; so Label/Section are enough for uniqueness.
|
||||
}
|
||||
void DIESectionOffset::Profile(FoldingSetNodeID &ID) {
|
||||
Profile(ID, Label, Section);
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
void DIESectionOffset::print(std::ostream &O) {
|
||||
O << "Off: ";
|
||||
Label.print(O);
|
||||
O << "-";
|
||||
Section.print(O);
|
||||
O << "-" << IsEH << "-" << UseSet;
|
||||
}
|
||||
#endif
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// DIEDelta Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// EmitValue - Emit delta value.
|
||||
///
|
||||
void DIEDelta::EmitValue(Dwarf *D, unsigned Form) const {
|
||||
bool IsSmall = Form == dwarf::DW_FORM_data4;
|
||||
D->EmitDifference(LabelHi, LabelLo, IsSmall);
|
||||
}
|
||||
|
||||
/// SizeOf - Determine size of delta value in bytes.
|
||||
///
|
||||
unsigned DIEDelta::SizeOf(const TargetData *TD, unsigned Form) const {
|
||||
if (Form == dwarf::DW_FORM_data4) return 4;
|
||||
return TD->getPointerSize();
|
||||
}
|
||||
|
||||
/// Profile - Used to gather unique data for the value folding set.
|
||||
///
|
||||
void DIEDelta::Profile(FoldingSetNodeID &ID, const DWLabel &LabelHi,
|
||||
const DWLabel &LabelLo) {
|
||||
ID.AddInteger(isDelta);
|
||||
LabelHi.Profile(ID);
|
||||
LabelLo.Profile(ID);
|
||||
}
|
||||
void DIEDelta::Profile(FoldingSetNodeID &ID) {
|
||||
Profile(ID, LabelHi, LabelLo);
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
void DIEDelta::print(std::ostream &O) {
|
||||
O << "Del: ";
|
||||
LabelHi.print(O);
|
||||
O << "-";
|
||||
LabelLo.print(O);
|
||||
}
|
||||
#endif
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// DIEEntry Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// EmitValue - Emit debug information entry offset.
|
||||
///
|
||||
void DIEEntry::EmitValue(Dwarf *D, unsigned Form) const {
|
||||
D->getAsm()->EmitInt32(Entry->getOffset());
|
||||
}
|
||||
|
||||
/// Profile - Used to gather unique data for the value folding set.
|
||||
///
|
||||
void DIEEntry::Profile(FoldingSetNodeID &ID, DIE *Entry) {
|
||||
ID.AddInteger(isEntry);
|
||||
ID.AddPointer(Entry);
|
||||
}
|
||||
void DIEEntry::Profile(FoldingSetNodeID &ID) {
|
||||
ID.AddInteger(isEntry);
|
||||
|
||||
if (Entry)
|
||||
ID.AddPointer(Entry);
|
||||
else
|
||||
ID.AddPointer(this);
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
void DIEEntry::print(std::ostream &O) {
|
||||
O << "Die: 0x" << std::hex << (intptr_t)Entry << std::dec;
|
||||
}
|
||||
#endif
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// DIEBlock Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// ComputeSize - calculate the size of the block.
|
||||
///
|
||||
unsigned DIEBlock::ComputeSize(const TargetData *TD) {
|
||||
if (!Size) {
|
||||
const SmallVector<DIEAbbrevData, 8> &AbbrevData = Abbrev.getData();
|
||||
for (unsigned i = 0, N = Values.size(); i < N; ++i)
|
||||
Size += Values[i]->SizeOf(TD, AbbrevData[i].getForm());
|
||||
}
|
||||
|
||||
return Size;
|
||||
}
|
||||
|
||||
/// EmitValue - Emit block data.
|
||||
///
|
||||
void DIEBlock::EmitValue(Dwarf *D, unsigned Form) const {
|
||||
const AsmPrinter *Asm = D->getAsm();
|
||||
switch (Form) {
|
||||
case dwarf::DW_FORM_block1: Asm->EmitInt8(Size); break;
|
||||
case dwarf::DW_FORM_block2: Asm->EmitInt16(Size); break;
|
||||
case dwarf::DW_FORM_block4: Asm->EmitInt32(Size); break;
|
||||
case dwarf::DW_FORM_block: Asm->EmitULEB128Bytes(Size); break;
|
||||
default: assert(0 && "Improper form for block"); break;
|
||||
}
|
||||
|
||||
const SmallVector<DIEAbbrevData, 8> &AbbrevData = Abbrev.getData();
|
||||
for (unsigned i = 0, N = Values.size(); i < N; ++i) {
|
||||
Asm->EOL();
|
||||
Values[i]->EmitValue(D, AbbrevData[i].getForm());
|
||||
}
|
||||
}
|
||||
|
||||
/// SizeOf - Determine size of block data in bytes.
|
||||
///
|
||||
unsigned DIEBlock::SizeOf(const TargetData *TD, unsigned Form) const {
|
||||
switch (Form) {
|
||||
case dwarf::DW_FORM_block1: return Size + sizeof(int8_t);
|
||||
case dwarf::DW_FORM_block2: return Size + sizeof(int16_t);
|
||||
case dwarf::DW_FORM_block4: return Size + sizeof(int32_t);
|
||||
case dwarf::DW_FORM_block: return Size + TargetAsmInfo::getULEB128Size(Size);
|
||||
default: assert(0 && "Improper form for block"); break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DIEBlock::Profile(FoldingSetNodeID &ID) {
|
||||
ID.AddInteger(isBlock);
|
||||
DIE::Profile(ID);
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
void DIEBlock::print(std::ostream &O) {
|
||||
O << "Blk: ";
|
||||
DIE::print(O, 5);
|
||||
}
|
||||
#endif
|
549
lib/CodeGen/AsmPrinter/DIE.h
Normal file
549
lib/CodeGen/AsmPrinter/DIE.h
Normal file
@ -0,0 +1,549 @@
|
||||
//===--- lib/CodeGen/DIE.h - DWARF Info Entries -----------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Data structures for DWARF info entries.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef DIE_H__
|
||||
#define DIE_H__
|
||||
|
||||
#include "DwarfLabel.h"
|
||||
#include "llvm/ADT/FoldingSet.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/Dwarf.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <iosfwd>
|
||||
|
||||
namespace llvm {
|
||||
class AsmPrinter;
|
||||
class Dwarf;
|
||||
class TargetData;
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// DIEAbbrevData - Dwarf abbreviation data, describes the one attribute of a
|
||||
/// Dwarf abbreviation.
|
||||
class VISIBILITY_HIDDEN DIEAbbrevData {
|
||||
/// Attribute - Dwarf attribute code.
|
||||
///
|
||||
unsigned Attribute;
|
||||
|
||||
/// Form - Dwarf form code.
|
||||
///
|
||||
unsigned Form;
|
||||
public:
|
||||
DIEAbbrevData(unsigned A, unsigned F) : Attribute(A), Form(F) {}
|
||||
|
||||
// Accessors.
|
||||
unsigned getAttribute() const { return Attribute; }
|
||||
unsigned getForm() const { return Form; }
|
||||
|
||||
/// Profile - Used to gather unique data for the abbreviation folding set.
|
||||
///
|
||||
void Profile(FoldingSetNodeID &ID) const;
|
||||
};
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// DIEAbbrev - Dwarf abbreviation, describes the organization of a debug
|
||||
/// information object.
|
||||
class VISIBILITY_HIDDEN DIEAbbrev : public FoldingSetNode {
|
||||
/// Tag - Dwarf tag code.
|
||||
///
|
||||
unsigned Tag;
|
||||
|
||||
/// Unique number for node.
|
||||
///
|
||||
unsigned Number;
|
||||
|
||||
/// ChildrenFlag - Dwarf children flag.
|
||||
///
|
||||
unsigned ChildrenFlag;
|
||||
|
||||
/// Data - Raw data bytes for abbreviation.
|
||||
///
|
||||
SmallVector<DIEAbbrevData, 8> Data;
|
||||
public:
|
||||
DIEAbbrev(unsigned T, unsigned C) : Tag(T), ChildrenFlag(C), Data() {}
|
||||
virtual ~DIEAbbrev() {}
|
||||
|
||||
// Accessors.
|
||||
unsigned getTag() const { return Tag; }
|
||||
unsigned getNumber() const { return Number; }
|
||||
unsigned getChildrenFlag() const { return ChildrenFlag; }
|
||||
const SmallVector<DIEAbbrevData, 8> &getData() const { return Data; }
|
||||
void setTag(unsigned T) { Tag = T; }
|
||||
void setChildrenFlag(unsigned CF) { ChildrenFlag = CF; }
|
||||
void setNumber(unsigned N) { Number = N; }
|
||||
|
||||
/// 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));
|
||||
}
|
||||
|
||||
/// Profile - Used to gather unique data for the abbreviation folding set.
|
||||
///
|
||||
void Profile(FoldingSetNodeID &ID) const;
|
||||
|
||||
/// Emit - Print the abbreviation using the specified asm printer.
|
||||
///
|
||||
void Emit(const AsmPrinter *Asm) const;
|
||||
|
||||
#ifndef NDEBUG
|
||||
void print(std::ostream *O) {
|
||||
if (O) print(*O);
|
||||
}
|
||||
void print(std::ostream &O);
|
||||
void dump();
|
||||
#endif
|
||||
};
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// DIE - A structured debug information entry. Has an abbreviation which
|
||||
/// describes it's organization.
|
||||
class CompileUnit;
|
||||
class DIEValue;
|
||||
|
||||
class VISIBILITY_HIDDEN DIE : public FoldingSetNode {
|
||||
protected:
|
||||
/// Abbrev - Buffer for constructing abbreviation.
|
||||
///
|
||||
DIEAbbrev Abbrev;
|
||||
|
||||
/// Offset - Offset in debug info section.
|
||||
///
|
||||
unsigned Offset;
|
||||
|
||||
/// Size - Size of instance + children.
|
||||
///
|
||||
unsigned Size;
|
||||
|
||||
/// Children DIEs.
|
||||
///
|
||||
std::vector<DIE *> Children;
|
||||
|
||||
/// Attributes values.
|
||||
///
|
||||
SmallVector<DIEValue*, 32> Values;
|
||||
|
||||
/// Abstract compile unit.
|
||||
CompileUnit *AbstractCU;
|
||||
public:
|
||||
explicit DIE(unsigned Tag)
|
||||
: Abbrev(Tag, dwarf::DW_CHILDREN_no), Offset(0), Size(0) {}
|
||||
virtual ~DIE();
|
||||
|
||||
// Accessors.
|
||||
DIEAbbrev &getAbbrev() { return Abbrev; }
|
||||
unsigned getAbbrevNumber() const { return Abbrev.getNumber(); }
|
||||
unsigned getTag() const { return Abbrev.getTag(); }
|
||||
unsigned getOffset() const { return Offset; }
|
||||
unsigned getSize() const { return Size; }
|
||||
const std::vector<DIE *> &getChildren() const { return Children; }
|
||||
SmallVector<DIEValue*, 32> &getValues() { return Values; }
|
||||
CompileUnit *getAbstractCompileUnit() const { return AbstractCU; }
|
||||
|
||||
void setTag(unsigned Tag) { Abbrev.setTag(Tag); }
|
||||
void setOffset(unsigned O) { Offset = O; }
|
||||
void setSize(unsigned S) { Size = S; }
|
||||
void setAbstractCompileUnit(CompileUnit *CU) { AbstractCU = CU; }
|
||||
|
||||
/// AddValue - Add a value and attributes to a DIE.
|
||||
///
|
||||
void AddValue(unsigned Attribute, unsigned Form, DIEValue *Value) {
|
||||
Abbrev.AddAttribute(Attribute, Form);
|
||||
Values.push_back(Value);
|
||||
}
|
||||
|
||||
/// 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();
|
||||
|
||||
/// AddChild - Add a child to the DIE.
|
||||
///
|
||||
void AddChild(DIE *Child) {
|
||||
Abbrev.setChildrenFlag(dwarf::DW_CHILDREN_yes);
|
||||
Children.push_back(Child);
|
||||
}
|
||||
|
||||
/// Detach - Detaches objects connected to it after copying.
|
||||
///
|
||||
void Detach() {
|
||||
Children.clear();
|
||||
}
|
||||
|
||||
/// Profile - Used to gather unique data for the value folding set.
|
||||
///
|
||||
void Profile(FoldingSetNodeID &ID) ;
|
||||
|
||||
#ifndef NDEBUG
|
||||
void print(std::ostream *O, unsigned IncIndent = 0) {
|
||||
if (O) print(*O, IncIndent);
|
||||
}
|
||||
void print(std::ostream &O, unsigned IncIndent = 0);
|
||||
void dump();
|
||||
#endif
|
||||
};
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// DIEValue - A debug information entry value.
|
||||
///
|
||||
class VISIBILITY_HIDDEN DIEValue : public FoldingSetNode {
|
||||
public:
|
||||
enum {
|
||||
isInteger,
|
||||
isString,
|
||||
isLabel,
|
||||
isAsIsLabel,
|
||||
isSectionOffset,
|
||||
isDelta,
|
||||
isEntry,
|
||||
isBlock
|
||||
};
|
||||
protected:
|
||||
/// Type - Type of data stored in the value.
|
||||
///
|
||||
unsigned Type;
|
||||
public:
|
||||
explicit DIEValue(unsigned T) : Type(T) {}
|
||||
virtual ~DIEValue() {}
|
||||
|
||||
// Accessors
|
||||
unsigned getType() const { return Type; }
|
||||
|
||||
/// EmitValue - Emit value via the Dwarf writer.
|
||||
///
|
||||
virtual void EmitValue(Dwarf *D, unsigned Form) const = 0;
|
||||
|
||||
/// SizeOf - Return the size of a value in bytes.
|
||||
///
|
||||
virtual unsigned SizeOf(const TargetData *TD, unsigned Form) const = 0;
|
||||
|
||||
/// Profile - Used to gather unique data for the value folding set.
|
||||
///
|
||||
virtual void Profile(FoldingSetNodeID &ID) = 0;
|
||||
|
||||
// Implement isa/cast/dyncast.
|
||||
static bool classof(const DIEValue *) { return true; }
|
||||
|
||||
#ifndef NDEBUG
|
||||
void print(std::ostream *O) {
|
||||
if (O) print(*O);
|
||||
}
|
||||
virtual void print(std::ostream &O) = 0;
|
||||
void dump();
|
||||
#endif
|
||||
};
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// DIEInteger - An integer value DIE.
|
||||
///
|
||||
class VISIBILITY_HIDDEN DIEInteger : public DIEValue {
|
||||
uint64_t Integer;
|
||||
public:
|
||||
explicit DIEInteger(uint64_t I) : DIEValue(isInteger), Integer(I) {}
|
||||
|
||||
/// BestForm - Choose the best form for integer.
|
||||
///
|
||||
static unsigned BestForm(bool IsSigned, uint64_t Int) {
|
||||
if (IsSigned) {
|
||||
if ((char)Int == (signed)Int) return dwarf::DW_FORM_data1;
|
||||
if ((short)Int == (signed)Int) return dwarf::DW_FORM_data2;
|
||||
if ((int)Int == (signed)Int) 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;
|
||||
}
|
||||
|
||||
/// EmitValue - Emit integer of appropriate size.
|
||||
///
|
||||
virtual void EmitValue(Dwarf *D, unsigned Form) const;
|
||||
|
||||
/// SizeOf - Determine size of integer value in bytes.
|
||||
///
|
||||
virtual unsigned SizeOf(const TargetData *TD, unsigned Form) const;
|
||||
|
||||
/// Profile - Used to gather unique data for the value folding set.
|
||||
///
|
||||
static void Profile(FoldingSetNodeID &ID, unsigned Int);
|
||||
virtual void Profile(FoldingSetNodeID &ID);
|
||||
|
||||
// Implement isa/cast/dyncast.
|
||||
static bool classof(const DIEInteger *) { return true; }
|
||||
static bool classof(const DIEValue *I) { return I->getType() == isInteger; }
|
||||
|
||||
#ifndef NDEBUG
|
||||
virtual void print(std::ostream &O);
|
||||
#endif
|
||||
};
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// DIEString - A string value DIE.
|
||||
///
|
||||
class VISIBILITY_HIDDEN DIEString : public DIEValue {
|
||||
const std::string Str;
|
||||
public:
|
||||
explicit DIEString(const std::string &S) : DIEValue(isString), Str(S) {}
|
||||
|
||||
/// EmitValue - Emit string value.
|
||||
///
|
||||
virtual void EmitValue(Dwarf *D, unsigned Form) const;
|
||||
|
||||
/// SizeOf - Determine size of string value in bytes.
|
||||
///
|
||||
virtual unsigned SizeOf(const TargetData *, unsigned /*Form*/) const {
|
||||
return Str.size() + sizeof(char); // sizeof('\0');
|
||||
}
|
||||
|
||||
/// Profile - Used to gather unique data for the value folding set.
|
||||
///
|
||||
static void Profile(FoldingSetNodeID &ID, const std::string &Str);
|
||||
virtual void Profile(FoldingSetNodeID &ID);
|
||||
|
||||
// Implement isa/cast/dyncast.
|
||||
static bool classof(const DIEString *) { return true; }
|
||||
static bool classof(const DIEValue *S) { return S->getType() == isString; }
|
||||
|
||||
#ifndef NDEBUG
|
||||
virtual void print(std::ostream &O);
|
||||
#endif
|
||||
};
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// DIEDwarfLabel - A Dwarf internal label expression DIE.
|
||||
//
|
||||
class VISIBILITY_HIDDEN DIEDwarfLabel : public DIEValue {
|
||||
const DWLabel Label;
|
||||
public:
|
||||
explicit DIEDwarfLabel(const DWLabel &L) : DIEValue(isLabel), Label(L) {}
|
||||
|
||||
/// EmitValue - Emit label value.
|
||||
///
|
||||
virtual void EmitValue(Dwarf *D, unsigned Form) const;
|
||||
|
||||
/// SizeOf - Determine size of label value in bytes.
|
||||
///
|
||||
virtual unsigned SizeOf(const TargetData *TD, unsigned Form) const;
|
||||
|
||||
/// Profile - Used to gather unique data for the value folding set.
|
||||
///
|
||||
static void Profile(FoldingSetNodeID &ID, const DWLabel &Label);
|
||||
virtual void Profile(FoldingSetNodeID &ID);
|
||||
|
||||
// Implement isa/cast/dyncast.
|
||||
static bool classof(const DIEDwarfLabel *) { return true; }
|
||||
static bool classof(const DIEValue *L) { return L->getType() == isLabel; }
|
||||
|
||||
#ifndef NDEBUG
|
||||
virtual void print(std::ostream &O);
|
||||
#endif
|
||||
};
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// DIEObjectLabel - A label to an object in code or data.
|
||||
//
|
||||
class VISIBILITY_HIDDEN DIEObjectLabel : public DIEValue {
|
||||
const std::string Label;
|
||||
public:
|
||||
explicit DIEObjectLabel(const std::string &L)
|
||||
: DIEValue(isAsIsLabel), Label(L) {}
|
||||
|
||||
/// EmitValue - Emit label value.
|
||||
///
|
||||
virtual void EmitValue(Dwarf *D, unsigned Form) const;
|
||||
|
||||
/// SizeOf - Determine size of label value in bytes.
|
||||
///
|
||||
virtual unsigned SizeOf(const TargetData *TD, unsigned Form) const;
|
||||
|
||||
/// Profile - Used to gather unique data for the value folding set.
|
||||
///
|
||||
static void Profile(FoldingSetNodeID &ID, const std::string &Label);
|
||||
virtual void Profile(FoldingSetNodeID &ID);
|
||||
|
||||
// Implement isa/cast/dyncast.
|
||||
static bool classof(const DIEObjectLabel *) { return true; }
|
||||
static bool classof(const DIEValue *L) {
|
||||
return L->getType() == isAsIsLabel;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
virtual void print(std::ostream &O);
|
||||
#endif
|
||||
};
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// DIESectionOffset - A section offset DIE.
|
||||
///
|
||||
class VISIBILITY_HIDDEN DIESectionOffset : public DIEValue {
|
||||
const DWLabel Label;
|
||||
const DWLabel Section;
|
||||
bool IsEH : 1;
|
||||
bool UseSet : 1;
|
||||
public:
|
||||
DIESectionOffset(const DWLabel &Lab, const DWLabel &Sec,
|
||||
bool isEH = false, bool useSet = true)
|
||||
: DIEValue(isSectionOffset), Label(Lab), Section(Sec),
|
||||
IsEH(isEH), UseSet(useSet) {}
|
||||
|
||||
/// EmitValue - Emit section offset.
|
||||
///
|
||||
virtual void EmitValue(Dwarf *D, unsigned Form) const;
|
||||
|
||||
/// SizeOf - Determine size of section offset value in bytes.
|
||||
///
|
||||
virtual unsigned SizeOf(const TargetData *TD, unsigned Form) const;
|
||||
|
||||
/// Profile - Used to gather unique data for the value folding set.
|
||||
///
|
||||
static void Profile(FoldingSetNodeID &ID, const DWLabel &Label,
|
||||
const DWLabel &Section);
|
||||
virtual void Profile(FoldingSetNodeID &ID);
|
||||
|
||||
// Implement isa/cast/dyncast.
|
||||
static bool classof(const DIESectionOffset *) { return true; }
|
||||
static bool classof(const DIEValue *D) {
|
||||
return D->getType() == isSectionOffset;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
virtual void print(std::ostream &O);
|
||||
#endif
|
||||
};
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// DIEDelta - A simple label difference DIE.
|
||||
///
|
||||
class VISIBILITY_HIDDEN DIEDelta : public DIEValue {
|
||||
const DWLabel LabelHi;
|
||||
const DWLabel LabelLo;
|
||||
public:
|
||||
DIEDelta(const DWLabel &Hi, const DWLabel &Lo)
|
||||
: DIEValue(isDelta), LabelHi(Hi), LabelLo(Lo) {}
|
||||
|
||||
/// EmitValue - Emit delta value.
|
||||
///
|
||||
virtual void EmitValue(Dwarf *D, unsigned Form) const;
|
||||
|
||||
/// SizeOf - Determine size of delta value in bytes.
|
||||
///
|
||||
virtual unsigned SizeOf(const TargetData *TD, unsigned Form) const;
|
||||
|
||||
/// Profile - Used to gather unique data for the value folding set.
|
||||
///
|
||||
static void Profile(FoldingSetNodeID &ID, const DWLabel &LabelHi,
|
||||
const DWLabel &LabelLo);
|
||||
virtual void Profile(FoldingSetNodeID &ID);
|
||||
|
||||
// Implement isa/cast/dyncast.
|
||||
static bool classof(const DIEDelta *) { return true; }
|
||||
static bool classof(const DIEValue *D) { return D->getType() == isDelta; }
|
||||
|
||||
#ifndef NDEBUG
|
||||
virtual void print(std::ostream &O);
|
||||
#endif
|
||||
};
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// DIEntry - A pointer to another debug information entry. An instance of
|
||||
/// this class can also be used as a proxy for a debug information entry not
|
||||
/// yet defined (ie. types.)
|
||||
class VISIBILITY_HIDDEN DIEEntry : public DIEValue {
|
||||
DIE *Entry;
|
||||
public:
|
||||
explicit DIEEntry(DIE *E) : DIEValue(isEntry), Entry(E) {}
|
||||
|
||||
DIE *getEntry() const { return Entry; }
|
||||
void setEntry(DIE *E) { Entry = E; }
|
||||
|
||||
/// EmitValue - Emit debug information entry offset.
|
||||
///
|
||||
virtual void EmitValue(Dwarf *D, unsigned Form) const;
|
||||
|
||||
/// SizeOf - Determine size of debug information entry in bytes.
|
||||
///
|
||||
virtual unsigned SizeOf(const TargetData *TD, unsigned Form) const {
|
||||
return sizeof(int32_t);
|
||||
}
|
||||
|
||||
/// Profile - Used to gather unique data for the value folding set.
|
||||
///
|
||||
static void Profile(FoldingSetNodeID &ID, DIE *Entry);
|
||||
virtual void Profile(FoldingSetNodeID &ID);
|
||||
|
||||
// Implement isa/cast/dyncast.
|
||||
static bool classof(const DIEEntry *) { return true; }
|
||||
static bool classof(const DIEValue *E) { return E->getType() == isEntry; }
|
||||
|
||||
#ifndef NDEBUG
|
||||
virtual void print(std::ostream &O);
|
||||
#endif
|
||||
};
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// DIEBlock - A block of values. Primarily used for location expressions.
|
||||
//
|
||||
class DIEBlock : public DIEValue, public DIE {
|
||||
unsigned Size; // Size in bytes excluding size header.
|
||||
public:
|
||||
DIEBlock()
|
||||
: DIEValue(isBlock), DIE(0), Size(0) {}
|
||||
virtual ~DIEBlock() {}
|
||||
|
||||
/// ComputeSize - calculate the size of the block.
|
||||
///
|
||||
unsigned ComputeSize(const TargetData *TD);
|
||||
|
||||
/// BestForm - Choose the best form for data.
|
||||
///
|
||||
unsigned 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;
|
||||
}
|
||||
|
||||
/// EmitValue - Emit block data.
|
||||
///
|
||||
virtual void EmitValue(Dwarf *D, unsigned Form) const;
|
||||
|
||||
/// SizeOf - Determine size of block data in bytes.
|
||||
///
|
||||
virtual unsigned SizeOf(const TargetData *TD, unsigned Form) const;
|
||||
|
||||
/// Profile - Used to gather unique data for the value folding set.
|
||||
///
|
||||
virtual void Profile(FoldingSetNodeID &ID);
|
||||
|
||||
// Implement isa/cast/dyncast.
|
||||
static bool classof(const DIEBlock *) { return true; }
|
||||
static bool classof(const DIEValue *E) { return E->getType() == isBlock; }
|
||||
|
||||
#ifndef NDEBUG
|
||||
virtual void print(std::ostream &O);
|
||||
#endif
|
||||
};
|
||||
|
||||
} // end llvm namespace
|
||||
|
||||
#endif
|
35
lib/CodeGen/AsmPrinter/DwarfLabel.cpp
Normal file
35
lib/CodeGen/AsmPrinter/DwarfLabel.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
//===--- lib/CodeGen/DwarfLabel.cpp - Dwarf Label -------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// DWARF Labels
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "DwarfLabel.h"
|
||||
#include "llvm/ADT/FoldingSet.h"
|
||||
#include <ostream>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
/// Profile - Used to gather unique data for the folding set.
|
||||
///
|
||||
void DWLabel::Profile(FoldingSetNodeID &ID) const {
|
||||
ID.AddString(Tag);
|
||||
ID.AddInteger(Number);
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
void DWLabel::print(std::ostream *O) const {
|
||||
if (O) print(*O);
|
||||
}
|
||||
void DWLabel::print(std::ostream &O) const {
|
||||
O << "." << Tag;
|
||||
if (Number) O << Number;
|
||||
}
|
||||
#endif
|
56
lib/CodeGen/AsmPrinter/DwarfLabel.h
Normal file
56
lib/CodeGen/AsmPrinter/DwarfLabel.h
Normal file
@ -0,0 +1,56 @@
|
||||
//===--- lib/CodeGen/DwarfLabel.h - Dwarf Label -----------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// DWARF Labels.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef DWARFLABEL_H__
|
||||
#define DWARFLABEL_H__
|
||||
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include <iosfwd>
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
class FoldingSetNodeID;
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// DWLabel - Labels are used to track locations in the assembler file.
|
||||
/// Labels appear in the form @verbatim <prefix><Tag><Number> @endverbatim,
|
||||
/// where the tag is a category of label (Ex. location) and number is a value
|
||||
/// unique in that category.
|
||||
class VISIBILITY_HIDDEN DWLabel {
|
||||
/// Tag - Label category tag. Should always be a statically declared C
|
||||
/// string.
|
||||
///
|
||||
const char *Tag;
|
||||
|
||||
/// Number - Value to make label unique.
|
||||
///
|
||||
unsigned Number;
|
||||
public:
|
||||
DWLabel(const char *T, unsigned N) : Tag(T), Number(N) {}
|
||||
|
||||
// Accessors.
|
||||
const char *getTag() const { return Tag; }
|
||||
unsigned getNumber() const { return Number; }
|
||||
|
||||
/// Profile - Used to gather unique data for the folding set.
|
||||
///
|
||||
void Profile(FoldingSetNodeID &ID) const;
|
||||
|
||||
#ifndef NDEBUG
|
||||
void print(std::ostream *O) const;
|
||||
void print(std::ostream &O) const;
|
||||
#endif
|
||||
};
|
||||
} // end llvm namespace
|
||||
|
||||
#endif
|
235
lib/CodeGen/AsmPrinter/DwarfPrinter.cpp
Normal file
235
lib/CodeGen/AsmPrinter/DwarfPrinter.cpp
Normal file
@ -0,0 +1,235 @@
|
||||
//===--- lib/CodeGen/DwarfPrinter.cpp - Dwarf Printer ---------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Emit general DWARF directives.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "DwarfPrinter.h"
|
||||
#include "llvm/Module.h"
|
||||
#include "llvm/CodeGen/AsmPrinter.h"
|
||||
#include "llvm/CodeGen/MachineFrameInfo.h"
|
||||
#include "llvm/CodeGen/MachineModuleInfo.h"
|
||||
#include "llvm/Support/Dwarf.h"
|
||||
#include "llvm/Target/TargetAsmInfo.h"
|
||||
#include "llvm/Target/TargetData.h"
|
||||
#include "llvm/Target/TargetFrameInfo.h"
|
||||
#include "llvm/Target/TargetRegisterInfo.h"
|
||||
#include <ostream>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
Dwarf::Dwarf(raw_ostream &OS, AsmPrinter *A, const TargetAsmInfo *T,
|
||||
const char *flavor)
|
||||
: O(OS), Asm(A), TAI(T), TD(Asm->TM.getTargetData()),
|
||||
RI(Asm->TM.getRegisterInfo()), M(NULL), MF(NULL), MMI(NULL),
|
||||
SubprogramCount(0), Flavor(flavor), SetCounter(1) {}
|
||||
|
||||
void Dwarf::PrintRelDirective(bool Force32Bit, bool isInSection) const {
|
||||
if (isInSection && TAI->getDwarfSectionOffsetDirective())
|
||||
O << TAI->getDwarfSectionOffsetDirective();
|
||||
else if (Force32Bit || TD->getPointerSize() == sizeof(int32_t))
|
||||
O << TAI->getData32bitsDirective();
|
||||
else
|
||||
O << TAI->getData64bitsDirective();
|
||||
}
|
||||
|
||||
/// PrintLabelName - Print label name in form used by Dwarf writer.
|
||||
///
|
||||
void Dwarf::PrintLabelName(const char *Tag, unsigned Number) const {
|
||||
O << TAI->getPrivateGlobalPrefix() << Tag;
|
||||
if (Number) O << Number;
|
||||
}
|
||||
void Dwarf::PrintLabelName(const char *Tag, unsigned Number,
|
||||
const char *Suffix) const {
|
||||
O << TAI->getPrivateGlobalPrefix() << Tag;
|
||||
if (Number) O << Number;
|
||||
O << Suffix;
|
||||
}
|
||||
|
||||
/// EmitLabel - Emit location label for internal use by Dwarf.
|
||||
///
|
||||
void Dwarf::EmitLabel(const char *Tag, unsigned Number) const {
|
||||
PrintLabelName(Tag, Number);
|
||||
O << ":\n";
|
||||
}
|
||||
|
||||
/// EmitReference - Emit a reference to a label.
|
||||
///
|
||||
void Dwarf::EmitReference(const char *Tag, unsigned Number,
|
||||
bool IsPCRelative, bool Force32Bit) const {
|
||||
PrintRelDirective(Force32Bit);
|
||||
PrintLabelName(Tag, Number);
|
||||
if (IsPCRelative) O << "-" << TAI->getPCSymbol();
|
||||
}
|
||||
void Dwarf::EmitReference(const std::string &Name, bool IsPCRelative,
|
||||
bool Force32Bit) const {
|
||||
PrintRelDirective(Force32Bit);
|
||||
O << Name;
|
||||
if (IsPCRelative) O << "-" << TAI->getPCSymbol();
|
||||
}
|
||||
|
||||
/// EmitDifference - Emit the difference between two labels. Some assemblers do
|
||||
/// not behave with absolute expressions with data directives, so there is an
|
||||
/// option (needsSet) to use an intermediary set expression.
|
||||
void Dwarf::EmitDifference(const char *TagHi, unsigned NumberHi,
|
||||
const char *TagLo, unsigned NumberLo,
|
||||
bool IsSmall) {
|
||||
if (TAI->needsSet()) {
|
||||
O << "\t.set\t";
|
||||
PrintLabelName("set", SetCounter, Flavor);
|
||||
O << ",";
|
||||
PrintLabelName(TagHi, NumberHi);
|
||||
O << "-";
|
||||
PrintLabelName(TagLo, NumberLo);
|
||||
O << "\n";
|
||||
|
||||
PrintRelDirective(IsSmall);
|
||||
PrintLabelName("set", SetCounter, Flavor);
|
||||
++SetCounter;
|
||||
} else {
|
||||
PrintRelDirective(IsSmall);
|
||||
PrintLabelName(TagHi, NumberHi);
|
||||
O << "-";
|
||||
PrintLabelName(TagLo, NumberLo);
|
||||
}
|
||||
}
|
||||
|
||||
void Dwarf::EmitSectionOffset(const char* Label, const char* Section,
|
||||
unsigned LabelNumber, unsigned SectionNumber,
|
||||
bool IsSmall, bool isEH,
|
||||
bool useSet) {
|
||||
bool printAbsolute = false;
|
||||
if (isEH)
|
||||
printAbsolute = TAI->isAbsoluteEHSectionOffsets();
|
||||
else
|
||||
printAbsolute = TAI->isAbsoluteDebugSectionOffsets();
|
||||
|
||||
if (TAI->needsSet() && useSet) {
|
||||
O << "\t.set\t";
|
||||
PrintLabelName("set", SetCounter, Flavor);
|
||||
O << ",";
|
||||
PrintLabelName(Label, LabelNumber);
|
||||
|
||||
if (!printAbsolute) {
|
||||
O << "-";
|
||||
PrintLabelName(Section, SectionNumber);
|
||||
}
|
||||
|
||||
O << "\n";
|
||||
PrintRelDirective(IsSmall);
|
||||
PrintLabelName("set", SetCounter, Flavor);
|
||||
++SetCounter;
|
||||
} else {
|
||||
PrintRelDirective(IsSmall, true);
|
||||
PrintLabelName(Label, LabelNumber);
|
||||
|
||||
if (!printAbsolute) {
|
||||
O << "-";
|
||||
PrintLabelName(Section, SectionNumber);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// EmitFrameMoves - Emit frame instructions to describe the layout of the
|
||||
/// frame.
|
||||
void Dwarf::EmitFrameMoves(const char *BaseLabel, unsigned BaseLabelID,
|
||||
const std::vector<MachineMove> &Moves, bool isEH) {
|
||||
int stackGrowth =
|
||||
Asm->TM.getFrameInfo()->getStackGrowthDirection() ==
|
||||
TargetFrameInfo::StackGrowsUp ?
|
||||
TD->getPointerSize() : -TD->getPointerSize();
|
||||
bool IsLocal = BaseLabel && strcmp(BaseLabel, "label") == 0;
|
||||
|
||||
for (unsigned i = 0, N = Moves.size(); i < N; ++i) {
|
||||
const MachineMove &Move = Moves[i];
|
||||
unsigned LabelID = Move.getLabelID();
|
||||
|
||||
if (LabelID) {
|
||||
LabelID = MMI->MappedLabel(LabelID);
|
||||
|
||||
// Throw out move if the label is invalid.
|
||||
if (!LabelID) continue;
|
||||
}
|
||||
|
||||
const MachineLocation &Dst = Move.getDestination();
|
||||
const MachineLocation &Src = Move.getSource();
|
||||
|
||||
// Advance row if new location.
|
||||
if (BaseLabel && LabelID && (BaseLabelID != LabelID || !IsLocal)) {
|
||||
Asm->EmitInt8(dwarf::DW_CFA_advance_loc4);
|
||||
Asm->EOL("DW_CFA_advance_loc4");
|
||||
EmitDifference("label", LabelID, BaseLabel, BaseLabelID, true);
|
||||
Asm->EOL();
|
||||
|
||||
BaseLabelID = LabelID;
|
||||
BaseLabel = "label";
|
||||
IsLocal = true;
|
||||
}
|
||||
|
||||
// If advancing cfa.
|
||||
if (Dst.isReg() && Dst.getReg() == MachineLocation::VirtualFP) {
|
||||
if (!Src.isReg()) {
|
||||
if (Src.getReg() == MachineLocation::VirtualFP) {
|
||||
Asm->EmitInt8(dwarf::DW_CFA_def_cfa_offset);
|
||||
Asm->EOL("DW_CFA_def_cfa_offset");
|
||||
} else {
|
||||
Asm->EmitInt8(dwarf::DW_CFA_def_cfa);
|
||||
Asm->EOL("DW_CFA_def_cfa");
|
||||
Asm->EmitULEB128Bytes(RI->getDwarfRegNum(Src.getReg(), isEH));
|
||||
Asm->EOL("Register");
|
||||
}
|
||||
|
||||
int Offset = -Src.getOffset();
|
||||
|
||||
Asm->EmitULEB128Bytes(Offset);
|
||||
Asm->EOL("Offset");
|
||||
} else {
|
||||
assert(0 && "Machine move no supported yet.");
|
||||
}
|
||||
} else if (Src.isReg() &&
|
||||
Src.getReg() == MachineLocation::VirtualFP) {
|
||||
if (Dst.isReg()) {
|
||||
Asm->EmitInt8(dwarf::DW_CFA_def_cfa_register);
|
||||
Asm->EOL("DW_CFA_def_cfa_register");
|
||||
Asm->EmitULEB128Bytes(RI->getDwarfRegNum(Dst.getReg(), isEH));
|
||||
Asm->EOL("Register");
|
||||
} else {
|
||||
assert(0 && "Machine move no supported yet.");
|
||||
}
|
||||
} else {
|
||||
unsigned Reg = RI->getDwarfRegNum(Src.getReg(), isEH);
|
||||
int Offset = Dst.getOffset() / stackGrowth;
|
||||
|
||||
if (Offset < 0) {
|
||||
Asm->EmitInt8(dwarf::DW_CFA_offset_extended_sf);
|
||||
Asm->EOL("DW_CFA_offset_extended_sf");
|
||||
Asm->EmitULEB128Bytes(Reg);
|
||||
Asm->EOL("Reg");
|
||||
Asm->EmitSLEB128Bytes(Offset);
|
||||
Asm->EOL("Offset");
|
||||
} else if (Reg < 64) {
|
||||
Asm->EmitInt8(dwarf::DW_CFA_offset + Reg);
|
||||
if (Asm->isVerbose())
|
||||
Asm->EOL("DW_CFA_offset + Reg (" + utostr(Reg) + ")");
|
||||
else
|
||||
Asm->EOL();
|
||||
Asm->EmitULEB128Bytes(Offset);
|
||||
Asm->EOL("Offset");
|
||||
} else {
|
||||
Asm->EmitInt8(dwarf::DW_CFA_offset_extended);
|
||||
Asm->EOL("DW_CFA_offset_extended");
|
||||
Asm->EmitULEB128Bytes(Reg);
|
||||
Asm->EOL("Reg");
|
||||
Asm->EmitULEB128Bytes(Offset);
|
||||
Asm->EOL("Offset");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
153
lib/CodeGen/AsmPrinter/DwarfPrinter.h
Normal file
153
lib/CodeGen/AsmPrinter/DwarfPrinter.h
Normal file
@ -0,0 +1,153 @@
|
||||
//===--- lib/CodeGen/DwarfPrinter.h - Dwarf Printer -------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Emit general DWARF directives.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef DWARFPRINTER_H__
|
||||
#define DWARFPRINTER_H__
|
||||
|
||||
#include "DwarfLabel.h"
|
||||
#include "llvm/CodeGen/MachineLocation.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
class AsmPrinter;
|
||||
class MachineFunction;
|
||||
class MachineModuleInfo;
|
||||
class Module;
|
||||
class TargetAsmInfo;
|
||||
class TargetData;
|
||||
class TargetRegisterInfo;
|
||||
|
||||
class VISIBILITY_HIDDEN Dwarf {
|
||||
protected:
|
||||
//===-------------------------------------------------------------==---===//
|
||||
// Core attributes used by the DWARF printer.
|
||||
//
|
||||
|
||||
/// O - Stream to .s file.
|
||||
///
|
||||
raw_ostream &O;
|
||||
|
||||
/// Asm - Target of Dwarf emission.
|
||||
///
|
||||
AsmPrinter *Asm;
|
||||
|
||||
/// TAI - Target asm information.
|
||||
///
|
||||
const TargetAsmInfo *TAI;
|
||||
|
||||
/// TD - Target data.
|
||||
///
|
||||
const TargetData *TD;
|
||||
|
||||
/// RI - Register Information.
|
||||
///
|
||||
const TargetRegisterInfo *RI;
|
||||
|
||||
/// M - Current module.
|
||||
///
|
||||
Module *M;
|
||||
|
||||
/// MF - Current machine function.
|
||||
///
|
||||
MachineFunction *MF;
|
||||
|
||||
/// MMI - Collected machine module information.
|
||||
///
|
||||
MachineModuleInfo *MMI;
|
||||
|
||||
/// SubprogramCount - The running count of functions being compiled.
|
||||
///
|
||||
unsigned SubprogramCount;
|
||||
|
||||
/// Flavor - A unique string indicating what dwarf producer this is, used to
|
||||
/// unique labels.
|
||||
///
|
||||
const char * const Flavor;
|
||||
|
||||
/// SetCounter - A unique number for each '.set' directive.
|
||||
///
|
||||
unsigned SetCounter;
|
||||
|
||||
Dwarf(raw_ostream &OS, AsmPrinter *A, const TargetAsmInfo *T,
|
||||
const char *flavor);
|
||||
public:
|
||||
//===------------------------------------------------------------------===//
|
||||
// Accessors.
|
||||
//
|
||||
const AsmPrinter *getAsm() const { return Asm; }
|
||||
MachineModuleInfo *getMMI() const { return MMI; }
|
||||
const TargetAsmInfo *getTargetAsmInfo() const { return TAI; }
|
||||
const TargetData *getTargetData() const { return TD; }
|
||||
|
||||
void PrintRelDirective(bool Force32Bit = false,
|
||||
bool isInSection = false) const;
|
||||
|
||||
|
||||
/// PrintLabelName - Print label name in form used by Dwarf writer.
|
||||
///
|
||||
void PrintLabelName(const DWLabel &Label) const {
|
||||
PrintLabelName(Label.getTag(), Label.getNumber());
|
||||
}
|
||||
void PrintLabelName(const char *Tag, unsigned Number) const;
|
||||
void PrintLabelName(const char *Tag, unsigned Number,
|
||||
const char *Suffix) const;
|
||||
|
||||
/// EmitLabel - Emit location label for internal use by Dwarf.
|
||||
///
|
||||
void EmitLabel(const DWLabel &Label) const {
|
||||
EmitLabel(Label.getTag(), Label.getNumber());
|
||||
}
|
||||
void EmitLabel(const char *Tag, unsigned Number) const;
|
||||
|
||||
/// EmitReference - Emit a reference to a label.
|
||||
///
|
||||
void EmitReference(const DWLabel &Label, bool IsPCRelative = false,
|
||||
bool Force32Bit = false) const {
|
||||
EmitReference(Label.getTag(), Label.getNumber(),
|
||||
IsPCRelative, Force32Bit);
|
||||
}
|
||||
void EmitReference(const char *Tag, unsigned Number,
|
||||
bool IsPCRelative = false,
|
||||
bool Force32Bit = false) const;
|
||||
void EmitReference(const std::string &Name, bool IsPCRelative = false,
|
||||
bool Force32Bit = false) const;
|
||||
|
||||
/// EmitDifference - Emit the difference between two labels. Some
|
||||
/// assemblers do not behave with absolute expressions with data directives,
|
||||
/// so there is an option (needsSet) to use an intermediary set expression.
|
||||
void EmitDifference(const DWLabel &LabelHi, const DWLabel &LabelLo,
|
||||
bool IsSmall = false) {
|
||||
EmitDifference(LabelHi.getTag(), LabelHi.getNumber(),
|
||||
LabelLo.getTag(), LabelLo.getNumber(),
|
||||
IsSmall);
|
||||
}
|
||||
void EmitDifference(const char *TagHi, unsigned NumberHi,
|
||||
const char *TagLo, unsigned NumberLo,
|
||||
bool IsSmall = false);
|
||||
|
||||
void EmitSectionOffset(const char* Label, const char* Section,
|
||||
unsigned LabelNumber, unsigned SectionNumber,
|
||||
bool IsSmall = false, bool isEH = false,
|
||||
bool useSet = true);
|
||||
|
||||
/// EmitFrameMoves - Emit frame instructions to describe the layout of the
|
||||
/// frame.
|
||||
void EmitFrameMoves(const char *BaseLabel, unsigned BaseLabelID,
|
||||
const std::vector<MachineMove> &Moves, bool isEH);
|
||||
};
|
||||
|
||||
} // end llvm namespace
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user