https://github.com/adams381 updated 
https://github.com/llvm/llvm-project/pull/201705

>From 9a7050baeebd30b6032e9d0be90907a54701534c Mon Sep 17 00:00:00 2001
From: Adam Smith <[email protected]>
Date: Thu, 4 Jun 2026 15:05:37 -0700
Subject: [PATCH 1/2] [CIR] Handle scalar-type element GEP in GlobalView offset
 computation

computeGlobalViewIndicesFromFlatOffset navigated into array and record
types to convert a flat byte offset into structured GEP indices, but
fell through to llvm_unreachable("unexpected type") when the pointee
type was scalar (e.g. !s8i for const char *).

This occurs when a constexpr struct is initialized with a pointer field
whose value is a global-string-literal address plus a non-zero byte
offset.  Classic CodeGen emits getelementptr i8, ptr @str, i64 N for
this case; CIR represents the same thing as a GlobalViewAttr with
index [N].  getAddrOfConstantStringFromLiteral creates the
GlobalViewAttr with ptr-to-char as the pointee type (not ptr-to-array),
so applyOffset passes a char type to the offset navigator rather than
an array type.

Fix: treat any non-array, non-record pointee type as a scalar element
and compute offset / sizeof(element) as the GEP index, mirroring the
array-element logic.  Apply the same fix to the inverse function
computeOffsetFromGlobalViewIndices.
---
 clang/lib/CIR/CodeGen/CIRGenBuilder.cpp       | 21 +++++++++++-----
 .../test/CIR/CodeGen/constexpr-ptr-offset.cpp | 24 +++++++++++++++++++
 2 files changed, 39 insertions(+), 6 deletions(-)
 create mode 100644 clang/test/CIR/CodeGen/constexpr-ptr-offset.cpp

diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.cpp 
b/clang/lib/CIR/CodeGen/CIRGenBuilder.cpp
index c48afa0c7c793..0004bdf35ead5 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuilder.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.cpp
@@ -148,11 +148,19 @@ void 
CIRGenBuilderTy::computeGlobalViewIndicesFromFlatOffset(
             }
             llvm_unreachable("offset was not found within the record");
           })
-          .Default([](mlir::Type otherTy) {
-            llvm_unreachable("unexpected type");
-            return otherTy; // Even though this is unreachable, we need to
-                            // return a type to satisfy the return type of the
-                            // lambda.
+          .Default([&](mlir::Type otherTy) -> mlir::Type {
+            // Scalar or pointer type: the offset is a flat element count.
+            // This covers pointer arithmetic through a plain scalar base, e.g.
+            // a char* GlobalViewAttr whose pointee is !s8i rather than an
+            // array — the generated GEP is getelementptr i8, ptr @sym, i64 N.
+            int64_t eltSize =
+                (int64_t)layout.getTypeAllocSize(otherTy).getFixedValue();
+            assert(eltSize > 0 && "element size must be positive");
+            const auto [index, newOffset] =
+                getIndexAndNewOffset(offset, eltSize);
+            indices.push_back(index);
+            offset = newOffset;
+            return otherTy;
           });
 
   assert(subType);
@@ -175,7 +183,8 @@ uint64_t 
CIRGenBuilderTy::computeOffsetFromGlobalViewIndices(
       ty = arrayTy.getElementType();
       offset += layout.getTypeAllocSize(ty) * idx;
     } else {
-      llvm_unreachable("unexpected type");
+      // Scalar or pointer type: the index is a flat element count.
+      offset += (int64_t)layout.getTypeAllocSize(ty).getFixedValue() * idx;
     }
   }
   return offset;
diff --git a/clang/test/CIR/CodeGen/constexpr-ptr-offset.cpp 
b/clang/test/CIR/CodeGen/constexpr-ptr-offset.cpp
new file mode 100644
index 0000000000000..cbe5fc8467293
--- /dev/null
+++ b/clang/test/CIR/CodeGen/constexpr-ptr-offset.cpp
@@ -0,0 +1,24 @@
+// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu -fclangir 
-emit-cir %s -o %t.cir
+// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s
+// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu -fclangir 
-emit-llvm %s -o %t-cir.ll
+// RUN: FileCheck --check-prefix=LLVM --input-file=%t-cir.ll %s
+// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu -emit-llvm %s 
-o %t.ll
+// RUN: FileCheck --check-prefix=LLVM --input-file=%t.ll %s
+
+struct View {
+  const char *ptr;
+  int len;
+  constexpr View(const char *p, int n) : ptr(p), len(n) {}
+};
+
+constexpr const char *global_str = "hello";
+
+void test() {
+  constexpr View v(global_str + 2, 3);
+  (void)v;
+}
+
+// CIR-LABEL: @_Z4testv
+// CIR: #cir.global_view<@{{.*}}str{{.*}}, [2 : i32]> : !cir.ptr<!s8i>
+
+// LLVM: getelementptr{{.*}}(i8, ptr @{{.*}}str{{.*}}, i64 2)

>From 6ad665af7b96afe220f27dc05caaf98a337cb30d Mon Sep 17 00:00:00 2001
From: Adam Smith <[email protected]>
Date: Tue, 9 Jun 2026 12:53:49 -0700
Subject: [PATCH 2/2] [CIR] Restrict GlobalView offset default to integers

Address review feedback: the broad TypeSwitch default in
computeGlobalViewIndicesFromFlatOffset treated any non-array, non-record
pointee as a flat element, which silenced the llvm_unreachable guard for
types that should never appear.  Replace it with a cir::IntType case and
restore llvm_unreachable for the default.

The only non-aggregate type that reaches the navigator is the integer
element of a string-literal GlobalViewAttr (applyOffset passes the
pointee, and getAddrOfConstantStringFromLiteral builds ptr-to-element
over an always-integral string element), so the integer case is
sufficient and the unreachable stays a real invariant guard.  Mirror the
same handling in computeOffsetFromGlobalViewIndices.
---
 clang/lib/CIR/CodeGen/CIRGenBuilder.cpp | 23 ++++++++++++++---------
 1 file changed, 14 insertions(+), 9 deletions(-)

diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.cpp 
b/clang/lib/CIR/CodeGen/CIRGenBuilder.cpp
index 0004bdf35ead5..a562c4b7b763f 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuilder.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.cpp
@@ -148,19 +148,22 @@ void 
CIRGenBuilderTy::computeGlobalViewIndicesFromFlatOffset(
             }
             llvm_unreachable("offset was not found within the record");
           })
-          .Default([&](mlir::Type otherTy) -> mlir::Type {
-            // Scalar or pointer type: the offset is a flat element count.
-            // This covers pointer arithmetic through a plain scalar base, e.g.
-            // a char* GlobalViewAttr whose pointee is !s8i rather than an
-            // array — the generated GEP is getelementptr i8, ptr @sym, i64 N.
+          .Case<cir::IntType>([&](cir::IntType intTy) -> mlir::Type {
+            // Integer element type: the offset is a flat element count.
+            // This covers pointer arithmetic through a plain integer base,
+            // e.g. a char* GlobalViewAttr whose pointee type is !s8i rather
+            // than an array — the GEP is getelementptr i8, ptr @sym, i64 N.
             int64_t eltSize =
-                (int64_t)layout.getTypeAllocSize(otherTy).getFixedValue();
+                (int64_t)layout.getTypeAllocSize(intTy).getFixedValue();
             assert(eltSize > 0 && "element size must be positive");
             const auto [index, newOffset] =
                 getIndexAndNewOffset(offset, eltSize);
             indices.push_back(index);
             offset = newOffset;
-            return otherTy;
+            return intTy;
+          })
+          .Default([](mlir::Type) -> mlir::Type {
+            llvm_unreachable("unexpected type");
           });
 
   assert(subType);
@@ -182,9 +185,11 @@ uint64_t 
CIRGenBuilderTy::computeOffsetFromGlobalViewIndices(
     } else if (auto arrayTy = dyn_cast<cir::ArrayType>(ty)) {
       ty = arrayTy.getElementType();
       offset += layout.getTypeAllocSize(ty) * idx;
-    } else {
-      // Scalar or pointer type: the index is a flat element count.
+    } else if (mlir::isa<cir::IntType>(ty)) {
+      // Integer element type: the index is a flat element count.
       offset += (int64_t)layout.getTypeAllocSize(ty).getFixedValue() * idx;
+    } else {
+      llvm_unreachable("unexpected type");
     }
   }
   return offset;

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to