https://github.com/AbdallahRashed created https://github.com/llvm/llvm-project/pull/196837
Implement pointer arithmetic on variable-length array types in CIR codegen, removing two NYI diagnostics: 1. Binary pointer arithmetic (p + i, p - i) where the pointee is a VLA: multiply the index by the runtime VLA size before emitting PtrStrideOp. 2. Unary increment/decrement (p++, p--) on pointers to VLA types: stride by the VLA element count, negating for decrement. Fixes #192318 >From 292aed1d7a30952a67a5f9b5e9530def33696395 Mon Sep 17 00:00:00 2001 From: AbdallahRashed <[email protected]> Date: Sun, 10 May 2026 22:25:17 +0200 Subject: [PATCH] [CIR][CodeGen] Support VLA pointer arithmetic Implement pointer arithmetic on variable-length array types in CIR codegen, removing two NYI diagnostics: 1. Binary pointer arithmetic (p + i, p - i) where the pointee is a VLA: multiply the index by the runtime VLA size before emitting PtrStrideOp. 2. Unary increment/decrement (p++, p--) on pointers to VLA types: stride by the VLA element count, negating for decrement. Fixes #192318 --- clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp | 29 +++++++--- clang/test/CIR/CodeGen/vla-pointer-arith.c | 62 ++++++++++++++++++++++ 2 files changed, 85 insertions(+), 6 deletions(-) create mode 100644 clang/test/CIR/CodeGen/vla-pointer-arith.c diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp index 231039ec5da29..5b058560cdefe 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp @@ -668,10 +668,15 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> { } } else if (const PointerType *ptr = type->getAs<PointerType>()) { QualType type = ptr->getPointeeType(); - if (cgf.getContext().getAsVariableArrayType(type)) { + if (const VariableArrayType *vla = + cgf.getContext().getAsVariableArrayType(type)) { // VLA types don't have constant size. - cgf.cgm.errorNYI(e->getSourceRange(), "Pointer arithmetic on VLA"); - return {}; + mlir::Location loc = cgf.getLoc(e->getSourceRange()); + mlir::Value numElts = cgf.getVLASize(vla).numElts; + if (!e->isIncrementOp()) + numElts = cgf.getBuilder().createNeg(numElts); + assert(!cir::MissingFeatures::sanitizers()); + value = cgf.getBuilder().createPtrStride(loc, value, numElts); } else { // For everything else, we can just do a simple increment. mlir::Location loc = cgf.getLoc(e->getSourceRange()); @@ -1898,9 +1903,21 @@ static mlir::Value emitPointerArithmetic(CIRGenFunction &cgf, } QualType elementType = pointerType->getPointeeType(); - if (cgf.getContext().getAsVariableArrayType(elementType)) { - cgf.cgm.errorNYI("variable array type"); - return nullptr; + if (const VariableArrayType *vla = + cgf.getContext().getAsVariableArrayType(elementType)) { + // The element count here is the total number of non-VLA elements. + mlir::Value numElements = cgf.getVLASize(vla).numElts; + + // GEP indexes are signed, and scaling an index isn't permitted to + // signed-overflow, so we use the same semantics for our explicit + // multiply. We suppress this if overflow is not undefined behavior. + mlir::Location loc = cgf.getLoc(op.e->getExprLoc()); + index = cgf.getBuilder().createCast(cir::CastKind::integral, index, + numElements.getType()); + index = cgf.getBuilder().createMul(loc, index, numElements); + assert(!cir::MissingFeatures::sanitizers()); + return cir::PtrStrideOp::create(cgf.getBuilder(), loc, pointer.getType(), + pointer, index); } assert(!cir::MissingFeatures::sanitizers()); diff --git a/clang/test/CIR/CodeGen/vla-pointer-arith.c b/clang/test/CIR/CodeGen/vla-pointer-arith.c new file mode 100644 index 0000000000000..aa59031433a78 --- /dev/null +++ b/clang/test/CIR/CodeGen/vla-pointer-arith.c @@ -0,0 +1,62 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir +// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t-cir.ll +// RUN: FileCheck --input-file=%t-cir.ll %s -check-prefix=LLVM +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll +// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG + +// Test pointer arithmetic on VLA types. + +void test_vla_ptr_add(int n) { + int arr[n]; + int (*p)[n] = &arr; + p = p + 1; +} + +// CIR-LABEL: @test_vla_ptr_add +// CIR: %[[P:.*]] = cir.load{{.*}} %{{.*}} : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i> +// CIR: %[[ONE:.*]] = cir.const #cir.int<1> : !u64i +// CIR: %[[SCALED:.*]] = cir.mul %[[ONE]], %{{.*}} : !u64i +// CIR: cir.ptr_stride %[[P]], %[[SCALED]] : (!cir.ptr<!s32i>, !u64i) -> !cir.ptr<!s32i> + +// LLVM-LABEL: @test_vla_ptr_add +// LLVM: %[[SCALED:.*]] = mul i64 1, %{{.*}} +// LLVM: %[[RESULT:.*]] = getelementptr i32, ptr %{{.*}}, i64 %[[SCALED]] + +// OGCG-LABEL: @test_vla_ptr_add +// OGCG: getelementptr inbounds i32, ptr %{{.*}}, i64 %{{.*}} + +void test_vla_ptr_inc(int n) { + int arr[n]; + int (*p)[n] = &arr; + p++; +} + +// CIR-LABEL: @test_vla_ptr_inc +// CIR: %[[P:.*]] = cir.load{{.*}} %{{.*}} : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i> +// CIR: cir.ptr_stride %[[P]], %{{.*}} : (!cir.ptr<!s32i>, !u64i) -> !cir.ptr<!s32i> + +// LLVM-LABEL: @test_vla_ptr_inc +// LLVM: getelementptr i32, ptr %{{.*}}, i64 %{{.*}} + +// OGCG-LABEL: @test_vla_ptr_inc +// OGCG: getelementptr inbounds nuw i32, ptr %{{.*}}, i64 %{{.*}} + +void test_vla_ptr_dec(int n) { + int arr[n]; + int (*p)[n] = &arr; + p--; +} + +// CIR-LABEL: @test_vla_ptr_dec +// CIR: %[[P:.*]] = cir.load{{.*}} %{{.*}} : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i> +// CIR: %[[SIGNED:.*]] = cir.cast integral %{{.*}} : !u64i -> !s64i +// CIR: %[[NEG:.*]] = cir.minus %[[SIGNED]] : !s64i +// CIR: cir.ptr_stride %[[P]], %[[NEG]] : (!cir.ptr<!s32i>, !s64i) -> !cir.ptr<!s32i> + +// LLVM-LABEL: @test_vla_ptr_dec +// LLVM: getelementptr i32, ptr %{{.*}}, i64 %{{.*}} + +// OGCG-LABEL: @test_vla_ptr_dec +// OGCG: getelementptr inbounds i32, ptr %{{.*}}, i64 %{{.*}} + _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
