Skip to content

Commit 5581e34

Browse files
authored
[CIR] Implement MemberExpr support for ComplexType (#154027)
This change adds support for the MemberExpr ComplexType Issue: #141365
1 parent 13d8ba7 commit 5581e34

File tree

4 files changed

+61
-3
lines changed

4 files changed

+61
-3
lines changed

clang/lib/CIR/CodeGen/CIRGenExpr.cpp

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2067,8 +2067,8 @@ cir::AllocaOp CIRGenFunction::createTempAlloca(mlir::Type ty,
20672067
///
20682068
/// For named members of enums, this is the only way they are emitted.
20692069
CIRGenFunction::ConstantEmission
2070-
CIRGenFunction::tryEmitAsConstant(DeclRefExpr *refExpr) {
2071-
ValueDecl *value = refExpr->getDecl();
2070+
CIRGenFunction::tryEmitAsConstant(const DeclRefExpr *refExpr) {
2071+
const ValueDecl *value = refExpr->getDecl();
20722072

20732073
// There is a lot more to do here, but for now only EnumConstantDecl is
20742074
// supported.
@@ -2101,6 +2101,25 @@ CIRGenFunction::tryEmitAsConstant(DeclRefExpr *refExpr) {
21012101
return ConstantEmission::forValue(cstToEmit);
21022102
}
21032103

2104+
static DeclRefExpr *tryToConvertMemberExprToDeclRefExpr(CIRGenFunction &cgf,
2105+
const MemberExpr *me) {
2106+
if (auto *vd = dyn_cast<VarDecl>(me->getMemberDecl())) {
2107+
// Try to emit static variable member expressions as DREs.
2108+
return DeclRefExpr::Create(
2109+
cgf.getContext(), NestedNameSpecifierLoc(), SourceLocation(), vd,
2110+
/*RefersToEnclosingVariableOrCapture=*/false, me->getExprLoc(),
2111+
me->getType(), me->getValueKind(), nullptr, nullptr, me->isNonOdrUse());
2112+
}
2113+
return nullptr;
2114+
}
2115+
2116+
CIRGenFunction::ConstantEmission
2117+
CIRGenFunction::tryEmitAsConstant(const MemberExpr *me) {
2118+
if (DeclRefExpr *dre = tryToConvertMemberExprToDeclRefExpr(*this, me))
2119+
return tryEmitAsConstant(dre);
2120+
return ConstantEmission();
2121+
}
2122+
21042123
mlir::Value CIRGenFunction::emitScalarConstant(
21052124
const CIRGenFunction::ConstantEmission &constant, Expr *e) {
21062125
assert(constant && "not a constant");

clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,14 @@ class ComplexExprEmitter : public StmtVisitor<ComplexExprEmitter, mlir::Value> {
6262
mlir::Value VisitImplicitCastExpr(ImplicitCastExpr *e);
6363
mlir::Value VisitInitListExpr(InitListExpr *e);
6464

65+
mlir::Value VisitMemberExpr(MemberExpr *me) {
66+
if (CIRGenFunction::ConstantEmission constant = cgf.tryEmitAsConstant(me)) {
67+
cgf.cgm.errorNYI("VisitMemberExpr tryEmitAsConstant");
68+
return {};
69+
}
70+
return emitLoadOfLValue(me);
71+
}
72+
6573
mlir::Value VisitCompoundLiteralExpr(CompoundLiteralExpr *e) {
6674
return emitLoadOfLValue(e);
6775
}

clang/lib/CIR/CodeGen/CIRGenFunction.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -452,7 +452,8 @@ class CIRGenFunction : public CIRGenTypeCache {
452452
}
453453
};
454454

455-
ConstantEmission tryEmitAsConstant(DeclRefExpr *refExpr);
455+
ConstantEmission tryEmitAsConstant(const DeclRefExpr *refExpr);
456+
ConstantEmission tryEmitAsConstant(const MemberExpr *me);
456457

457458
struct AutoVarEmission {
458459
const clang::VarDecl *Variable;

clang/test/CIR/CodeGen/complex.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -799,3 +799,33 @@ void foo30() {
799799
// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 1
800800
// OGCG: store float 1.000000e+00, ptr %[[A_REAL_PTR]], align 4
801801
// OGCG: store float 0.000000e+00, ptr %[[A_IMAG_PTR]], align 4
802+
803+
void foo31() {
804+
struct Wrapper {
805+
int _Complex c;
806+
};
807+
808+
Wrapper w;
809+
int r = __real__ w.c;
810+
}
811+
812+
// CIR: %[[W_ADDR:.*]] = cir.alloca !rec_Wrapper, !cir.ptr<!rec_Wrapper>, ["w"]
813+
// CIR: %[[REAL_ADDR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["r", init]
814+
// CIR: %[[ELEM_PTR:.*]] = cir.get_member %[[W_ADDR]][0] {name = "c"} : !cir.ptr<!rec_Wrapper> -> !cir.ptr<!cir.complex<!s32i>>
815+
// CIR: %[[TMP_ELEM_PTR:.*]] = cir.load{{.*}} %[[ELEM_PTR]] : !cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i>
816+
// CIR: %[[REAL:.*]] = cir.complex.real %[[TMP_ELEM_PTR]] : !cir.complex<!s32i> -> !s32i
817+
// CIR: cir.store{{.*}} %[[REAL]], %[[REAL_ADDR]] : !s32i, !cir.ptr<!s32i>
818+
819+
// LLVM: %[[W_ADDR:.*]] = alloca %struct.Wrapper, i64 1, align 4
820+
// LLVM: %[[REAL_ADDR:.*]] = alloca i32, i64 1, align 4
821+
// LLVM: %[[ELEM_PTR:.*]] = getelementptr %struct.Wrapper, ptr %[[W_ADDR]], i32 0, i32 0
822+
// LLVM: %[[TMP_ELEM_PTR:.*]] = load { i32, i32 }, ptr %[[ELEM_PTR]], align 4
823+
// LLVM: %[[REAL:.*]] = extractvalue { i32, i32 } %[[TMP_ELEM_PTR]], 0
824+
// LLVM: store i32 %[[REAL]], ptr %[[REAL_ADDR]], align 4
825+
826+
// OGCG: %[[W_ADDR:.*]] = alloca %struct.Wrapper, align 4
827+
// OGCG: %[[REAL_ADDR:.*]] = alloca i32, align 4
828+
// OGCG: %[[ELEM_PTR:.*]] = getelementptr inbounds nuw %struct.Wrapper, ptr %[[W_ADDR]], i32 0, i32 0
829+
// OGCG: %[[REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[ELEM_PTR]], i32 0, i32 0
830+
// OGCG: %[[REAL:.*]] = load i32, ptr %[[REAL_PTR]], align 4
831+
// OGCG: store i32 %[[REAL]], ptr %[[REAL_ADDR]], align 4

0 commit comments

Comments
 (0)