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; }
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; }