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
