Index: llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h =================================================================== --- llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h +++ llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h @@ -107,29 +107,21 @@ /// Holds information about all subregisters comprising a register location. struct Register { int DwarfRegNo; - uint16_t SubRegisterSizeInBits; - uint16_t SubRegisterOffsetInBits; - enum : char { Full, SuperReg, SubReg } Kind; + unsigned SubRegSize; + const char *Comment; /// Create a full register, no extra DW_OP_piece operators necessary. - static Register create(int RegNo) { - return {RegNo, 0, 0, Full}; - } - - /// Stencil a subregister out of a superregister. - static Register createSuperReg(int RegNo, uint16_t SizeInBits, - uint16_t OffsetInBits) { - return {RegNo, SizeInBits, OffsetInBits, SuperReg}; + static Register createRegister(int RegNo, const char *Comment) { + return {RegNo, 0, Comment}; } /// Create a subregister that needs a DW_OP_piece operator with SizeInBits. - static Register createSubReg(int RegNo, uint16_t SizeInBits, - uint16_t OffsetInBits) { - return {RegNo, SizeInBits, OffsetInBits, SubReg}; + static Register createSubRegister(int RegNo, unsigned SizeInBits, + const char *Comment) { + return {RegNo, SizeInBits, Comment}; } - /// Return the assembler comment for this register. - const char *getComment() const; + bool isSubRegister() const { return SubRegSize; } }; /// Whether we are currently emitting an entry value operation. @@ -144,8 +136,8 @@ uint64_t OffsetInBits = 0; /// Sometimes we need to add a DW_OP_bit_piece to describe a subregister. - uint16_t SubRegisterSizeInBits = 0; - uint16_t SubRegisterOffsetInBits = 0; + unsigned SubRegisterSizeInBits : 16; + unsigned SubRegisterOffsetInBits : 16; /// The kind of location description being produced. enum { Unknown = 0, Register, Memory, Implicit }; @@ -174,12 +166,16 @@ protected: /// Push a DW_OP_piece / DW_OP_bit_piece for emitting later, if one is needed - /// to represent a register as a piece of a superregister. - void setSuperRegisterPiece(uint16_t SizeInBits, uint16_t OffsetInBits) { + /// to represent a subregister. + void setSubRegisterPiece(unsigned SizeInBits, unsigned OffsetInBits) { + assert(SizeInBits < 65536 && OffsetInBits < 65536); SubRegisterSizeInBits = SizeInBits; SubRegisterOffsetInBits = OffsetInBits; } + /// Add masking operations to stencil out a subregister. + void maskSubRegister(); + /// Output a dwarf operand and an optional assembler comment. virtual void emitOp(uint8_t Op, const char *Comment = nullptr) = 0; @@ -222,7 +218,7 @@ void addReg(int DwarfReg, const char *Comment = nullptr); /// Emit a DW_OP_breg operation. - void addBReg(int DwarfReg, int Offset, const char *Comment = nullptr); + void addBReg(int DwarfReg, int Offset); /// Emit DW_OP_fbreg . void addFBReg(int Offset); @@ -230,6 +226,10 @@ /// Emit a partial DWARF register operation. /// /// \param MachineReg The register number. + /// \param MaxSize If the register must be composed from + /// sub-registers this is an upper bound + /// for how many bits the emitted DW_OP_piece + /// may cover. /// /// If size and offset is zero an operation for the entire register is /// emitted: Some targets do not provide a DWARF register number for every @@ -238,7 +238,8 @@ /// multiple subregisters that alias the register. /// /// \return false if no DWARF register exists for MachineReg. - bool addMachineReg(const TargetRegisterInfo &TRI, unsigned MachineReg); + bool addMachineReg(const TargetRegisterInfo &TRI, unsigned MachineReg, + unsigned MaxSize = ~1U); /// Emit a DW_OP_piece or DW_OP_bit_piece operation for a variable fragment. /// \param OffsetInBits This is an optional offset into the location that @@ -272,7 +273,8 @@ public: DwarfExpression(unsigned DwarfVersion, DwarfCompileUnit &CU) - : CU(CU), LocationKind(Unknown), LocationFlags(Unknown), + : CU(CU), SubRegisterSizeInBits(0), SubRegisterOffsetInBits(0), + LocationKind(Unknown), LocationFlags(Unknown), DwarfVersion(DwarfVersion) {} /// This needs to be called last to commit any pending changes. Index: llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp =================================================================== --- llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp +++ llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp @@ -13,7 +13,6 @@ #include "DwarfExpression.h" #include "DwarfCompileUnit.h" #include "llvm/ADT/APInt.h" -#include "llvm/ADT/ScopeExit.h" #include "llvm/ADT/SmallBitVector.h" #include "llvm/BinaryFormat/Dwarf.h" #include "llvm/CodeGen/Register.h" @@ -53,13 +52,13 @@ } } -void DwarfExpression::addBReg(int DwarfReg, int Offset, const char *Comment) { +void DwarfExpression::addBReg(int DwarfReg, int Offset) { assert(DwarfReg >= 0 && "invalid negative dwarf register number"); assert(!isRegisterLocation() && "location description already locked down"); if (DwarfReg < 32) { emitOp(dwarf::DW_OP_breg0 + DwarfReg); } else { - emitOp(dwarf::DW_OP_bregx, Comment); + emitOp(dwarf::DW_OP_bregx); emitUnsigned(DwarfReg); } emitSigned(Offset); @@ -98,10 +97,10 @@ } bool DwarfExpression::addMachineReg(const TargetRegisterInfo &TRI, - unsigned MachineReg) { + unsigned MachineReg, unsigned MaxSize) { if (!llvm::Register::isPhysicalRegister(MachineReg)) { if (isFrameRegister(TRI, MachineReg)) { - DwarfRegs.push_back(Register::create(-1)); + DwarfRegs.push_back(Register::createRegister(-1, nullptr)); return true; } return false; @@ -111,7 +110,7 @@ // If this is a valid register number, emit it. if (Reg >= 0) { - DwarfRegs.push_back(Register::create(Reg)); + DwarfRegs.push_back(Register::createRegister(Reg, nullptr)); return true; } @@ -123,9 +122,9 @@ unsigned Idx = TRI.getSubRegIndex(*SR, MachineReg); unsigned Size = TRI.getSubRegIdxSize(Idx); unsigned RegOffset = TRI.getSubRegIdxOffset(Idx); + DwarfRegs.push_back(Register::createRegister(Reg, "super-register")); // Use a DW_OP_bit_piece to describe the sub-register. - DwarfRegs.push_back(Register::createSuperReg(Reg, Size, RegOffset)); - setSuperRegisterPiece(Size, RegOffset); + setSubRegisterPiece(Size, RegOffset); return true; } } @@ -157,11 +156,16 @@ // If this sub-register has a DWARF number and we haven't covered // its range, and its range covers the value, emit a DWARF piece for it. - if (CurSubReg.test(Coverage)) { - // Give up if there is a gap in the coverage. + if (Offset < MaxSize && CurSubReg.test(Coverage)) { + // Emit a piece for any gap in the coverage. if (Offset > CurPos) - return false; - DwarfRegs.push_back(Register::createSubReg(Reg, Size, Offset)); + DwarfRegs.push_back(Register::createSubRegister( + -1, Offset - CurPos, "no DWARF register encoding")); + if (Offset == 0 && Size >= MaxSize) + DwarfRegs.push_back(Register::createRegister(Reg, "sub-register")); + else + DwarfRegs.push_back(Register::createSubRegister( + Reg, std::min(Size, MaxSize - Offset), "sub-register")); } // Mark it as emitted. Coverage.set(Offset, Offset + Size); @@ -172,18 +176,11 @@ return false; // Found a partial or complete DWARF encoding. if (CurPos < RegSize) - return false; + DwarfRegs.push_back(Register::createSubRegister( + -1, RegSize - CurPos, "no DWARF register encoding")); return true; } -const char *DwarfExpression::Register::getComment() const { - switch(Kind) { - case Register::Full: return nullptr; - case Register::SuperReg: return "super-register"; - case Register::SubReg: return "sub-register"; - } -} - void DwarfExpression::addStackValue() { if (DwarfVersion >= 4) emitOp(dwarf::DW_OP_stack_value); @@ -226,9 +223,8 @@ DIExpressionCursor &ExprCursor, unsigned MachineReg, unsigned FragmentOffsetInBits) { - auto ClearDwarfRegs = make_scope_exit([this] { DwarfRegs.clear(); }); - - if (!addMachineReg(TRI, MachineReg)) { + auto Fragment = ExprCursor.getFragmentInfo(); + if (!addMachineReg(TRI, MachineReg, Fragment ? Fragment->SizeInBits : ~1U)) { LocationKind = Unknown; return false; } @@ -238,13 +234,15 @@ if (Op && Op->getOp() != dwarf::DW_OP_LLVM_fragment) HasComplexExpression = true; - // If the register itself can only be described by combining - // multiple subregisters, we cannot use DW_OP_piece, since it - // doesn't safely compose with another complex expression, Since it - // is not possible to apply any DWARF operation to the combined - // DW_OP_pieces. - if (HasComplexExpression && DwarfRegs.size() > 1) + // 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 we are supposed to emit // a call site parameter expression and if that expression is just a register @@ -252,42 +250,19 @@ // expression representing a value, rather than a location. if (!isMemoryLocation() && !HasComplexExpression && (!isParameterValue() || isEntryValue())) { - unsigned BitsEmitted = 0; - auto Fragment = ExprCursor.getFragmentInfo(); - unsigned FragmentBits = - Fragment ? Fragment->SizeInBits : std::numeric_limits::max(); for (auto &Reg : DwarfRegs) { - switch (Reg.Kind) { - case Register::Full: - case Register::SuperReg: - if (Reg.DwarfRegNo >= 0) - addReg(Reg.DwarfRegNo, Reg.getComment()); - break; - case Register::SubReg: { - // If the last subregister(s) extend beyond the size of the - // fragment, truncate the DW_OP_piece accordingly. This is safe - // because we have a simple expression. - unsigned SubRegBits = Reg.SubRegisterSizeInBits; - if (BitsEmitted + SubRegBits > FragmentBits) - SubRegBits -= (BitsEmitted + SubRegBits) - FragmentBits; - BitsEmitted += SubRegBits; - if (SubRegBits == 0) - break; - if (Reg.DwarfRegNo >= 0) - addReg(Reg.DwarfRegNo, Reg.getComment()); - if (SubRegBits < FragmentBits) - addOpPiece(SubRegBits); - break; - } - } + if (Reg.DwarfRegNo >= 0) + addReg(Reg.DwarfRegNo, Reg.Comment); + addOpPiece(Reg.SubRegSize); } - + if (isEntryValue()) finalizeEntryValue(); if (isEntryValue() && !isParameterValue() && DwarfVersion >= 4) emitOp(dwarf::DW_OP_stack_value); + DwarfRegs.clear(); return true; } @@ -296,21 +271,16 @@ if (any_of(ExprCursor, [](DIExpression::ExprOperand Op) -> bool { return Op.getOp() == dwarf::DW_OP_stack_value; })) { + DwarfRegs.clear(); LocationKind = Unknown; return false; } - if (DwarfRegs.size() != 1) { - // While this could happen legitimately, it is more likely to - // indicate a bug. - assert(isMemoryLocation() && "pointer spawns multiple registers"); - return false; - } - - auto Reg = DwarfRegs.front(); + assert(DwarfRegs.size() == 1); + auto Reg = DwarfRegs[0]; bool FBReg = isFrameRegister(TRI, MachineReg); int SignedOffset = 0; - assert(Reg.Kind != Register::SubReg && "full register expected"); + assert(!Reg.isSubRegister() && "full register expected"); // Pattern-match combinations for which more efficient representations exist. // [Reg, DW_OP_plus_uconst, Offset] --> [DW_OP_breg, Offset]. @@ -334,7 +304,7 @@ SignedOffset = Offset; ExprCursor.consume(2); } else if (N && N->getOp() == dwarf::DW_OP_minus && - !Reg.SubRegisterSizeInBits && Offset <= IntMax + 1) { + !SubRegisterSizeInBits && Offset <= IntMax + 1) { SignedOffset = -static_cast(Offset); ExprCursor.consume(2); } @@ -344,6 +314,7 @@ addFBReg(SignedOffset); else addBReg(Reg.DwarfRegNo, SignedOffset); + DwarfRegs.clear(); return true; } @@ -410,16 +381,11 @@ void DwarfExpression::addExpression(DIExpressionCursor &&ExprCursor, unsigned FragmentOffsetInBits) { - auto N = ExprCursor.peek(); - // If we need to mask out a subregister, do it now, unless the next // operation would emit an OpPiece anyway. - if (SubRegisterSizeInBits && N && (N->getOp() != dwarf::DW_OP_LLVM_fragment)) { - if (SubRegisterOffsetInBits > 0) - addShr(SubRegisterOffsetInBits); - uint64_t Mask = (1ULL << (uint64_t)SubRegisterSizeInBits) - 1ULL; - addAnd(Mask); - } + auto N = ExprCursor.peek(); + if (SubRegisterSizeInBits && N && (N->getOp() != dwarf::DW_OP_LLVM_fragment)) + maskSubRegister(); Optional PrevConvertOp = None; @@ -461,7 +427,7 @@ // Emit the DW_OP_piece. addOpPiece(SizeInBits, SubRegisterOffsetInBits); - setSuperRegisterPiece(0, 0); + setSubRegisterPiece(0, 0); // Reset the location description kind. LocationKind = Unknown; return; @@ -562,6 +528,15 @@ addStackValue(); } +/// add masking operations to stencil out a subregister. +void DwarfExpression::maskSubRegister() { + assert(SubRegisterSizeInBits && "no subregister was registered"); + if (SubRegisterOffsetInBits > 0) + addShr(SubRegisterOffsetInBits); + uint64_t Mask = (1ULL << (uint64_t)SubRegisterSizeInBits) - 1ULL; + addAnd(Mask); +} + void DwarfExpression::finalize() { assert(DwarfRegs.size() == 0 && "dwarf registers not emitted"); // Emit any outstanding DW_OP_piece operations to mask out subregisters.