diff --git a/flang/include/flang/Optimizer/Builder/Runtime/Assign.h b/flang/include/flang/Optimizer/Builder/Runtime/Assign.h --- a/flang/include/flang/Optimizer/Builder/Runtime/Assign.h +++ b/flang/include/flang/Optimizer/Builder/Runtime/Assign.h @@ -28,5 +28,12 @@ void genAssign(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value destBox, mlir::Value sourceBox); +/// Generate runtime call to AssignPolymorphic \p sourceBox to \p destBox. +/// \p destBox must be a fir.ref> and \p sourceBox a fir.box. +/// \p destBox Fortran descriptor may be modified if destBox is an allocatable +/// according to Fortran allocatable assignment rules. +void genAssignPolymorphic(fir::FirOpBuilder &builder, mlir::Location loc, + mlir::Value destBox, mlir::Value sourceBox); + } // namespace fir::runtime #endif // FORTRAN_OPTIMIZER_BUILDER_RUNTIME_ASSIGN_H diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp --- a/flang/lib/Lower/Bridge.cpp +++ b/flang/lib/Lower/Bridge.cpp @@ -3038,7 +3038,12 @@ lhs = fir::getBase(genExprBox(loc, assign.lhs, stmtCtx)); mlir::Value rhs = fir::getBase(genExprBox(loc, assign.rhs, stmtCtx)); - fir::runtime::genAssign(*builder, loc, lhs, rhs); + if ((lhsType->IsPolymorphic() || + lhsType->IsUnlimitedPolymorphic()) && + Fortran::lower::isWholeAllocatable(assign.lhs)) + fir::runtime::genAssignPolymorphic(*builder, loc, lhs, rhs); + else + fir::runtime::genAssign(*builder, loc, lhs, rhs); return; } diff --git a/flang/lib/Optimizer/Builder/Runtime/Assign.cpp b/flang/lib/Optimizer/Builder/Runtime/Assign.cpp --- a/flang/lib/Optimizer/Builder/Runtime/Assign.cpp +++ b/flang/lib/Optimizer/Builder/Runtime/Assign.cpp @@ -24,3 +24,17 @@ sourceBox, sourceFile, sourceLine); builder.create(loc, func, args); } + +void fir::runtime::genAssignPolymorphic(fir::FirOpBuilder &builder, + mlir::Location loc, mlir::Value destBox, + mlir::Value sourceBox) { + auto func = + fir::runtime::getRuntimeFunc(loc, builder); + auto fTy = func.getFunctionType(); + auto sourceFile = fir::factory::locationToFilename(builder, loc); + auto sourceLine = + fir::factory::locationToLineNo(builder, loc, fTy.getInput(3)); + auto args = fir::runtime::createArguments(builder, loc, fTy, destBox, + sourceBox, sourceFile, sourceLine); + builder.create(loc, func, args); +} diff --git a/flang/test/Lower/polymorphic.f90 b/flang/test/Lower/polymorphic.f90 --- a/flang/test/Lower/polymorphic.f90 +++ b/flang/test/Lower/polymorphic.f90 @@ -411,7 +411,7 @@ ! CHECK: %[[BOXED_T:.*]] = fir.embox %[[T]](%[[SHAPE]]) : (!fir.ref>>, !fir.shape<2>) -> !fir.box>> ! CHECK: %[[CONV_C:.*]] = fir.convert %[[C]] : (!fir.ref>>>>) -> !fir.ref> ! CHECK: %[[CONV_BOXED_T:.*]] = fir.convert %[[BOXED_T]] : (!fir.box>>) -> !fir.box -! CHECK: %{{.*}} = fir.call @_FortranAAssign(%[[CONV_C]], %[[CONV_BOXED_T]], %{{.*}}, %{{.*}}) fastmath : (!fir.ref>, !fir.box, !fir.ref, i32) -> none +! CHECK: %{{.*}} = fir.call @_FortranAAssignPolymorphic(%[[CONV_C]], %[[CONV_BOXED_T]], %{{.*}}, %{{.*}}) fastmath : (!fir.ref>, !fir.box, !fir.ref, i32) -> none ! CHECK: return subroutine pointer_assign_remap()