This is an archive of the discontinued LLVM Phabricator instance.

[flang][hlfir] work towards handling char_convert in hlfir
ClosedPublic

Authored by cabreraam on Jul 18 2023, 3:23 PM.

Details

Summary

This patch aims to address the TODO for handling character conversion in HLFIR found here using this similar operation but for FIR as inspiration.

Diff Detail

Event Timeline

cabreraam created this revision.Jul 18 2023, 3:23 PM
Herald added projects: Restricted Project, Restricted Project. · View Herald TranscriptJul 18 2023, 3:24 PM
cabreraam edited the summary of this revision. (Show Details)Jul 18 2023, 3:29 PM
cabreraam edited the summary of this revision. (Show Details)Jul 18 2023, 3:29 PM
cabreraam edited the summary of this revision. (Show Details)

It looks like it is complaining about this store:

"fir.store"(%1#0, %5) : (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) -> ()

It is incorrect. Try to check if lhs entity is always !fir.ref<!fir.char... that you can directly use in char_convert.

cabreraam added a comment.EditedJul 19 2023, 2:40 PM

It looks like it is complaining about this store:

"fir.store"(%1#0, %5) : (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) -> ()

It is incorrect. Try to check if lhs entity is always !fir.ref<!fir.char... that you can directly use in char_convert.

Could you provide a little more help? I tried changing

builder.create<fir::StoreOp>(loc, lhs, tmp);
builder.create<fir::StoreOp>(loc, lhs.getFirBase(), tmp);

which results in

cpp
 "fir.store"(%1#1, %5) : (!fir.ref<!fir.char<1,?>>, !fir.ref<!fir.char<1,?>>) -> ()

Yet I still get the same error

error: loc("/noback/93u/Research/secretariat/llvm-project/flang/test/Lower/charconvert.f90":7:3): 'fir.store' op store value type must match memory reference type

I figured the issue was that the types in the store operation weren't the same, so I forced them to be the same, yet I'm still getting the same issue.

Here is the whole output log:

$ /noback/93u/Research/secretariat/llvm-project/build_relwithdebnfo_clang_lld_static/bin/bbc -emit-hlfir /noback/93u/Research/secretariat/llvm-project/flang/test/Lower/charconvert.f90 -o - -debug
Args: /noback/93u/Research/secretariat/llvm-project/build_relwithdebnfo_clang_lld_static/bin/bbc -emit-hlfir /noback/93u/Research/secretariat/llvm-project/flang/test/Lower/charconvert.f90 -o - -debug 
ImplicitTypeIDRegistry::lookupOrInsert(fir::FIROpsDialect)
Load new dialect in Context builtin
ImplicitTypeIDRegistry::lookupOrInsert(mlir::ShapedType)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::MemRefLayoutAttrInterface)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::TypedAttr)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::ElementsAttr)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::DistinctAttr)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::BytecodeOpInterface)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::SymbolOpInterface)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::OpAsmOpInterface)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::RegionKindInterface)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::ConditionallySpeculatable)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::MemoryEffectOpInterface)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::ResourceBlobManagerDialectInterface)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::OpAsmDialectInterface)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::BytecodeDialectInterface)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::detail::AffineBinaryOpExprStorage)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::detail::AffineConstantExprStorage)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::detail::AffineDimExprStorage)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::detail::AffineMapStorage)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::detail::IntegerSetStorage)
Load new dialect in Context affine
Load new dialect in Context arith
ImplicitTypeIDRegistry::lookupOrInsert(mlir::arith::ArithFastMathInterface)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::VectorUnrollOpInterface)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::InferTypeOpInterface)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::InferIntRangeInterface)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::CastOpInterface)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::DialectInlinerInterface)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::affine::AffineDmaStartOp)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::affine::AffineMapAccessInterface)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::affine::AffineDmaWaitOp)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::LoopLikeOpInterface)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::RegionBranchOpInterface)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::affine::AffineReadOpInterface)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::affine::AffineWriteOpInterface)
Load new dialect in Context fir
ImplicitTypeIDRegistry::lookupOrInsert(mlir::omp::PointerLikeType)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::acc::PointerLikeType)
ImplicitTypeIDRegistry::lookupOrInsert(fir::ClosedIntervalAttr)
ImplicitTypeIDRegistry::lookupOrInsert(fir::ExactTypeAttr)
ImplicitTypeIDRegistry::lookupOrInsert(fir::LowerBoundAttr)
ImplicitTypeIDRegistry::lookupOrInsert(fir::PointIntervalAttr)
ImplicitTypeIDRegistry::lookupOrInsert(fir::RealAttr)
ImplicitTypeIDRegistry::lookupOrInsert(fir::SubclassAttr)
ImplicitTypeIDRegistry::lookupOrInsert(fir::UpperBoundAttr)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::CallOpInterface)
ImplicitTypeIDRegistry::lookupOrInsert(fir::FortranVariableOpInterface)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::BranchOpInterface)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::omp::DeclareTargetInterface)
Load new dialect in Context hlfir
ImplicitTypeIDRegistry::lookupOrInsert(hlfir::ElementalOpInterface)
ImplicitTypeIDRegistry::lookupOrInsert(hlfir::OrderedAssignmentTreeOpInterface)
Load new dialect in Context acc
Load new dialect in Context memref
ImplicitTypeIDRegistry::lookupOrInsert(mlir::CopyOpInterface)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::PromotableMemOpInterface)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::DestructurableAccessorOpInterface)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::PromotableAllocationOpInterface)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::DestructurableAllocationOpInterface)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::ViewLikeOpInterface)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::ShapedDimOpInterface)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::SymbolUserOpInterface)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::OffsetSizeAndStrideOpInterface)
Load new dialect in Context llvm
ImplicitTypeIDRegistry::lookupOrInsert(mlir::LLVM::LLVMVoidType)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::LLVM::LLVMPPCFP128Type)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::LLVM::LLVMX86MMXType)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::LLVM::LLVMTokenType)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::LLVM::LLVMLabelType)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::LLVM::LLVMMetadataType)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::LLVM::LLVMStructType)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::DataLayoutTypeInterface)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::DestructurableTypeInterface)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::PromotableOpInterface)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::LLVM::GetResultPtrElementType)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::LLVM::AccessGroupOpInterface)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::LLVM::AliasAnalysisOpInterface)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::LLVM::FastmathFlagsInterface)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::SafeMemorySlotAccessOpInterface)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::FunctionOpInterface)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::CallableOpInterface)
Load new dialect in Context omp
Load new dialect in Context func
Load new dialect in Context cf
[dialect] repeated interface registration for dialect funcImplicitTypeIDRegistry::lookupOrInsert(mlir::omp::OutlineableOpenMPOpInterface)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::omp::ReductionClauseInterface)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::DialectFoldInterface)
Ignoring repeated interface registration
ImplicitTypeIDRegistry::lookupOrInsert(mlir::omp::OffloadModuleInterface)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::omp::EarlyOutliningInterface)
Load new dialect in Context scf
ImplicitTypeIDRegistry::lookupOrInsert(mlir::RegionBranchTerminatorOpInterface)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::ParallelCombiningOpInterface)
Load new dialect in Context vector
ImplicitTypeIDRegistry::lookupOrInsert(mlir::vector::MaskableOpInterface)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::vector::MaskingOpInterface)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::VectorTransferOpInterface)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::DestinationStyleOpInterface)
Load new dialect in Context math
Load new dialect in Context complex
Load new dialect in Context dlti
ImplicitTypeIDRegistry::lookupOrInsert(mlir::DataLayoutEntryAttr)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::DataLayoutEntryInterface)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::DataLayoutSpecAttr)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::DataLayoutSpecInterface)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::DataLayoutDialectInterface)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::OpTrait::ZeroOperands<Empty>)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::OpTrait::OneRegion<Empty>)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::OpTrait::ZeroResults<Empty>)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::OpTrait::ZeroSuccessors<Empty>)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::OpTrait::NoRegionArguments<Empty>)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::OpTrait::NoTerminator<Empty>)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::OpTrait::SingleBlock<Empty>)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::OpTrait::OpInvariants<Empty>)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::BytecodeOpInterface::Trait<Empty>)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::OpTrait::AffineScope<Empty>)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::OpTrait::IsIsolatedFromAbove<Empty>)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::OpTrait::SymbolTable<Empty>)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::SymbolOpInterface::Trait<Empty>)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::OpAsmOpInterface::Trait<Empty>)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::RegionKindInterface::Trait<Empty>)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::OpTrait::HasOnlyGraphRegion<Empty>)
Full program scope information.
Addresses in angle brackets are scopes. Unbracketed addresses are symbols.
<0x39426f0> IntrinsicModules (no detail)
<0x39c1590> 0x395c750 name: MainProgram
  0x395c900   c1 size=5 offset=0: ObjectEntity type: CHARACTER(5_4,1) init:"hello"
  0x395cab0   c4 size=10 offset=6: ObjectEntity type: CHARACTER(5_4,2)
<0x3951ed0> 0x395c090 test_c1_to_c4, EXTERNAL (Subroutine): Subprogram (CHARACTER(*,2) c4,CHARACTER(*,1) c1)
  0x395c5a0   c1 size=24 offset=24: ObjectEntity dummy type: CHARACTER(*,1)
  0x395c3f0   c4 size=24 offset=0: ObjectEntity dummy type: CHARACTER(*,2)
  0x395c240   test_c1_to_c4 (Subroutine): HostAssoc
ImplicitTypeIDRegistry::lookupOrInsert(mlir::OpTrait::AutomaticAllocationScope<Empty>)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::CallableOpInterface::Trait<Empty>)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::FunctionOpInterface::Trait<Empty>)

[bridge - startNewFunction] test_c1_to_c4, EXTERNAL (Subroutine): Subprogram (CHARACTER(*,2) c4,CHARACTER(*,1) c1)

getScopeVariableList of [sub]program|block scope <0x3951ed0> test_c1_to_c4
analyze symbol 0x395c5a0 in <0x3951ed0>: c1 size=24 offset=24: ObjectEntity dummy type: CHARACTER(*,1)
analyze symbol 0x395c3f0 in <0x3951ed0>: c4 size=24 offset=0: ObjectEntity dummy type: CHARACTER(*,2)
analyze symbol 0x395c240 in <0x3951ed0>: test_c1_to_c4 (Subroutine): HostAssoc
instantiateVariable: 0x395c5a0 c1 size=24 offset=24: ObjectEntity dummy type: CHARACTER(*,1) (depth: 0)
instantiateVariable: 0x395c3f0 c4 size=24 offset=0: ObjectEntity dummy type: CHARACTER(*,2) (depth: 0)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::OpTrait::IsTerminator<Empty>)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::OpTrait::ZeroRegions<Empty>)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::OpTrait::NOperands<2>::Impl<Empty>)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::MemoryEffectOpInterface::Trait<Empty>)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::OpTrait::VariadicOperands<Empty>)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::OpTrait::HasParent<mlir::func::FuncOp>::Impl<Empty>)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::ConditionallySpeculatable::Trait<Empty>)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::OpTrait::AlwaysSpeculatableImplTrait<Empty>)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::OpTrait::MemRefsNormalizable<Empty>)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::OpTrait::ReturnLike<Empty>)

[bridge - endNewFunction test_c1_to_c4] generated IR:

mlir-asm-printer: Verifying operation: func.func
'fir.store' op store value type must match memory reference type
mlir-asm-printer: 'func.func' failed to verify and will be printed in generic form
"func.func"() <{arg_attrs = [{fir.bindc_name = "c4"}, {fir.bindc_name = "c1"}], function_type = (!fir.boxchar<2>, !fir.boxchar<1>) -> (), sym_name = "_QPtest_c1_to_c4"}> ({
^bb0(%arg0: !fir.boxchar<2>, %arg1: !fir.boxchar<1>):
  %0:2 = "fir.unboxchar"(%arg1) : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
  %1:2 = "hlfir.declare"(%0#0, %0#1) {operand_segment_sizes = array<i32: 1, 0, 1>, uniq_name = "_QFtest_c1_to_c4Ec1"} : (!fir.ref<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>)
  %2:2 = "fir.unboxchar"(%arg0) : (!fir.boxchar<2>) -> (!fir.ref<!fir.char<2,?>>, index)
  %3:2 = "hlfir.declare"(%2#0, %2#1) {operand_segment_sizes = array<i32: 1, 0, 1>, uniq_name = "_QFtest_c1_to_c4Ec4"} : (!fir.ref<!fir.char<2,?>>, index) -> (!fir.boxchar<2>, !fir.ref<!fir.char<2,?>>)
  %4 = "fir.alloca"(%0#1) {in_type = !fir.char<2,?>, operand_segment_sizes = array<i32: 1, 0>} : (index) -> !fir.ref<!fir.char<2,?>>
  %5 = "fir.alloca"(%0#1) {in_type = !fir.char<1,?>, operand_segment_sizes = array<i32: 1, 0>} : (index) -> !fir.ref<!fir.char<1,?>>
  "fir.store"(%1#1, %5) : (!fir.ref<!fir.char<1,?>>, !fir.ref<!fir.char<1,?>>) -> ()
  "fir.char_convert"(%5, %0#1, %4) : (!fir.ref<!fir.char<1,?>>, index, !fir.ref<!fir.char<2,?>>) -> ()
  %6:2 = "hlfir.declare"(%5) {operand_segment_sizes = array<i32: 1, 0, 0>, uniq_name = "ctor.temp"} : (!fir.ref<!fir.char<1,?>>) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>)
  "hlfir.assign"(%6#0, %3#0) : (!fir.boxchar<1>, !fir.boxchar<2>) -> ()
  "func.return"() : () -> ()
}) : () -> ()
ImplicitTypeIDRegistry::lookupOrInsert(mlir::OpTrait::HasRecursiveMemoryEffects<Empty>)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::MemoryEffects::Write)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::SideEffects::DefaultResource)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::MemoryEffects::Allocate)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::MemoryEffects::Read)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::OpTrait::NResults<2>::Impl<Empty>)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::OpTrait::AtLeastNOperands<1>::Impl<Empty>)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::OpTrait::AttrSizedOperandSegments<Empty>)
ImplicitTypeIDRegistry::lookupOrInsert(fir::FortranVariableOpInterface::Trait<Empty>)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::OpTrait::NOperands<3>::Impl<Empty>)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::OpTrait::OneResult<Empty>)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::OpTrait::OneTypedResult<fir::ReferenceType>::Impl<Empty>)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::SideEffects::AutomaticAllocationScopeResource)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::OpTrait::OneOperand<Empty>)

[bridge - startNewFunction] name: MainProgram

getScopeVariableList of [sub]program|block scope <0x39c1590> name
analyze symbol 0x395c900 in <0x39c1590>: c1 size=5 offset=0: ObjectEntity type: CHARACTER(5_4,1) init:"hello"
analyze symbol 0x395cab0 in <0x39c1590>: c4 size=10 offset=6: ObjectEntity type: CHARACTER(5_4,2)
instantiateVariable: 0x395c900 c1 size=5 offset=0: ObjectEntity type: CHARACTER(5_4,1) init:"hello" (depth: 0), global
expr: "hello"
ImplicitTypeIDRegistry::lookupOrInsert(mlir::OpTrait::OneTypedResult<fir::CharacterType>::Impl<Empty>)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::arith::detail::ConstantOpGenericAdaptorBase::Properties)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::OpTrait::OneTypedResult<mlir::Type>::Impl<Empty>)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::OpTrait::ConstantLike<Empty>)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::InferIntRangeInterface::Trait<Empty>)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::InferTypeOpInterface::Trait<Empty>)
instantiateVariable: 0x395cab0 c4 size=10 offset=6: ObjectEntity type: CHARACTER(5_4,2) (depth: 0)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::OpTrait::VariadicResults<Empty>)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::CallOpInterface::Trait<Empty>)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::arith::ArithFastMathInterface::Trait<Empty>)

[bridge - endNewFunction name] generated IR:

mlir-asm-printer: Verifying operation: func.func
func.func @_QQmain() attributes {fir.bindc_name = "name"} {
  %0 = fir.address_of(@_QFEc1) : !fir.ref<!fir.char<1,5>>
  %c5 = arith.constant 5 : index
  %1:2 = hlfir.declare %0 typeparams %c5 {uniq_name = "_QFEc1"} : (!fir.ref<!fir.char<1,5>>, index) -> (!fir.ref<!fir.char<1,5>>, !fir.ref<!fir.char<1,5>>)
  %c5_0 = arith.constant 5 : index
  %2 = fir.alloca !fir.char<2,5> {bindc_name = "c4", uniq_name = "_QFEc4"}
  %3:2 = hlfir.declare %2 typeparams %c5_0 {uniq_name = "_QFEc4"} : (!fir.ref<!fir.char<2,5>>, index) -> (!fir.ref<!fir.char<2,5>>, !fir.ref<!fir.char<2,5>>)
  %4 = fir.emboxchar %3#1, %c5_0 : (!fir.ref<!fir.char<2,5>>, index) -> !fir.boxchar<2>
  %5 = fir.emboxchar %1#1, %c5 : (!fir.ref<!fir.char<1,5>>, index) -> !fir.boxchar<1>
  fir.call @_QPtest_c1_to_c4(%4, %5) fastmath<contract> : (!fir.boxchar<2>, !fir.boxchar<1>) -> ()
  %c-1_i32 = arith.constant -1 : i32
  %6 = fir.address_of(@_QQcl.10b785af4bead00189ac8781715b2730) : !fir.ref<!fir.char<1,79>>
  %c79 = arith.constant 79 : index
  %7 = fir.convert %6 : (!fir.ref<!fir.char<1,79>>) -> !fir.ref<i8>
  %c14_i32 = arith.constant 14 : i32
  %8 = fir.call @_FortranAioBeginExternalListOutput(%c-1_i32, %7, %c14_i32) fastmath<contract> : (i32, !fir.ref<i8>, i32) -> !fir.ref<i8>
  %9 = fir.embox %3#1 : (!fir.ref<!fir.char<2,5>>) -> !fir.box<!fir.char<2,5>>
  %10 = fir.convert %9 : (!fir.box<!fir.char<2,5>>) -> !fir.box<none>
  %11 = fir.call @_FortranAioOutputDescriptor(%8, %10) fastmath<contract> : (!fir.ref<i8>, !fir.box<none>) -> i1
  %12 = fir.call @_FortranAioEndIoStatement(%8) fastmath<contract> : (!fir.ref<i8>) -> i32
  return
}
ImplicitTypeIDRegistry::lookupOrInsert(mlir::OpTrait::OneTypedResult<fir::BoxCharType>::Impl<Empty>)
ImplicitTypeIDRegistry::lookupOrInsert(Fortran::lower::VerifierPass)
ImplicitTypeIDRegistry::lookupOrInsert(mlir::detail::OpToOpPassAdaptor)
error: loc("/noback/93u/Research/secretariat/llvm-project/flang/test/Lower/charconvert.f90":7:3): 'fir.store' op store value type must match memory reference type
ImplicitTypeIDRegistry::lookupOrInsert(mlir::detail::PreservedAnalyses::AllAnalysesType)
FATAL: verification of lowering to FIR failed(base)

The types of operands in fir.store must be such that if the value being stored has type !whatever, then the address operand must have type !fir.ref<!whatever>.

For simplicity, I suggest unconditionally make a temporary out of the lhs using hlfir.as_expr and hlfir.associate/end_associate. Then you will be able to get the temporary's base for passing to hlfir.char_convert.

cabreraam updated this revision to Diff 543090.Jul 21 2023, 3:14 PM

Updating D155650: [flang][hlfir] work towards handling char_convert in hlfir

cabreraam edited the summary of this revision. (Show Details)Jul 21 2023, 3:15 PM
cabreraam edited the summary of this revision. (Show Details)
cabreraam published this revision for review.Jul 21 2023, 3:17 PM
tblah added inline comments.Jul 24 2023, 2:48 AM
flang/lib/Lower/ConvertExprToHLFIR.cpp
1405

Can fromBits ever be less than toBits? Why don't we need to scale the buffer this way?

cabreraam added inline comments.Jul 24 2023, 9:02 AM
flang/lib/Lower/ConvertExprToHLFIR.cpp
1405

This is a good question.
This is based off the char_convert implementation for FIR.

This is my assumption:
I think this has to do with char_convert handling "code points", which is the second argument in the char_convert op.
This is how I made sense of it (though my understanding may be wrong):

Consider two characters 'aa' of KIND=2.
The hex-level representation of this would be 0x00410041.
If we want to char_convert this to KIND=1, we would need to perform the ratio calculation in order to grab all of the bytes from the bigger representation.
In this case

bufferSize = ratio * bufferSize = 2 * 2 = 4
char_convert !fir.ref<!fir.char<2,?>> for 4 to !fir.ref<!fir.char<1,?>>

In the case where we convert to KIND=4, for example, we don't need to modify the number of code points that we need to copy.
We'd go from 0x00410041 --> 0x0000004100000041 and we can copy the same number of code points as the original buffer's size into the bigger buffer's size without loss of generality.

Is this the right way to think about this?
This is how I rationalized why you only need the ratio calculation in one direction but not the other.

vzakhari added inline comments.Jul 24 2023, 9:35 PM
flang/lib/Lower/ConvertExprToHLFIR.cpp
1388–1415

Please clean up.

1405

I am not sure either if the scaling is needed. The Alloca and CharConvert have the size operand in "code points", so the do-loop created for CharConvert will store the same amount of "code points" that are allocated by Alloca.

vzakhari accepted this revision.Jul 24 2023, 9:36 PM

Thank you for the changes. It looks good to me. Please wait for Tom's review as well.

This revision is now accepted and ready to land.Jul 24 2023, 9:36 PM
tblah added inline comments.
flang/lib/Lower/ConvertExprToHLFIR.cpp
1405

I too am not sure why this is needed. It seems to be trying to make sure the buffer never gets smaller (in bytes) when the character width decreases.

The FIR lowering does the same thing.

I think @clementval wrote the FIR lowering. Do you remember why this was needed?

tblah accepted this revision.Jul 25 2023, 6:05 AM

I'm going to approve this now and we can fix along with the FIR lowering if the scaling turns out to be unnecessary.