[clang] [CIR] Support ComplexType in CallExpr args (PR #156236)
Amr Hesham via cfe-commits
cfe-commits at lists.llvm.org
Sun Aug 31 04:35:15 PDT 2025
https://github.com/AmrDeveloper updated https://github.com/llvm/llvm-project/pull/156236
>From b823f59b8fcf77bfa3a7077773b86dc692fea8b8 Mon Sep 17 00:00:00 2001
From: AmrDeveloper <amr96 at programmer.net>
Date: Sun, 31 Aug 2025 12:44:19 +0200
Subject: [PATCH] [CIR] Support ComplexType in CallExpr args
---
clang/lib/CIR/CodeGen/CIRGenCall.cpp | 27 +++++++++++++----
clang/lib/CIR/CodeGen/CIRGenCall.h | 3 ++
clang/test/CIR/CodeGen/complex.cpp | 43 ++++++++++++++++++++++++++++
3 files changed, 67 insertions(+), 6 deletions(-)
diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
index 25859885296fa..d0e0a66df904b 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
@@ -15,6 +15,7 @@
#include "CIRGenCXXABI.h"
#include "CIRGenFunction.h"
#include "CIRGenFunctionInfo.h"
+#include "mlir/IR/Location.h"
#include "clang/CIR/MissingFeatures.h"
using namespace clang;
@@ -518,7 +519,8 @@ RValue CIRGenFunction::emitCall(const CIRGenFunctionInfo &funcInfo,
assert(!cir::MissingFeatures::opCallPaddingArgs());
mlir::Type argType = convertType(canQualArgType);
- if (!mlir::isa<cir::RecordType>(argType)) {
+ if (!mlir::isa<cir::RecordType>(argType) &&
+ !mlir::isa<cir::ComplexType>(argType)) {
mlir::Value v;
if (arg.isAggregate())
cgm.errorNYI(loc, "emitCall: aggregate call argument");
@@ -536,15 +538,16 @@ RValue CIRGenFunction::emitCall(const CIRGenFunctionInfo &funcInfo,
cirCallArgs[argNo] = v;
} else {
Address src = Address::invalid();
- if (!arg.isAggregate())
- cgm.errorNYI(loc, "emitCall: non-aggregate call argument");
- else
+ if (!arg.isAggregate()) {
+ src = createMemTemp(arg.ty, loc, "coerce");
+ arg.copyInto(*this, src, loc);
+ } else {
src = arg.hasLValue() ? arg.getKnownLValue().getAddress()
: arg.getKnownRValue().getAggregateAddress();
+ }
// Fast-isel and the optimizer generally like scalar values better than
// FCAs, so we flatten them if this is safe to do for this argument.
- auto argRecordTy = cast<cir::RecordType>(argType);
mlir::Type srcTy = src.getElementType();
// FIXME(cir): get proper location for each argument.
mlir::Location argLoc = loc;
@@ -560,7 +563,7 @@ RValue CIRGenFunction::emitCall(const CIRGenFunctionInfo &funcInfo,
// uint64_t DstSize = CGM.getDataLayout().getTypeAllocSize(STy);
// if (SrcSize < DstSize) {
assert(!cir::MissingFeatures::dataLayoutTypeAllocSize());
- if (srcTy != argRecordTy) {
+ if (srcTy != argType) {
cgm.errorNYI(loc, "emitCall: source type does not match argument type");
} else {
// FIXME(cir): this currently only runs when the types are exactly the
@@ -672,6 +675,18 @@ RValue CIRGenFunction::emitCall(const CIRGenFunctionInfo &funcInfo,
llvm_unreachable("Invalid evaluation kind");
}
+void CallArg::copyInto(CIRGenFunction &cgf, Address addr,
+ mlir::Location loc) const {
+ LValue dst = cgf.makeAddrLValue(addr, ty);
+ if (!hasLV && rv.isScalar())
+ cgf.cgm.errorNYI(loc, "copyInto scalar value");
+ else if (!hasLV && rv.isComplex())
+ cgf.emitStoreOfComplex(loc, rv.getComplexValue(), dst, /*isInit=*/true);
+ else
+ cgf.cgm.errorNYI(loc, "copyInto hasLV");
+ isUsed = true;
+}
+
void CIRGenFunction::emitCallArg(CallArgList &args, const clang::Expr *e,
clang::QualType argType) {
assert(argType->isReferenceType() == e->isGLValue() &&
diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.h b/clang/lib/CIR/CodeGen/CIRGenCall.h
index 81cbb854f3b7d..994d960e3f17f 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCall.h
+++ b/clang/lib/CIR/CodeGen/CIRGenCall.h
@@ -15,6 +15,7 @@
#define CLANG_LIB_CODEGEN_CIRGENCALL_H
#include "CIRGenValue.h"
+#include "mlir/IR/Location.h"
#include "mlir/IR/Operation.h"
#include "clang/AST/GlobalDecl.h"
#include "llvm/ADT/SmallVector.h"
@@ -224,6 +225,8 @@ struct CallArg {
}
bool isAggregate() const { return hasLV || rv.isAggregate(); }
+
+ void copyInto(CIRGenFunction &cgf, Address addr, mlir::Location loc) const;
};
class CallArgList : public llvm::SmallVector<CallArg, 8> {
diff --git a/clang/test/CIR/CodeGen/complex.cpp b/clang/test/CIR/CodeGen/complex.cpp
index db837e568e0be..c09a9ce6d5079 100644
--- a/clang/test/CIR/CodeGen/complex.cpp
+++ b/clang/test/CIR/CodeGen/complex.cpp
@@ -909,3 +909,46 @@ void foo33(__builtin_va_list a) {
// OGCG: %[[B_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[B_ADDR]], i32 0, i32 1
// OGCG: store float %[[RESULT_REAL]], ptr %[[B_REAL_PTR]], align 4
// OGCG: store float %[[RESULT_IMAG]], ptr %[[B_IMAG_PTR]], align 4
+
+void foo34(float _Complex a) {}
+
+// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["a", init]
+// CIR: cir.store %{{.*}}, %[[A_ADDR]] : !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>
+
+// LLVM: %[[A_ADDR:.*]] = alloca { float, float }, i64 1, align 4
+// LLVM: store { float, float } %{{.*}}, ptr %[[A_ADDR]], align 4
+
+// OGCG: %[[A_ADDR:.*]] = alloca { float, float }, align 4
+// OGCG: store <2 x float> %a.coerce, ptr %[[A_ADDR]], align 4
+
+void foo35() {
+ float _Complex a;
+ foo34(a);
+}
+
+// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["a"]
+// CIR: %[[ARG_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["coerce"]
+// CIR: %[[TMP_A:.*]] = cir.load{{.*}} %[[A_ADDR]] : !cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>
+// CIR: cir.store{{.*}} %[[TMP_A]], %[[ARG_ADDR]] : !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>
+// CIR: %[[TMP_ARG:.*]] = cir.load{{.*}} %[[ARG_ADDR]] : !cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>
+// CIR: cir.call @_Z5foo34Cf(%[[TMP_ARG]]) : (!cir.complex<!cir.float>) -> ()
+
+// LLVM: %[[A_ADDR:.*]] = alloca { float, float }, i64 1, align 4
+// LLVM: %[[ARG_ADDR:.*]] = alloca { float, float }, i64 1, align 4
+// LLVM: %[[TMP_A:.*]] = load { float, float }, ptr %[[A_ADDR]], align 4
+// LLVM: store { float, float } %[[TMP_A]], ptr %[[ARG_ADDR]], align 4
+// LLVM: %[[TMP_ARG:.*]] = load { float, float }, ptr %[[ARG_ADDR]], align 4
+// LLVM: call void @_Z5foo34Cf({ float, float } %[[TMP_ARG]])
+
+// OGCG: %[[A_ADDR:.*]] = alloca { float, float }, align 4
+// OGCG: %[[ARG_ADDR:.*]] = alloca { float, float }, align 4
+// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 0
+// OGCG: %[[A_REAL:.*]] = load float, ptr %[[A_REAL_PTR]], align 4
+// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 1
+// OGCG: %[[A_IMAG:.*]] = load float, ptr %[[A_IMAG_PTR]], align 4
+// OGCG: %[[ARG_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[ARG_ADDR]], i32 0, i32 0
+// OGCG: %[[ARG_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[ARG_ADDR]], i32 0, i32 1
+// OGCG: store float %[[A_REAL]], ptr %[[ARG_REAL_PTR]], align 4
+// OGCG: store float %[[A_IMAG]], ptr %[[ARG_IMAG_PTR]], align 4
+// OGCG: %[[TMP_ARG:.*]] = load <2 x float>, ptr %[[ARG_ADDR]], align 4
+// OGCG: call void @_Z5foo34Cf(<2 x float> noundef %[[TMP_ARG]])
More information about the cfe-commits
mailing list