-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[CIR] Implement MemberExpr support for ComplexType #154027
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-clang Author: Amr Hesham (AmrDeveloper) ChangesThis change adds support for the MemberExpr ComplexType Issue: #141365 Full diff: https://github.com/llvm/llvm-project/pull/154027.diff 4 Files Affected:
diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
index 8bcca6f5d1803..707ae83d0d1b0 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
@@ -2063,8 +2063,8 @@ cir::AllocaOp CIRGenFunction::createTempAlloca(mlir::Type ty,
///
/// For named members of enums, this is the only way they are emitted.
CIRGenFunction::ConstantEmission
-CIRGenFunction::tryEmitAsConstant(DeclRefExpr *refExpr) {
- ValueDecl *value = refExpr->getDecl();
+CIRGenFunction::tryEmitAsConstant(const DeclRefExpr *refExpr) {
+ const ValueDecl *value = refExpr->getDecl();
// There is a lot more to do here, but for now only EnumConstantDecl is
// supported.
@@ -2097,6 +2097,25 @@ CIRGenFunction::tryEmitAsConstant(DeclRefExpr *refExpr) {
return ConstantEmission::forValue(cstToEmit);
}
+static DeclRefExpr *tryToConvertMemberExprToDeclRefExpr(CIRGenFunction &cgf,
+ const MemberExpr *me) {
+ if (auto *vd = dyn_cast<VarDecl>(me->getMemberDecl())) {
+ // Try to emit static variable member expressions as DREs.
+ return DeclRefExpr::Create(
+ cgf.getContext(), NestedNameSpecifierLoc(), SourceLocation(), vd,
+ /*RefersToEnclosingVariableOrCapture=*/false, me->getExprLoc(),
+ me->getType(), me->getValueKind(), nullptr, nullptr, me->isNonOdrUse());
+ }
+ return nullptr;
+}
+
+CIRGenFunction::ConstantEmission
+CIRGenFunction::tryEmitAsConstant(const MemberExpr *me) {
+ if (DeclRefExpr *dre = tryToConvertMemberExprToDeclRefExpr(*this, me))
+ return tryEmitAsConstant(dre);
+ return ConstantEmission();
+}
+
mlir::Value CIRGenFunction::emitScalarConstant(
const CIRGenFunction::ConstantEmission &constant, Expr *e) {
assert(constant && "not a constant");
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
index 85cd0282ffc2a..98310e63daaf4 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
@@ -62,6 +62,14 @@ class ComplexExprEmitter : public StmtVisitor<ComplexExprEmitter, mlir::Value> {
mlir::Value VisitImplicitCastExpr(ImplicitCastExpr *e);
mlir::Value VisitInitListExpr(InitListExpr *e);
+ mlir::Value VisitMemberExpr(MemberExpr *me) {
+ if (CIRGenFunction::ConstantEmission constant = cgf.tryEmitAsConstant(me)) {
+ cgf.emitIgnoredExpr(me->getBase());
+ return emitConstant(constant, me);
+ }
+ return emitLoadOfLValue(me);
+ }
+
mlir::Value VisitCompoundLiteralExpr(CompoundLiteralExpr *e) {
return emitLoadOfLValue(e);
}
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h
index 9a887ec047f86..7096c8189b7db 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -452,7 +452,8 @@ class CIRGenFunction : public CIRGenTypeCache {
}
};
- ConstantEmission tryEmitAsConstant(DeclRefExpr *refExpr);
+ ConstantEmission tryEmitAsConstant(const DeclRefExpr *refExpr);
+ ConstantEmission tryEmitAsConstant(const MemberExpr *me);
struct AutoVarEmission {
const clang::VarDecl *Variable;
diff --git a/clang/test/CIR/CodeGen/complex.cpp b/clang/test/CIR/CodeGen/complex.cpp
index bd7de9a3a5039..90504bee3549f 100644
--- a/clang/test/CIR/CodeGen/complex.cpp
+++ b/clang/test/CIR/CodeGen/complex.cpp
@@ -799,3 +799,33 @@ void foo30() {
// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 1
// OGCG: store float 1.000000e+00, ptr %[[A_REAL_PTR]], align 4
// OGCG: store float 0.000000e+00, ptr %[[A_IMAG_PTR]], align 4
+
+void foo31() {
+ struct Wrapper {
+ int _Complex c;
+ };
+
+ Wrapper w;
+ int r = __real__ w.c;
+}
+
+// CIR: %[[W_ADDR:.*]] = cir.alloca !rec_Wrapper, !cir.ptr<!rec_Wrapper>, ["w"]
+// CIR: %[[REAL_ADDR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["r", init]
+// CIR: %[[ELEM_PTR:.*]] = cir.get_member %[[W_ADDR]][0] {name = "c"} : !cir.ptr<!rec_Wrapper> -> !cir.ptr<!cir.complex<!s32i>>
+// CIR: %[[TMP_ELEM_PTR:.*]] = cir.load{{.*}} %[[ELEM_PTR]] : !cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i>
+// CIR: %[[REAL:.*]] = cir.complex.real %[[TMP_ELEM_PTR]] : !cir.complex<!s32i> -> !s32i
+// CIR: cir.store{{.*}} %[[REAL]], %[[REAL_ADDR]] : !s32i, !cir.ptr<!s32i>
+
+// LLVM: %[[W_ADDR:.*]] = alloca %struct.Wrapper, i64 1, align 4
+// LLVM: %[[REAL_ADDR:.*]] = alloca i32, i64 1, align 4
+// LLVM: %[[ELEM_PTR:.*]] = getelementptr %struct.Wrapper, ptr %[[W_ADDR]], i32 0, i32 0
+// LLVM: %[[TMP_ELEM_PTR:.*]] = load { i32, i32 }, ptr %[[ELEM_PTR]], align 4
+// LLVM: %[[REAL:.*]] = extractvalue { i32, i32 } %[[TMP_ELEM_PTR]], 0
+// LLVM: store i32 %[[REAL]], ptr %[[REAL_ADDR]], align 4
+
+// OGCG: %[[W_ADDR:.*]] = alloca %struct.Wrapper, align 4
+// OGCG: %[[REAL_ADDR:.*]] = alloca i32, align 4
+// OGCG: %[[ELEM_PTR:.*]] = getelementptr inbounds nuw %struct.Wrapper, ptr %[[W_ADDR]], i32 0, i32 0
+// OGCG: %[[REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[ELEM_PTR]], i32 0, i32 0
+// OGCG: %[[REAL:.*]] = load i32, ptr %[[REAL_PTR]], align 4
+// OGCG: store i32 %[[REAL]], ptr %[[REAL_ADDR]], align 4
|
|
@llvm/pr-subscribers-clangir Author: Amr Hesham (AmrDeveloper) ChangesThis change adds support for the MemberExpr ComplexType Issue: #141365 Full diff: https://github.com/llvm/llvm-project/pull/154027.diff 4 Files Affected:
diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
index 8bcca6f5d1803..707ae83d0d1b0 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
@@ -2063,8 +2063,8 @@ cir::AllocaOp CIRGenFunction::createTempAlloca(mlir::Type ty,
///
/// For named members of enums, this is the only way they are emitted.
CIRGenFunction::ConstantEmission
-CIRGenFunction::tryEmitAsConstant(DeclRefExpr *refExpr) {
- ValueDecl *value = refExpr->getDecl();
+CIRGenFunction::tryEmitAsConstant(const DeclRefExpr *refExpr) {
+ const ValueDecl *value = refExpr->getDecl();
// There is a lot more to do here, but for now only EnumConstantDecl is
// supported.
@@ -2097,6 +2097,25 @@ CIRGenFunction::tryEmitAsConstant(DeclRefExpr *refExpr) {
return ConstantEmission::forValue(cstToEmit);
}
+static DeclRefExpr *tryToConvertMemberExprToDeclRefExpr(CIRGenFunction &cgf,
+ const MemberExpr *me) {
+ if (auto *vd = dyn_cast<VarDecl>(me->getMemberDecl())) {
+ // Try to emit static variable member expressions as DREs.
+ return DeclRefExpr::Create(
+ cgf.getContext(), NestedNameSpecifierLoc(), SourceLocation(), vd,
+ /*RefersToEnclosingVariableOrCapture=*/false, me->getExprLoc(),
+ me->getType(), me->getValueKind(), nullptr, nullptr, me->isNonOdrUse());
+ }
+ return nullptr;
+}
+
+CIRGenFunction::ConstantEmission
+CIRGenFunction::tryEmitAsConstant(const MemberExpr *me) {
+ if (DeclRefExpr *dre = tryToConvertMemberExprToDeclRefExpr(*this, me))
+ return tryEmitAsConstant(dre);
+ return ConstantEmission();
+}
+
mlir::Value CIRGenFunction::emitScalarConstant(
const CIRGenFunction::ConstantEmission &constant, Expr *e) {
assert(constant && "not a constant");
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
index 85cd0282ffc2a..98310e63daaf4 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
@@ -62,6 +62,14 @@ class ComplexExprEmitter : public StmtVisitor<ComplexExprEmitter, mlir::Value> {
mlir::Value VisitImplicitCastExpr(ImplicitCastExpr *e);
mlir::Value VisitInitListExpr(InitListExpr *e);
+ mlir::Value VisitMemberExpr(MemberExpr *me) {
+ if (CIRGenFunction::ConstantEmission constant = cgf.tryEmitAsConstant(me)) {
+ cgf.emitIgnoredExpr(me->getBase());
+ return emitConstant(constant, me);
+ }
+ return emitLoadOfLValue(me);
+ }
+
mlir::Value VisitCompoundLiteralExpr(CompoundLiteralExpr *e) {
return emitLoadOfLValue(e);
}
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h
index 9a887ec047f86..7096c8189b7db 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -452,7 +452,8 @@ class CIRGenFunction : public CIRGenTypeCache {
}
};
- ConstantEmission tryEmitAsConstant(DeclRefExpr *refExpr);
+ ConstantEmission tryEmitAsConstant(const DeclRefExpr *refExpr);
+ ConstantEmission tryEmitAsConstant(const MemberExpr *me);
struct AutoVarEmission {
const clang::VarDecl *Variable;
diff --git a/clang/test/CIR/CodeGen/complex.cpp b/clang/test/CIR/CodeGen/complex.cpp
index bd7de9a3a5039..90504bee3549f 100644
--- a/clang/test/CIR/CodeGen/complex.cpp
+++ b/clang/test/CIR/CodeGen/complex.cpp
@@ -799,3 +799,33 @@ void foo30() {
// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 1
// OGCG: store float 1.000000e+00, ptr %[[A_REAL_PTR]], align 4
// OGCG: store float 0.000000e+00, ptr %[[A_IMAG_PTR]], align 4
+
+void foo31() {
+ struct Wrapper {
+ int _Complex c;
+ };
+
+ Wrapper w;
+ int r = __real__ w.c;
+}
+
+// CIR: %[[W_ADDR:.*]] = cir.alloca !rec_Wrapper, !cir.ptr<!rec_Wrapper>, ["w"]
+// CIR: %[[REAL_ADDR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["r", init]
+// CIR: %[[ELEM_PTR:.*]] = cir.get_member %[[W_ADDR]][0] {name = "c"} : !cir.ptr<!rec_Wrapper> -> !cir.ptr<!cir.complex<!s32i>>
+// CIR: %[[TMP_ELEM_PTR:.*]] = cir.load{{.*}} %[[ELEM_PTR]] : !cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i>
+// CIR: %[[REAL:.*]] = cir.complex.real %[[TMP_ELEM_PTR]] : !cir.complex<!s32i> -> !s32i
+// CIR: cir.store{{.*}} %[[REAL]], %[[REAL_ADDR]] : !s32i, !cir.ptr<!s32i>
+
+// LLVM: %[[W_ADDR:.*]] = alloca %struct.Wrapper, i64 1, align 4
+// LLVM: %[[REAL_ADDR:.*]] = alloca i32, i64 1, align 4
+// LLVM: %[[ELEM_PTR:.*]] = getelementptr %struct.Wrapper, ptr %[[W_ADDR]], i32 0, i32 0
+// LLVM: %[[TMP_ELEM_PTR:.*]] = load { i32, i32 }, ptr %[[ELEM_PTR]], align 4
+// LLVM: %[[REAL:.*]] = extractvalue { i32, i32 } %[[TMP_ELEM_PTR]], 0
+// LLVM: store i32 %[[REAL]], ptr %[[REAL_ADDR]], align 4
+
+// OGCG: %[[W_ADDR:.*]] = alloca %struct.Wrapper, align 4
+// OGCG: %[[REAL_ADDR:.*]] = alloca i32, align 4
+// OGCG: %[[ELEM_PTR:.*]] = getelementptr inbounds nuw %struct.Wrapper, ptr %[[W_ADDR]], i32 0, i32 0
+// OGCG: %[[REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[ELEM_PTR]], i32 0, i32 0
+// OGCG: %[[REAL:.*]] = load i32, ptr %[[REAL_PTR]], align 4
+// OGCG: store i32 %[[REAL]], ptr %[[REAL_ADDR]], align 4
|
xlauko
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
|
|
||
| mlir::Value VisitMemberExpr(MemberExpr *me) { | ||
| if (CIRGenFunction::ConstantEmission constant = cgf.tryEmitAsConstant(me)) { | ||
| cgf.emitIgnoredExpr(me->getBase()); |
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.
Is it possible to have a test case that gets here? I don't think it is with what's currently upstreamed. If we can't test this code, I'd like to see a call to errorNYI here until we can.
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, it requires upstreaming one part of CIRGenFunction::emitMemberExpr, I added NYI until we add it
This change adds support for the MemberExpr ComplexType
Issue: #141365