/// EmitDwarfRegOp - Emit dwarf register operation. void AsmPrinter::EmitDwarfRegOp(ByteStreamer &Streamer, const MachineLocation &MLoc) const { DebugLocDwarfExpression Expr(*MF->getSubtarget().getRegisterInfo(), getDwarfDebug()->getDwarfVersion(), Streamer); const MCRegisterInfo *MRI = MMI->getContext().getRegisterInfo(); int Reg = MRI->getDwarfRegNum(MLoc.getReg(), false); if (Reg < 0) { // We assume that pointers are always in an addressable register. if (MLoc.isIndirect()) // FIXME: We have no reasonable way of handling errors in here. The // caller might be in the middle of a dwarf expression. We should // probably assert that Reg >= 0 once debug info generation is more // mature. return Expr.EmitOp(dwarf::DW_OP_nop, "nop (could not find a dwarf register number)"); // Attempt to find a valid super- or sub-register. if (!Expr.AddMachineRegPiece(MLoc.getReg())) Expr.EmitOp(dwarf::DW_OP_nop, "nop (could not find a dwarf register number)"); return; } if (MLoc.isIndirect()) Expr.AddRegIndirect(Reg, MLoc.getOffset()); else Expr.AddReg(Reg); }
/// EmitDwarfRegOp - Emit dwarf register operation. void AsmPrinter::EmitDwarfRegOp(ByteStreamer &Streamer, const MachineLocation &MLoc, bool Indirect) const { const TargetRegisterInfo *TRI = TM.getRegisterInfo(); int Reg = TRI->getDwarfRegNum(MLoc.getReg(), false); if (Reg < 0) { // We assume that pointers are always in an addressable register. if (Indirect || MLoc.isIndirect()) { // FIXME: We have no reasonable way of handling errors in here. The // caller might be in the middle of a dwarf expression. We should // probably assert that Reg >= 0 once debug info generation is more // mature. Streamer.EmitInt8(dwarf::DW_OP_nop, "nop (invalid dwarf register number for indirect loc)"); return; } // Attempt to find a valid super- or sub-register. if (!Indirect && !MLoc.isIndirect()) return EmitDwarfRegOpPiece(Streamer, *this, MLoc); } if (MLoc.isIndirect()) emitDwarfRegOpIndirect(Streamer, Reg, MLoc.getOffset(), Indirect); else if (Indirect) emitDwarfRegOpIndirect(Streamer, Reg, 0, false); else emitDwarfRegOp(Streamer, Reg); }
/// 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 CompileUnit::addComplexAddress(DbgVariable *&DV, DIE *Die, unsigned Attribute, const MachineLocation &Location) { DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); unsigned N = DV->getNumAddrElements(); unsigned i = 0; if (Location.isReg()) { if (N >= 2 && DV->getAddrElement(0) == DIBuilder::OpPlus) { // If first address element is OpPlus then emit // DW_OP_breg + Offset instead of DW_OP_reg + Offset. addRegisterOffset(Block, Location.getReg(), DV->getAddrElement(1)); i = 2; } else addRegisterOp(Block, Location.getReg()); } else addRegisterOffset(Block, Location.getReg(), Location.getOffset()); for (;i < N; ++i) { uint64_t Element = DV->getAddrElement(i); if (Element == DIBuilder::OpPlus) { addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst); addUInt(Block, 0, dwarf::DW_FORM_udata, DV->getAddrElement(++i)); } else if (Element == DIBuilder::OpDeref) { addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); } else llvm_unreachable("unknown DIBuilder Opcode"); } // Now attach the location information to the DIE. addBlock(Die, Attribute, 0, Block); }
/// addAddress - Add an address attribute to a die based on the location /// provided. void CompileUnit::addAddress(DIE *Die, unsigned Attribute, const MachineLocation &Location) { DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); if (Location.isReg()) addRegisterOp(Block, Location.getReg()); else addRegisterOffset(Block, Location.getReg(), Location.getOffset()); // Now attach the location information to the DIE. addBlock(Die, Attribute, 0, Block); }
/// 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. For /// more information, read large comment just above here. /// void CompileUnit::addBlockByrefAddress(DbgVariable *&DV, DIE *Die, unsigned Attribute, const MachineLocation &Location) { DIType Ty = DV->getType(); DIType TmpTy = Ty; unsigned Tag = Ty.getTag(); bool isPointer = false; StringRef varName = DV->getName(); if (Tag == dwarf::DW_TAG_pointer_type) { DIDerivedType DTy = DIDerivedType(Ty); TmpTy = DTy.getTypeDerivedFrom(); isPointer = true; } DICompositeType blockStruct = DICompositeType(TmpTy); // Find the __forwarding field and the variable field in the __Block_byref // struct. DIArray Fields = blockStruct.getTypeArray(); DIDescriptor varField = DIDescriptor(); DIDescriptor forwardingField = DIDescriptor(); for (unsigned i = 0, N = Fields.getNumElements(); i < N; ++i) { DIDescriptor Element = Fields.getElement(i); DIDerivedType DT = DIDerivedType(Element); StringRef fieldName = DT.getName(); if (fieldName == "__forwarding") forwardingField = Element; else if (fieldName == varName) varField = Element; } // Get the offsets for the forwarding field and the variable field. unsigned forwardingFieldOffset = DIDerivedType(forwardingField).getOffsetInBits() >> 3; unsigned varFieldOffset = DIDerivedType(varField).getOffsetInBits() >> 3; // Decode the original location, and use that as the start of the byref // variable's location. const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo(); unsigned Reg = RI->getDwarfRegNum(Location.getReg(), false); DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); if (Location.isReg()) { if (Reg < 32) addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_reg0 + Reg); else { 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); 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()); } // 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); // 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); } // 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); // 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); } // Now attach the location information to the DIE. addBlock(Die, Attribute, 0, Block); }