diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp index ff38bbeb529d..66721c0fd640 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp @@ -718,6 +718,47 @@ RValue CIRGenFunction::buildBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, switch (BuiltinIDIfNoAsmLabel) { default: break; + + case Builtin::BI__builtin_complex: { + mlir::Value Real = buildScalarExpr(E->getArg(0)); + mlir::Value Imag = buildScalarExpr(E->getArg(1)); + mlir::Value Complex = + builder.createComplexCreate(getLoc(E->getExprLoc()), Real, Imag); + return RValue::getComplex(Complex); + } + + case Builtin::BI__builtin_creal: + case Builtin::BI__builtin_crealf: + case Builtin::BI__builtin_creall: + case Builtin::BIcreal: + case Builtin::BIcrealf: + case Builtin::BIcreall: { + mlir::Value ComplexVal = buildComplexExpr(E->getArg(0)); + mlir::Value Real = + builder.createComplexReal(getLoc(E->getExprLoc()), ComplexVal); + return RValue::get(Real); + } + + case Builtin::BI__builtin_cimag: + case Builtin::BI__builtin_cimagf: + case Builtin::BI__builtin_cimagl: + case Builtin::BIcimag: + case Builtin::BIcimagf: + case Builtin::BIcimagl: { + mlir::Value ComplexVal = buildComplexExpr(E->getArg(0)); + mlir::Value Real = + builder.createComplexImag(getLoc(E->getExprLoc()), ComplexVal); + return RValue::get(Real); + } + + case Builtin::BI__builtin_conj: + case Builtin::BI__builtin_conjf: + case Builtin::BI__builtin_conjl: + case Builtin::BIconj: + case Builtin::BIconjf: + case Builtin::BIconjl: + llvm_unreachable("NYI"); + case Builtin::BI__builtin___CFStringMakeConstantString: case Builtin::BI__builtin___NSStringMakeConstantString: llvm_unreachable("NYI"); diff --git a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp index e1c4af1748c8..51a7c6b72e82 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp @@ -129,7 +129,7 @@ class ComplexExprEmitter : public StmtVisitor { return buildCast(E->getCastKind(), E->getSubExpr(), E->getType()); } mlir::Value VisitCastExpr(CastExpr *E) { llvm_unreachable("NYI"); } - mlir::Value VisitCallExpr(const CallExpr *E) { llvm_unreachable("NYI"); } + mlir::Value VisitCallExpr(const CallExpr *E); mlir::Value VisitStmtExpr(const StmtExpr *E) { llvm_unreachable("NYI"); } // Operators. @@ -501,6 +501,13 @@ mlir::Value ComplexExprEmitter::buildCast(CastKind CK, Expr *Op, llvm_unreachable("unknown cast resulting in complex value"); } +mlir::Value ComplexExprEmitter::VisitCallExpr(const CallExpr *E) { + if (E->getCallReturnType(CGF.getContext())->isReferenceType()) + return buildLoadOfLValue(E); + + return CGF.buildCallExpr(E).getComplexVal(); +} + ComplexExprEmitter::BinOpInfo ComplexExprEmitter::buildBinOps(const BinaryOperator *E, QualType PromotionTy) { BinOpInfo Ops{CGF.getLoc(E->getExprLoc())}; diff --git a/clang/test/CIR/CodeGen/complex.c b/clang/test/CIR/CodeGen/complex.c index 41ffca8334f3..e8c9885f685f 100644 --- a/clang/test/CIR/CodeGen/complex.c +++ b/clang/test/CIR/CodeGen/complex.c @@ -48,6 +48,21 @@ void list_init_2(double r, double i) { // LLVM-NEXT: store { double, double } %[[#B]], ptr %5, align 8 // LLVM: } +void builtin_init(double r, double i) { + double _Complex c = __builtin_complex(r, i); +} + +// C: cir.func @builtin_init +// CPP: cir.func @_Z12builtin_initdd +// CHECK: %{{.+}} = cir.complex.create %{{.+}}, %{{.+}} : !cir.double -> !cir.complex +// CHECK: } + +// LLVM: define void @builtin_init +// LLVM: %[[#A:]] = insertvalue { double, double } undef, double %{{.+}}, 0 +// LLVM-NEXT: %[[#B:]] = insertvalue { double, double } %[[#A]], double %{{.+}}, 1 +// LLVM-NEXT: store { double, double } %[[#B]], ptr %{{.+}}, align 8 +// LLVM: } + void imag_literal() { c = 3.0i; ci = 3i; @@ -116,6 +131,38 @@ void load_store_volatile() { // LLVM-NEXT: store volatile { i32, i32 } %[[#B]], ptr @vci, align 4 // LLVM: } +void real() { + double r = __builtin_creal(c); +} + +// C: cir.func no_proto @real() +// CPP: cir.func @_Z4realv() +// CHECK: %[[#A:]] = cir.get_global @c : !cir.ptr> +// CHECK-NEXT: %[[#B:]] = cir.load %[[#A]] : !cir.ptr>, !cir.complex +// CHECK-NEXT: %{{.+}} = cir.complex.real %[[#B]] : !cir.complex -> !cir.double +// CHECK: } + +// LLVM: define void @real() +// LLVM: %[[#A:]] = extractvalue { double, double } %{{.+}}, 0 +// LLVM-NEXT: store double %[[#A]], ptr %{{.+}}, align 8 +// LLVM: } + +void imag() { + double i = __builtin_cimag(c); +} + +// C: cir.func no_proto @imag() +// CPP: cir.func @_Z4imagv() +// CHECK: %[[#A:]] = cir.get_global @c : !cir.ptr> +// CHECK-NEXT: %[[#B:]] = cir.load %[[#A]] : !cir.ptr>, !cir.complex +// CHECK-NEXT: %{{.+}} = cir.complex.imag %[[#B]] : !cir.complex -> !cir.double +// CHECK: } + +// LLVM: define void @imag() +// LLVM: %[[#A:]] = extractvalue { double, double } %{{.+}}, 1 +// LLVM-NEXT: store double %[[#A]], ptr %{{.+}}, align 8 +// LLVM: } + void real_ptr() { double *r1 = &__real__ c; int *r2 = &__real__ ci;