-
Notifications
You must be signed in to change notification settings - Fork 15.6k
[CIR] Add support for EmbedExpr for ScalarExpr #172088
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
Conversation
|
@llvm/pr-subscribers-clangir @llvm/pr-subscribers-clang Author: Amr Hesham (AmrDeveloper) ChangesAdd support for the EmbedExpr for ScalarExpr Full diff: https://github.com/llvm/llvm-project/pull/172088.diff 2 Files Affected:
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index e86c62bf7793f..4577b646ea00c 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -263,8 +263,14 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
return {};
}
mlir::Value VisitEmbedExpr(EmbedExpr *e) {
- cgf.cgm.errorNYI(e->getSourceRange(), "ScalarExprEmitter: embed");
- return {};
+ assert(e->getDataElementCount() == 1);
+ auto it = e->begin();
+ QualType qualTy = e->getType();
+ mlir::Type ty = cgf.convertType(qualTy);
+ llvm::APInt value = (*it)->getValue();
+ uint64_t actualValue = qualTy->isSignedIntegerType() ? value.getSExtValue()
+ : value.getZExtValue();
+ return builder.getConstInt(cgf.getLoc(e->getExprLoc()), ty, actualValue);
}
mlir::Value VisitOpaqueValueExpr(OpaqueValueExpr *e) {
if (e->isGLValue())
diff --git a/clang/test/CIR/CodeGen/embed-expr.c b/clang/test/CIR/CodeGen/embed-expr.c
new file mode 100644
index 0000000000000..24009e3732736
--- /dev/null
+++ b/clang/test/CIR/CodeGen/embed-expr.c
@@ -0,0 +1,68 @@
+// RUN: %clang_cc1 -std=c23 -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=c23 -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=c23 -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 embed_expr_on_scalar_with_constants() {
+ int a[3] = {
+ 1,
+ 2,
+#embed __FILE__
+ };
+}
+
+// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.array<!s32i x 3>, !cir.ptr<!cir.array<!s32i x 3>>, ["a", init]
+// CIR: %[[ARRAY:.*]] = cir.const #cir.const_array<[#cir.int<1> : !s32i, #cir.int<2> : !s32i, #cir.int<47> : !s32i]> : !cir.array<!s32i x 3>
+// CIR: cir.store {{.*}} %[[ARRAY]], %[[A_ADDR]] : !cir.array<!s32i x 3>, !cir.ptr<!cir.array<!s32i x 3>>
+
+// LLVM: %[[A_ADDR:.*]] = alloca [3 x i32], i64 1, align 4
+// LLVM: store [3 x i32] [i32 1, i32 2, i32 47], ptr %[[A_ADDR]], align 4
+
+// OGCG: %[[A_ADDR:.*]] = alloca [3 x i32], align 4
+// OGCG: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %[[A_ADDR]], ptr align 4 @__const.embed_expr_on_scalar_with_constants.a, i64 12, i1 false)
+
+void embed_expr_on_scalar_with_non_constants() {
+ int a;
+ int b[3] = {
+ a,
+ a,
+#embed __FILE__
+ };
+}
+
+// CIR: %[[A_ADDR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["a"]
+// CIR: %[[B_ADDR:.*]] = cir.alloca !cir.array<!s32i x 3>, !cir.ptr<!cir.array<!s32i x 3>>, ["b", init]
+// CIR: %[[B_PTR:.*]] = cir.cast array_to_ptrdecay %[[B_ADDR]] : !cir.ptr<!cir.array<!s32i x 3>> -> !cir.ptr<!s32i>
+// CIR: %[[TMP_A:.*]] = cir.load {{.*}} %[[A_ADDR]] : !cir.ptr<!s32i>, !s32i
+// CIR: cir.store {{.*}} %[[TMP_A]], %[[B_PTR]] : !s32i, !cir.ptr<!s32i>
+// CIR: %[[CONST_1:.*]] = cir.const #cir.int<1> : !s64i
+// CIR: %[[B_ELEM_1_PTR:.*]] = cir.ptr_stride %[[B_PTR]], %[[CONST_1]] : (!cir.ptr<!s32i>, !s64i) -> !cir.ptr<!s32i>
+// CIR: %[[TMP_A:.*]] = cir.load {{.*}} %[[A_ADDR]] : !cir.ptr<!s32i>, !s32i
+// CIR: cir.store {{.*}} %[[TMP_A]], %[[B_ELEM_1_PTR]] : !s32i, !cir.ptr<!s32i>
+// CIR: %[[CONST_2:.*]] = cir.const #cir.int<2> : !s64i
+// CIR: %[[B_ELEM_2_PTR:.*]] = cir.ptr_stride %[[B_PTR]], %[[CONST_2]] : (!cir.ptr<!s32i>, !s64i) -> !cir.ptr<!s32i>
+// CIR: %[[CONST_47:.*]] = cir.const #cir.int<47> : !s32i
+// CIR: cir.store {{.*}} %[[CONST_47]], %[[B_ELEM_2_PTR]] : !s32i, !cir.ptr<!s32i>
+
+// LLVM: %[[A_ADDR:.*]] = alloca i32, i64 1, align 4
+// LLVM: %[[B_ADDR:.*]] = alloca [3 x i32], i64 1, align 4
+// LLVM: %[[B_ELEM_0_PTR:.*]] = getelementptr i32, ptr %[[B_ADDR]], i32 0
+// LLVM: %[[TMP_A:.*]] = load i32, ptr %[[A_ADDR]], align 4
+// LLVM: store i32 %[[TMP_A]], ptr %[[B_ELEM_0_PTR]], align 4
+// LLVM: %[[B_ELEM_1_PTR:.*]] = getelementptr i32, ptr %[[B_ELEM_0_PTR]], i64 1
+// LLVM: %[[TMP_A:.*]] = load i32, ptr %[[A_ADDR]], align 4
+// LLVM: store i32 %[[TMP_A]], ptr %[[B_ELEM_1_PTR]], align 4
+// LLVM: %[[B_ELEM_2_PTR:.*]] = getelementptr i32, ptr %[[B_ELEM_0_PTR]], i64 2
+// LLVM: store i32 47, ptr %[[B_ELEM_2_PTR]], align 4
+
+// OGCG: %[[A_ADDR:.*]] = alloca i32, align 4
+// OGCG: %[[B_ADDR:.*]] = alloca [3 x i32], align 4
+// OGCG: %[[TMP_A:.*]] = load i32, ptr %[[A_ADDR]], align 4
+// OGCG: store i32 %[[TMP_A]], ptr %[[B_ADDR]], align 4
+// OGCG: %[[B_ELEM_1_PTR:.*]] = getelementptr inbounds i32, ptr %[[B_ADDR]], i64 1
+// OGCG: %[[TMP_A:.*]] = load i32, ptr %[[A_ADDR]], align 4
+// OGCG: store i32 %[[TMP_A]], ptr %[[B_ELEM_1_PTR]], align 4
+// OGCG: %[[B_ELEM_2_PTR:.*]] = getelementptr inbounds i32, ptr %[[B_ADDR]], i64 2
+// OGCG: store i32 47, ptr %[[B_ELEM_2_PTR]], align 4
|
| assert(e->getDataElementCount() == 1); | ||
| auto it = e->begin(); | ||
| QualType qualTy = e->getType(); | ||
| mlir::Type ty = cgf.convertType(qualTy); | ||
| llvm::APInt value = (*it)->getValue(); | ||
| uint64_t actualValue = qualTy->isSignedIntegerType() ? value.getSExtValue() | ||
| : value.getZExtValue(); | ||
| return builder.getConstInt(cgf.getLoc(e->getExprLoc()), ty, actualValue); |
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.
Identically, we should use getConstInt and pass the APInt, but in our builder, when we pass APInt, we just construct APSInt with unsigned = true, so maybe we should add another parameter to this helper to control singing
llvm-project/clang/lib/CIR/CodeGen/CIRGenBuilder.cpp
Lines 55 to 58 in 333ee93
| cir::ConstantOp CIRGenBuilderTy::getConstInt(mlir::Location loc, | |
| llvm::APInt intVal) { | |
| return getConstInt(loc, llvm::APSInt(intVal)); | |
| } |
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.
Yes, I think return builder.getConstInt(cgf.getLoc(e->getExprLoc()), value, qualTy->isSignedIntegerType()); would make more sense here if the APInt overload for getConstInt took a isSigned argument. Then we could get rid of a lot of the type handling here.
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 getConstInt, we pass llvm::APInt always by copy, but I will keep this change to NFC PR :D
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.
lgtm
Add support for the EmbedExpr for ScalarExpr
Add support for the EmbedExpr for ScalarExpr