diff --git a/flang/lib/Lower/ConvertExprToHLFIR.cpp b/flang/lib/Lower/ConvertExprToHLFIR.cpp --- a/flang/lib/Lower/ConvertExprToHLFIR.cpp +++ b/flang/lib/Lower/ConvertExprToHLFIR.cpp @@ -1385,7 +1385,34 @@ hlfir::Entity lhs) { if constexpr (TC1 == Fortran::common::TypeCategory::Character && TC2 == TC1) { - TODO(loc, "character conversion in HLFIR"); + // TODO(loc, "character conversion in HLFIR"); + auto kindMap = builder.getKindMap(); + mlir::Type fromTy = lhs.getFortranElementType(); + mlir::Value origBufferSize = genCharLength(loc, builder, lhs); + mlir::Value bufferSize{origBufferSize}; + auto fromBits = kindMap.getCharacterBitsize( + fir::unwrapRefType(fromTy).cast().getFKind()); + mlir::Type toTy = Fortran::lower::getFIRType( + builder.getContext(), TC1, KIND, /*params=*/std::nullopt); + auto toBits = kindMap.getCharacterBitsize( + toTy.cast().getFKind()); + if (toBits < fromBits) { + // Scale by relative ratio to give a buffer of the same length. + auto ratio = builder.createIntegerConstant(loc, bufferSize.getType(), + fromBits / toBits); + bufferSize = + builder.create(loc, bufferSize, ratio); + } + // allocate space on the stack for toBuffer + auto dest = builder.create(loc, toTy, + mlir::ValueRange{bufferSize}); + builder.create(loc, lhs.getFirBase(), origBufferSize, + dest); + + return hlfir::EntityWithAttributes{builder.create( + loc, dest, "ctor.temp", /*shape=*/nullptr, + /*typeparams=*/mlir::ValueRange{origBufferSize}, + fir::FortranVariableFlagsAttr{})}; } mlir::Type type = Fortran::lower::getFIRType(builder.getContext(), TC1, KIND, /*params=*/std::nullopt); diff --git a/flang/test/Lower/charconvert.f90 b/flang/test/Lower/charconvert.f90 new file mode 100644 --- /dev/null +++ b/flang/test/Lower/charconvert.f90 @@ -0,0 +1,39 @@ +! RUN: bbc -emit-hlfir %s -o - | FileCheck %s + +subroutine test_c1_to_c4(c4, c1) + character(len=*, kind=4) :: c4 + character(len=*, kind=1) :: c1 + c4 = c1 +end subroutine + +subroutine test_c4_to_c1(c4, c1) + character(len=*, kind=4) :: c4 + character(len=*, kind=1) :: c1 + c1 = c4 +end subroutine + +! CHECK: func.func @_QPtest_c1_to_c4(%[[ARG0:.*]]: !fir.boxchar<4> {fir.bindc_name = "c4"}, %[[ARG1:.*]]: !fir.boxchar<1> {fir.bindc_name = "c1"}) { +! CHECK: %[[VAL_0:.*]]:2 = fir.unboxchar %[[ARG1]] : (!fir.boxchar<1>) -> (!fir.ref>, index) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]]#0 typeparams %[[VAL_0]]#1 {uniq_name = "_QFtest_c1_to_c4Ec1"} : (!fir.ref>, index) -> (!fir.boxchar<1>, !fir.ref>) +! CHECK: %[[VAL_2:.*]]:2 = fir.unboxchar %[[ARG0]] : (!fir.boxchar<4>) -> (!fir.ref>, index) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]]#0 typeparams %[[VAL_2]]#1 {uniq_name = "_QFtest_c1_to_c4Ec4"} : (!fir.ref>, index) -> (!fir.boxchar<4>, !fir.ref>) +! CHECK: %[[VAL_4:.*]] = fir.alloca !fir.char<4,?>(%[[VAL_0]]#1 : index) +! CHECK: fir.char_convert %[[VAL_1]]#1 for %[[VAL_0]]#1 to %[[VAL_4:.*]] : !fir.ref>, index, !fir.ref> +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]] typeparams %[[VAL_0]]#1 {uniq_name = "ctor.temp"} : (!fir.ref>, index) -> (!fir.boxchar<4>, !fir.ref>) +! CHECK: hlfir.assign %[[VAL_5]]#0 to %[[VAL_3]]#0 : !fir.boxchar<4>, !fir.boxchar<4> +! CHECK: return +! CHECK: } + +! CHECK: func.func @_QPtest_c4_to_c1(%[[ARG0:.*]]: !fir.boxchar<4> {fir.bindc_name = "c4"}, %[[ARG1:.*]]: !fir.boxchar<1> {fir.bindc_name = "c1"}) { +! CHECK: %[[VAL_0:.*]]:2 = fir.unboxchar %[[ARG1]] : (!fir.boxchar<1>) -> (!fir.ref>, index) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]]#0 typeparams %[[VAL_0]]#1 {uniq_name = "_QFtest_c4_to_c1Ec1"} : (!fir.ref>, index) -> (!fir.boxchar<1>, !fir.ref>) +! CHECK: %[[VAL_2:.*]]:2 = fir.unboxchar %[[ARG0]] : (!fir.boxchar<4>) -> (!fir.ref>, index) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]]#0 typeparams %[[VAL_2]]#1 {uniq_name = "_QFtest_c4_to_c1Ec4"} : (!fir.ref>, index) -> (!fir.boxchar<4>, !fir.ref>) +! CHECK: %[[C4:.*]] = arith.constant 4 : index +! CHECK: %[[VAL_4:.*]] = arith.muli %[[VAL_2]]#1, %[[C4]] : index +! CHECK: %[[VAL_5:.*]] = fir.alloca !fir.char<1,?>(%[[VAL_4]] : index) +! CHECK: fir.char_convert %[[VAL_3]]#1 for %[[VAL_2]]#1 to %[[VAL_5:.*]] : !fir.ref>, index, !fir.ref> +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_5]] typeparams %[[VAL_2]]#1 {uniq_name = "ctor.temp"} : (!fir.ref>, index) -> (!fir.boxchar<1>, !fir.ref>) +! CHECK: hlfir.assign %[[VAL_6]]#0 to %[[VAL_1]]#0 : !fir.boxchar<1>, !fir.boxchar<1> +! CHECK: return +! CHECK: } \ No newline at end of file