diff --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp --- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp +++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp @@ -1162,6 +1162,37 @@ } }; +/// Convert `!fir.emboxchar, #n>` into a sequence of +/// instructions that generates `!llvm.struct<(ptr, i64)>`. The 1st element +/// in this struct is a pointer. Its type is determined from `KIND`. The 2nd +/// element is the length of the character buffer (`#n`). +struct EmboxCharOpConversion : public FIROpConversion { + using FIROpConversion::FIROpConversion; + + mlir::LogicalResult + matchAndRewrite(fir::EmboxCharOp emboxChar, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const override { + auto operands = adaptor.getOperands(); + + mlir::Value char_buffer = operands[0]; + mlir::Value char_buffer_len = operands[1]; + mlir::Location loc = emboxChar.getLoc(); + MLIRContext *ctx = emboxChar.getContext(); + auto ty = convertType(emboxChar.getType()); + + auto c0 = mlir::ArrayAttr::get(ctx, rewriter.getI32IntegerAttr(0)); + auto c1 = mlir::ArrayAttr::get(ctx, rewriter.getI32IntegerAttr(1)); + auto un = rewriter.create(loc, ty); + auto lenTy = ty.cast().getBody()[1]; + auto b = integerCast(loc, rewriter, lenTy, char_buffer_len); + auto r = rewriter.create(loc, ty, un, + char_buffer, c0); + rewriter.replaceOpWithNewOp(emboxChar, ty, r, b, + c1); + return success(); + } +}; + } // namespace namespace { @@ -1189,12 +1220,12 @@ BoxAddrOpConversion, BoxDimsOpConversion, BoxEleSizeOpConversion, BoxIsAllocOpConversion, BoxIsArrayOpConversion, BoxIsPtrOpConversion, BoxRankOpConversion, CallOpConversion, ConvertOpConversion, - DivcOpConversion, ExtractValueOpConversion, HasValueOpConversion, - GlobalOpConversion, InsertOnRangeOpConversion, InsertValueOpConversion, - LoadOpConversion, NegcOpConversion, MulcOpConversion, - SelectOpConversion, SelectRankOpConversion, StoreOpConversion, - SubcOpConversion, UndefOpConversion, UnreachableOpConversion, - ZeroOpConversion>(typeConverter); + DivcOpConversion, EmboxCharOpConversion, ExtractValueOpConversion, + HasValueOpConversion, GlobalOpConversion, InsertOnRangeOpConversion, + InsertValueOpConversion, LoadOpConversion, NegcOpConversion, + MulcOpConversion, SelectOpConversion, SelectRankOpConversion, + StoreOpConversion, SubcOpConversion, UndefOpConversion, + UnreachableOpConversion, ZeroOpConversion>(typeConverter); mlir::populateStdToLLVMConversionPatterns(typeConverter, pattern); mlir::arith::populateArithmeticToLLVMConversionPatterns(typeConverter, pattern); diff --git a/flang/test/Fir/convert-to-llvm.fir b/flang/test/Fir/convert-to-llvm.fir --- a/flang/test/Fir/convert-to-llvm.fir +++ b/flang/test/Fir/convert-to-llvm.fir @@ -961,3 +961,21 @@ // CHECK: [[PROD3:%.*]] = llvm.mul [[PROD2]], [[B]] : i64 // CHECK: [[RES:%.*]] = llvm.alloca [[PROD3]] x i32 {in_type = !fir.array<4x?x3x?x5xi32> // CHECK: llvm.return [[RES]] : !llvm.ptr + +// ----- + +// Test fir.emboxchar + +func @test_embox(%char_array : !fir.ref>) -> () { + %c10 = arith.constant 10 : i64 + %box_char = fir.emboxchar %char_array, %c10 : (!fir.ref>, i64) -> !fir.boxchar<1> + return +} + +// CHECK-LABEL: test_embox +// CHECK-SAME: (%[[char_array:.*]]: !llvm.ptr) +// CHECK: %[[c10:.*]] = llvm.mlir.constant(10 : i64) : i64 +// CHECK: %[[empty_struct:.*]] = llvm.mlir.undef : !llvm.struct<(ptr, i{{.*}})> +// CHECK: %[[struct_with_buffer:.*]] = llvm.insertvalue %[[char_array]], %[[empty_struct]][0 : i32] : !llvm.struct<(ptr, i{{.*}})> +// CHECK: %{{.*}} = llvm.insertvalue %[[c10]], %[[struct_with_buffer]][1 : i32] : !llvm.struct<(ptr, i{{.*}})> +// CHECK-NEXT: llvm.return