Skip to content

Commit c9c403c

Browse files
committedJun 13, 2017
Align definition of DW_OP_plus with DWARF spec [1/3]
Summary: This patch is part of 3 patches that together form a single patch, but must be introduced in stages in order not to break things. The way that LLVM interprets DW_OP_plus in DIExpression nodes is basically that of the DW_OP_plus_uconst operator since LLVM expects an unsigned constant operand. This unnecessarily restricts the DW_OP_plus operator, preventing it from being used to describe the evaluation of runtime values on the expression stack. These patches try to align the semantics of DW_OP_plus and DW_OP_minus with that of the DWARF definition, which pops two elements off the expression stack, performs the operation and pushes the result back on the stack. This is done in three stages: • The first patch (LLVM) adds support for DW_OP_plus_uconst. • The second patch (Clang) contains changes all its uses from DW_OP_plus to DW_OP_plus_uconst. • The third patch (LLVM) changes the semantics of DW_OP_plus and DW_OP_minus to be in line with its DWARF meaning. This patch includes the bitcode upgrade from legacy DIExpressions. Patch by Sander de Smalen. Reviewers: pcc, echristo, aprantl Reviewed By: aprantl Subscribers: fhahn, aprantl, javed.absar, llvm-commits Differential Revision: https://reviews.llvm.org/D33892 llvm-svn: 305304
1 parent 4c73b40 commit c9c403c

File tree

5 files changed

+19
-3
lines changed

5 files changed

+19
-3
lines changed
 

‎llvm/docs/LangRef.rst

+2
Original file line numberDiff line numberDiff line change
@@ -4405,6 +4405,7 @@ The current supported vocabulary is limited:
44054405

44064406
- ``DW_OP_deref`` dereferences the top of the expression stack.
44074407
- ``DW_OP_plus, 93`` adds ``93`` to the working expression.
4408+
- ``DW_OP_plus_uconst, 93`` adds ``93`` to the working expression.
44084409
- ``DW_OP_LLVM_fragment, 16, 8`` specifies the offset and size (``16`` and ``8``
44094410
here, respectively) of the variable fragment from the working expression. Note
44104411
that contrary to DW_OP_bit_piece, the offset is describing the the location
@@ -4427,6 +4428,7 @@ combined with a concrete location.
44274428
44284429
!0 = !DIExpression(DW_OP_deref)
44294430
!1 = !DIExpression(DW_OP_plus, 3)
4431+
!1 = !DIExpression(DW_OP_plus_uconst, 3)
44304432
!2 = !DIExpression(DW_OP_bit_piece, 3, 7)
44314433
!3 = !DIExpression(DW_OP_deref, DW_OP_plus, 3, DW_OP_LLVM_fragment, 3, 7)
44324434
!4 = !DIExpression(DW_OP_constu, 2, DW_OP_swap, DW_OP_xderef)

‎llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,12 @@ bool DwarfExpression::addMachineRegExpression(const TargetRegisterInfo &TRI,
248248
assert(Reg.Size == 0 && "subregister has same size as superregister");
249249

250250
// Pattern-match combinations for which more efficient representations exist.
251+
// [Reg, DW_OP_plus_uconst, Offset] --> [DW_OP_breg, Offset].
252+
if (Op && (Op->getOp() == dwarf::DW_OP_plus_uconst)) {
253+
SignedOffset = Op->getArg(0);
254+
ExprCursor.take();
255+
}
256+
251257
// [Reg, Offset, DW_OP_plus] --> [DW_OP_breg, Offset].
252258
// [Reg, Offset, DW_OP_minus] --> [DW_OP_breg, -Offset].
253259
// If Reg is a subregister we need to mask it out before subtracting.
@@ -321,6 +327,7 @@ void DwarfExpression::addExpression(DIExpressionCursor &&ExprCursor,
321327
return;
322328
}
323329
case dwarf::DW_OP_plus:
330+
case dwarf::DW_OP_plus_uconst:
324331
assert(LocationKind != Register);
325332
emitOp(dwarf::DW_OP_plus_uconst);
326333
emitUnsigned(Op->getArg(0));

‎llvm/lib/IR/DebugInfoMetadata.cpp

+4-1
Original file line numberDiff line numberDiff line change
@@ -599,6 +599,7 @@ unsigned DIExpression::ExprOperand::getSize() const {
599599
return 3;
600600
case dwarf::DW_OP_constu:
601601
case dwarf::DW_OP_plus:
602+
case dwarf::DW_OP_plus_uconst:
602603
case dwarf::DW_OP_minus:
603604
return 2;
604605
default:
@@ -641,6 +642,7 @@ bool DIExpression::isValid() const {
641642
break;
642643
}
643644
case dwarf::DW_OP_constu:
645+
case dwarf::DW_OP_plus_uconst:
644646
case dwarf::DW_OP_plus:
645647
case dwarf::DW_OP_minus:
646648
case dwarf::DW_OP_deref:
@@ -679,7 +681,8 @@ bool DIExpression::extractIfOffset(int64_t &Offset) const {
679681
}
680682
if (getNumElements() != 2)
681683
return false;
682-
if (Elements[0] == dwarf::DW_OP_plus) {
684+
if (Elements[0] == dwarf::DW_OP_plus ||
685+
Elements[0] == dwarf::DW_OP_plus_uconst) {
683686
Offset = Elements[1];
684687
return true;
685688
}

‎llvm/test/Assembler/diexpression.ll

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,20 @@
11
; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s
22
; RUN: verify-uselistorder %s
33

4-
; CHECK: !named = !{!0, !1, !2, !3, !4, !5}
5-
!named = !{!0, !1, !2, !3, !4, !5}
4+
; CHECK: !named = !{!0, !1, !2, !3, !4, !5, !6}
5+
!named = !{!0, !1, !2, !3, !4, !5, !6}
66

77
; CHECK: !0 = !DIExpression()
88
; CHECK-NEXT: !1 = !DIExpression(DW_OP_deref)
99
; CHECK-NEXT: !2 = !DIExpression(DW_OP_plus, 3)
1010
; CHECK-NEXT: !3 = !DIExpression(DW_OP_LLVM_fragment, 3, 7)
1111
; CHECK-NEXT: !4 = !DIExpression(DW_OP_deref, DW_OP_plus, 3, DW_OP_LLVM_fragment, 3, 7)
1212
; CHECK-NEXT: !5 = !DIExpression(DW_OP_constu, 2, DW_OP_swap, DW_OP_xderef)
13+
; CHECK-NEXT: !6 = !DIExpression(DW_OP_plus_uconst, 3)
1314
!0 = !DIExpression()
1415
!1 = !DIExpression(DW_OP_deref)
1516
!2 = !DIExpression(DW_OP_plus, 3)
1617
!3 = !DIExpression(DW_OP_LLVM_fragment, 3, 7)
1718
!4 = !DIExpression(DW_OP_deref, DW_OP_plus, 3, DW_OP_LLVM_fragment, 3, 7)
1819
!5 = !DIExpression(DW_OP_constu, 2, DW_OP_swap, DW_OP_xderef)
20+
!6 = !DIExpression(DW_OP_plus_uconst, 3)

‎llvm/unittests/IR/MetadataTest.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -2043,6 +2043,7 @@ TEST_F(DIExpressionTest, isValid) {
20432043

20442044
// Valid constructions.
20452045
EXPECT_VALID(dwarf::DW_OP_plus, 6);
2046+
EXPECT_VALID(dwarf::DW_OP_plus_uconst, 6);
20462047
EXPECT_VALID(dwarf::DW_OP_deref);
20472048
EXPECT_VALID(dwarf::DW_OP_LLVM_fragment, 3, 7);
20482049
EXPECT_VALID(dwarf::DW_OP_plus, 6, dwarf::DW_OP_deref);
@@ -2054,6 +2055,7 @@ TEST_F(DIExpressionTest, isValid) {
20542055
// Invalid constructions.
20552056
EXPECT_INVALID(~0u);
20562057
EXPECT_INVALID(dwarf::DW_OP_plus);
2058+
EXPECT_INVALID(dwarf::DW_OP_plus_uconst);
20572059
EXPECT_INVALID(dwarf::DW_OP_LLVM_fragment);
20582060
EXPECT_INVALID(dwarf::DW_OP_LLVM_fragment, 3);
20592061
EXPECT_INVALID(dwarf::DW_OP_LLVM_fragment, 3, 7, dwarf::DW_OP_plus, 3);

0 commit comments

Comments
 (0)
Please sign in to comment.