@@ -400,17 +400,19 @@ constexpr TypeBuilderFunc getModel<bool &>() {
400
400
return fir::ReferenceType::get (f (context));
401
401
};
402
402
}
403
- template <>
404
- constexpr TypeBuilderFunc getModel<std::complex<float >>() {
405
- return [](mlir::MLIRContext *context) -> mlir::Type {
406
- return mlir::ComplexType::get (mlir::FloatType::getF32 (context));
407
- };
408
- }
403
+
404
+ // getModel<std::complex<T>> are not implemented on purpose.
405
+ // Prefer passing/returning the complex by reference in the runtime to
406
+ // avoid ABI issues.
407
+ // C++ std::complex is not an intrinsic type, and while it is storage
408
+ // compatible with C/Fortran complex type, it follows the struct value passing
409
+ // ABI rule, which may differ from how C complex are passed on some platforms.
410
+
409
411
template <>
410
412
constexpr TypeBuilderFunc getModel<std::complex<float > &>() {
411
413
return [](mlir::MLIRContext *context) -> mlir::Type {
412
- TypeBuilderFunc f{ getModel<std::complex< float >>()} ;
413
- return fir::ReferenceType::get (f (context ));
414
+ mlir::Type floatTy = getModel<float >()(context) ;
415
+ return fir::ReferenceType::get (mlir::ComplexType::get (floatTy ));
414
416
};
415
417
}
416
418
template <>
@@ -422,16 +424,10 @@ constexpr TypeBuilderFunc getModel<const std::complex<float> *>() {
422
424
return getModel<std::complex<float > *>();
423
425
}
424
426
template <>
425
- constexpr TypeBuilderFunc getModel<std::complex<double >>() {
426
- return [](mlir::MLIRContext *context) -> mlir::Type {
427
- return mlir::ComplexType::get (mlir::FloatType::getF64 (context));
428
- };
429
- }
430
- template <>
431
427
constexpr TypeBuilderFunc getModel<std::complex<double > &>() {
432
428
return [](mlir::MLIRContext *context) -> mlir::Type {
433
- TypeBuilderFunc f{ getModel<std::complex< double >>()} ;
434
- return fir::ReferenceType::get (f (context ));
429
+ mlir::Type floatTy = getModel<double >()(context) ;
430
+ return fir::ReferenceType::get (mlir::ComplexType::get (floatTy ));
435
431
};
436
432
}
437
433
template <>
@@ -521,10 +517,45 @@ REDUCTION_VALUE_OPERATION_MODEL(double)
521
517
REDUCTION_REF_OPERATION_MODEL (long double )
522
518
REDUCTION_VALUE_OPERATION_MODEL (long double )
523
519
524
- REDUCTION_REF_OPERATION_MODEL (std::complex<float >)
525
- REDUCTION_VALUE_OPERATION_MODEL (std::complex<float >)
526
- REDUCTION_REF_OPERATION_MODEL (std::complex<double >)
527
- REDUCTION_VALUE_OPERATION_MODEL (std::complex<double >)
520
+ // FIXME: the runtime is not using the correct ABIs when calling complex
521
+ // callbacks. lowering either need to create wrappers or just have an inline
522
+ // implementation for it. https://github.com/llvm/llvm-project/issues/110674
523
+ template <>
524
+ constexpr TypeBuilderFunc
525
+ getModel<Fortran::runtime::ValueReductionOperation<std::complex<float >>>() {
526
+ return [](mlir::MLIRContext *context) -> mlir::Type {
527
+ mlir::Type cplx = mlir::ComplexType::get (getModel<float >()(context));
528
+ auto refTy = fir::ReferenceType::get (cplx);
529
+ return mlir::FunctionType::get (context, {cplx, cplx}, refTy);
530
+ };
531
+ }
532
+ template <>
533
+ constexpr TypeBuilderFunc
534
+ getModel<Fortran::runtime::ValueReductionOperation<std::complex<double >>>() {
535
+ return [](mlir::MLIRContext *context) -> mlir::Type {
536
+ mlir::Type cplx = mlir::ComplexType::get (getModel<double >()(context));
537
+ auto refTy = fir::ReferenceType::get (cplx);
538
+ return mlir::FunctionType::get (context, {cplx, cplx}, refTy);
539
+ };
540
+ }
541
+ template <>
542
+ constexpr TypeBuilderFunc
543
+ getModel<Fortran::runtime::ReferenceReductionOperation<std::complex<float >>>() {
544
+ return [](mlir::MLIRContext *context) -> mlir::Type {
545
+ mlir::Type cplx = mlir::ComplexType::get (getModel<float >()(context));
546
+ auto refTy = fir::ReferenceType::get (cplx);
547
+ return mlir::FunctionType::get (context, {refTy, refTy}, refTy);
548
+ };
549
+ }
550
+ template <>
551
+ constexpr TypeBuilderFunc getModel<
552
+ Fortran::runtime::ReferenceReductionOperation<std::complex<double >>>() {
553
+ return [](mlir::MLIRContext *context) -> mlir::Type {
554
+ mlir::Type cplx = mlir::ComplexType::get (getModel<double >()(context));
555
+ auto refTy = fir::ReferenceType::get (cplx);
556
+ return mlir::FunctionType::get (context, {refTy, refTy}, refTy);
557
+ };
558
+ }
528
559
529
560
REDUCTION_CHAR_OPERATION_MODEL (char )
530
561
REDUCTION_CHAR_OPERATION_MODEL (char16_t )
0 commit comments