@@ -727,12 +727,15 @@ class TypeInfo {
727
727
// Is the type inside a box?
728
728
bool isBox () const { return inBox; }
729
729
730
+ bool isBoxChar () const { return inBoxChar; }
731
+
730
732
private:
731
733
void typeScan (mlir::Type type);
732
734
733
735
std::optional<fir::CharacterType::LenType> charLen;
734
736
llvm::SmallVector<int64_t > shape;
735
737
bool inBox = false ;
738
+ bool inBoxChar = false ;
736
739
};
737
740
738
741
void TypeInfo::typeScan (mlir::Type ty) {
@@ -748,6 +751,9 @@ void TypeInfo::typeScan(mlir::Type ty) {
748
751
typeScan (cty.getEleTy ());
749
752
} else if (auto cty = mlir::dyn_cast<fir::CharacterType>(ty)) {
750
753
charLen = cty.getLen ();
754
+ } else if (auto cty = mlir::dyn_cast<fir::BoxCharType>(ty)) {
755
+ inBoxChar = true ;
756
+ typeScan (cty.getEleTy ());
751
757
} else if (auto hty = mlir::dyn_cast<fir::HeapType>(ty)) {
752
758
typeScan (hty.getEleTy ());
753
759
} else if (auto pty = mlir::dyn_cast<fir::PointerType>(ty)) {
@@ -791,12 +797,6 @@ createCopyFunc(mlir::Location loc, lower::AbstractConverter &converter,
791
797
fir::FortranVariableFlagsAttr attrs;
792
798
if (varAttrs != fir::FortranVariableFlagsEnum::None)
793
799
attrs = fir::FortranVariableFlagsAttr::get (builder.getContext (), varAttrs);
794
- llvm::SmallVector<mlir::Value> typeparams;
795
- if (typeInfo.getCharLength ().has_value ()) {
796
- mlir::Value charLen = builder.createIntegerConstant (
797
- loc, builder.getCharacterLengthType (), *typeInfo.getCharLength ());
798
- typeparams.push_back (charLen);
799
- }
800
800
mlir::Value shape;
801
801
if (!typeInfo.isBox () && !typeInfo.getShape ().empty ()) {
802
802
llvm::SmallVector<mlir::Value> extents;
@@ -805,11 +805,34 @@ createCopyFunc(mlir::Location loc, lower::AbstractConverter &converter,
805
805
builder.createIntegerConstant (loc, builder.getIndexType (), extent));
806
806
shape = builder.create <fir::ShapeOp>(loc, extents);
807
807
}
808
+ mlir::Value dst = funcOp.getArgument (0 );
809
+ mlir::Value src = funcOp.getArgument (1 );
810
+ llvm::SmallVector<mlir::Value> typeparams;
811
+ if (typeInfo.isBoxChar ()) {
812
+ // fir.boxchar will be passed here as fir.ref<fir.boxchar>
813
+ auto loadDst = builder.create <fir::LoadOp>(loc, dst);
814
+ auto loadSrc = builder.create <fir::LoadOp>(loc, src);
815
+ // get the actual fir.ref<fir.char> type
816
+ mlir::Type refType =
817
+ fir::ReferenceType::get (mlir::cast<fir::BoxCharType>(eleTy).getEleTy ());
818
+ auto unboxedDst = builder.create <fir::UnboxCharOp>(
819
+ loc, refType, builder.getIndexType (), loadDst);
820
+ auto unboxedSrc = builder.create <fir::UnboxCharOp>(
821
+ loc, refType, builder.getIndexType (), loadSrc);
822
+ // Add length to type parameters
823
+ typeparams.push_back (unboxedDst.getResult (1 ));
824
+ dst = unboxedDst.getResult (0 );
825
+ src = unboxedSrc.getResult (0 );
826
+ } else if (typeInfo.getCharLength ().has_value ()) {
827
+ mlir::Value charLen = builder.createIntegerConstant (
828
+ loc, builder.getCharacterLengthType (), *typeInfo.getCharLength ());
829
+ typeparams.push_back (charLen);
830
+ }
808
831
auto declDst = builder.create <hlfir::DeclareOp>(
809
- loc, funcOp. getArgument ( 0 ) , copyFuncName + " _dst" , shape, typeparams,
832
+ loc, dst , copyFuncName + " _dst" , shape, typeparams,
810
833
/* dummy_scope=*/ nullptr , attrs);
811
834
auto declSrc = builder.create <hlfir::DeclareOp>(
812
- loc, funcOp. getArgument ( 1 ) , copyFuncName + " _src" , shape, typeparams,
835
+ loc, src , copyFuncName + " _src" , shape, typeparams,
813
836
/* dummy_scope=*/ nullptr , attrs);
814
837
converter.copyVar (loc, declDst.getBase (), declSrc.getBase (), varAttrs);
815
838
builder.create <mlir::func::ReturnOp>(loc);
@@ -835,10 +858,13 @@ bool ClauseProcessor::processCopyprivate(
835
858
836
859
// CopyPrivate variables must be passed by reference. However, in the case
837
860
// of assumed shapes/vla the type is not a !fir.ref, but a !fir.box.
838
- // In these cases to retrieve the appropriate !fir.ref<!fir.box<...>> to
839
- // access the data we need we must perform an alloca and then store to it
840
- // and retrieve the data from the new alloca.
841
- if (mlir::isa<fir::BaseBoxType>(symType)) {
861
+ // In the case of character types, the passed in type can also be
862
+ // !fir.boxchar. In these cases to retrieve the appropriate
863
+ // !fir.ref<!fir.box<...>> or !fir.ref<!fir.boxchar<..>> to access the data
864
+ // we need we must perform an alloca and then store to it and retrieve the
865
+ // data from the new alloca.
866
+ if (mlir::isa<fir::BaseBoxType>(symType) ||
867
+ mlir::isa<fir::BoxCharType>(symType)) {
842
868
fir::FirOpBuilder &builder = converter.getFirOpBuilder ();
843
869
auto alloca = builder.create <fir::AllocaOp>(currentLocation, symType);
844
870
builder.create <fir::StoreOp>(currentLocation, symVal, alloca);
0 commit comments