예제 #1
0
bool DwarfExpression::addMachineRegExpression(const TargetRegisterInfo &TRI,
                                              DIExpressionCursor &ExprCursor,
                                              unsigned MachineReg,
                                              unsigned FragmentOffsetInBits) {
  auto Fragment = ExprCursor.getFragmentInfo();
  if (!addMachineReg(TRI, MachineReg, Fragment ? Fragment->SizeInBits : ~1U))
    return false;

  bool HasComplexExpression = false;
  auto Op = ExprCursor.peek();
  if (Op && Op->getOp() != dwarf::DW_OP_LLVM_fragment)
    HasComplexExpression = true;

  // If the register can only be described by a complex expression (i.e.,
  // multiple subregisters) it doesn't safely compose with another complex
  // expression. For example, it is not possible to apply a DW_OP_deref
  // operation to multiple DW_OP_pieces.
  if (HasComplexExpression && DwarfRegs.size() > 1) {
    DwarfRegs.clear();
    return false;
  }

  // Handle simple register locations.
  if (!HasComplexExpression) {
    for (auto &Reg : DwarfRegs) {
      if (Reg.DwarfRegNo >= 0)
        addReg(Reg.DwarfRegNo, Reg.Comment);
      addOpPiece(Reg.Size);
    }
    DwarfRegs.clear();
    return true;
  }

  assert(DwarfRegs.size() == 1);
  auto Reg = DwarfRegs[0];
  bool FBReg = isFrameRegister(TRI, MachineReg); 
  assert(Reg.Size == 0 && "subregister has same size as superregister");

  // Pattern-match combinations for which more efficient representations exist.
  switch (Op->getOp()) {
  default: {
    if (FBReg)
      addFBReg(0);
    else
      addReg(Reg.DwarfRegNo, 0);
    break;
  }
  case dwarf::DW_OP_plus:
  case dwarf::DW_OP_minus: {
    // [DW_OP_reg,Offset,DW_OP_plus, DW_OP_deref] --> [DW_OP_breg, Offset].
    // [DW_OP_reg,Offset,DW_OP_minus,DW_OP_deref] --> [DW_OP_breg,-Offset].
    auto N = ExprCursor.peekNext();
    if (N && N->getOp() == dwarf::DW_OP_deref) {
      int Offset = Op->getArg(0);
      int SignedOffset = (Op->getOp() == dwarf::DW_OP_plus) ? Offset : -Offset;
      if (FBReg)
        addFBReg(SignedOffset);
      else
        addBReg(Reg.DwarfRegNo, SignedOffset);

      ExprCursor.consume(2);
      break;
    }
    addReg(Reg.DwarfRegNo, 0);
    break;
  }
  case dwarf::DW_OP_deref:
    // [DW_OP_reg,DW_OP_deref] --> [DW_OP_breg].
    if (FBReg)
      addFBReg(0);
    else
      addBReg(Reg.DwarfRegNo, 0);
    ExprCursor.take();
    break;
  }
  DwarfRegs.clear();
  return true;
}
예제 #2
0
bool DwarfExpression::addMachineRegExpression(const TargetRegisterInfo &TRI,
                                              DIExpressionCursor &ExprCursor,
                                              unsigned MachineReg,
                                              unsigned FragmentOffsetInBits) {
  auto Fragment = ExprCursor.getFragmentInfo();
  if (!addMachineReg(TRI, MachineReg, Fragment ? Fragment->SizeInBits : ~1U)) {
    LocationKind = Unknown;
    return false;
  }

  bool HasComplexExpression = false;
  auto Op = ExprCursor.peek();
  if (Op && Op->getOp() != dwarf::DW_OP_LLVM_fragment)
    HasComplexExpression = true;

  // If the register can only be described by a complex expression (i.e.,
  // multiple subregisters) it doesn't safely compose with another complex
  // expression. For example, it is not possible to apply a DW_OP_deref
  // operation to multiple DW_OP_pieces.
  if (HasComplexExpression && DwarfRegs.size() > 1) {
    DwarfRegs.clear();
    LocationKind = Unknown;
    return false;
  }

  // Handle simple register locations.
  if (LocationKind != Memory && !HasComplexExpression) {
    for (auto &Reg : DwarfRegs) {
      if (Reg.DwarfRegNo >= 0)
        addReg(Reg.DwarfRegNo, Reg.Comment);
      addOpPiece(Reg.Size);
    }
    DwarfRegs.clear();
    return true;
  }

  // Don't emit locations that cannot be expressed without DW_OP_stack_value.
  if (DwarfVersion < 4)
    if (std::any_of(ExprCursor.begin(), ExprCursor.end(),
                    [](DIExpression::ExprOperand Op) -> bool {
                      return Op.getOp() == dwarf::DW_OP_stack_value;
                    })) {
      DwarfRegs.clear();
      LocationKind = Unknown;
      return false;
    }

  assert(DwarfRegs.size() == 1);
  auto Reg = DwarfRegs[0];
  bool FBReg = isFrameRegister(TRI, MachineReg);
  int SignedOffset = 0;
  assert(Reg.Size == 0 && "subregister has same size as superregister");

  // Pattern-match combinations for which more efficient representations exist.
  // [Reg, DW_OP_plus_uconst, Offset] --> [DW_OP_breg, Offset].
  if (Op && (Op->getOp() == dwarf::DW_OP_plus_uconst)) {
    SignedOffset = Op->getArg(0);
    ExprCursor.take();
  }

  // [Reg, DW_OP_constu, Offset, DW_OP_plus]  --> [DW_OP_breg, Offset]
  // [Reg, DW_OP_constu, Offset, DW_OP_minus] --> [DW_OP_breg,-Offset]
  // If Reg is a subregister we need to mask it out before subtracting.
  if (Op && Op->getOp() == dwarf::DW_OP_constu) {
    auto N = ExprCursor.peekNext();
    if (N && (N->getOp() == dwarf::DW_OP_plus ||
             (N->getOp() == dwarf::DW_OP_minus && !SubRegisterSizeInBits))) {
      int Offset = Op->getArg(0);
      SignedOffset = (N->getOp() == dwarf::DW_OP_minus) ? -Offset : Offset;
      ExprCursor.consume(2);
    }
  }

  if (FBReg)
    addFBReg(SignedOffset);
  else
    addBReg(Reg.DwarfRegNo, SignedOffset);
  DwarfRegs.clear();
  return true;
}