diff options
author | Mike Stump <mrs@apple.com> | 2009-09-30 00:08:22 +0000 |
---|---|---|
committer | Mike Stump <mrs@apple.com> | 2009-09-30 00:08:22 +0000 |
commit | 3e4c9bdb67db9b6d65b17d474e3268b520a93514 (patch) | |
tree | 303dcada7defc4cf42447ffa6e3f4d0a32522760 /lib/CodeGen/AsmPrinter/DwarfDebug.cpp | |
parent | 17487ba60d171aa32b17e6c3ad6d5809e78f9868 (diff) |
Add a way for a frontend to generate more complex dwarf location
information. This allows arbitrary code involving DW_OP_plus_uconst
and DW_OP_deref. The scheme allows for easy extention to include,
any, or all of the DW_OP_ opcodes. I thought about just exposing all
of them, but, wasn't sure if people wanted the dwarf opcodes exposed
in the api. Is that a layering violation?
With this scheme, the entire existing block scheme used by llvm-gcc
can be switched over to the new scheme. I think that would be
cleaner, as then the compiler specific bits are not present in llvm
proper. Before the old code can be yanked however, similar code in
clang would have to be removed.
Next up, more testing.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@83120 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/AsmPrinter/DwarfDebug.cpp')
-rw-r--r-- | lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 61 |
1 files changed, 57 insertions, 4 deletions
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); |