Index: llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h =================================================================== --- llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h +++ llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h @@ -107,8 +107,21 @@ /// Holds information about all subregisters comprising a register location. struct Register { int DwarfRegNo; - unsigned Size; + unsigned SubRegSize; const char *Comment; + + /// Create a full register, not extra DW_OP_piece operators necessary. + 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 createSubRegister(int RegNo, unsigned SizeInBits, + const char *Comment) { + return {RegNo, SizeInBits, Comment}; + } + + bool isSubRegister() const { return SubRegSize; } }; /// Whether we are currently emitting an entry value operation. Index: llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp =================================================================== --- llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp +++ llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp @@ -100,7 +100,7 @@ unsigned MachineReg, unsigned MaxSize) { if (!llvm::Register::isPhysicalRegister(MachineReg)) { if (isFrameRegister(TRI, MachineReg)) { - DwarfRegs.push_back({-1, 0, nullptr}); + DwarfRegs.push_back(Register::createRegister(-1, nullptr)); return true; } return false; @@ -110,7 +110,7 @@ // If this is a valid register number, emit it. if (Reg >= 0) { - DwarfRegs.push_back({Reg, 0, nullptr}); + DwarfRegs.push_back(Register::createRegister(Reg, nullptr)); return true; } @@ -122,7 +122,7 @@ unsigned Idx = TRI.getSubRegIndex(*SR, MachineReg); unsigned Size = TRI.getSubRegIdxSize(Idx); unsigned RegOffset = TRI.getSubRegIdxOffset(Idx); - DwarfRegs.push_back({Reg, 0, "super-register"}); + DwarfRegs.push_back(Register::createRegister(Reg, "super-register")); // Use a DW_OP_bit_piece to describe the sub-register. setSubRegisterPiece(Size, RegOffset); return true; @@ -159,10 +159,13 @@ if (Offset < MaxSize && CurSubReg.test(Coverage)) { // Emit a piece for any gap in the coverage. if (Offset > CurPos) - DwarfRegs.push_back( - {-1, Offset - CurPos, "no DWARF register encoding"}); - DwarfRegs.push_back( - {Reg, std::min(Size, MaxSize - Offset), "sub-register"}); + 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); @@ -173,7 +176,8 @@ return false; // Found a partial or complete DWARF encoding. if (CurPos < RegSize) - DwarfRegs.push_back({-1, RegSize - CurPos, "no DWARF register encoding"}); + DwarfRegs.push_back(Register::createSubRegister( + -1, RegSize - CurPos, "no DWARF register encoding")); return true; } @@ -249,7 +253,7 @@ for (auto &Reg : DwarfRegs) { if (Reg.DwarfRegNo >= 0) addReg(Reg.DwarfRegNo, Reg.Comment); - addOpPiece(Reg.Size); + addOpPiece(Reg.SubRegSize); } if (isEntryValue()) @@ -276,7 +280,7 @@ auto Reg = DwarfRegs[0]; bool FBReg = isFrameRegister(TRI, MachineReg); int SignedOffset = 0; - assert(Reg.Size == 0 && "subregister has same size as superregister"); + 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]. Index: llvm/test/DebugInfo/MIR/ARM/subregister-full-piece.mir =================================================================== --- /dev/null +++ llvm/test/DebugInfo/MIR/ARM/subregister-full-piece.mir @@ -0,0 +1,40 @@ +# RUN: llc -start-after=livedebugvalues -filetype=obj -o - %s | \ +# RUN: llvm-dwarfdump - | FileCheck %s +# +# This tests the edge-case where a complex fragment has exactly +# the size of a subregister of the register the DBG_VALUE points to. +# +# CHECK: .debug_info contents: +# CHECK: DW_TAG_variable +# CHECK-NOT: DW_TAG +# CHECK: DW_AT_location +# Q8 = {D16, D17} +# CHECK-NEXT: DW_OP_bregx D16+208, DW_OP_piece 0x8) +# CHECK-NOT: DW_TAG +# CHECK: DW_AT_name ("p1") + +# CHECK-NOT: DW_AT_location +# CHECK: DW_TAG +--- | + target triple = "thumbv7s-apple-ios" + define hidden void @f() !dbg !118 { + for.body: + ret void, !dbg !260 + } + !llvm.module.flags = !{!1, !2} + !llvm.dbg.cu = !{!6} + !1 = !{i32 7, !"Dwarf Version", i32 4} + !2 = !{i32 2, !"Debug Info Version", i32 3} + !6 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !50, isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug) + !50 = !DIFile(filename: "t.cpp", directory: "/") + !118 = distinct !DISubprogram(name: "f",scope: !50, file: !50, line: 1, type: !120, scopeLine: 1, unit: !6) + !120 = !DISubroutineType(types: !{}) + !134 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "uint8x8x2_t", file: !50, line: 113, size: 128, flags: DIFlagTypePassByValue, elements: !{}) + !139 = !DILocalVariable(name: "p1", scope: !118, file: !50, line: 1, type: !134) + !260 = !DILocation(line: 0, scope: !118) +name: f +body: | + bb.2.for.body: + t2Bcc %bb.2.for.body, 0, killed $cpsr, debug-location !260 + DBG_VALUE $q8, 0, !139, !DIExpression(DW_OP_plus_uconst, 208, DW_OP_LLVM_fragment, 0, 64), debug-location !260 + tB %bb.2.for.body, 14, $noreg