Skip to content

Commit a033bf2

Browse files
committed
[flang][hlfir] work towards handling char_convert in hlfir
This patch aims to address the TODO for handling character conversion in HLFIR found [here](https://github.com/llvm/llvm-project/blob/1defa781243f9d0bc66719465e4de33e9fb7a243/flang/lib/Lower/ConvertExprToHLFIR.cpp#L1388) using [this similar operation but for FIR as inspiration](https://github.com/llvm/llvm-project/blob/3ea673a97b0583affc22345b9d62e863ba36b3d8/flang/lib/Lower/ConvertExpr.cpp#L1212-L1271). Reviewed By: vzakhari, tblah Differential Revision: https://reviews.llvm.org/D155650
1 parent 896aada commit a033bf2

File tree

2 files changed

+67
-1
lines changed

2 files changed

+67
-1
lines changed

flang/lib/Lower/ConvertExprToHLFIR.cpp

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1385,7 +1385,34 @@ struct UnaryOp<
13851385
hlfir::Entity lhs) {
13861386
if constexpr (TC1 == Fortran::common::TypeCategory::Character &&
13871387
TC2 == TC1) {
1388-
TODO(loc, "character conversion in HLFIR");
1388+
// TODO(loc, "character conversion in HLFIR");
1389+
auto kindMap = builder.getKindMap();
1390+
mlir::Type fromTy = lhs.getFortranElementType();
1391+
mlir::Value origBufferSize = genCharLength(loc, builder, lhs);
1392+
mlir::Value bufferSize{origBufferSize};
1393+
auto fromBits = kindMap.getCharacterBitsize(
1394+
fir::unwrapRefType(fromTy).cast<fir::CharacterType>().getFKind());
1395+
mlir::Type toTy = Fortran::lower::getFIRType(
1396+
builder.getContext(), TC1, KIND, /*params=*/std::nullopt);
1397+
auto toBits = kindMap.getCharacterBitsize(
1398+
toTy.cast<fir::CharacterType>().getFKind());
1399+
if (toBits < fromBits) {
1400+
// Scale by relative ratio to give a buffer of the same length.
1401+
auto ratio = builder.createIntegerConstant(loc, bufferSize.getType(),
1402+
fromBits / toBits);
1403+
bufferSize =
1404+
builder.create<mlir::arith::MulIOp>(loc, bufferSize, ratio);
1405+
}
1406+
// allocate space on the stack for toBuffer
1407+
auto dest = builder.create<fir::AllocaOp>(loc, toTy,
1408+
mlir::ValueRange{bufferSize});
1409+
builder.create<fir::CharConvertOp>(loc, lhs.getFirBase(), origBufferSize,
1410+
dest);
1411+
1412+
return hlfir::EntityWithAttributes{builder.create<hlfir::DeclareOp>(
1413+
loc, dest, "ctor.temp", /*shape=*/nullptr,
1414+
/*typeparams=*/mlir::ValueRange{origBufferSize},
1415+
fir::FortranVariableFlagsAttr{})};
13891416
}
13901417
mlir::Type type = Fortran::lower::getFIRType(builder.getContext(), TC1,
13911418
KIND, /*params=*/std::nullopt);

flang/test/Lower/charconvert.f90

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
! RUN: bbc -emit-hlfir %s -o - | FileCheck %s
2+
3+
subroutine test_c1_to_c4(c4, c1)
4+
character(len=*, kind=4) :: c4
5+
character(len=*, kind=1) :: c1
6+
c4 = c1
7+
end subroutine
8+
9+
subroutine test_c4_to_c1(c4, c1)
10+
character(len=*, kind=4) :: c4
11+
character(len=*, kind=1) :: c1
12+
c1 = c4
13+
end subroutine
14+
15+
! CHECK: func.func @_QPtest_c1_to_c4(%[[ARG0:.*]]: !fir.boxchar<4> {fir.bindc_name = "c4"}, %[[ARG1:.*]]: !fir.boxchar<1> {fir.bindc_name = "c1"}) {
16+
! CHECK: %[[VAL_0:.*]]:2 = fir.unboxchar %[[ARG1]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
17+
! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]]#0 typeparams %[[VAL_0]]#1 {uniq_name = "_QFtest_c1_to_c4Ec1"} : (!fir.ref<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>)
18+
! CHECK: %[[VAL_2:.*]]:2 = fir.unboxchar %[[ARG0]] : (!fir.boxchar<4>) -> (!fir.ref<!fir.char<4,?>>, index)
19+
! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]]#0 typeparams %[[VAL_2]]#1 {uniq_name = "_QFtest_c1_to_c4Ec4"} : (!fir.ref<!fir.char<4,?>>, index) -> (!fir.boxchar<4>, !fir.ref<!fir.char<4,?>>)
20+
! CHECK: %[[VAL_4:.*]] = fir.alloca !fir.char<4,?>(%[[VAL_0]]#1 : index)
21+
! CHECK: fir.char_convert %[[VAL_1]]#1 for %[[VAL_0]]#1 to %[[VAL_4:.*]] : !fir.ref<!fir.char<1,?>>, index, !fir.ref<!fir.char<4,?>>
22+
! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]] typeparams %[[VAL_0]]#1 {uniq_name = "ctor.temp"} : (!fir.ref<!fir.char<4,?>>, index) -> (!fir.boxchar<4>, !fir.ref<!fir.char<4,?>>)
23+
! CHECK: hlfir.assign %[[VAL_5]]#0 to %[[VAL_3]]#0 : !fir.boxchar<4>, !fir.boxchar<4>
24+
! CHECK: return
25+
! CHECK: }
26+
27+
! CHECK: func.func @_QPtest_c4_to_c1(%[[ARG0:.*]]: !fir.boxchar<4> {fir.bindc_name = "c4"}, %[[ARG1:.*]]: !fir.boxchar<1> {fir.bindc_name = "c1"}) {
28+
! CHECK: %[[VAL_0:.*]]:2 = fir.unboxchar %[[ARG1]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
29+
! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]]#0 typeparams %[[VAL_0]]#1 {uniq_name = "_QFtest_c4_to_c1Ec1"} : (!fir.ref<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>)
30+
! CHECK: %[[VAL_2:.*]]:2 = fir.unboxchar %[[ARG0]] : (!fir.boxchar<4>) -> (!fir.ref<!fir.char<4,?>>, index)
31+
! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]]#0 typeparams %[[VAL_2]]#1 {uniq_name = "_QFtest_c4_to_c1Ec4"} : (!fir.ref<!fir.char<4,?>>, index) -> (!fir.boxchar<4>, !fir.ref<!fir.char<4,?>>)
32+
! CHECK: %[[C4:.*]] = arith.constant 4 : index
33+
! CHECK: %[[VAL_4:.*]] = arith.muli %[[VAL_2]]#1, %[[C4]] : index
34+
! CHECK: %[[VAL_5:.*]] = fir.alloca !fir.char<1,?>(%[[VAL_4]] : index)
35+
! CHECK: fir.char_convert %[[VAL_3]]#1 for %[[VAL_2]]#1 to %[[VAL_5:.*]] : !fir.ref<!fir.char<4,?>>, index, !fir.ref<!fir.char<1,?>>
36+
! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_5]] typeparams %[[VAL_2]]#1 {uniq_name = "ctor.temp"} : (!fir.ref<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>)
37+
! CHECK: hlfir.assign %[[VAL_6]]#0 to %[[VAL_1]]#0 : !fir.boxchar<1>, !fir.boxchar<1>
38+
! CHECK: return
39+
! CHECK: }

0 commit comments

Comments
 (0)