llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Amr Hesham (AmrDeveloper) <details> <summary>Changes</summary> This change adds support for the MemberExpr ComplexType Issue: https://github.com/llvm/llvm-project/issues/141365 --- Full diff: https://github.com/llvm/llvm-project/pull/154027.diff 4 Files Affected: - (modified) clang/lib/CIR/CodeGen/CIRGenExpr.cpp (+21-2) - (modified) clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp (+8) - (modified) clang/lib/CIR/CodeGen/CIRGenFunction.h (+2-1) - (modified) clang/test/CIR/CodeGen/complex.cpp (+30) ``````````diff 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 `````````` </details> https://github.com/llvm/llvm-project/pull/154027 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits