diff options
Diffstat (limited to 'llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp')
| -rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp index 76b58684da8..0b7f0f339f7 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -743,4 +743,61 @@ void DwarfCompileUnit::addAddress(DIE &Die, dwarf::Attribute Attribute, // Now attach the location information to the DIE. addBlock(Die, Attribute, Loc); } + +/// 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 DbgVariable, starting from the starting +/// location. Add the DWARF information to the die. +void DwarfCompileUnit::addComplexAddress(const DbgVariable &DV, DIE &Die, + dwarf::Attribute Attribute, + const MachineLocation &Location) { + DIELoc *Loc = new (DIEValueAllocator) DIELoc(); + unsigned N = DV.getNumAddrElements(); + unsigned i = 0; + if (Location.isReg()) { + if (N >= 2 && DV.getAddrElement(0) == dwarf::DW_OP_plus) { + assert(!DV.getVariable().isIndirect() && + "double indirection not handled"); + // If first address element is OpPlus then emit + // DW_OP_breg + Offset instead of DW_OP_reg + Offset. + addRegisterOffset(*Loc, Location.getReg(), DV.getAddrElement(1)); + i = 2; + } else if (N >= 2 && DV.getAddrElement(0) == dwarf::DW_OP_deref) { + assert(!DV.getVariable().isIndirect() && + "double indirection not handled"); + addRegisterOpPiece(*Loc, Location.getReg(), + DV.getExpression().getPieceSize(), + DV.getExpression().getPieceOffset()); + i = 3; + } else + addRegisterOpPiece(*Loc, Location.getReg()); + } else + addRegisterOffset(*Loc, Location.getReg(), Location.getOffset()); + + for (; i < N; ++i) { + uint64_t Element = DV.getAddrElement(i); + if (Element == dwarf::DW_OP_plus) { + addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst); + addUInt(*Loc, dwarf::DW_FORM_udata, DV.getAddrElement(++i)); + + } else if (Element == dwarf::DW_OP_deref) { + if (!Location.isReg()) + addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); + + } else if (Element == dwarf::DW_OP_piece) { + const unsigned SizeOfByte = 8; + unsigned PieceOffsetInBits = DV.getAddrElement(++i) * SizeOfByte; + unsigned PieceSizeInBits = DV.getAddrElement(++i) * SizeOfByte; + // Emit DW_OP_bit_piece Size Offset. + assert(PieceSizeInBits > 0 && "piece has zero size"); + addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_bit_piece); + addUInt(*Loc, dwarf::DW_FORM_udata, PieceSizeInBits); + addUInt(*Loc, dwarf::DW_FORM_udata, PieceOffsetInBits); + } else + llvm_unreachable("unknown DIBuilder Opcode"); + } + + // Now attach the location information to the DIE. + addBlock(Die, Attribute, Loc); +} } // end llvm namespace |

