"llvm/lib/git@repo.hca.bsc.es:rferrer/llvm-epi-0.8.git" did not exist on "c54d8462fb9ec5554ed51e5f1ae24fad330ecfea"
Newer
Older
//===-- llvm/CodeGen/DwarfDebug.cpp - Dwarf Debug Framework ---------------===//
//
// The LLVM Compiler Infrastructure
//
// This file 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 "DwarfDebug.h"
#include "llvm/Module.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/Target/Mangler.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetFrameInfo.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ValueHandle.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/Timer.h"
#include "llvm/System/Path.h"
using namespace llvm;
//===----------------------------------------------------------------------===//
/// Configuration values for initial hash set sizes (log2).
///
static const unsigned InitAbbreviationsSetSize = 9; // log2(512)
namespace llvm {
//===----------------------------------------------------------------------===//
/// CompileUnit - This dwarf writer support class manages information associate
/// with a source file.
/// ID - File identifier for source.
///
unsigned ID;
/// Die - Compile unit debug information entry.
///
DIE *CUDie;
/// IndexTyDie - An anonymous type for index type.
/// GVToDieMap - Tracks the mapping of unit level debug informaton
/// variables to debug information entries.
Devang Patel
committed
DenseMap<MDNode *, DIE *> GVToDieMap;
/// GVToDIEEntryMap - Tracks the mapping of unit level debug informaton
/// descriptors to debug information entries using a DIEEntry proxy.
Devang Patel
committed
DenseMap<MDNode *, DIEEntry *> GVToDIEEntryMap;
/// Globals - A map of globally visible named entities for this unit.
///
StringMap<DIE*> Globals;
/// GlobalTypes - A map of globally visible types for this unit.
///
StringMap<DIE*> GlobalTypes;
public:
CompileUnit(unsigned I, DIE *D)
: ID(I), CUDie(D), IndexTyDie(0) {}
~CompileUnit() { delete CUDie; delete IndexTyDie; }
// Accessors.
DIE* getCUDie() const { return CUDie; }
const StringMap<DIE*> &getGlobals() const { return Globals; }
const StringMap<DIE*> &getGlobalTypes() const { return GlobalTypes; }
/// hasContent - Return true if this compile unit has something to write out.
///
bool hasContent() const { return !CUDie->getChildren().empty(); }
/// addGlobal - Add a new global entity to the compile unit.
void addGlobal(const std::string &Name, DIE *Die) { Globals[Name] = Die; }
/// addGlobalType - Add a new global type to the compile unit.
///
void addGlobalType(const std::string &Name, DIE *Die) {
GlobalTypes[Name] = Die;
}
/// getDIE - Returns the debug information entry map slot for the
/// specified debug variable.
DIE *getDIE(MDNode *N) { return GVToDieMap.lookup(N); }
/// insertDIE - Insert DIE into the map.
void insertDIE(MDNode *N, DIE *D) {
GVToDieMap.insert(std::make_pair(N, D));
}
/// getDIEEntry - Returns the debug information entry for the speciefied
/// debug variable.
DIEEntry *getDIEEntry(MDNode *N) {
Devang Patel
committed
DenseMap<MDNode *, DIEEntry *>::iterator I = GVToDIEEntryMap.find(N);
if (I == GVToDIEEntryMap.end())
return NULL;
return I->second;
}
/// insertDIEEntry - Insert debug information entry into the map.
void insertDIEEntry(MDNode *N, DIEEntry *E) {
GVToDIEEntryMap.insert(std::make_pair(N, E));
/// addDie - Adds or interns the DIE to the compile unit.
void addDie(DIE *Buffer) {
this->CUDie->addChild(Buffer);
// getIndexTyDie - Get an anonymous type for index type.
DIE *getIndexTyDie() {
return IndexTyDie;
// setIndexTyDie - Set D as anonymous type for index which can be reused
// later.
void setIndexTyDie(DIE *D) {
IndexTyDie = D;
}
};
//===----------------------------------------------------------------------===//
/// DbgVariable - This class is used to track local variable information.
///
DIVariable Var; // Variable Descriptor.
unsigned FrameIndex; // Variable frame index.
DbgVariable *AbstractVar; // Abstract variable for this variable.
DIE *TheDIE;
DbgVariable(DIVariable V, unsigned I)
: Var(V), FrameIndex(I), AbstractVar(0), TheDIE(0) {}
// Accessors.
DIVariable getVariable() const { return Var; }
unsigned getFrameIndex() const { return FrameIndex; }
void setAbstractVariable(DbgVariable *V) { AbstractVar = V; }
DbgVariable *getAbstractVariable() const { return AbstractVar; }
void setDIE(DIE *D) { TheDIE = D; }
DIE *getDIE() const { return TheDIE; }
};
//===----------------------------------------------------------------------===//
/// DbgScope - This class is used to track scope information.
///
DbgScope *Parent; // Parent to this scope.
DIDescriptor Desc; // Debug info descriptor for scope.
// Location at which this scope is inlined.
AssertingVH<MDNode> InlinedAtLocation;
bool AbstractScope; // Abstract Scope
unsigned StartLabelID; // Label ID of the beginning of scope.
unsigned EndLabelID; // Label ID of the end of scope.
const MachineInstr *LastInsn; // Last instruction of this scope.
const MachineInstr *FirstInsn; // First instruction of this scope.
SmallVector<DbgScope *, 4> Scopes; // Scopes defined in scope.
SmallVector<DbgVariable *, 8> Variables;// Variables declared in scope.
// Private state for dump()
mutable unsigned IndentLevel;
DbgScope(DbgScope *P, DIDescriptor D, MDNode *I = 0)
: Parent(P), Desc(D), InlinedAtLocation(I), AbstractScope(false),
LastInsn(0), FirstInsn(0), IndentLevel(0) {}
virtual ~DbgScope();
// Accessors.
DbgScope *getParent() const { return Parent; }
void setParent(DbgScope *P) { Parent = P; }
DIDescriptor getDesc() const { return Desc; }
MDNode *getScopeNode() const { return Desc.getNode(); }
unsigned getStartLabelID() const { return StartLabelID; }
unsigned getEndLabelID() const { return EndLabelID; }
SmallVector<DbgScope *, 4> &getScopes() { return Scopes; }
SmallVector<DbgVariable *, 8> &getVariables() { return Variables; }
void setStartLabelID(unsigned S) { StartLabelID = S; }
void setEndLabelID(unsigned E) { EndLabelID = E; }
void setLastInsn(const MachineInstr *MI) { LastInsn = MI; }
const MachineInstr *getLastInsn() { return LastInsn; }
void setFirstInsn(const MachineInstr *MI) { FirstInsn = MI; }
void setAbstractScope() { AbstractScope = true; }
bool isAbstractScope() const { return AbstractScope; }
const MachineInstr *getFirstInsn() { return FirstInsn; }
/// addScope - Add a scope to the scope.
void addScope(DbgScope *S) { Scopes.push_back(S); }
/// addVariable - Add a variable to the scope.
void addVariable(DbgVariable *V) { Variables.push_back(V); }
void fixInstructionMarkers(DenseMap<const MachineInstr *,
unsigned> &MIIndexMap) {
Devang Patel
committed
assert (getFirstInsn() && "First instruction is missing!");
// Use the end of last child scope as end of this scope.
SmallVector<DbgScope *, 4> &Scopes = getScopes();
Devang Patel
committed
const MachineInstr *LastInsn = getFirstInsn();
unsigned LIndex = 0;
if (Scopes.empty()) {
assert (getLastInsn() && "Inner most scope does not have last insn!");
return;
}
for (SmallVector<DbgScope *, 4>::iterator SI = Scopes.begin(),
SE = Scopes.end(); SI != SE; ++SI) {
DbgScope *DS = *SI;
DS->fixInstructionMarkers(MIIndexMap);
const MachineInstr *DSLastInsn = DS->getLastInsn();
unsigned DSI = MIIndexMap[DSLastInsn];
if (DSI > LIndex) {
LastInsn = DSLastInsn;
LIndex = DSI;
}
}
unsigned CurrentLastInsnIndex = 0;
if (const MachineInstr *CL = getLastInsn())
CurrentLastInsnIndex = MIIndexMap[CL];
unsigned FIndex = MIIndexMap[getFirstInsn()];
// Set LastInsn as the last instruction for this scope only if
// it follows
// 1) this scope's first instruction and
// 2) current last instruction for this scope, if any.
if (LIndex >= CurrentLastInsnIndex && LIndex >= FIndex)
setLastInsn(LastInsn);
Devang Patel
committed
}
#ifndef NDEBUG
void dump() const;
#endif
};
#ifndef NDEBUG
void DbgScope::dump() const {
err.indent(IndentLevel);
MDNode *N = Desc.getNode();
N->dump();
err << " [" << StartLabelID << ", " << EndLabelID << "]\n";
if (AbstractScope)
err << "Abstract Scope\n";
IndentLevel += 2;
if (!Scopes.empty())
err << "Children ...\n";
for (unsigned i = 0, e = Scopes.size(); i != e; ++i)
if (Scopes[i] != this)
Scopes[i]->dump();
IndentLevel -= 2;
}
#endif
DbgScope::~DbgScope() {
for (unsigned i = 0, N = Scopes.size(); i < N; ++i)
delete Scopes[i];
for (unsigned j = 0, M = Variables.size(); j < M; ++j)
delete Variables[j];
}
} // end llvm namespace
DwarfDebug::DwarfDebug(raw_ostream &OS, AsmPrinter *A, const MCAsmInfo *T)
: DwarfPrinter(OS, A, T, "dbg"), ModuleCU(0),
AbbreviationsSet(InitAbbreviationsSetSize), Abbreviations(),
DIEValues(), StringPool(),
SectionSourceLines(), didInitial(false), shouldEmit(false),
CurrentFnDbgScope(0), DebugTimer(0) {
if (TimePassesIsEnabled)
DebugTimer = new Timer("Dwarf Debug Writer");
}
DwarfDebug::~DwarfDebug() {
for (unsigned j = 0, M = DIEValues.size(); j < M; ++j)
delete DIEValues[j];
delete DebugTimer;
}
/// assignAbbrevNumber - Define a unique number for the abbreviation.
void DwarfDebug::assignAbbrevNumber(DIEAbbrev &Abbrev) {
// Profile the node so that we can make it unique.
FoldingSetNodeID ID;
Abbrev.Profile(ID);
// Check the set for priors.
DIEAbbrev *InSet = AbbreviationsSet.GetOrInsertNode(&Abbrev);
// If it's newly added.
if (InSet == &Abbrev) {
// Add to abbreviation list.
Abbreviations.push_back(&Abbrev);
// Assign the vector position + 1 as its number.
Abbrev.setNumber(Abbreviations.size());
} else {
// Assign existing abbreviation number.
Abbrev.setNumber(InSet->getNumber());
}
}
/// createDIEEntry - Creates a new DIEEntry to be a proxy for a debug
Bill Wendling
committed
/// information entry.
DIEEntry *DwarfDebug::createDIEEntry(DIE *Entry) {
DIEEntry *Value = new DIEEntry(Entry);
DIEValues.push_back(Value);
return Value;
}
/// addUInt - Add an unsigned integer attribute data and value.
void DwarfDebug::addUInt(DIE *Die, unsigned Attribute,
unsigned Form, uint64_t Integer) {
if (!Form) Form = DIEInteger::BestForm(false, Integer);
DIEValue *Value = new DIEInteger(Integer);
DIEValues.push_back(Value);
Die->addValue(Attribute, Form, Value);
/// addSInt - Add an signed integer attribute data and value.
void DwarfDebug::addSInt(DIE *Die, unsigned Attribute,
unsigned Form, int64_t Integer) {
if (!Form) Form = DIEInteger::BestForm(true, Integer);
DIEValue *Value = new DIEInteger(Integer);
DIEValues.push_back(Value);
Die->addValue(Attribute, Form, Value);
/// addString - Add a string attribute data and value. DIEString only
/// keeps string reference.
void DwarfDebug::addString(DIE *Die, unsigned Attribute, unsigned Form,
StringRef String) {
DIEValue *Value = new DIEString(String);
DIEValues.push_back(Value);
Die->addValue(Attribute, Form, Value);
/// addLabel - Add a Dwarf label attribute data and value.
void DwarfDebug::addLabel(DIE *Die, unsigned Attribute, unsigned Form,
const DWLabel &Label) {
DIEValue *Value = new DIEDwarfLabel(Label);
DIEValues.push_back(Value);
Die->addValue(Attribute, Form, Value);
/// addObjectLabel - Add an non-Dwarf label attribute data and value.
void DwarfDebug::addObjectLabel(DIE *Die, unsigned Attribute, unsigned Form,
const MCSymbol *Sym) {
DIEValue *Value = new DIEObjectLabel(Sym);
DIEValues.push_back(Value);
Die->addValue(Attribute, Form, Value);
/// addSectionOffset - Add a section offset label attribute data and value.
void DwarfDebug::addSectionOffset(DIE *Die, unsigned Attribute, unsigned Form,
const DWLabel &Label, const DWLabel &Section,
bool isEH, bool useSet) {
DIEValue *Value = new DIESectionOffset(Label, Section, isEH, useSet);
DIEValues.push_back(Value);
Die->addValue(Attribute, Form, Value);
/// addDelta - Add a label delta attribute data and value.
void DwarfDebug::addDelta(DIE *Die, unsigned Attribute, unsigned Form,
const DWLabel &Hi, const DWLabel &Lo) {
DIEValue *Value = new DIEDelta(Hi, Lo);
DIEValues.push_back(Value);
Die->addValue(Attribute, Form, Value);
/// addBlock - Add block data.
void DwarfDebug::addBlock(DIE *Die, unsigned Attribute, unsigned Form,
DIEBlock *Block) {
Block->ComputeSize(TD);
DIEValues.push_back(Block);
Die->addValue(Attribute, Block->BestForm(), Block);
/// addSourceLine - Add location information to specified debug information
void DwarfDebug::addSourceLine(DIE *Die, const DIVariable *V) {
// If there is no compile unit specified, don't add a line #.
return;
unsigned Line = V->getLineNumber();
unsigned FileID = findCompileUnit(V->getCompileUnit())->getID();
assert(FileID && "Invalid file id");
addUInt(Die, dwarf::DW_AT_decl_file, 0, FileID);
addUInt(Die, dwarf::DW_AT_decl_line, 0, Line);
/// addSourceLine - Add location information to specified debug information
void DwarfDebug::addSourceLine(DIE *Die, const DIGlobal *G) {
// If there is no compile unit specified, don't add a line #.
return;
unsigned Line = G->getLineNumber();
unsigned FileID = findCompileUnit(G->getCompileUnit())->getID();
assert(FileID && "Invalid file id");
addUInt(Die, dwarf::DW_AT_decl_file, 0, FileID);
addUInt(Die, dwarf::DW_AT_decl_line, 0, Line);
/// addSourceLine - Add location information to specified debug information
void DwarfDebug::addSourceLine(DIE *Die, const DISubprogram *SP) {
// If there is no compile unit specified, don't add a line #.
// If the line number is 0, don't add it.
if (SP->getLineNumber() == 0)
return;
unsigned Line = SP->getLineNumber();
unsigned FileID = findCompileUnit(SP->getCompileUnit())->getID();
assert(FileID && "Invalid file id");
addUInt(Die, dwarf::DW_AT_decl_file, 0, FileID);
addUInt(Die, dwarf::DW_AT_decl_line, 0, Line);
/// addSourceLine - Add location information to specified debug information
void DwarfDebug::addSourceLine(DIE *Die, const DIType *Ty) {
// If there is no compile unit specified, don't add a line #.
DICompileUnit CU = Ty->getCompileUnit();
return;
unsigned Line = Ty->getLineNumber();
unsigned FileID = findCompileUnit(CU)->getID();
assert(FileID && "Invalid file id");
addUInt(Die, dwarf::DW_AT_decl_file, 0, FileID);
addUInt(Die, dwarf::DW_AT_decl_line, 0, Line);
/// addSourceLine - Add location information to specified debug information
/// entry.
void DwarfDebug::addSourceLine(DIE *Die, const DINameSpace *NS) {
// If there is no compile unit specified, don't add a line #.
return;
unsigned Line = NS->getLineNumber();
StringRef FN = NS->getFilename();
StringRef Dir = NS->getDirectory();
unsigned FileID = GetOrCreateSourceID(Dir, FN);
assert(FileID && "Invalid file id");
addUInt(Die, dwarf::DW_AT_decl_file, 0, FileID);
addUInt(Die, dwarf::DW_AT_decl_line, 0, Line);
}
Caroline Tice
committed
/* Byref variables, in Blocks, are declared by the programmer as
"SomeType VarName;", but the compiler creates a
__Block_byref_x_VarName struct, and gives the variable VarName
either the struct, or a pointer to the struct, as its type. This
is necessary for various behind-the-scenes things the compiler
needs to do with by-reference variables in blocks.
However, as far as the original *programmer* is concerned, the
variable should still have type 'SomeType', as originally declared.
The following function dives into the __Block_byref_x_VarName
struct to find the original type of the variable. This will be
passed back to the code generating the type for the Debug
Information Entry for the variable 'VarName'. 'VarName' will then
have the original type 'SomeType' in its debug information.
The original type 'SomeType' will be the type of the field named
'VarName' inside the __Block_byref_x_VarName struct.
NOTE: In order for this to not completely fail on the debugger
side, the Debug Information Entry for the variable VarName needs to
have a DW_AT_location that tells the debugger how to unwind through
the pointers and __Block_byref_x_VarName struct to find the actual
value of the variable. The function addBlockByrefType does this. */
Caroline Tice
committed
/// Find the type the programmer originally declared the variable to be
/// and return that type.
///
DIType DwarfDebug::getBlockByrefType(DIType Ty, std::string Name) {
Caroline Tice
committed
DIType subType = Ty;
unsigned tag = Ty.getTag();
if (tag == dwarf::DW_TAG_pointer_type) {
DIDerivedType DTy = DIDerivedType(Ty.getNode());
Caroline Tice
committed
subType = DTy.getTypeDerivedFrom();
}
DICompositeType blockStruct = DICompositeType(subType.getNode());
Caroline Tice
committed
DIArray Elements = blockStruct.getTypeArray();
Caroline Tice
committed
for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) {
DIDescriptor Element = Elements.getElement(i);
DIDerivedType DT = DIDerivedType(Element.getNode());
Caroline Tice
committed
return (DT.getTypeDerivedFrom());
}
return Ty;
}
/// addComplexAddress - Start with the address based on the location provided,
/// and generate the DWARF information necessary to find the actual variable
/// given the extra address information encoded in the DIVariable, starting from
/// the starting location. Add the DWARF information to the die.
///
void DwarfDebug::addComplexAddress(DbgVariable *&DV, DIE *Die,
unsigned Attribute,
const MachineLocation &Location) {
const DIVariable &VD = DV->getVariable();
DIType Ty = VD.getType();
// Decode the original location, and use that as the start of the byref
// variable's location.
unsigned Reg = RI->getDwarfRegNum(Location.getReg(), false);
DIEBlock *Block = new DIEBlock();
if (Location.isReg()) {
if (Reg < 32) {
addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_reg0 + Reg);
} else {
Reg = Reg - dwarf::DW_OP_reg0;
addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_breg0 + Reg);
addUInt(Block, 0, dwarf::DW_FORM_udata, Reg);
}
} else {
if (Reg < 32)
addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_breg0 + Reg);
addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_bregx);
addUInt(Block, 0, dwarf::DW_FORM_udata, Reg);
addUInt(Block, 0, dwarf::DW_FORM_sdata, Location.getOffset());
}
for (unsigned i = 0, N = VD.getNumAddrElements(); i < N; ++i) {
uint64_t Element = VD.getAddrElement(i);
if (Element == DIFactory::OpPlus) {
addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst);
addUInt(Block, 0, dwarf::DW_FORM_udata, VD.getAddrElement(++i));
} else if (Element == DIFactory::OpDeref) {
addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_deref);
} else llvm_unreachable("unknown DIFactory Opcode");
}
// Now attach the location information to the DIE.
addBlock(Die, Attribute, 0, Block);
Caroline Tice
committed
/* Byref variables, in Blocks, are declared by the programmer as "SomeType
VarName;", but the compiler creates a __Block_byref_x_VarName struct, and
gives the variable VarName either the struct, or a pointer to the struct, as
its type. This is necessary for various behind-the-scenes things the
compiler needs to do with by-reference variables in Blocks.
However, as far as the original *programmer* is concerned, the variable
should still have type 'SomeType', as originally declared.
The function getBlockByrefType dives into the __Block_byref_x_VarName
Caroline Tice
committed
struct to find the original type of the variable, which is then assigned to
the variable's Debug Information Entry as its real type. So far, so good.
However now the debugger will expect the variable VarName to have the type
SomeType. So we need the location attribute for the variable to be an
expression that explains to the debugger how to navigate through the
Caroline Tice
committed
pointers and struct to find the actual variable of type SomeType.
The following function does just that. We start by getting
the "normal" location for the variable. This will be the location
of either the struct __Block_byref_x_VarName or the pointer to the
struct __Block_byref_x_VarName.
The struct will look something like:
struct __Block_byref_x_VarName {
... <various fields>
struct __Block_byref_x_VarName *forwarding;
... <various other fields>
SomeType VarName;
... <maybe more fields>
};
If we are given the struct directly (as our starting point) we
need to tell the debugger to:
1). Add the offset of the forwarding field.
2). Follow that pointer to get the real __Block_byref_x_VarName
Caroline Tice
committed
struct to use (the real one may have been copied onto the heap).
3). Add the offset for the field VarName, to find the actual variable.
If we started with a pointer to the struct, then we need to
dereference that pointer first, before the other steps.
Translating this into DWARF ops, we will need to append the following
to the current location description for the variable:
DW_OP_deref -- optional, if we start with a pointer
DW_OP_plus_uconst <forward_fld_offset>
DW_OP_deref
DW_OP_plus_uconst <varName_fld_offset>
That is what this function does. */
/// addBlockByrefAddress - Start with the address based on the location
Caroline Tice
committed
/// provided, and generate the DWARF information necessary to find the
/// actual Block variable (navigating the Block struct) based on the
/// starting location. Add the DWARF information to the die. For
/// more information, read large comment just above here.
///
void DwarfDebug::addBlockByrefAddress(DbgVariable *&DV, DIE *Die,
unsigned Attribute,
const MachineLocation &Location) {
Caroline Tice
committed
const DIVariable &VD = DV->getVariable();
DIType Ty = VD.getType();
DIType TmpTy = Ty;
unsigned Tag = Ty.getTag();
bool isPointer = false;
StringRef varName = VD.getName();
Caroline Tice
committed
if (Tag == dwarf::DW_TAG_pointer_type) {
DIDerivedType DTy = DIDerivedType(Ty.getNode());
Caroline Tice
committed
TmpTy = DTy.getTypeDerivedFrom();
isPointer = true;
}
DICompositeType blockStruct = DICompositeType(TmpTy.getNode());
// Find the __forwarding field and the variable field in the __Block_byref
// struct.
DIArray Fields = blockStruct.getTypeArray();
DIDescriptor varField = DIDescriptor();
DIDescriptor forwardingField = DIDescriptor();
Caroline Tice
committed
for (unsigned i = 0, N = Fields.getNumElements(); i < N; ++i) {
DIDescriptor Element = Fields.getElement(i);
DIDerivedType DT = DIDerivedType(Element.getNode());
StringRef fieldName = DT.getName();
if (fieldName == "__forwarding")
else if (fieldName == varName)
assert(!varField.isNull() && "Can't find byref variable in Block struct");
assert(!forwardingField.isNull()
&& "Can't find forwarding field in Block struct");
// Get the offsets for the forwarding field and the variable field.
unsigned int forwardingFieldOffset =
DIDerivedType(forwardingField.getNode()).getOffsetInBits() >> 3;
unsigned int varFieldOffset =
DIDerivedType(varField.getNode()).getOffsetInBits() >> 3;
Caroline Tice
committed
// Decode the original location, and use that as the start of the byref
// variable's location.
unsigned Reg = RI->getDwarfRegNum(Location.getReg(), false);
DIEBlock *Block = new DIEBlock();
Caroline Tice
committed
addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_reg0 + Reg);
addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_breg0 + Reg);
addUInt(Block, 0, dwarf::DW_FORM_udata, Reg);
addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_breg0 + Reg);
addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_bregx);
addUInt(Block, 0, dwarf::DW_FORM_udata, Reg);
Caroline Tice
committed
addUInt(Block, 0, dwarf::DW_FORM_sdata, Location.getOffset());
Caroline Tice
committed
// If we started with a pointer to the __Block_byref... struct, then
// the first thing we need to do is dereference the pointer (DW_OP_deref).
if (isPointer)
addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_deref);
Caroline Tice
committed
// Next add the offset for the '__forwarding' field:
// DW_OP_plus_uconst ForwardingFieldOffset. Note there's no point in
// adding the offset if it's 0.
if (forwardingFieldOffset > 0) {
addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst);
addUInt(Block, 0, dwarf::DW_FORM_udata, forwardingFieldOffset);
Caroline Tice
committed
// Now dereference the __forwarding field to get to the real __Block_byref
// struct: DW_OP_deref.
addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_deref);
Caroline Tice
committed
// Now that we've got the real __Block_byref... struct, add the offset
// for the variable's field to get to the location of the actual variable:
// DW_OP_plus_uconst varFieldOffset. Again, don't add if it's 0.
if (varFieldOffset > 0) {
addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst);
addUInt(Block, 0, dwarf::DW_FORM_udata, varFieldOffset);
Caroline Tice
committed
addBlock(Die, Attribute, 0, Block);
Caroline Tice
committed
}
/// addAddress - Add an address attribute to a die based on the location
/// provided.
void DwarfDebug::addAddress(DIE *Die, unsigned Attribute,
const MachineLocation &Location) {
unsigned Reg = RI->getDwarfRegNum(Location.getReg(), false);
DIEBlock *Block = new DIEBlock();
if (Location.isReg()) {
if (Reg < 32) {
addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_reg0 + Reg);
addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_regx);
addUInt(Block, 0, dwarf::DW_FORM_udata, Reg);
}
} else {
if (Reg < 32) {
addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_breg0 + Reg);
addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_bregx);
addUInt(Block, 0, dwarf::DW_FORM_udata, Reg);
addUInt(Block, 0, dwarf::DW_FORM_sdata, Location.getOffset());
addBlock(Die, Attribute, 0, Block);
/// addToContextOwner - Add Die into the list of its context owner's children.
void DwarfDebug::addToContextOwner(DIE *Die, DIDescriptor Context) {
if (Context.isNull())
ModuleCU->addDie(Die);
else if (Context.isType()) {
DIE *ContextDIE = getOrCreateTypeDIE(DIType(Context.getNode()));
ContextDIE->addChild(Die);
} else if (Context.isNameSpace()) {
DIE *ContextDIE = getOrCreateNameSpace(DINameSpace(Context.getNode()));
ContextDIE->addChild(Die);
} else if (DIE *ContextDIE = ModuleCU->getDIE(Context.getNode()))
ContextDIE->addChild(Die);
else
ModuleCU->addDie(Die);
}
/// getOrCreateTypeDIE - Find existing DIE or create new DIE for the
/// given DIType.
DIE *DwarfDebug::getOrCreateTypeDIE(DIType Ty) {
DIE *TyDIE = ModuleCU->getDIE(Ty.getNode());
if (TyDIE)
return TyDIE;
// Create new type.
TyDIE = new DIE(dwarf::DW_TAG_base_type);
ModuleCU->insertDIE(Ty.getNode(), TyDIE);
if (Ty.isBasicType())
constructTypeDIE(*TyDIE, DIBasicType(Ty.getNode()));
else if (Ty.isCompositeType())
constructTypeDIE(*TyDIE, DICompositeType(Ty.getNode()));
else {
assert(Ty.isDerivedType() && "Unknown kind of DIType");
constructTypeDIE(*TyDIE, DIDerivedType(Ty.getNode()));
}
addToContextOwner(TyDIE, Ty.getContext());
/// addType - Add a new type attribute to the specified entity.
void DwarfDebug::addType(DIE *Entity, DIType Ty) {
return;
// Check for pre-existence.
DIEEntry *Entry = ModuleCU->getDIEEntry(Ty.getNode());
// If it exists then use the existing value.
if (Entry) {
Entity->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, Entry);
return;
}
// Set up proxy.
Entry = createDIEEntry();
ModuleCU->insertDIEEntry(Ty.getNode(), Entry);
// Construct type.
Entry->setEntry(Buffer);
Entity->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, Entry);
/// constructTypeDIE - Construct basic type die from DIBasicType.
void DwarfDebug::constructTypeDIE(DIE &Buffer, DIBasicType BTy) {
// Get core information.
StringRef Name = BTy.getName();
Buffer.setTag(dwarf::DW_TAG_base_type);
addUInt(&Buffer, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1,
BTy.getEncoding());
// Add name if not anonymous or intermediate type.
addString(&Buffer, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name);
uint64_t Size = BTy.getSizeInBits() >> 3;
addUInt(&Buffer, dwarf::DW_AT_byte_size, 0, Size);
/// constructTypeDIE - Construct derived type die from DIDerivedType.
void DwarfDebug::constructTypeDIE(DIE &Buffer, DIDerivedType DTy) {
// Get core information.
StringRef Name = DTy.getName();
uint64_t Size = DTy.getSizeInBits() >> 3;
unsigned Tag = DTy.getTag();
// FIXME - Workaround for templates.
if (Tag == dwarf::DW_TAG_inheritance) Tag = dwarf::DW_TAG_reference_type;
Buffer.setTag(Tag);
// Map to main type, void will not have a type.
DIType FromTy = DTy.getTypeDerivedFrom();
// Add name if not anonymous or intermediate type.
if (!Name.empty())
addString(&Buffer, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name);
// Add size if non-zero (derived types might be zero-sized.)
if (Size)
addUInt(&Buffer, dwarf::DW_AT_byte_size, 0, Size);
// Add source line info if available and TyDesc is not a forward declaration.
addSourceLine(&Buffer, &DTy);
/// constructTypeDIE - Construct type DIE from DICompositeType.
void DwarfDebug::constructTypeDIE(DIE &Buffer, DICompositeType CTy) {
// Get core information.
StringRef Name = CTy.getName();
uint64_t Size = CTy.getSizeInBits() >> 3;
unsigned Tag = CTy.getTag();
Buffer.setTag(Tag);
switch (Tag) {
case dwarf::DW_TAG_vector_type:
case dwarf::DW_TAG_array_type:
break;
case dwarf::DW_TAG_enumeration_type: {
DIArray Elements = CTy.getTypeArray();
// Add enumerators to enumeration type.
for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) {
DIE *ElemDie = NULL;
DIEnumerator Enum(Elements.getElement(i).getNode());
if (!Enum.isNull()) {
ElemDie = constructEnumTypeDIE(&Enum);
Buffer.addChild(ElemDie);
Devang Patel
committed
}
}
}
break;
case dwarf::DW_TAG_subroutine_type: {
// Add return type.
DIArray Elements = CTy.getTypeArray();
DIDescriptor RTy = Elements.getElement(0);
addType(&Buffer, DIType(RTy.getNode()));
// Add prototype flag.
addUInt(&Buffer, dwarf::DW_AT_prototyped, dwarf::DW_FORM_flag, 1);
// Add arguments.
for (unsigned i = 1, N = Elements.getNumElements(); i < N; ++i) {
DIE *Arg = new DIE(dwarf::DW_TAG_formal_parameter);
DIDescriptor Ty = Elements.getElement(i);
Buffer.addChild(Arg);
}
}
break;
case dwarf::DW_TAG_structure_type:
case dwarf::DW_TAG_union_type:
case dwarf::DW_TAG_class_type: {
// Add elements to structure type.
DIArray Elements = CTy.getTypeArray();
// A forward struct declared type may not have elements available.
break;
// Add elements to structure type.
for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) {
DIDescriptor Element = Elements.getElement(i);
DIE *ElemDie = NULL;
ElemDie = createSubprogramDIE(DISubprogram(Element.getNode()));
else if (Element.getTag() == dwarf::DW_TAG_auto_variable) {
DIVariable DV(Element.getNode());
ElemDie = new DIE(dwarf::DW_TAG_variable);
addString(ElemDie, dwarf::DW_AT_name, dwarf::DW_FORM_string,
DV.getName());
addType(ElemDie, DV.getType());
addUInt(ElemDie, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1);
addUInt(ElemDie, dwarf::DW_AT_external, dwarf::DW_FORM_flag, 1);
addSourceLine(ElemDie, &DV);
ElemDie = createMemberDIE(DIDerivedType(Element.getNode()));
Buffer.addChild(ElemDie);
if (CTy.isAppleBlockExtension())
addUInt(&Buffer, dwarf::DW_AT_APPLE_block, dwarf::DW_FORM_flag, 1);
unsigned RLang = CTy.getRunTimeLang();
if (RLang)
addUInt(&Buffer, dwarf::DW_AT_APPLE_runtime_class,
dwarf::DW_FORM_data1, RLang);
Devang Patel
committed
DICompositeType ContainingType = CTy.getContainingType();
Devang Patel
committed
addDIEEntry(&Buffer, dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4,
getOrCreateTypeDIE(DIType(ContainingType.getNode())));
break;
}
default:
break;
}
// Add name if not anonymous or intermediate type.
addString(&Buffer, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name);
if (Tag == dwarf::DW_TAG_enumeration_type || Tag == dwarf::DW_TAG_class_type ||
Tag == dwarf::DW_TAG_structure_type || Tag == dwarf::DW_TAG_union_type) {
// Add size if non-zero (derived types might be zero-sized.)
if (Size)
addUInt(&Buffer, dwarf::DW_AT_byte_size, 0, Size);
else {
// Add zero size if it is not a forward declaration.
if (CTy.isForwardDecl())
addUInt(&Buffer, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1);
addUInt(&Buffer, dwarf::DW_AT_byte_size, 0, 0);