mlir::Value genAssociated(fir::FirOpBuilder &, mlir::Location,
mlir::Value pointer, mlir::Value target);
+void genPointerAssociate(fir::FirOpBuilder &, mlir::Location,
+ mlir::Value pointer, mlir::Value target);
+
mlir::Value genCpuTime(fir::FirOpBuilder &, mlir::Location);
void genDateAndTime(fir::FirOpBuilder &, mlir::Location,
llvm::Optional<fir::CharBoxValue> date,
/// e.g. !fir.box<!fir.type<derived>>
bool isBoxedRecordType(mlir::Type ty);
+/// Return true iff `ty` is a !fir.ref<!fir.box<T>> type.
+bool isRefBoxType(mlir::Type ty);
+
+/// Return true iff `ty` is !fir.box<none> type.
+bool isOpaqueDescType(mlir::Type ty);
+
/// Return true iff `ty` is the type of an polymorphic entity or
/// value.
bool isPolymorphicType(mlir::Type ty);
[&](const Fortran::evaluate::Assignment::BoundsSpec &lbExprs) {
if (Fortran::evaluate::IsProcedure(assign.rhs))
TODO(loc, "procedure pointer assignment");
+
+ std::optional<Fortran::evaluate::DynamicType> lhsType =
+ assign.lhs.GetType();
+ // Delegate pointer association to unlimited polymorphic pointer
+ // to the runtime. element size, type code, attribute and of
+ // course base_addr might need to be updated.
+ if (lhsType && lhsType->IsUnlimitedPolymorphic()) {
+ mlir::Value lhs = genExprMutableBox(loc, assign.lhs).getAddr();
+ mlir::Value rhs = genExprMutableBox(loc, assign.rhs).getAddr();
+ Fortran::lower::genPointerAssociate(*builder, loc, lhs, rhs);
+ return;
+ }
+
llvm::SmallVector<mlir::Value> lbounds;
for (const Fortran::evaluate::ExtentExpr &lbExpr : lbExprs)
lbounds.push_back(
return builder.create<fir::CallOp>(loc, func, args).getResult(0);
}
+void Fortran::lower::genPointerAssociate(fir::FirOpBuilder &builder,
+ mlir::Location loc,
+ mlir::Value pointer,
+ mlir::Value target) {
+ mlir::func::FuncOp func =
+ fir::runtime::getRuntimeFunc<mkRTKey(PointerAssociate)>(loc, builder);
+ llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(
+ builder, loc, func.getFunctionType(), pointer, target);
+ builder.create<fir::CallOp>(loc, func, args).getResult(0);
+}
+
mlir::Value Fortran::lower::genCpuTime(fir::FirOpBuilder &builder,
mlir::Location loc) {
mlir::func::FuncOp func =
(inType.isa<fir::BoxProcType>() && outType.isa<fir::BoxProcType>()) ||
(fir::isa_complex(inType) && fir::isa_complex(outType)) ||
(fir::isBoxedRecordType(inType) && fir::isPolymorphicType(outType)) ||
- (fir::isPolymorphicType(inType) && fir::isPolymorphicType(outType)))
+ (fir::isPolymorphicType(inType) && fir::isPolymorphicType(outType)) ||
+ (fir::isRefBoxType(inType) && fir::isOpaqueDescType(outType)))
return mlir::success();
+ llvm::errs() << inType << " / " << outType << "\n";
return emitOpError("invalid type conversion");
}
return false;
}
+bool isRefBoxType(mlir::Type ty) {
+ if (auto refTy = ty.dyn_cast<fir::ReferenceType>())
+ return refTy.getEleTy().isa<fir::BaseBoxType>();
+ return false;
+}
+
+bool isOpaqueDescType(mlir::Type ty) {
+ if (auto boxTy = ty.dyn_cast<fir::BoxType>())
+ if (boxTy.getEleTy().isa<mlir::NoneType>())
+ return true;
+ return false;
+}
+
static bool isAssumedType(mlir::Type ty) {
if (auto boxTy = ty.dyn_cast<fir::BoxType>()) {
if (boxTy.getEleTy().isa<mlir::NoneType>())
! CHECK-LABEL: func.func @_QMpolymorphic_testPcall_up_ret() {
! CHECK: %{{.*}} = fir.call @_QMpolymorphic_testPup_ret() {{.*}} : () -> !fir.class<!fir.ptr<!fir.array<?xnone>>>
- subroutine rebox_f32_to_none(r)
+ subroutine associate_up_pointer(r)
class(r1) :: r
class(*), pointer :: p(:)
p => r%rp
end subroutine
-! CHECK-LABEL: func.func @_QMpolymorphic_testPrebox_f32_to_none(
+! CHECK-LABEL: func.func @_QMpolymorphic_testPassociate_up_pointer(
! CHECK-SAME: %[[ARG0:.*]]: !fir.class<!fir.type<_QMpolymorphic_testTr1{rp:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>> {fir.bindc_name = "r"}) {
-! CHECK: %[[P:.*]] = fir.alloca !fir.class<!fir.ptr<!fir.array<?xnone>>> {bindc_name = "p", uniq_name = "_QMpolymorphic_testFrebox_f32_to_noneEp"}
+! CHECK: %[[P:.*]] = fir.alloca !fir.class<!fir.ptr<!fir.array<?xnone>>> {bindc_name = "p", uniq_name = "_QMpolymorphic_testFassociate_up_pointerEp"}
! CHECK: %[[FIELD_RP:.*]] = fir.field_index rp, !fir.type<_QMpolymorphic_testTr1{rp:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>
! CHECK: %[[COORD_RP:.*]] = fir.coordinate_of %[[ARG0]], %[[FIELD_RP]] : (!fir.class<!fir.type<_QMpolymorphic_testTr1{rp:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>, !fir.field) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>
-! CHECK: %[[LOADED_RP:.*]] = fir.load %[[COORD_RP]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>
-! CHECK: %[[C0:.*]] = arith.constant 0 : index
-! CHECK: %[[RP_DIMS:.*]]:3 = fir.box_dims %[[LOADED_RP]], %[[C0]] : (!fir.box<!fir.ptr<!fir.array<?xf32>>>, index) -> (index, index, index)
-! CHECK: %[[SHIFT:.*]] = fir.shift %[[RP_DIMS]]#0 : (index) -> !fir.shift<1>
-! CHECK: %[[REBOX_TO_BOX:.*]] = fir.rebox %[[LOADED_RP]](%[[SHIFT]]) : (!fir.box<!fir.ptr<!fir.array<?xf32>>>, !fir.shift<1>) -> !fir.box<!fir.array<?xf32>>
-! CHECK: %[[REBOX_TO_UP:.*]] = fir.rebox %[[REBOX_TO_BOX]] : (!fir.box<!fir.array<?xf32>>) -> !fir.class<!fir.ptr<!fir.array<?xnone>>>
-! CHECK: fir.store %[[REBOX_TO_UP]] to %[[P]] : !fir.ref<!fir.class<!fir.ptr<!fir.array<?xnone>>>>
+! CHECK: %[[CONV_P:.*]] = fir.convert %[[P]] : (!fir.ref<!fir.class<!fir.ptr<!fir.array<?xnone>>>>) -> !fir.ref<!fir.box<none>>
+! CHECK: %[[CONV_RP:.*]] = fir.convert %[[COORD_RP]] : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>) -> !fir.box<none>
+! CHECK: %{{.*}} = fir.call @_FortranAPointerAssociate(%[[CONV_P]], %[[CONV_RP]]) {{.*}} : (!fir.ref<!fir.box<none>>, !fir.box<none>) -> none
! CHECK: return
! Test that the fir.dispatch operation is created with the correct pass object