aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llvm/Analysis/DebugInfo.h29
-rw-r--r--lib/Analysis/DebugInfo.cpp22
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfDebug.cpp61
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfDebug.h15
4 files changed, 117 insertions, 10 deletions
diff --git a/include/llvm/Analysis/DebugInfo.h b/include/llvm/Analysis/DebugInfo.h
index 8082279a25..c40cfb2671 100644
--- a/include/llvm/Analysis/DebugInfo.h
+++ b/include/llvm/Analysis/DebugInfo.h
@@ -187,10 +187,10 @@ namespace llvm {
class DIType : public DIDescriptor {
public:
enum {
- FlagPrivate = 1 << 0,
- FlagProtected = 1 << 1,
- FlagFwdDecl = 1 << 2,
- FlagAppleBlock = 1 << 3,
+ FlagPrivate = 1 << 0,
+ FlagProtected = 1 << 1,
+ FlagFwdDecl = 1 << 2,
+ FlagAppleBlock = 1 << 3,
FlagBlockByrefStruct = 1 << 4
};
@@ -409,6 +409,17 @@ namespace llvm {
/// Verify - Verify that a variable descriptor is well formed.
bool Verify() const;
+ /// HasComplexAddr - Return true if the variable has a complex address.
+ bool hasComplexAddress() const {
+ return getNumAddrElements() > 0;
+ }
+
+ unsigned getNumAddrElements() const { return DbgNode->getNumElements()-6; }
+
+ uint64_t getAddrElement(unsigned Idx) const {
+ return getUInt64Field(Idx+6);
+ }
+
/// isBlockByrefVariable - Return true if the variable was declared as
/// a "__block" variable (Apple Blocks).
bool isBlockByrefVariable() const {
@@ -463,6 +474,8 @@ namespace llvm {
DIFactory(const DIFactory &); // DO NOT IMPLEMENT
void operator=(const DIFactory&); // DO NOT IMPLEMENT
public:
+ enum ComplexAddrKind { OpPlus=1, OpDeref };
+
explicit DIFactory(Module &m);
/// GetOrCreateArray - Create an descriptor for an array of descriptors.
@@ -540,6 +553,14 @@ namespace llvm {
DICompileUnit CompileUnit, unsigned LineNo,
DIType Type);
+ /// CreateComplexVariable - Create a new descriptor for the specified
+ /// variable which has a complex address expression for its address.
+ DIVariable CreateComplexVariable(unsigned Tag, DIDescriptor Context,
+ const std::string &Name,
+ DICompileUnit CompileUnit, unsigned LineNo,
+ DIType Type,
+ SmallVector<Value *, 9> &addr);
+
/// CreateLexicalBlock - This creates a descriptor for a lexical block
/// with the specified parent context.
DILexicalBlock CreateLexicalBlock(DIDescriptor Context);
diff --git a/lib/Analysis/DebugInfo.cpp b/lib/Analysis/DebugInfo.cpp
index 58bee90372..db5a0cbb21 100644
--- a/lib/Analysis/DebugInfo.cpp
+++ b/lib/Analysis/DebugInfo.cpp
@@ -531,6 +531,8 @@ void DIVariable::dump() const {
errs() << " [" << getLineNumber() << "] ";
getType().dump();
errs() << "\n";
+
+ // FIXME: Dump complex addresses
}
//===----------------------------------------------------------------------===//
@@ -781,6 +783,26 @@ DIVariable DIFactory::CreateVariable(unsigned Tag, DIDescriptor Context,
}
+/// CreateComplexVariable - Create a new descriptor for the specified variable
+/// which has a complex address expression for its address.
+DIVariable DIFactory::CreateComplexVariable(unsigned Tag, DIDescriptor Context,
+ const std::string &Name,
+ DICompileUnit CompileUnit,
+ unsigned LineNo,
+ DIType Type, SmallVector<Value *, 9> &addr) {
+ SmallVector<Value *, 9> Elts;
+ Elts.push_back(GetTagConstant(Tag));
+ Elts.push_back(Context.getNode());
+ Elts.push_back(MDString::get(VMContext, Name));
+ Elts.push_back(CompileUnit.getNode());
+ Elts.push_back(ConstantInt::get(Type::getInt32Ty(VMContext), LineNo));
+ Elts.push_back(Type.getNode());
+ Elts.insert(Elts.end(), addr.begin(), addr.end());
+
+ return DIVariable(MDNode::get(VMContext, &Elts[0], 6+addr.size()));
+}
+
+
/// CreateBlock - This creates a descriptor for a lexical block with the
/// specified parent VMContext.
DILexicalBlock DIFactory::CreateLexicalBlock(DIDescriptor Context) {
diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index f667e31569..8a74a8ee44 100644
--- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -556,7 +556,7 @@ DIType DwarfDebug::GetBlockByrefType(DIType Ty, std::string Name) {
unsigned tag = Ty.getTag();
if (tag == dwarf::DW_TAG_pointer_type) {
- DIDerivedType DTy = DIDerivedType (Ty.getNode());
+ DIDerivedType DTy = DIDerivedType(Ty.getNode());
subType = DTy.getTypeDerivedFrom();
}
@@ -577,6 +577,56 @@ DIType DwarfDebug::GetBlockByrefType(DIType Ty, std::string Name) {
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);
+ else {
+ 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);
+}
+
/* 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
@@ -649,7 +699,7 @@ void DwarfDebug::AddBlockByrefAddress(DbgVariable *&DV, DIE *Die,
const char *varName = VD.getName();
if (Tag == dwarf::DW_TAG_pointer_type) {
- DIDerivedType DTy = DIDerivedType (Ty.getNode());
+ DIDerivedType DTy = DIDerivedType(Ty.getNode());
TmpTy = DTy.getTypeDerivedFrom();
isPointer = true;
}
@@ -790,7 +840,6 @@ void DwarfDebug::AddType(CompileUnit *DW_Unit, DIE *Entity, DIType Ty) {
else {
assert(Ty.isDerivedType() && "Unknown kind of DIType");
ConstructTypeDIE(DW_Unit, Buffer, DIDerivedType(Ty.getNode()));
-
}
// Add debug information entry to entity and appropriate context.
@@ -1187,6 +1236,7 @@ DIE *DwarfDebug::CreateDbgScopeVariable(DbgVariable *DV, CompileUnit *Unit) {
AddSourceLine(VariableDie, &VD);
// Add variable type.
+ // FIXME: isBlockByrefVariable should be reformulated in terms of complex addresses instead.
if (VD.isBlockByrefVariable())
AddType(Unit, VariableDie, GetBlockByrefType(VD.getType(), Name));
else
@@ -1200,7 +1250,10 @@ DIE *DwarfDebug::CreateDbgScopeVariable(DbgVariable *DV, CompileUnit *Unit) {
Location.set(RI->getFrameRegister(*MF),
RI->getFrameIndexOffset(*MF, DV->getFrameIndex()));
- if (VD.isBlockByrefVariable())
+
+ if (VD.hasComplexAddress())
+ AddComplexAddress(DV, VariableDie, dwarf::DW_AT_location, Location);
+ else if (VD.isBlockByrefVariable())
AddBlockByrefAddress(DV, VariableDie, dwarf::DW_AT_location, Location);
else
AddAddress(VariableDie, dwarf::DW_AT_location, Location);
diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.h b/lib/CodeGen/AsmPrinter/DwarfDebug.h
index f582f9b829..8899529698 100644
--- a/lib/CodeGen/AsmPrinter/DwarfDebug.h
+++ b/lib/CodeGen/AsmPrinter/DwarfDebug.h
@@ -284,10 +284,20 @@ class VISIBILITY_HIDDEN DwarfDebug : public Dwarf {
void AddAddress(DIE *Die, unsigned Attribute,
const MachineLocation &Location);
+ /// AddComplexAddress - Start with the address based on the location provided,
+ /// and generate the DWARF information necessary to find the actual variable
+ /// (navigating the extra location information encoded in the type) based on
+ /// the starting location. Add the DWARF information to the die.
+ ///
+ void AddComplexAddress(DbgVariable *&DV, DIE *Die, unsigned Attribute,
+ const MachineLocation &Location);
+
+ // FIXME: Should be reformulated in terms of AddComplexAddress.
/// AddBlockByrefAddress - Start with the address based on the location
/// 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.
+ /// starting location. Add the DWARF information to the die. Obsolete,
+ /// please use AddComplexAddress instead.
///
void AddBlockByrefAddress(DbgVariable *&DV, DIE *Die, unsigned Attribute,
const MachineLocation &Location);
@@ -459,8 +469,9 @@ class VISIBILITY_HIDDEN DwarfDebug : public Dwarf {
void ConstructSubprogram(MDNode *N);
+ // FIXME: This should go away in favor of complex addresses.
/// Find the type the programmer originally declared the variable to be
- /// and return that type.
+ /// and return that type. Obsolete, use GetComplexAddrType instead.
///
DIType GetBlockByrefType(DIType Ty, std::string Name);