]> granicus.if.org Git - llvm/commitdiff
Align definition of DW_OP_plus with DWARF spec [1/3]
authorFlorian Hahn <florian.hahn@arm.com>
Tue, 13 Jun 2017 16:54:44 +0000 (16:54 +0000)
committerFlorian Hahn <florian.hahn@arm.com>
Tue, 13 Jun 2017 16:54:44 +0000 (16:54 +0000)
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

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@305304 91177308-0d34-0410-b5e6-96231b3b80d8

docs/LangRef.rst
lib/CodeGen/AsmPrinter/DwarfExpression.cpp
lib/IR/DebugInfoMetadata.cpp
test/Assembler/diexpression.ll
unittests/IR/MetadataTest.cpp

index 794f896806e7e695f37838b2b186497ef474514a..24362825d8220ef7385ec5dbff9107d5c09727d4 100644 (file)
@@ -4405,6 +4405,7 @@ The current supported vocabulary is limited:
 
 - ``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 @@ combined with a concrete location.
 
     !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 d96479f434333ad39b7ec7cc4ed1a00fb46bb530..73ce58e3ca52505be73c3d1ac15bf7a69fbd5aec 100644 (file)
@@ -248,6 +248,12 @@ bool DwarfExpression::addMachineRegExpression(const TargetRegisterInfo &TRI,
   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 @@ void DwarfExpression::addExpression(DIExpressionCursor &&ExprCursor,
       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 e6c49cad0722fb0ff206aa00039df30d0e1289cc..a34f8d9eac1c635ff2b00c75ca37d834883170c3 100644 (file)
@@ -599,6 +599,7 @@ unsigned DIExpression::ExprOperand::getSize() const {
     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 @@ bool DIExpression::isValid() const {
       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 @@ bool DIExpression::extractIfOffset(int64_t &Offset) const {
   }
   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 c2fa3ee14c23482cee863b6c3479b8e6054cbff4..7d2d45b8bd0fb6242c76caca90430a8145845d44 100644 (file)
@@ -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)
 ; 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 bcf3babf7f688e6769c86273958d97715ce5371d..a09a4239ec46e533984d95a339f7fb1602f77895 100644 (file)
@@ -2043,6 +2043,7 @@ TEST_F(DIExpressionTest, isValid) {
 
   // 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 @@ TEST_F(DIExpressionTest, isValid) {
   // 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);