Index: docs/LangRef.rst =================================================================== --- docs/LangRef.rst +++ docs/LangRef.rst @@ -4405,6 +4405,7 @@ - ``DW_OP_deref`` dereferences the top of the expression stack. - ``DW_OP_plus, 93`` adds ``93`` to the working expression. +- ``DW_OP_plus_uconst, 93`` adds ``93`` to the working expression. - ``DW_OP_LLVM_fragment, 16, 8`` specifies the offset and size (``16`` and ``8`` here, respectively) of the variable fragment from the working expression. Note that contrary to DW_OP_bit_piece, the offset is describing the the location @@ -4427,6 +4428,7 @@ !0 = !DIExpression(DW_OP_deref) !1 = !DIExpression(DW_OP_plus, 3) + !1 = !DIExpression(DW_OP_plus_uconst, 3) !2 = !DIExpression(DW_OP_bit_piece, 3, 7) !3 = !DIExpression(DW_OP_deref, DW_OP_plus, 3, DW_OP_LLVM_fragment, 3, 7) !4 = !DIExpression(DW_OP_constu, 2, DW_OP_swap, DW_OP_xderef) Index: lib/CodeGen/AsmPrinter/DwarfExpression.cpp =================================================================== --- lib/CodeGen/AsmPrinter/DwarfExpression.cpp +++ lib/CodeGen/AsmPrinter/DwarfExpression.cpp @@ -248,6 +248,12 @@ 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, Offset, DW_OP_plus] --> [DW_OP_breg, Offset]. // [Reg, Offset, DW_OP_minus] --> [DW_OP_breg, -Offset]. // If Reg is a subregister we need to mask it out before subtracting. @@ -321,6 +327,7 @@ return; } case dwarf::DW_OP_plus: + case dwarf::DW_OP_plus_uconst: assert(LocationKind != Register); emitOp(dwarf::DW_OP_plus_uconst); emitUnsigned(Op->getArg(0)); Index: lib/IR/DebugInfoMetadata.cpp =================================================================== --- lib/IR/DebugInfoMetadata.cpp +++ lib/IR/DebugInfoMetadata.cpp @@ -599,6 +599,7 @@ return 3; case dwarf::DW_OP_constu: case dwarf::DW_OP_plus: + case dwarf::DW_OP_plus_uconst: case dwarf::DW_OP_minus: return 2; default: @@ -641,6 +642,7 @@ break; } case dwarf::DW_OP_constu: + case dwarf::DW_OP_plus_uconst: case dwarf::DW_OP_plus: case dwarf::DW_OP_minus: case dwarf::DW_OP_deref: @@ -679,7 +681,8 @@ } if (getNumElements() != 2) return false; - if (Elements[0] == dwarf::DW_OP_plus) { + if (Elements[0] == dwarf::DW_OP_plus || + Elements[0] == dwarf::DW_OP_plus_uconst) { Offset = Elements[1]; return true; } Index: test/Assembler/diexpression.ll =================================================================== --- test/Assembler/diexpression.ll +++ test/Assembler/diexpression.ll @@ -1,8 +1,8 @@ ; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s ; RUN: verify-uselistorder %s -; CHECK: !named = !{!0, !1, !2, !3, !4, !5} -!named = !{!0, !1, !2, !3, !4, !5} +; CHECK: !named = !{!0, !1, !2, !3, !4, !5, !6} +!named = !{!0, !1, !2, !3, !4, !5, !6} ; CHECK: !0 = !DIExpression() ; CHECK-NEXT: !1 = !DIExpression(DW_OP_deref) @@ -10,9 +10,11 @@ ; CHECK-NEXT: !3 = !DIExpression(DW_OP_LLVM_fragment, 3, 7) ; CHECK-NEXT: !4 = !DIExpression(DW_OP_deref, DW_OP_plus, 3, DW_OP_LLVM_fragment, 3, 7) ; CHECK-NEXT: !5 = !DIExpression(DW_OP_constu, 2, DW_OP_swap, DW_OP_xderef) +; CHECK-NEXT: !6 = !DIExpression(DW_OP_plus_uconst, 3) !0 = !DIExpression() !1 = !DIExpression(DW_OP_deref) !2 = !DIExpression(DW_OP_plus, 3) !3 = !DIExpression(DW_OP_LLVM_fragment, 3, 7) !4 = !DIExpression(DW_OP_deref, DW_OP_plus, 3, DW_OP_LLVM_fragment, 3, 7) !5 = !DIExpression(DW_OP_constu, 2, DW_OP_swap, DW_OP_xderef) +!6 = !DIExpression(DW_OP_plus_uconst, 3) Index: unittests/IR/MetadataTest.cpp =================================================================== --- unittests/IR/MetadataTest.cpp +++ unittests/IR/MetadataTest.cpp @@ -2043,6 +2043,7 @@ // Valid constructions. EXPECT_VALID(dwarf::DW_OP_plus, 6); + EXPECT_VALID(dwarf::DW_OP_plus_uconst, 6); EXPECT_VALID(dwarf::DW_OP_deref); EXPECT_VALID(dwarf::DW_OP_LLVM_fragment, 3, 7); EXPECT_VALID(dwarf::DW_OP_plus, 6, dwarf::DW_OP_deref); @@ -2054,6 +2055,7 @@ // Invalid constructions. EXPECT_INVALID(~0u); EXPECT_INVALID(dwarf::DW_OP_plus); + EXPECT_INVALID(dwarf::DW_OP_plus_uconst); EXPECT_INVALID(dwarf::DW_OP_LLVM_fragment); EXPECT_INVALID(dwarf::DW_OP_LLVM_fragment, 3); EXPECT_INVALID(dwarf::DW_OP_LLVM_fragment, 3, 7, dwarf::DW_OP_plus, 3);