return success();
}
};
+
+/// Convert `!fir.emboxchar<!fir.char<KIND, ?>, #n>` into a sequence of
+/// instructions that generate `!llvm.struct<(ptr<ik>, 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<fir::EmboxCharOp> {
+ using FIROpConversion::FIROpConversion;
+
+ mlir::LogicalResult
+ matchAndRewrite(fir::EmboxCharOp emboxChar, OpAdaptor adaptor,
+ mlir::ConversionPatternRewriter &rewriter) const override {
+ mlir::ValueRange operands = adaptor.getOperands();
+ MLIRContext *ctx = emboxChar.getContext();
+
+ mlir::Value charBuffer = operands[0];
+ mlir::Value charBufferLen = operands[1];
+
+ mlir::Location loc = emboxChar.getLoc();
+ mlir::Type llvmStructTy = convertType(emboxChar.getType());
+ auto llvmStruct = rewriter.create<mlir::LLVM::UndefOp>(loc, llvmStructTy);
+
+ mlir::Type lenTy =
+ llvmStructTy.cast<mlir::LLVM::LLVMStructType>().getBody()[1];
+ mlir::Value lenAfterCast = integerCast(loc, rewriter, lenTy, charBufferLen);
+
+ auto c0 = mlir::ArrayAttr::get(ctx, rewriter.getI32IntegerAttr(0));
+ auto c1 = mlir::ArrayAttr::get(ctx, rewriter.getI32IntegerAttr(1));
+ auto insertBufferOp = rewriter.create<mlir::LLVM::InsertValueOp>(
+ loc, llvmStructTy, llvmStruct, charBuffer, c0);
+ rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(
+ emboxChar, llvmStructTy, insertBufferOp, lenAfterCast, c1);
+
+ return success();
+ }
+};
} // namespace
namespace {
BoxEleSizeOpConversion, BoxIsAllocOpConversion, BoxIsArrayOpConversion,
BoxIsPtrOpConversion, BoxRankOpConversion, CallOpConversion,
ConvertOpConversion, DispatchOpConversion, DispatchTableOpConversion,
- DTEntryOpConversion, DivcOpConversion, ExtractValueOpConversion,
- HasValueOpConversion, GlobalOpConversion, InsertOnRangeOpConversion,
- InsertValueOpConversion, IsPresentOpConversion, LoadOpConversion,
- NegcOpConversion, MulcOpConversion, SelectCaseOpConversion,
- SelectOpConversion, SelectRankOpConversion, StoreOpConversion,
- SubcOpConversion, UndefOpConversion, UnreachableOpConversion,
- ZeroOpConversion>(typeConverter);
+ DTEntryOpConversion, DivcOpConversion, EmboxCharOpConversion,
+ ExtractValueOpConversion, HasValueOpConversion, GlobalOpConversion,
+ InsertOnRangeOpConversion, InsertValueOpConversion,
+ IsPresentOpConversion, LoadOpConversion, NegcOpConversion,
+ MulcOpConversion, SelectCaseOpConversion, SelectOpConversion,
+ SelectRankOpConversion, StoreOpConversion, SubcOpConversion,
+ UndefOpConversion, UnreachableOpConversion, ZeroOpConversion>(
+ typeConverter);
mlir::populateStdToLLVMConversionPatterns(typeConverter, pattern);
mlir::arith::populateArithmeticToLLVMConversionPatterns(typeConverter,
pattern);
--- /dev/null
+// RUN: fir-opt --split-input-file --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" %s | FileCheck %s --check-prefix INT64
+// RUN: fir-opt --split-input-file --fir-to-llvm-ir="target=aarch64-unknown-linux-gnu" %s | FileCheck %s --check-prefixes INT64
+// RUN: fir-opt --split-input-file --fir-to-llvm-ir="target=i386-unknown-linux-gnu" %s | FileCheck %s --check-prefixes INT32
+// RUN: fir-opt --split-input-file --fir-to-llvm-ir="target=powerpc64le-unknown-linux-gn" %s | FileCheck %s --check-prefixes INT64
+
+//=============================================================================
+// SUMMARY: Tests for FIR --> LLVM MLIR conversion that *depend* on the target
+//=============================================================================
+
+// Test fir.emboxchar
+
+func @test_embox(%char_array : !fir.ref<!fir.char<1,?>>) -> () {
+ %c10 = arith.constant 10 : i64
+ %box_char = fir.emboxchar %char_array, %c10 : (!fir.ref<!fir.char<1,?>>, i64) -> !fir.boxchar<1>
+ return
+}
+
+// INT64-LABEL: test_embox
+// INT64-SAME: (%[[char_array:.*]]: !llvm.ptr<i8>)
+// INT64: %[[c10:.*]] = llvm.mlir.constant(10 : i64) : i64
+// INT64: %[[empty_struct:.*]] = llvm.mlir.undef : !llvm.struct<(ptr<i8>, i{{.*}})>
+// INT64: %[[struct_with_buffer:.*]] = llvm.insertvalue %[[char_array]], %[[empty_struct]][0 : i32] : !llvm.struct<(ptr<i8>, i{{.*}})>
+// INT64: %{{.*}} = llvm.insertvalue %[[c10]], %[[struct_with_buffer]][1 : i32] : !llvm.struct<(ptr<i8>, i{{.*}})>
+// INT64-NEXT: llvm.return
+
+// INT32-LABEL: llvm.func @test_embox
+// INT32-SAME: %[[char_array:.*]]: !llvm.ptr<i8>)
+// INT32: %[[c10:.*]] = llvm.mlir.constant(10 : i64) : i64
+// INT32: %[[empty_struct:.*]] = llvm.mlir.undef : !llvm.struct<(ptr<i8>, i32)>
+// INT32: %[[c10_truncated:.*]] = llvm.trunc %[[c10]] : i64 to i32
+// INT32: %[[struct_with_buffer:.*]] = llvm.insertvalue %[[char_array]], %[[empty_struct]][0 : i32] : !llvm.struct<(ptr<i8>, i32)>
+// INT32: %{{.*}} = llvm.insertvalue %[[c10_truncated:.*]], %[[struct_with_buffer]][1 : i32] : !llvm.struct<(ptr<i8>, i32)>
+// INT32-NEXT: llvm.return