@@ -751,4 +751,226 @@ template bool OpenACCMappableModel<fir::PointerType>::generatePrivateDestroy(
751751 mlir::Type type, mlir::OpBuilder &builder, mlir::Location loc,
752752 mlir::Value privatized) const ;
753753
754+ template <typename Ty>
755+ mlir::Value OpenACCPointerLikeModel<Ty>::genAllocate(
756+ mlir::Type pointer, mlir::OpBuilder &builder, mlir::Location loc,
757+ llvm::StringRef varName, mlir::Type varType, mlir::Value originalVar,
758+ bool &needsFree) const {
759+
760+ // Get the element type from the pointer type
761+ mlir::Type eleTy = mlir::cast<Ty>(pointer).getElementType ();
762+
763+ // Unlimited polymorphic (class(*)) cannot be handled - size unknown
764+ if (fir::isUnlimitedPolymorphicType (eleTy))
765+ return {};
766+
767+ // Character types with dynamic length cannot be handled without a descriptor.
768+ if (auto charTy = mlir::dyn_cast<fir::CharacterType>(eleTy))
769+ if (charTy.hasDynamicLen ())
770+ return {};
771+
772+ // Return null for dynamic or unknown shape arrays because the size of the
773+ // allocation cannot be determined simply from the type.
774+ if (auto seqTy = mlir::dyn_cast<fir::SequenceType>(eleTy))
775+ if (seqTy.hasDynamicExtents () || seqTy.hasUnknownShape ())
776+ return {};
777+
778+ // Use heap allocation for fir.heap, stack allocation for others (fir.ref,
779+ // fir.ptr, fir.llvm_ptr). For fir.ptr, which is supposed to represent a
780+ // Fortran pointer type, it feels a bit odd to "allocate" since it is meant
781+ // to point to an existing entity - but one can imagine where a pointee is
782+ // privatized - thus it makes sense to issue an allocate.
783+ mlir::Value allocation;
784+ if (std::is_same_v<Ty, fir::HeapType>) {
785+ needsFree = true ;
786+ allocation = fir::AllocMemOp::create (builder, loc, eleTy);
787+ } else {
788+ needsFree = false ;
789+ allocation = fir::AllocaOp::create (builder, loc, eleTy);
790+ }
791+
792+ // Convert to the requested pointer type if needed.
793+ // This means converting from a fir.ref to either a fir.llvm_ptr or a fir.ptr.
794+ // fir.heap is already correct type in this case.
795+ if (allocation.getType () != pointer) {
796+ assert (!(std::is_same_v<Ty, fir::HeapType>) &&
797+ " fir.heap is already correct type because of allocmem" );
798+ return fir::ConvertOp::create (builder, loc, pointer, allocation);
799+ }
800+
801+ return allocation;
802+ }
803+
804+ template mlir::Value OpenACCPointerLikeModel<fir::ReferenceType>::genAllocate(
805+ mlir::Type pointer, mlir::OpBuilder &builder, mlir::Location loc,
806+ llvm::StringRef varName, mlir::Type varType, mlir::Value originalVar,
807+ bool &needsFree) const ;
808+
809+ template mlir::Value OpenACCPointerLikeModel<fir::PointerType>::genAllocate(
810+ mlir::Type pointer, mlir::OpBuilder &builder, mlir::Location loc,
811+ llvm::StringRef varName, mlir::Type varType, mlir::Value originalVar,
812+ bool &needsFree) const ;
813+
814+ template mlir::Value OpenACCPointerLikeModel<fir::HeapType>::genAllocate(
815+ mlir::Type pointer, mlir::OpBuilder &builder, mlir::Location loc,
816+ llvm::StringRef varName, mlir::Type varType, mlir::Value originalVar,
817+ bool &needsFree) const ;
818+
819+ template mlir::Value OpenACCPointerLikeModel<fir::LLVMPointerType>::genAllocate(
820+ mlir::Type pointer, mlir::OpBuilder &builder, mlir::Location loc,
821+ llvm::StringRef varName, mlir::Type varType, mlir::Value originalVar,
822+ bool &needsFree) const ;
823+
824+ static mlir::Value stripCasts (mlir::Value value, bool stripDeclare = true ) {
825+ mlir::Value currentValue = value;
826+
827+ while (currentValue) {
828+ auto *definingOp = currentValue.getDefiningOp ();
829+ if (!definingOp)
830+ break ;
831+
832+ if (auto convertOp = mlir::dyn_cast<fir::ConvertOp>(definingOp)) {
833+ currentValue = convertOp.getValue ();
834+ continue ;
835+ }
836+
837+ if (auto viewLike = mlir::dyn_cast<mlir::ViewLikeOpInterface>(definingOp)) {
838+ currentValue = viewLike.getViewSource ();
839+ continue ;
840+ }
841+
842+ if (stripDeclare) {
843+ if (auto declareOp = mlir::dyn_cast<hlfir::DeclareOp>(definingOp)) {
844+ currentValue = declareOp.getMemref ();
845+ continue ;
846+ }
847+
848+ if (auto declareOp = mlir::dyn_cast<fir::DeclareOp>(definingOp)) {
849+ currentValue = declareOp.getMemref ();
850+ continue ;
851+ }
852+ }
853+ break ;
854+ }
855+
856+ return currentValue;
857+ }
858+
859+ template <typename Ty>
860+ bool OpenACCPointerLikeModel<Ty>::genFree(
861+ mlir::Type pointer, mlir::OpBuilder &builder, mlir::Location loc,
862+ mlir::TypedValue<mlir::acc::PointerLikeType> varToFree,
863+ mlir::Value allocRes, mlir::Type varType) const {
864+
865+ // If pointer type is HeapType, assume it's a heap allocation
866+ if (std::is_same_v<Ty, fir::HeapType>) {
867+ fir::FreeMemOp::create (builder, loc, varToFree);
868+ return true ;
869+ }
870+
871+ // Use allocRes if provided to determine the allocation type
872+ mlir::Value valueToInspect = allocRes ? allocRes : varToFree;
873+
874+ // Strip casts and declare operations to find the original allocation
875+ mlir::Value strippedValue = stripCasts (valueToInspect);
876+ mlir::Operation *originalAlloc = strippedValue.getDefiningOp ();
877+
878+ // If we found an AllocMemOp (heap allocation), free it
879+ if (mlir::isa_and_nonnull<fir::AllocMemOp>(originalAlloc)) {
880+ mlir::Value toFree = varToFree;
881+ if (!mlir::isa<fir::HeapType>(valueToInspect.getType ()))
882+ toFree = fir::ConvertOp::create (
883+ builder, loc,
884+ fir::HeapType::get (varToFree.getType ().getElementType ()), toFree);
885+ fir::FreeMemOp::create (builder, loc, toFree);
886+ return true ;
887+ }
888+
889+ // If we found an AllocaOp (stack allocation), no deallocation needed
890+ if (mlir::isa_and_nonnull<fir::AllocaOp>(originalAlloc))
891+ return true ;
892+
893+ // Unable to determine allocation type
894+ return false ;
895+ }
896+
897+ template bool OpenACCPointerLikeModel<fir::ReferenceType>::genFree(
898+ mlir::Type pointer, mlir::OpBuilder &builder, mlir::Location loc,
899+ mlir::TypedValue<mlir::acc::PointerLikeType> varToFree,
900+ mlir::Value allocRes, mlir::Type varType) const ;
901+
902+ template bool OpenACCPointerLikeModel<fir::PointerType>::genFree(
903+ mlir::Type pointer, mlir::OpBuilder &builder, mlir::Location loc,
904+ mlir::TypedValue<mlir::acc::PointerLikeType> varToFree,
905+ mlir::Value allocRes, mlir::Type varType) const ;
906+
907+ template bool OpenACCPointerLikeModel<fir::HeapType>::genFree(
908+ mlir::Type pointer, mlir::OpBuilder &builder, mlir::Location loc,
909+ mlir::TypedValue<mlir::acc::PointerLikeType> varToFree,
910+ mlir::Value allocRes, mlir::Type varType) const ;
911+
912+ template bool OpenACCPointerLikeModel<fir::LLVMPointerType>::genFree(
913+ mlir::Type pointer, mlir::OpBuilder &builder, mlir::Location loc,
914+ mlir::TypedValue<mlir::acc::PointerLikeType> varToFree,
915+ mlir::Value allocRes, mlir::Type varType) const ;
916+
917+ template <typename Ty>
918+ bool OpenACCPointerLikeModel<Ty>::genCopy(
919+ mlir::Type pointer, mlir::OpBuilder &builder, mlir::Location loc,
920+ mlir::TypedValue<mlir::acc::PointerLikeType> destination,
921+ mlir::TypedValue<mlir::acc::PointerLikeType> source,
922+ mlir::Type varType) const {
923+
924+ // Check that source and destination types match
925+ if (source.getType () != destination.getType ())
926+ return false ;
927+
928+ mlir::Type eleTy = mlir::cast<Ty>(pointer).getElementType ();
929+
930+ // Unlimited polymorphic (class(*)) cannot be handled because source and
931+ // destination types are not known.
932+ if (fir::isUnlimitedPolymorphicType (eleTy))
933+ return false ;
934+
935+ // Dynamic lengths without descriptor do not have size information.
936+ if (auto charTy = mlir::dyn_cast<fir::CharacterType>(eleTy))
937+ if (charTy.hasDynamicLen ())
938+ return false ;
939+ if (auto seqTy = mlir::dyn_cast<fir::SequenceType>(eleTy))
940+ if (seqTy.hasDynamicExtents () || seqTy.hasUnknownShape ())
941+ return false ;
942+
943+ if (fir::isa_trivial (eleTy)) {
944+ auto loadVal = fir::LoadOp::create (builder, loc, source);
945+ fir::StoreOp::create (builder, loc, loadVal, destination);
946+ } else {
947+ hlfir::AssignOp::create (builder, loc, source, destination);
948+ }
949+ return true ;
950+ }
951+
952+ template bool OpenACCPointerLikeModel<fir::ReferenceType>::genCopy(
953+ mlir::Type pointer, mlir::OpBuilder &builder, mlir::Location loc,
954+ mlir::TypedValue<mlir::acc::PointerLikeType> destination,
955+ mlir::TypedValue<mlir::acc::PointerLikeType> source,
956+ mlir::Type varType) const ;
957+
958+ template bool OpenACCPointerLikeModel<fir::PointerType>::genCopy(
959+ mlir::Type pointer, mlir::OpBuilder &builder, mlir::Location loc,
960+ mlir::TypedValue<mlir::acc::PointerLikeType> destination,
961+ mlir::TypedValue<mlir::acc::PointerLikeType> source,
962+ mlir::Type varType) const ;
963+
964+ template bool OpenACCPointerLikeModel<fir::HeapType>::genCopy(
965+ mlir::Type pointer, mlir::OpBuilder &builder, mlir::Location loc,
966+ mlir::TypedValue<mlir::acc::PointerLikeType> destination,
967+ mlir::TypedValue<mlir::acc::PointerLikeType> source,
968+ mlir::Type varType) const ;
969+
970+ template bool OpenACCPointerLikeModel<fir::LLVMPointerType>::genCopy(
971+ mlir::Type pointer, mlir::OpBuilder &builder, mlir::Location loc,
972+ mlir::TypedValue<mlir::acc::PointerLikeType> destination,
973+ mlir::TypedValue<mlir::acc::PointerLikeType> source,
974+ mlir::Type varType) const ;
975+
754976} // namespace fir::acc
0 commit comments