-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[CIR] Implement support for OffsetOfExpr #167726
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 Author: Amr Hesham (AmrDeveloper) ChangesImplement support for the OffsetOfExpr Full diff: https://github.com/llvm/llvm-project/pull/167726.diff 2 Files Affected:
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index c1a36134d8942..c62e30d7e9c98 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -197,6 +197,8 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
return emitNullValue(e->getType(), cgf.getLoc(e->getSourceRange()));
}
+ mlir::Value VisitOffsetOfExpr(OffsetOfExpr *e);
+
mlir::Value VisitOpaqueValueExpr(OpaqueValueExpr *e) {
if (e->isGLValue())
return emitLoadOfLValue(cgf.getOrCreateOpaqueLValueMapping(e),
@@ -2164,6 +2166,21 @@ mlir::Value ScalarExprEmitter::VisitUnaryLNot(const UnaryOperator *e) {
return maybePromoteBoolResult(boolVal, cgf.convertType(e->getType()));
}
+mlir::Value ScalarExprEmitter::VisitOffsetOfExpr(OffsetOfExpr *e) {
+ // Try folding the offsetof to a constant.
+ Expr::EvalResult evalResult;
+ if (e->EvaluateAsInt(evalResult, cgf.getContext())) {
+ mlir::Type type = cgf.convertType(e->getType());
+ llvm::APSInt value = evalResult.Val.getInt();
+ return builder.getConstAPInt(cgf.getLoc(e->getExprLoc()), type, value);
+ }
+
+ cgf.getCIRGenModule().errorNYI(
+ e->getSourceRange(),
+ "ScalarExprEmitter::VisitOffsetOfExpr Can't eval expr as int");
+ return {};
+}
+
mlir::Value ScalarExprEmitter::VisitUnaryReal(const UnaryOperator *e) {
QualType promotionTy = getPromotionType(e->getSubExpr()->getType());
mlir::Value result = VisitRealImag(e, promotionTy);
diff --git a/clang/test/CIR/CodeGen/offset-of.cpp b/clang/test/CIR/CodeGen/offset-of.cpp
new file mode 100644
index 0000000000000..f62da9e6d9413
--- /dev/null
+++ b/clang/test/CIR/CodeGen/offset-of.cpp
@@ -0,0 +1,93 @@
+// RUN: %clang_cc1 -std=c++20 -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=c++20 -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=c++20 -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
+
+struct Struct {
+ int a;
+ float b;
+ double c;
+ bool d;
+};
+
+void offset_of_builtin() {
+ unsigned long a = __builtin_offsetof(Struct, a);
+ unsigned long b = __builtin_offsetof(Struct, b);
+ unsigned long c = __builtin_offsetof(Struct, c);
+ unsigned long d = __builtin_offsetof(Struct, d);
+}
+
+// CIR: %[[A_ADDR:.*]] = cir.alloca !u64i, !cir.ptr<!u64i>, ["a", init]
+// CIR: %[[B_ADDR:.*]] = cir.alloca !u64i, !cir.ptr<!u64i>, ["b", init]
+// CIR: %[[C_ADDR:.*]] = cir.alloca !u64i, !cir.ptr<!u64i>, ["c", init]
+// CIR: %[[D_ADDR:.*]] = cir.alloca !u64i, !cir.ptr<!u64i>, ["d", init]
+// CIR: %[[CONST_0:.*]] = cir.const #cir.int<0> : !u64i
+// CIR: cir.store {{.*}} %[[CONST_0]], %[[A_ADDR]] : !u64i, !cir.ptr<!u64i>
+// CIR: %[[CONST_4:.*]] = cir.const #cir.int<4> : !u64i
+// CIR: cir.store {{.*}} %[[CONST_4]], %[[B_ADDR]] : !u64i, !cir.ptr<!u64i>
+// CIR: %[[CONST_8:.*]] = cir.const #cir.int<8> : !u64i
+// CIR: cir.store {{.*}} %[[CONST_8]], %[[C_ADDR]] : !u64i, !cir.ptr<!u64i>
+// CIR: %[[CONST_16:.*]] = cir.const #cir.int<16> : !u64i
+// CIR: cir.store {{.*}} %[[CONST_16]], %[[D_ADDR]] : !u64i, !cir.ptr<!u64i>
+
+// LLVM: %[[A_ADDR:.*]] = alloca i64, i64 1, align 8
+// LLVM: %[[B_ADDR:.*]] = alloca i64, i64 1, align 8
+// LLVM: %[[C_ADDR:.*]] = alloca i64, i64 1, align 8
+// LLVM: %[[D_ADDR:.*]] = alloca i64, i64 1, align 8
+// LLVM: store i64 0, ptr %[[A_ADDR]], align 8
+// LLVM: store i64 4, ptr %[[B_ADDR]], align 8
+// LLVM: store i64 8, ptr %[[C_ADDR]], align 8
+// LLVM: store i64 16, ptr %[[D_ADDR]], align 8
+
+// OGCG: %[[A_ADDR:.*]] = alloca i64, align 8
+// OGCG: %[[B_ADDR:.*]] = alloca i64, align 8
+// OGCG: %[[C_ADDR:.*]] = alloca i64, align 8
+// OGCG: %[[D_ADDR:.*]] = alloca i64, align 8
+// OGCG: store i64 0, ptr %[[A_ADDR]], align 8
+// OGCG: store i64 4, ptr %[[B_ADDR]], align 8
+// OGCG: store i64 8, ptr %[[C_ADDR]], align 8
+// OGCG: store i64 16, ptr %[[D_ADDR]], align 8
+
+struct StructWithArray {
+ Struct array[4][4];
+};
+
+void offset_of_builtin_from_array_element() {
+ unsigned long a = __builtin_offsetof(StructWithArray, array[0][0].a);
+ unsigned long b = __builtin_offsetof(StructWithArray, array[1][1].b);
+ unsigned long c = __builtin_offsetof(StructWithArray, array[2][2].c);
+ unsigned long d = __builtin_offsetof(StructWithArray, array[3][3].d);
+}
+
+// CIR: %[[A_ADDR:.*]] = cir.alloca !u64i, !cir.ptr<!u64i>, ["a", init]
+// CIR: %[[B_ADDR:.*]] = cir.alloca !u64i, !cir.ptr<!u64i>, ["b", init]
+// CIR: %[[C_ADDR:.*]] = cir.alloca !u64i, !cir.ptr<!u64i>, ["c", init]
+// CIR: %[[D_ADDR:.*]] = cir.alloca !u64i, !cir.ptr<!u64i>, ["d", init]
+// CIR: %[[CONST_0:.*]] = cir.const #cir.int<0> : !u64i
+// CIR: cir.store {{.*}} %[[CONST_0]], %[[A_ADDR]] : !u64i, !cir.ptr<!u64i>
+// CIR: %[[CONST_124:.*]] = cir.const #cir.int<124> : !u64i
+// CIR: cir.store {{.*}} %[[CONST_124]], %[[B_ADDR]] : !u64i, !cir.ptr<!u64i>
+// CIR: %[[CONST_248:.*]] = cir.const #cir.int<248> : !u64i
+// CIR: cir.store {{.*}} %[[CONST_248]], %[[C_ADDR]] : !u64i, !cir.ptr<!u64i>
+// CIR: %[[CONST_376:.*]] = cir.const #cir.int<376> : !u64i
+// CIR: cir.store {{.*}} %[[CONST_376]], %[[D_ADDR]] : !u64i, !cir.ptr<!u64i>
+
+// LLVM: %[[A_ADDR:.*]] = alloca i64, i64 1, align 8
+// LLVM: %[[B_ADDR:.*]] = alloca i64, i64 1, align 8
+// LLVM: %[[C_ADDR:.*]] = alloca i64, i64 1, align 8
+// LLVM: %[[D_ADDR:.*]] = alloca i64, i64 1, align 8
+// LLVM: store i64 0, ptr %[[A_ADDR]], align 8
+// LLVM: store i64 124, ptr %[[B_ADDR]], align 8
+// LLVM: store i64 248, ptr %[[C_ADDR]], align 8
+// LLVM: store i64 376, ptr %[[D_ADDR]], align 8
+
+// OGCG: %[[A_ADDR:.*]] = alloca i64, align 8
+// OGCG: %[[B_ADDR:.*]] = alloca i64, align 8
+// OGCG: %[[C_ADDR:.*]] = alloca i64, align 8
+// OGCG: %[[D_ADDR:.*]] = alloca i64, align 8
+// OGCG: store i64 0, ptr %[[A_ADDR]], align 8
+// OGCG: store i64 124, ptr %[[B_ADDR]], align 8
+// OGCG: store i64 248, ptr %[[C_ADDR]], align 8
+// OGCG: store i64 376, ptr %[[D_ADDR]], align 8
|
|
@llvm/pr-subscribers-clang Author: Amr Hesham (AmrDeveloper) ChangesImplement support for the OffsetOfExpr Full diff: https://github.com/llvm/llvm-project/pull/167726.diff 2 Files Affected:
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index c1a36134d8942..c62e30d7e9c98 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -197,6 +197,8 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
return emitNullValue(e->getType(), cgf.getLoc(e->getSourceRange()));
}
+ mlir::Value VisitOffsetOfExpr(OffsetOfExpr *e);
+
mlir::Value VisitOpaqueValueExpr(OpaqueValueExpr *e) {
if (e->isGLValue())
return emitLoadOfLValue(cgf.getOrCreateOpaqueLValueMapping(e),
@@ -2164,6 +2166,21 @@ mlir::Value ScalarExprEmitter::VisitUnaryLNot(const UnaryOperator *e) {
return maybePromoteBoolResult(boolVal, cgf.convertType(e->getType()));
}
+mlir::Value ScalarExprEmitter::VisitOffsetOfExpr(OffsetOfExpr *e) {
+ // Try folding the offsetof to a constant.
+ Expr::EvalResult evalResult;
+ if (e->EvaluateAsInt(evalResult, cgf.getContext())) {
+ mlir::Type type = cgf.convertType(e->getType());
+ llvm::APSInt value = evalResult.Val.getInt();
+ return builder.getConstAPInt(cgf.getLoc(e->getExprLoc()), type, value);
+ }
+
+ cgf.getCIRGenModule().errorNYI(
+ e->getSourceRange(),
+ "ScalarExprEmitter::VisitOffsetOfExpr Can't eval expr as int");
+ return {};
+}
+
mlir::Value ScalarExprEmitter::VisitUnaryReal(const UnaryOperator *e) {
QualType promotionTy = getPromotionType(e->getSubExpr()->getType());
mlir::Value result = VisitRealImag(e, promotionTy);
diff --git a/clang/test/CIR/CodeGen/offset-of.cpp b/clang/test/CIR/CodeGen/offset-of.cpp
new file mode 100644
index 0000000000000..f62da9e6d9413
--- /dev/null
+++ b/clang/test/CIR/CodeGen/offset-of.cpp
@@ -0,0 +1,93 @@
+// RUN: %clang_cc1 -std=c++20 -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=c++20 -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=c++20 -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
+
+struct Struct {
+ int a;
+ float b;
+ double c;
+ bool d;
+};
+
+void offset_of_builtin() {
+ unsigned long a = __builtin_offsetof(Struct, a);
+ unsigned long b = __builtin_offsetof(Struct, b);
+ unsigned long c = __builtin_offsetof(Struct, c);
+ unsigned long d = __builtin_offsetof(Struct, d);
+}
+
+// CIR: %[[A_ADDR:.*]] = cir.alloca !u64i, !cir.ptr<!u64i>, ["a", init]
+// CIR: %[[B_ADDR:.*]] = cir.alloca !u64i, !cir.ptr<!u64i>, ["b", init]
+// CIR: %[[C_ADDR:.*]] = cir.alloca !u64i, !cir.ptr<!u64i>, ["c", init]
+// CIR: %[[D_ADDR:.*]] = cir.alloca !u64i, !cir.ptr<!u64i>, ["d", init]
+// CIR: %[[CONST_0:.*]] = cir.const #cir.int<0> : !u64i
+// CIR: cir.store {{.*}} %[[CONST_0]], %[[A_ADDR]] : !u64i, !cir.ptr<!u64i>
+// CIR: %[[CONST_4:.*]] = cir.const #cir.int<4> : !u64i
+// CIR: cir.store {{.*}} %[[CONST_4]], %[[B_ADDR]] : !u64i, !cir.ptr<!u64i>
+// CIR: %[[CONST_8:.*]] = cir.const #cir.int<8> : !u64i
+// CIR: cir.store {{.*}} %[[CONST_8]], %[[C_ADDR]] : !u64i, !cir.ptr<!u64i>
+// CIR: %[[CONST_16:.*]] = cir.const #cir.int<16> : !u64i
+// CIR: cir.store {{.*}} %[[CONST_16]], %[[D_ADDR]] : !u64i, !cir.ptr<!u64i>
+
+// LLVM: %[[A_ADDR:.*]] = alloca i64, i64 1, align 8
+// LLVM: %[[B_ADDR:.*]] = alloca i64, i64 1, align 8
+// LLVM: %[[C_ADDR:.*]] = alloca i64, i64 1, align 8
+// LLVM: %[[D_ADDR:.*]] = alloca i64, i64 1, align 8
+// LLVM: store i64 0, ptr %[[A_ADDR]], align 8
+// LLVM: store i64 4, ptr %[[B_ADDR]], align 8
+// LLVM: store i64 8, ptr %[[C_ADDR]], align 8
+// LLVM: store i64 16, ptr %[[D_ADDR]], align 8
+
+// OGCG: %[[A_ADDR:.*]] = alloca i64, align 8
+// OGCG: %[[B_ADDR:.*]] = alloca i64, align 8
+// OGCG: %[[C_ADDR:.*]] = alloca i64, align 8
+// OGCG: %[[D_ADDR:.*]] = alloca i64, align 8
+// OGCG: store i64 0, ptr %[[A_ADDR]], align 8
+// OGCG: store i64 4, ptr %[[B_ADDR]], align 8
+// OGCG: store i64 8, ptr %[[C_ADDR]], align 8
+// OGCG: store i64 16, ptr %[[D_ADDR]], align 8
+
+struct StructWithArray {
+ Struct array[4][4];
+};
+
+void offset_of_builtin_from_array_element() {
+ unsigned long a = __builtin_offsetof(StructWithArray, array[0][0].a);
+ unsigned long b = __builtin_offsetof(StructWithArray, array[1][1].b);
+ unsigned long c = __builtin_offsetof(StructWithArray, array[2][2].c);
+ unsigned long d = __builtin_offsetof(StructWithArray, array[3][3].d);
+}
+
+// CIR: %[[A_ADDR:.*]] = cir.alloca !u64i, !cir.ptr<!u64i>, ["a", init]
+// CIR: %[[B_ADDR:.*]] = cir.alloca !u64i, !cir.ptr<!u64i>, ["b", init]
+// CIR: %[[C_ADDR:.*]] = cir.alloca !u64i, !cir.ptr<!u64i>, ["c", init]
+// CIR: %[[D_ADDR:.*]] = cir.alloca !u64i, !cir.ptr<!u64i>, ["d", init]
+// CIR: %[[CONST_0:.*]] = cir.const #cir.int<0> : !u64i
+// CIR: cir.store {{.*}} %[[CONST_0]], %[[A_ADDR]] : !u64i, !cir.ptr<!u64i>
+// CIR: %[[CONST_124:.*]] = cir.const #cir.int<124> : !u64i
+// CIR: cir.store {{.*}} %[[CONST_124]], %[[B_ADDR]] : !u64i, !cir.ptr<!u64i>
+// CIR: %[[CONST_248:.*]] = cir.const #cir.int<248> : !u64i
+// CIR: cir.store {{.*}} %[[CONST_248]], %[[C_ADDR]] : !u64i, !cir.ptr<!u64i>
+// CIR: %[[CONST_376:.*]] = cir.const #cir.int<376> : !u64i
+// CIR: cir.store {{.*}} %[[CONST_376]], %[[D_ADDR]] : !u64i, !cir.ptr<!u64i>
+
+// LLVM: %[[A_ADDR:.*]] = alloca i64, i64 1, align 8
+// LLVM: %[[B_ADDR:.*]] = alloca i64, i64 1, align 8
+// LLVM: %[[C_ADDR:.*]] = alloca i64, i64 1, align 8
+// LLVM: %[[D_ADDR:.*]] = alloca i64, i64 1, align 8
+// LLVM: store i64 0, ptr %[[A_ADDR]], align 8
+// LLVM: store i64 124, ptr %[[B_ADDR]], align 8
+// LLVM: store i64 248, ptr %[[C_ADDR]], align 8
+// LLVM: store i64 376, ptr %[[D_ADDR]], align 8
+
+// OGCG: %[[A_ADDR:.*]] = alloca i64, align 8
+// OGCG: %[[B_ADDR:.*]] = alloca i64, align 8
+// OGCG: %[[C_ADDR:.*]] = alloca i64, align 8
+// OGCG: %[[D_ADDR:.*]] = alloca i64, align 8
+// OGCG: store i64 0, ptr %[[A_ADDR]], align 8
+// OGCG: store i64 124, ptr %[[B_ADDR]], align 8
+// OGCG: store i64 248, ptr %[[C_ADDR]], align 8
+// OGCG: store i64 376, ptr %[[D_ADDR]], align 8
|
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
9204e48 to
9329cdf
Compare
Implement support for the OffsetOfExpr