Skip to content

Commit a6a78eb

Browse files
authored
[CIR] Support ComplexType in CallExpr args (llvm#156236)
This change adds support for ComplexType in the CallExpr args Issue: llvm#141365
1 parent 7c666e2 commit a6a78eb

File tree

3 files changed

+68
-6
lines changed

3 files changed

+68
-6
lines changed

clang/lib/CIR/CodeGen/CIRGenCall.cpp

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -522,7 +522,8 @@ RValue CIRGenFunction::emitCall(const CIRGenFunctionInfo &funcInfo,
522522
assert(!cir::MissingFeatures::opCallPaddingArgs());
523523

524524
mlir::Type argType = convertType(canQualArgType);
525-
if (!mlir::isa<cir::RecordType>(argType)) {
525+
if (!mlir::isa<cir::RecordType>(argType) &&
526+
!mlir::isa<cir::ComplexType>(argType)) {
526527
mlir::Value v;
527528
if (arg.isAggregate())
528529
cgm.errorNYI(loc, "emitCall: aggregate call argument");
@@ -540,15 +541,16 @@ RValue CIRGenFunction::emitCall(const CIRGenFunctionInfo &funcInfo,
540541
cirCallArgs[argNo] = v;
541542
} else {
542543
Address src = Address::invalid();
543-
if (!arg.isAggregate())
544-
cgm.errorNYI(loc, "emitCall: non-aggregate call argument");
545-
else
544+
if (!arg.isAggregate()) {
545+
src = createMemTemp(arg.ty, loc, "coerce");
546+
arg.copyInto(*this, src, loc);
547+
} else {
546548
src = arg.hasLValue() ? arg.getKnownLValue().getAddress()
547549
: arg.getKnownRValue().getAggregateAddress();
550+
}
548551

549552
// Fast-isel and the optimizer generally like scalar values better than
550553
// FCAs, so we flatten them if this is safe to do for this argument.
551-
auto argRecordTy = cast<cir::RecordType>(argType);
552554
mlir::Type srcTy = src.getElementType();
553555
// FIXME(cir): get proper location for each argument.
554556
mlir::Location argLoc = loc;
@@ -564,7 +566,7 @@ RValue CIRGenFunction::emitCall(const CIRGenFunctionInfo &funcInfo,
564566
// uint64_t DstSize = CGM.getDataLayout().getTypeAllocSize(STy);
565567
// if (SrcSize < DstSize) {
566568
assert(!cir::MissingFeatures::dataLayoutTypeAllocSize());
567-
if (srcTy != argRecordTy) {
569+
if (srcTy != argType) {
568570
cgm.errorNYI(loc, "emitCall: source type does not match argument type");
569571
} else {
570572
// FIXME(cir): this currently only runs when the types are exactly the
@@ -676,6 +678,18 @@ RValue CIRGenFunction::emitCall(const CIRGenFunctionInfo &funcInfo,
676678
llvm_unreachable("Invalid evaluation kind");
677679
}
678680

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

clang/lib/CIR/CodeGen/CIRGenCall.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,8 @@ struct CallArg {
224224
}
225225

226226
bool isAggregate() const { return hasLV || rv.isAggregate(); }
227+
228+
void copyInto(CIRGenFunction &cgf, Address addr, mlir::Location loc) const;
227229
};
228230

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

clang/test/CIR/CodeGen/complex.cpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1311,3 +1311,49 @@ 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+
// TODO(CIR): the difference between the CIR LLVM and OGCG is because the lack of calling convention lowering,
1321+
// Test will be updated when that is implemented
1322+
1323+
// LLVM: %[[A_ADDR:.*]] = alloca { float, float }, i64 1, align 4
1324+
// LLVM: store { float, float } %{{.*}}, ptr %[[A_ADDR]], align 4
1325+
1326+
// OGCG: %[[A_ADDR:.*]] = alloca { float, float }, align 4
1327+
// OGCG: store <2 x float> %a.coerce, ptr %[[A_ADDR]], align 4
1328+
1329+
void complex_type_argument() {
1330+
float _Complex a;
1331+
complex_type_parameter(a);
1332+
}
1333+
1334+
// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["a"]
1335+
// CIR: %[[ARG_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["coerce"]
1336+
// CIR: %[[TMP_A:.*]] = cir.load{{.*}} %[[A_ADDR]] : !cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>
1337+
// CIR: cir.store{{.*}} %[[TMP_A]], %[[ARG_ADDR]] : !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>
1338+
// CIR: %[[TMP_ARG:.*]] = cir.load{{.*}} %[[ARG_ADDR]] : !cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>
1339+
// CIR: cir.call @_Z22complex_type_parameterCf(%[[TMP_ARG]]) : (!cir.complex<!cir.float>) -> ()
1340+
1341+
// LLVM: %[[A_ADDR:.*]] = alloca { float, float }, i64 1, align 4
1342+
// LLVM: %[[ARG_ADDR:.*]] = alloca { float, float }, i64 1, align 4
1343+
// LLVM: %[[TMP_A:.*]] = load { float, float }, ptr %[[A_ADDR]], align 4
1344+
// LLVM: store { float, float } %[[TMP_A]], ptr %[[ARG_ADDR]], align 4
1345+
// LLVM: %[[TMP_ARG:.*]] = load { float, float }, ptr %[[ARG_ADDR]], align 4
1346+
// LLVM: call void @_Z22complex_type_parameterCf({ float, float } %[[TMP_ARG]])
1347+
1348+
// OGCG: %[[A_ADDR:.*]] = alloca { float, float }, align 4
1349+
// OGCG: %[[ARG_ADDR:.*]] = alloca { float, float }, align 4
1350+
// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 0
1351+
// OGCG: %[[A_REAL:.*]] = load float, ptr %[[A_REAL_PTR]], align 4
1352+
// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 1
1353+
// OGCG: %[[A_IMAG:.*]] = load float, ptr %[[A_IMAG_PTR]], align 4
1354+
// OGCG: %[[ARG_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[ARG_ADDR]], i32 0, i32 0
1355+
// OGCG: %[[ARG_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[ARG_ADDR]], i32 0, i32 1
1356+
// OGCG: store float %[[A_REAL]], ptr %[[ARG_REAL_PTR]], align 4
1357+
// OGCG: store float %[[A_IMAG]], ptr %[[ARG_IMAG_PTR]], align 4
1358+
// OGCG: %[[TMP_ARG:.*]] = load <2 x float>, ptr %[[ARG_ADDR]], align 4
1359+
// OGCG: call void @_Z22complex_type_parameterCf(<2 x float> noundef %[[TMP_ARG]])

0 commit comments

Comments
 (0)