https://github.com/AmrDeveloper updated https://github.com/llvm/llvm-project/pull/175370
>From b73eabc93fae094c2a2ef92642166aae6181ee15 Mon Sep 17 00:00:00 2001 From: Amr Hesham <[email protected]> Date: Sat, 10 Jan 2026 17:39:01 +0100 Subject: [PATCH 1/2] [CIR] SubscriptExpr for VariableLengthArray --- clang/lib/CIR/CodeGen/CIRGenExpr.cpp | 52 ++++++++++++++++++------ clang/test/CIR/CodeGen/vla.c | 60 ++++++++++++++++++++++++++-- 2 files changed, 97 insertions(+), 15 deletions(-) diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp index cd13498e3702f..0f0e9c67e9dae 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp @@ -1128,12 +1128,6 @@ static Address emitArraySubscriptPtr(CIRGenFunction &cgf, LValue CIRGenFunction::emitArraySubscriptExpr(const clang::ArraySubscriptExpr *e) { - if (getContext().getAsVariableArrayType(e->getType())) { - cgm.errorNYI(e->getSourceRange(), - "emitArraySubscriptExpr: VariableArrayType"); - return LValue::makeAddr(Address::invalid(), e->getType(), LValueBaseInfo()); - } - if (e->getType()->getAs<ObjCObjectType>()) { cgm.errorNYI(e->getSourceRange(), "emitArraySubscriptExpr: ObjCObjectType"); return LValue::makeAddr(Address::invalid(), e->getType(), LValueBaseInfo()); @@ -1165,7 +1159,14 @@ CIRGenFunction::emitArraySubscriptExpr(const clang::ArraySubscriptExpr *e) { lv.getBaseInfo()); } - const mlir::Value idx = emitIdxAfterBase(/*promote=*/true); + // The HLSL runtime handles subscript expressions on global resource arrays + // and objects with HLSL buffer layouts. + if (getLangOpts().HLSL) { + cgm.errorNYI(e->getSourceRange(), "emitArraySubscriptExpr: HLSL"); + return {}; + } + + mlir::Value idx = emitIdxAfterBase(/*promote=*/true); // Handle the extvector case we ignored above. if (isa<ExtVectorElementExpr>(e->getBase())) { @@ -1181,6 +1182,36 @@ CIRGenFunction::emitArraySubscriptExpr(const clang::ArraySubscriptExpr *e) { return makeAddrLValue(addr, elementType, lv.getBaseInfo()); } + if (const VariableArrayType *vla = + getContext().getAsVariableArrayType(e->getType())) { + // The base must be a pointer, which is not an aggregate. Emit + // it. It needs to be emitted first in case it's what captures + // the VLA bounds. + Address addr = emitPointerWithAlignment(e->getBase()); + + // The element count here is the total number of non-VLA elements. + mlir::Value numElements = getVLASize(vla).numElts; + idx = builder.createIntCast(idx, numElements.getType()); + + // Effectively, the multiply by the VLA size is part of the GEP. + // 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. + OverflowBehavior overflowBehavior = getLangOpts().PointerOverflowDefined + ? OverflowBehavior::None + : OverflowBehavior::NoSignedWrap; + idx = builder.createMul(cgm.getLoc(e->getExprLoc()), idx, numElements, + overflowBehavior); + + assert(!cir::MissingFeatures::emitCheckedInBoundsGEP()); + addr = emitArraySubscriptPtr(*this, cgm.getLoc(e->getBeginLoc()), + cgm.getLoc(e->getEndLoc()), addr, e->getType(), + idx, cgm.getLoc(e->getExprLoc()), + /*shouldDecay=*/false); + + return makeAddrLValue(addr, vla->getElementType(), LValueBaseInfo()); + } + if (const Expr *array = getSimpleArrayDecayOperand(e->getBase())) { LValue arrayLV; if (const auto *ase = dyn_cast<ArraySubscriptExpr>(array)) @@ -1738,11 +1769,8 @@ LValue CIRGenFunction::emitCompoundLiteralLValue(const CompoundLiteralExpr *e) { return {}; } - if (e->getType()->isVariablyModifiedType()) { - cgm.errorNYI(e->getSourceRange(), - "emitCompoundLiteralLValue: VariablyModifiedType"); - return {}; - } + if (e->getType()->isVariablyModifiedType()) + emitVariablyModifiedType(e->getType()); Address declPtr = createMemTemp(e->getType(), getLoc(e->getSourceRange()), ".compoundliteral"); diff --git a/clang/test/CIR/CodeGen/vla.c b/clang/test/CIR/CodeGen/vla.c index 971a7def0db44..ce0cbee11add7 100644 --- a/clang/test/CIR/CodeGen/vla.c +++ b/clang/test/CIR/CodeGen/vla.c @@ -1,8 +1,8 @@ -// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -fclangir -emit-cir %s -o %t.cir +// RUN: %clang_cc1 -Wno-error=incompatible-pointer-types -triple x86_64-unknown-linux-gnu -Wno-unused-value -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 -Wno-unused-value -fclangir -emit-llvm %s -o %t-cir.ll +// RUN: %clang_cc1 -Wno-error=incompatible-pointer-types -triple x86_64-unknown-linux-gnu -Wno-unused-value -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 -Wno-unused-value -emit-llvm %s -o %t.ll +// RUN: %clang_cc1 -Wno-error=incompatible-pointer-types -triple x86_64-unknown-linux-gnu -Wno-unused-value -emit-llvm %s -o %t.ll // RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG void f0(int len) { @@ -339,3 +339,57 @@ int f5(unsigned long len) { // OGCG: %[[STACK_RESTORE_PTR:.*]] = load ptr, ptr %[[SAVED_STACK]] // OGCG: call void @llvm.stackrestore.p0(ptr %[[STACK_RESTORE_PTR]]) // OGCG: ret i32 %[[ARR_VAL]] + +void vla_subscript_expr() { + int **a; + unsigned long n = 5; + (int (**)[n]){&a}[0][1][5] = 0; +} + +// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!cir.ptr<!cir.ptr<!s32i>>>, ["a"] +// CIR: %[[N_ADDR:.*]] = cir.alloca !u64i, !cir.ptr<!u64i>, ["n", init] +// CIR: %[[COMPOUND_ADDR:.*]] = cir.alloca !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!cir.ptr<!cir.ptr<!s32i>>>, [".compoundliteral"] +// CIR: %[[CONST_5:.*]] = cir.const #cir.int<5> : !u64i +// CIR: cir.store {{.*}} %[[CONST_5]], %[[N_ADDR]] : !u64i, !cir.ptr<!u64i> +// CIR: %[[CONST_0_VAL:.*]] = cir.const #cir.int<0> : !s32i +// CIR: %[[CONST_5:.*]] = cir.const #cir.int<5> : !s32i +// CIR: %[[CONST_0:.*]] = cir.const #cir.int<0> : !s32i +// CIR: %[[TMP_N:.*]] = cir.load {{.*}} %[[N_ADDR]] : !cir.ptr<!u64i>, !u64i +// CIR: %[[A_VAL:.*]] = cir.cast bitcast %[[A_ADDR]] : !cir.ptr<!cir.ptr<!cir.ptr<!s32i>>> -> !cir.ptr<!cir.ptr<!s32i>> +// CIR: cir.store {{.*}} %[[A_VAL]], %[[COMPOUND_ADDR]] : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!cir.ptr<!cir.ptr<!s32i>>> +// CIR: %[[TMP_COMPOUND:.*]] = cir.load {{.*}} %[[COMPOUND_ADDR]] : !cir.ptr<!cir.ptr<!cir.ptr<!s32i>>>, !cir.ptr<!cir.ptr<!s32i>> +// CIR: %[[COMPOUND_PTR:.*]] = cir.ptr_stride %[[TMP_COMPOUND]], %[[CONST_0]] : (!cir.ptr<!cir.ptr<!s32i>>, !s32i) -> !cir.ptr<!cir.ptr<!s32i>> +// CIR: %[[TMP_COMPOUND:.*]] = cir.load {{.*}} %10 : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i> +// CIR: %[[CONST_1:.*]] = cir.const #cir.int<1> : !u64i +// CIR: %[[VLA_IDX:.*]] = cir.binop(mul, %[[CONST_1]], %7) nsw : !u64i +// CIR: %[[VLA_A_PTR:.*]] = cir.ptr_stride %[[TMP_COMPOUND]], %[[VLA_IDX]] : (!cir.ptr<!s32i>, !u64i) -> !cir.ptr<!s32i> +// CIR: %[[ELEM_5_PTR:.*]] = cir.ptr_stride %[[VLA_A_PTR]], %[[CONST_5]] : (!cir.ptr<!s32i>, !s32i) -> !cir.ptr<!s32i> +// CIR: cir.store {{.*}} %[[CONST_0_VAL]], %[[ELEM_5_PTR]] : !s32i, !cir.ptr<!s32i> + +// LLVM: %[[A_ADDR:.*]] = alloca ptr, i64 1, align 8 +// LLVM: %[[N_ADDR:.*]] = alloca i64, i64 1, align 8 +// LLVM: %[[COMPOUND_ADDR:.*]] = alloca ptr, i64 1, align 8 +// LLVM: store i64 5, ptr %[[N_ADDR]], align 8 +// LLVM: %[[TMP_N:.*]] = load i64, ptr %[[N_ADDR]], align 8 +// LLVM: store ptr %[[A_ADDR]], ptr %[[COMPOUND_ADDR]], align 8 +// LLVM: %[[TMP_COMPOUND:.*]] = load ptr, ptr %[[COMPOUND_ADDR]], align 8 +// LLVM: %[[COMPOUND_PTR:.*]] = getelementptr ptr, ptr %[[TMP_COMPOUND]], i64 0 +// LLVM: %[[TMP_COMPOUND:.*]] = load ptr, ptr %[[COMPOUND_PTR]], align 8 +// LLVM: %[[VLA_IDX:.*]] = mul nsw i64 1, %[[TMP_N]] +// LLVM: %[[VLA_A_PTR:.*]] = getelementptr i32, ptr %[[TMP_COMPOUND]], i64 %[[VLA_IDX]] +// LLVM: %[[ELEM_5_PTR:.*]] = getelementptr i32, ptr %[[VLA_A_PTR]], i64 5 +// LLVM: store i32 0, ptr %[[ELEM_5_PTR]], align 4 + +// OGCG: %[[A_ADDR:.*]] = alloca ptr, align 8 +// OGCG: %[[N_ADDR:.*]] = alloca i64, align 8 +// OGCG: %[[COMPOUND_ADDR:.*]] = alloca ptr, align 8 +// OGCG: store i64 5, ptr %[[N_ADDR]], align 8 +// OGCG: %[[TMP_N:.*]] = load i64, ptr %[[N_ADDR]], align 8 +// OGCG: store ptr %[[A_ADDR]], ptr %[[COMPOUND_ADDR]], align 8 +// OGCG: %[[TMP_COMPOUND:.*]] = load ptr, ptr %[[COMPOUND_ADDR]], align 8 +// OGCG: %[[COMPOUND_PTR:.*]] = getelementptr inbounds ptr, ptr %[[TMP_COMPOUND]], i64 0 +// OGCG: %[[TMP_COMPOUND:.*]] = load ptr, ptr %[[COMPOUND_PTR]], align 8 +// OGCG: %[[VLA_IDX:.*]] = mul nsw i64 1, %[[TMP_N]] +// OGCG: %[[VLA_A_PTR:.*]] = getelementptr inbounds i32, ptr %[[TMP_COMPOUND]], i64 %[[VLA_IDX]] +// OGCG: %[[ELEM_5_PTR:.*]] = getelementptr inbounds i32, ptr %[[VLA_A_PTR]], i64 5 +// OGCG: store i32 0, ptr %[[ELEM_5_PTR]], align 4 >From f90cf9b4c5fa2594487d6d67046585c8210ec2e7 Mon Sep 17 00:00:00 2001 From: Amr Hesham <[email protected]> Date: Tue, 13 Jan 2026 18:41:41 +0100 Subject: [PATCH 2/2] Remove MissingFeatures --- clang/lib/CIR/CodeGen/CIRGenExpr.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp index 0f0e9c67e9dae..cc97af90d823c 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp @@ -1203,7 +1203,6 @@ CIRGenFunction::emitArraySubscriptExpr(const clang::ArraySubscriptExpr *e) { idx = builder.createMul(cgm.getLoc(e->getExprLoc()), idx, numElements, overflowBehavior); - assert(!cir::MissingFeatures::emitCheckedInBoundsGEP()); addr = emitArraySubscriptPtr(*this, cgm.getLoc(e->getBeginLoc()), cgm.getLoc(e->getEndLoc()), addr, e->getType(), idx, cgm.getLoc(e->getExprLoc()), _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
