[llvm] [NFC] Allow fragment expressions in extractIfOffset (PR #69006)

via llvm-commits llvm-commits at lists.llvm.org
Fri Oct 13 09:03:47 PDT 2023


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-debuginfo

Author: Orlando Cazalet-Hyams (OCHyams)

<details>
<summary>Changes</summary>

A fragment is part of the variable identity and should be ignored for the purposes of checking whether the expression contains an offset.

This NFC patch is required for a subsequent change that addresses #<!-- -->61981.

---
Full diff: https://github.com/llvm/llvm-project/pull/69006.diff


2 Files Affected:

- (modified) llvm/lib/IR/DebugInfoMetadata.cpp (+6-3) 
- (modified) llvm/unittests/IR/MetadataTest.cpp (+51) 


``````````diff
diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp
index f7f36129ec8557c..2ab41e55db1caef 100644
--- a/llvm/lib/IR/DebugInfoMetadata.cpp
+++ b/llvm/lib/IR/DebugInfoMetadata.cpp
@@ -1673,18 +1673,21 @@ bool DIExpression::extractIfOffset(int64_t &Offset) const {
     return false;
   auto SingleLocElts = *SingleLocEltsOpt;
 
-  if (SingleLocElts.size() == 0) {
+  unsigned FragmentOpsCount = isFragment() ? 3 : 0;
+
+  if (SingleLocElts.size() == FragmentOpsCount) {
     Offset = 0;
     return true;
   }
 
-  if (SingleLocElts.size() == 2 &&
+  if (SingleLocElts.size() == 2 + FragmentOpsCount &&
       SingleLocElts[0] == dwarf::DW_OP_plus_uconst) {
     Offset = SingleLocElts[1];
     return true;
   }
 
-  if (SingleLocElts.size() == 3 && SingleLocElts[0] == dwarf::DW_OP_constu) {
+  if (SingleLocElts.size() == 3 + FragmentOpsCount &&
+      SingleLocElts[0] == dwarf::DW_OP_constu) {
     if (SingleLocElts[2] == dwarf::DW_OP_plus) {
       Offset = SingleLocElts[1];
       return true;
diff --git a/llvm/unittests/IR/MetadataTest.cpp b/llvm/unittests/IR/MetadataTest.cpp
index 1570631287b2a78..e68d27b36054767 100644
--- a/llvm/unittests/IR/MetadataTest.cpp
+++ b/llvm/unittests/IR/MetadataTest.cpp
@@ -3511,6 +3511,57 @@ TEST_F(DIExpressionTest, isEqualExpression) {
 #undef GET_EXPR
 }
 
+TEST_F(DIExpressionTest, extractIfOffset) {
+#define GET_EXPR(...) DIExpression::get(Context, {__VA_ARGS__})
+#define GET_FRAG(...)                                                          \
+  DIExpression::get(Context, {__VA_ARGS__, dwarf::DW_OP_LLVM_fragment, 0, 32})
+#define EXPECT_OFFSET_IMPL(Offset, Success, Expr)                              \
+  do {                                                                         \
+    int64_t ActualOffset;                                                      \
+    bool Result = Expr->extractIfOffset(ActualOffset);                         \
+    EXPECT_EQ(Success, Result);                                                \
+    if (Success) {                                                             \
+      EXPECT_EQ(Offset, ActualOffset);                                         \
+    }                                                                          \
+  } while (0)
+#define EXPECT_OFFSET_EQ(Offset, Expr) EXPECT_OFFSET_IMPL(Offset, true, Expr)
+#define EXPECT_NO_OFFSET(Expr) EXPECT_OFFSET_IMPL(0, false, Expr)
+
+  // Check extractIfOffset behaves as expected with and without a fragment
+  // in the expression. extractIfOffset reads a constant offset out from the
+  // expression. It fails for all but exactly these with and without fragments:
+  //   no expression
+  //   DW_OP_plus_uconst, <u>
+  //   DW_OP_constu, <u>, DW_OP_plus/minus
+  EXPECT_OFFSET_EQ(0, GET_EXPR());
+  EXPECT_OFFSET_EQ(0, GET_EXPR(dwarf::DW_OP_LLVM_fragment, 0, 32));
+
+  EXPECT_OFFSET_EQ(1, GET_EXPR(dwarf::DW_OP_plus_uconst, 1));
+  EXPECT_OFFSET_EQ(1, GET_FRAG(dwarf::DW_OP_plus_uconst, 1));
+
+  EXPECT_OFFSET_EQ(2, GET_EXPR(dwarf::DW_OP_constu, 2, dwarf::DW_OP_plus));
+  EXPECT_OFFSET_EQ(2, GET_FRAG(dwarf::DW_OP_constu, 2, dwarf::DW_OP_plus));
+
+  EXPECT_OFFSET_EQ(-3, GET_EXPR(dwarf::DW_OP_constu, 3, dwarf::DW_OP_minus));
+  EXPECT_OFFSET_EQ(-3, GET_FRAG(dwarf::DW_OP_constu, 3, dwarf::DW_OP_minus));
+
+  // Test some failure cases, e.g. unsupported operations and too many
+  // operations.
+  EXPECT_NO_OFFSET(GET_EXPR(dwarf::DW_OP_constu, 3, dwarf::DW_OP_mul));
+  EXPECT_NO_OFFSET(GET_FRAG(dwarf::DW_OP_constu, 3, dwarf::DW_OP_mul));
+
+  EXPECT_NO_OFFSET(
+      GET_EXPR(dwarf::DW_OP_constu, 3, dwarf::DW_OP_plus, dwarf::DW_OP_deref));
+  EXPECT_NO_OFFSET(
+      GET_FRAG(dwarf::DW_OP_constu, 3, dwarf::DW_OP_plus, dwarf::DW_OP_deref));
+
+#undef EXPECT_NO_OFFSET
+#undef EXPECT_OFFSET_EQ
+#undef EXPECT_OFFSET_IMPL
+#undef GET_FRAG
+#undef GET_EXPR
+}
+
 TEST_F(DIExpressionTest, foldConstant) {
   const ConstantInt *Int;
   const ConstantInt *NewInt;

``````````

</details>


https://github.com/llvm/llvm-project/pull/69006


More information about the llvm-commits mailing list