-
Notifications
You must be signed in to change notification settings - Fork 15.3k
[CIR] CountOf VLA with Array element type #169404
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[CIR] CountOf VLA with Array element type #169404
Conversation
|
@llvm/pr-subscribers-clang @llvm/pr-subscribers-clangir Author: Amr Hesham (AmrDeveloper) ChangesImplement CountOf on VariableArrayType with IntegerConstant SizeExpr Full diff: https://github.com/llvm/llvm-project/pull/169404.diff 2 Files Affected:
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index 7c94743d5ffc6..feb019292715c 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -2325,14 +2325,27 @@ mlir::Value ScalarExprEmitter::VisitUnaryExprOrTypeTraitExpr(
const QualType typeToSize = e->getTypeOfArgument();
const mlir::Location loc = cgf.getLoc(e->getSourceRange());
if (auto kind = e->getKind();
- kind == UETT_SizeOf || kind == UETT_DataSizeOf) {
- if (cgf.getContext().getAsVariableArrayType(typeToSize)) {
- cgf.getCIRGenModule().errorNYI(e->getSourceRange(),
- "sizeof operator for VariableArrayType",
- e->getStmtClassName());
- return builder.getConstant(
- loc, cir::IntAttr::get(cgf.cgm.uInt64Ty,
- llvm::APSInt(llvm::APInt(64, 1), true)));
+ kind == UETT_SizeOf || kind == UETT_DataSizeOf || kind == UETT_CountOf) {
+ if (const VariableArrayType *vat =
+ cgf.getContext().getAsVariableArrayType(typeToSize)) {
+ // For _Countof, we only want to evaluate if the extent is actually
+ // variable as opposed to a multi-dimensional array whose extent is
+ // constant but whose element type is variable.
+ bool evaluateExtent = true;
+ if (kind == UETT_CountOf && vat->getElementType()->isArrayType()) {
+ evaluateExtent =
+ !vat->getSizeExpr()->isIntegerConstantExpr(cgf.getContext());
+ }
+
+ if (evaluateExtent) {
+ cgf.getCIRGenModule().errorNYI(
+ e->getSourceRange(),
+ "sizeof operator for VariableArrayType & evaluateExtent",
+ e->getStmtClassName());
+ return builder.getConstant(
+ loc, cir::IntAttr::get(cgf.cgm.uInt64Ty,
+ -llvm::APSInt(llvm::APInt(64, 1), true)));
+ }
}
} else if (e->getKind() == UETT_OpenMPRequiredSimdAlign) {
cgf.getCIRGenModule().errorNYI(
diff --git a/clang/test/CIR/CodeGen/count-of.c b/clang/test/CIR/CodeGen/count-of.c
new file mode 100644
index 0000000000000..78c905e285969
--- /dev/null
+++ b/clang/test/CIR/CodeGen/count-of.c
@@ -0,0 +1,28 @@
+// RUN: %clang_cc1 -std=c2y -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 -std=c2y -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 -std=c2y -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
+
+unsigned long vla_with_array_element_type() {
+ long size;
+#define int_arr int[5]
+ return _Countof(int_arr[size]);
+}
+
+// CIR: %[[RET_ADDR:.*]] = cir.alloca !u64i, !cir.ptr<!u64i>, ["__retval"]
+// CIR: %[[SIZE_ADDR:.*]] = cir.alloca !s64i, !cir.ptr<!s64i>, ["size"]
+// CIR: %[[CONST_5:.*]] = cir.const #cir.int<5> : !u64i
+// CIR: cir.store %[[CONST_5]], %[[RET_ADDR]] : !u64i, !cir.ptr<!u64i>
+// CIR: %[[RET_VAL:.*]] = cir.load %[[RET_ADDR]] : !cir.ptr<!u64i>, !u64i
+// CIR: cir.return %[[RET_VAL]] : !u64i
+
+// LLVM: %[[RET_ADDR:.*]] = alloca i64, i64 1, align 8
+// LLVM: %[[SIZE_ADDR:.*]] = alloca i64, i64 1, align 8
+// LLVM: store i64 5, ptr %[[RET_ADDR]], align 8
+// LLVM: %[[RET_VAL:.*]] = load i64, ptr %[[RET_ADDR]], align 8
+// LLVM: ret i64 %[[RET_VAL]]
+
+// OGCG: %[[SIZE_ADDR:.*]] = alloca i64, align 8
+// OGCG: ret i64 5
|
andykaylor
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks fine, except for an issue with the test case. The implementation for evaluateExtent looks small. Why not include that in this same PR?
clang/test/CIR/CodeGen/count-of.c
Outdated
| #define int_arr int[5] | ||
| return _Countof(int_arr[size]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is an off way to represent the array. Why are you using #define here? Also, I believe this is using an uninitialized variable to describe a two-dimensional array, which is likely UB. Maybe make the variable an argument?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this test case, I want to create an array type, not an array int[5][size] 🤔, i think it's TypeExpr and will not init array right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The rest of the evaluateExtent implementation has one part related to CountOf and other parts are related to sizeof, I will address the countof part here and all sizeof part will be in follow up PR if thats okey
🐧 Linux x64 Test Results
All tests passed but another part of the build failed. Click on a failure below to see the details. tools/clang/lib/CIR/CodeGen/CMakeFiles/obj.clangCIR.dir/CIRGenFunction.cpp.oIf these failures are unrelated to your changes (for example tests are broken or flaky at HEAD), please open an issue at https://github.com/llvm/llvm-project/issues and add the |
d12ce8d to
8eede9c
Compare
| CIRGenFunction::getVLAElements1D(const VariableArrayType *vla) { | ||
| mlir::Value vlaSize = vlaSizeMap[vla->getSizeExpr()]; | ||
| assert(vlaSize && "no size for VLA!"); | ||
| assert(vlaSize->getType() == sizeTy); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
vlaSize isn't a pointer, so this fails to build:
runner/_work/llvm-project/llvm-project/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
2025-11-26T19:23:08.6857824Z /home/gha/actions-runner/_work/llvm-project/llvm-project/clang/lib/CIR/CodeGen/CIRGenFunction.cpp:1145:17: error: member reference type 'mlir::Value' is not a pointer; did you mean to use '.'?
2025-11-26T19:23:08.6859083Z 1145 | assert(vlaSize->getType() == sizeTy);
2025-11-26T19:23:08.6859503Z | ~~~~~~~^~
2025-11-26T19:23:08.6859814Z | .
2025-11-26T19:23:08.6860251Z /usr/include/assert.h:103:27: note: expanded from macro 'assert'
2025-11-26T19:23:08.6860727Z 103 | (static_cast <bool> (expr) \
2025-11-26T19:23:08.6861052Z | ^~~~
Note this seems to have been caught by pre-commit CI as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm preparing a fix for it now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for catching it
Implement CountOf on VariableArrayType with IntegerConstant SizeExpr
Implement CountOf on VariableArrayType with IntegerConstant SizeExpr
Implement CountOf on VariableArrayType with IntegerConstant SizeExpr