/// 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);
}
예제 #2
0
/// 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);
}
예제 #3
0
/// 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);
}
예제 #4
0
// Some targets do not provide a DWARF register number for every
// register.  This function attempts to emit a DWARF register by
// emitting a piece of a super-register or by piecing together
// multiple subregisters that alias the register.
void AsmPrinter::EmitDwarfRegOpPiece(ByteStreamer &Streamer,
                                     const MachineLocation &MLoc,
                                     unsigned PieceSizeInBits,
                                     unsigned PieceOffsetInBits) const {
  assert(MLoc.isReg() && "MLoc must be a register");
  DebugLocDwarfExpression Expr(*this, Streamer);
  Expr.AddMachineRegPiece(MLoc.getReg(), PieceSizeInBits, PieceOffsetInBits);
}
예제 #5
0
MachineLocation 
X86AsmPrinter::getDebugValueLocation(const MachineInstr *MI) const {
  MachineLocation Location;
  assert (MI->getNumOperands() == 7 && "Invalid no. of machine operands!");
  // Frame address.  Currently handles register +- offset only.
  assert(MI->getOperand(0).isReg() && MI->getOperand(3).isImm());
  Location.set(MI->getOperand(0).getReg(), MI->getOperand(3).getImm());
  return Location;
}
예제 #6
0
MachineLocation
AArch64AsmPrinter::getDebugValueLocation(const MachineInstr *MI) const {
  MachineLocation Location;
  assert(MI->getNumOperands() == 4 && "Invalid no. of machine operands!");
  // Frame address.  Currently handles register +- offset only.
  if (MI->getOperand(0).isReg() && MI->getOperand(1).isImm())
    Location.set(MI->getOperand(0).getReg(), MI->getOperand(1).getImm());
  else {
    DEBUG(dbgs() << "DBG_VALUE instruction ignored! " << *MI << "\n");
  }
  return Location;
}
예제 #7
0
/// 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);
}
예제 #8
0
/// Add an address attribute to a die based on the location provided.
void DwarfCompileUnit::addAddress(DIE &Die, dwarf::Attribute Attribute,
                                  const MachineLocation &Location) {
  DIELoc *Loc = new (DIEValueAllocator) DIELoc;
  DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc);
  if (Location.isIndirect())
    DwarfExpr.setMemoryLocationKind();

  DIExpressionCursor Cursor({});
  const TargetRegisterInfo &TRI = *Asm->MF->getSubtarget().getRegisterInfo();
  if (!DwarfExpr.addMachineRegExpression(TRI, Cursor, Location.getReg()))
    return;
  DwarfExpr.addExpression(std::move(Cursor));

  // Now attach the location information to the DIE.
  addBlock(Die, Attribute, DwarfExpr.finalize());
}
/// Some targets do not provide a DWARF register number for every
/// register.  This function attempts to emit a dwarf register by
/// emitting a piece of a super-register or by piecing together
/// multiple subregisters that alias the register.
static void EmitDwarfRegOpPiece(ByteStreamer &Streamer, const AsmPrinter &AP,
                                const MachineLocation &MLoc) {
  assert(!MLoc.isIndirect());
  const TargetRegisterInfo *TRI = AP.TM.getRegisterInfo();
  int Reg = TRI->getDwarfRegNum(MLoc.getReg(), false);

  // Walk up the super-register chain until we find a valid number.
  // For example, EAX on x86_64 is a 32-bit piece of RAX with offset 0.
  for (MCSuperRegIterator SR(MLoc.getReg(), TRI); SR.isValid(); ++SR) {
    Reg = TRI->getDwarfRegNum(*SR, false);
    if (Reg >= 0) {
      unsigned Idx = TRI->getSubRegIndex(*SR, MLoc.getReg());
      unsigned Size = TRI->getSubRegIdxSize(Idx);
      unsigned Offset = TRI->getSubRegIdxOffset(Idx);
      AP.OutStreamer.AddComment("super-register");
      emitDwarfRegOp(Streamer, Reg);
      emitDwarfOpPiece(Streamer, Size, Offset);
      return;
    }
  }

  // Otherwise, attempt to find a covering set of sub-register numbers.
  // For example, Q0 on ARM is a composition of D0+D1.
  //
  // Keep track of the current position so we can emit the more
  // efficient DW_OP_piece.
  unsigned CurPos = 0;
  // The size of the register in bits, assuming 8 bits per byte.
  unsigned RegSize = TRI->getMinimalPhysRegClass(MLoc.getReg())->getSize() * 8;
  // Keep track of the bits in the register we already emitted, so we
  // can avoid emitting redundant aliasing subregs.
  SmallBitVector Coverage(RegSize, false);
  for (MCSubRegIterator SR(MLoc.getReg(), TRI); SR.isValid(); ++SR) {
    unsigned Idx = TRI->getSubRegIndex(MLoc.getReg(), *SR);
    unsigned Size = TRI->getSubRegIdxSize(Idx);
    unsigned Offset = TRI->getSubRegIdxOffset(Idx);
    Reg = TRI->getDwarfRegNum(*SR, false);

    // Intersection between the bits we already emitted and the bits
    // covered by this subregister.
    SmallBitVector Intersection(RegSize, false);
    Intersection.set(Offset, Offset + Size);
    Intersection ^= Coverage;

    // If this sub-register has a DWARF number and we haven't covered
    // its range, emit a DWARF piece for it.
    if (Reg >= 0 && Intersection.any()) {
      AP.OutStreamer.AddComment("sub-register");
      emitDwarfRegOp(Streamer, Reg);
      emitDwarfOpPiece(Streamer, Size, Offset == CurPos ? 0 : Offset);
      CurPos = Offset + Size;

      // Mark it as emitted.
      Coverage.set(Offset, Offset + Size);
    }
  }

  if (CurPos == 0) {
    // FIXME: We have no reasonable way of handling errors in here.
    Streamer.EmitInt8(dwarf::DW_OP_nop,
                      "nop (could not find a dwarf register number)");
  }
}
예제 #10
0
// Some targets do not provide a DWARF register number for every
// register.  This function attempts to emit a DWARF register by
// emitting a piece of a super-register or by piecing together
// multiple subregisters that alias the register.
void AsmPrinter::EmitDwarfRegOpPiece(ByteStreamer &Streamer,
                                     const MachineLocation &MLoc,
                                     unsigned PieceSizeInBits,
                                     unsigned PieceOffsetInBits) const {
  assert(MLoc.isReg() && "MLoc must be a register");
  const TargetRegisterInfo *TRI = TM.getSubtargetImpl()->getRegisterInfo();
  int Reg = TRI->getDwarfRegNum(MLoc.getReg(), false);

  // If this is a valid register number, emit it.
  if (Reg >= 0) {
    emitDwarfRegOp(Streamer, Reg);
    EmitDwarfOpPiece(Streamer, PieceSizeInBits, PieceOffsetInBits);
    return;
  }

  // Walk up the super-register chain until we find a valid number.
  // For example, EAX on x86_64 is a 32-bit piece of RAX with offset 0.
  for (MCSuperRegIterator SR(MLoc.getReg(), TRI); SR.isValid(); ++SR) {
    Reg = TRI->getDwarfRegNum(*SR, false);
    if (Reg >= 0) {
      unsigned Idx = TRI->getSubRegIndex(*SR, MLoc.getReg());
      unsigned Size = TRI->getSubRegIdxSize(Idx);
      unsigned RegOffset = TRI->getSubRegIdxOffset(Idx);
      OutStreamer.AddComment("super-register");
      emitDwarfRegOp(Streamer, Reg);
      if (PieceOffsetInBits == RegOffset) {
        EmitDwarfOpPiece(Streamer, Size, RegOffset);
      } else {
        // If this is part of a variable in a sub-register at a
        // non-zero offset, we need to manually shift the value into
        // place, since the DW_OP_piece describes the part of the
        // variable, not the position of the subregister.
        if (RegOffset)
          emitDwarfOpShr(Streamer, RegOffset);
        EmitDwarfOpPiece(Streamer, Size, PieceOffsetInBits);
      }
      return;
    }
  }

  // Otherwise, attempt to find a covering set of sub-register numbers.
  // For example, Q0 on ARM is a composition of D0+D1.
  //
  // Keep track of the current position so we can emit the more
  // efficient DW_OP_piece.
  unsigned CurPos = PieceOffsetInBits;
  // The size of the register in bits, assuming 8 bits per byte.
  unsigned RegSize = TRI->getMinimalPhysRegClass(MLoc.getReg())->getSize() * 8;
  // Keep track of the bits in the register we already emitted, so we
  // can avoid emitting redundant aliasing subregs.
  SmallBitVector Coverage(RegSize, false);
  for (MCSubRegIterator SR(MLoc.getReg(), TRI); SR.isValid(); ++SR) {
    unsigned Idx = TRI->getSubRegIndex(MLoc.getReg(), *SR);
    unsigned Size = TRI->getSubRegIdxSize(Idx);
    unsigned Offset = TRI->getSubRegIdxOffset(Idx);
    Reg = TRI->getDwarfRegNum(*SR, false);

    // Intersection between the bits we already emitted and the bits
    // covered by this subregister.
    SmallBitVector Intersection(RegSize, false);
    Intersection.set(Offset, Offset + Size);
    Intersection ^= Coverage;

    // If this sub-register has a DWARF number and we haven't covered
    // its range, emit a DWARF piece for it.
    if (Reg >= 0 && Intersection.any()) {
      OutStreamer.AddComment("sub-register");
      emitDwarfRegOp(Streamer, Reg);
      EmitDwarfOpPiece(Streamer, Size, Offset == CurPos ? 0 : Offset);
      CurPos = Offset + Size;

      // Mark it as emitted.
      Coverage.set(Offset, Offset + Size);
    }
  }

  if (CurPos == PieceOffsetInBits) {
    // FIXME: We have no reasonable way of handling errors in here.
    Streamer.EmitInt8(dwarf::DW_OP_nop,
                      "nop (could not find a dwarf register number)");
  }
}
예제 #11
0
/// 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);
}