@@ -400,17 +400,19 @@ constexpr TypeBuilderFunc getModel<bool &>() {
400400 return fir::ReferenceType::get (f (context));
401401 };
402402}
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+
409411template <>
410412constexpr TypeBuilderFunc getModel<std::complex <float > &>() {
411413 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 ));
414416 };
415417}
416418template <>
@@ -422,16 +424,10 @@ constexpr TypeBuilderFunc getModel<const std::complex<float> *>() {
422424 return getModel<std::complex <float > *>();
423425}
424426template <>
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 <>
431427constexpr TypeBuilderFunc getModel<std::complex <double > &>() {
432428 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 ));
435431 };
436432}
437433template <>
@@ -521,10 +517,45 @@ REDUCTION_VALUE_OPERATION_MODEL(double)
521517REDUCTION_REF_OPERATION_MODEL (long double )
522518REDUCTION_VALUE_OPERATION_MODEL (long double )
523519
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+ }
528559
529560REDUCTION_CHAR_OPERATION_MODEL (char )
530561REDUCTION_CHAR_OPERATION_MODEL (char16_t )
0 commit comments