Skip to content

Commit 1289be6

Browse files
committed
[CIR] Support ComplexType in CallExpr args
1 parent b86fef8 commit 1289be6

File tree

3 files changed

+67
-6
lines changed

3 files changed

+67
-6
lines changed

clang/lib/CIR/CodeGen/CIRGenCall.cpp

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "CIRGenCXXABI.h"
1616
#include "CIRGenFunction.h"
1717
#include "CIRGenFunctionInfo.h"
18+
#include "mlir/IR/Location.h"
1819
#include "clang/CIR/MissingFeatures.h"
1920

2021
using namespace clang;
@@ -522,7 +523,8 @@ RValue CIRGenFunction::emitCall(const CIRGenFunctionInfo &funcInfo,
522523
assert(!cir::MissingFeatures::opCallPaddingArgs());
523524

524525
mlir::Type argType = convertType(canQualArgType);
525-
if (!mlir::isa<cir::RecordType>(argType)) {
526+
if (!mlir::isa<cir::RecordType>(argType) &&
527+
!mlir::isa<cir::ComplexType>(argType)) {
526528
mlir::Value v;
527529
if (arg.isAggregate())
528530
cgm.errorNYI(loc, "emitCall: aggregate call argument");
@@ -540,15 +542,16 @@ RValue CIRGenFunction::emitCall(const CIRGenFunctionInfo &funcInfo,
540542
cirCallArgs[argNo] = v;
541543
} else {
542544
Address src = Address::invalid();
543-
if (!arg.isAggregate())
544-
cgm.errorNYI(loc, "emitCall: non-aggregate call argument");
545-
else
545+
if (!arg.isAggregate()) {
546+
src = createMemTemp(arg.ty, loc, "coerce");
547+
arg.copyInto(*this, src, loc);
548+
} else {
546549
src = arg.hasLValue() ? arg.getKnownLValue().getAddress()
547550
: arg.getKnownRValue().getAggregateAddress();
551+
}
548552

549553
// Fast-isel and the optimizer generally like scalar values better than
550554
// FCAs, so we flatten them if this is safe to do for this argument.
551-
auto argRecordTy = cast<cir::RecordType>(argType);
552555
mlir::Type srcTy = src.getElementType();
553556
// FIXME(cir): get proper location for each argument.
554557
mlir::Location argLoc = loc;
@@ -564,7 +567,7 @@ RValue CIRGenFunction::emitCall(const CIRGenFunctionInfo &funcInfo,
564567
// uint64_t DstSize = CGM.getDataLayout().getTypeAllocSize(STy);
565568
// if (SrcSize < DstSize) {
566569
assert(!cir::MissingFeatures::dataLayoutTypeAllocSize());
567-
if (srcTy != argRecordTy) {
570+
if (srcTy != argType) {
568571
cgm.errorNYI(loc, "emitCall: source type does not match argument type");
569572
} else {
570573
// FIXME(cir): this currently only runs when the types are exactly the
@@ -676,6 +679,18 @@ RValue CIRGenFunction::emitCall(const CIRGenFunctionInfo &funcInfo,
676679
llvm_unreachable("Invalid evaluation kind");
677680
}
678681

682+
void CallArg::copyInto(CIRGenFunction &cgf, Address addr,
683+
mlir::Location loc) const {
684+
LValue dst = cgf.makeAddrLValue(addr, ty);
685+
if (!hasLV && rv.isScalar())
686+
cgf.cgm.errorNYI(loc, "copyInto scalar value");
687+
else if (!hasLV && rv.isComplex())
688+
cgf.emitStoreOfComplex(loc, rv.getComplexValue(), dst, /*isInit=*/true);
689+
else
690+
cgf.cgm.errorNYI(loc, "copyInto hasLV");
691+
isUsed = true;
692+
}
693+
679694
void CIRGenFunction::emitCallArg(CallArgList &args, const clang::Expr *e,
680695
clang::QualType argType) {
681696
assert(argType->isReferenceType() == e->isGLValue() &&

clang/lib/CIR/CodeGen/CIRGenCall.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#define CLANG_LIB_CODEGEN_CIRGENCALL_H
1616

1717
#include "CIRGenValue.h"
18+
#include "mlir/IR/Location.h"
1819
#include "mlir/IR/Operation.h"
1920
#include "clang/AST/GlobalDecl.h"
2021
#include "llvm/ADT/SmallVector.h"
@@ -224,6 +225,8 @@ struct CallArg {
224225
}
225226

226227
bool isAggregate() const { return hasLV || rv.isAggregate(); }
228+
229+
void copyInto(CIRGenFunction &cgf, Address addr, mlir::Location loc) const;
227230
};
228231

229232
class CallArgList : public llvm::SmallVector<CallArg, 8> {

clang/test/CIR/CodeGen/complex.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1311,3 +1311,46 @@ void real_on_scalar_from_imag_with_type_promotion() {
13111311
// OGCG: %[[A_IMAG_F32:.*]] = fpext half %[[A_IMAG]] to float
13121312
// OGCG: %[[A_IMAG_F16:.*]] = fptrunc float %[[A_IMAG_F32]] to half
13131313
// OGCG: store half %[[A_IMAG_F16]], ptr %[[B_ADDR]], align 2
1314+
1315+
void complex_type_parameter(float _Complex a) {}
1316+
1317+
// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["a", init]
1318+
// CIR: cir.store %{{.*}}, %[[A_ADDR]] : !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>
1319+
1320+
// LLVM: %[[A_ADDR:.*]] = alloca { float, float }, i64 1, align 4
1321+
// LLVM: store { float, float } %{{.*}}, ptr %[[A_ADDR]], align 4
1322+
1323+
// OGCG: %[[A_ADDR:.*]] = alloca { float, float }, align 4
1324+
// OGCG: store <2 x float> %a.coerce, ptr %[[A_ADDR]], align 4
1325+
1326+
void complex_type_argument() {
1327+
float _Complex a;
1328+
complex_type_parameter(a);
1329+
}
1330+
1331+
// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["a"]
1332+
// CIR: %[[ARG_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["coerce"]
1333+
// CIR: %[[TMP_A:.*]] = cir.load{{.*}} %[[A_ADDR]] : !cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>
1334+
// CIR: cir.store{{.*}} %[[TMP_A]], %[[ARG_ADDR]] : !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>
1335+
// CIR: %[[TMP_ARG:.*]] = cir.load{{.*}} %[[ARG_ADDR]] : !cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>
1336+
// CIR: cir.call @_Z5foo34Cf(%[[TMP_ARG]]) : (!cir.complex<!cir.float>) -> ()
1337+
1338+
// LLVM: %[[A_ADDR:.*]] = alloca { float, float }, i64 1, align 4
1339+
// LLVM: %[[ARG_ADDR:.*]] = alloca { float, float }, i64 1, align 4
1340+
// LLVM: %[[TMP_A:.*]] = load { float, float }, ptr %[[A_ADDR]], align 4
1341+
// LLVM: store { float, float } %[[TMP_A]], ptr %[[ARG_ADDR]], align 4
1342+
// LLVM: %[[TMP_ARG:.*]] = load { float, float }, ptr %[[ARG_ADDR]], align 4
1343+
// LLVM: call void @_Z5foo34Cf({ float, float } %[[TMP_ARG]])
1344+
1345+
// OGCG: %[[A_ADDR:.*]] = alloca { float, float }, align 4
1346+
// OGCG: %[[ARG_ADDR:.*]] = alloca { float, float }, align 4
1347+
// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 0
1348+
// OGCG: %[[A_REAL:.*]] = load float, ptr %[[A_REAL_PTR]], align 4
1349+
// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 1
1350+
// OGCG: %[[A_IMAG:.*]] = load float, ptr %[[A_IMAG_PTR]], align 4
1351+
// OGCG: %[[ARG_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[ARG_ADDR]], i32 0, i32 0
1352+
// OGCG: %[[ARG_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[ARG_ADDR]], i32 0, i32 1
1353+
// OGCG: store float %[[A_REAL]], ptr %[[ARG_REAL_PTR]], align 4
1354+
// OGCG: store float %[[A_IMAG]], ptr %[[ARG_IMAG_PTR]], align 4
1355+
// OGCG: %[[TMP_ARG:.*]] = load <2 x float>, ptr %[[ARG_ADDR]], align 4
1356+
// OGCG: call void @_Z5foo34Cf(<2 x float> noundef %[[TMP_ARG]])

0 commit comments

Comments
 (0)