diff --git a/flang/lib/Optimizer/HLFIR/Transforms/BufferizeHLFIR.cpp b/flang/lib/Optimizer/HLFIR/Transforms/BufferizeHLFIR.cpp --- a/flang/lib/Optimizer/HLFIR/Transforms/BufferizeHLFIR.cpp +++ b/flang/lib/Optimizer/HLFIR/Transforms/BufferizeHLFIR.cpp @@ -94,6 +94,44 @@ TODO(bufferizedExpr.getLoc(), "general extract storage case"); } +static std::pair +createTempFromMold(mlir::Location loc, fir::FirOpBuilder &builder, + hlfir::Entity mold) { + if (mold.isArray()) + TODO(loc, "create temps from array mold"); + llvm::SmallVector lenParams; + hlfir::genLengthParameters(loc, builder, mold, lenParams); + llvm::StringRef tmpName{".tmp"}; + mlir::Value alloca = + builder.createTemporary(loc, mold.getFortranElementType(), tmpName, + /*shape*/ llvm::None, lenParams); + auto declareOp = builder.create( + loc, alloca, tmpName, /*shapeOrShift*/ mlir::Value{}, lenParams, + fir::FortranVariableFlagsAttr{}); + mlir::Value falseVal = builder.createBool(loc, false); + return {hlfir::Entity{declareOp.getBase()}, falseVal}; +} + +struct AsExprOpConversion : public mlir::OpConversionPattern { + using mlir::OpConversionPattern::OpConversionPattern; + explicit AsExprOpConversion(mlir::MLIRContext *ctx) + : mlir::OpConversionPattern{ctx} {} + mlir::LogicalResult + matchAndRewrite(hlfir::AsExprOp asExpr, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const override { + mlir::Location loc = asExpr->getLoc(); + auto module = asExpr->getParentOfType(); + fir::FirOpBuilder builder(rewriter, fir::getKindMapping(module)); + hlfir::Entity source = hlfir::Entity{adaptor.getVar()}; + auto [temp, cleanup] = createTempFromMold(loc, builder, source); + builder.create(loc, source, temp); + mlir::Value bufferizedExpr = + packageBufferizedExpr(loc, builder, temp, cleanup); + rewriter.replaceOp(asExpr, bufferizedExpr); + return mlir::success(); + } +}; + struct AssignOpConversion : public mlir::OpConversionPattern { using mlir::OpConversionPattern::OpConversionPattern; explicit AssignOpConversion(mlir::MLIRContext *ctx) @@ -219,8 +257,9 @@ auto module = this->getOperation(); auto *context = &getContext(); mlir::RewritePatternSet patterns(context); - patterns.insert(context); + patterns + .insert(context); mlir::ConversionTarget target(*context); target.addIllegalOp(); target.markUnknownOpDynamicallyLegal([](mlir::Operation *op) { diff --git a/flang/test/HLFIR/as_expr-codegen.fir b/flang/test/HLFIR/as_expr-codegen.fir new file mode 100644 --- /dev/null +++ b/flang/test/HLFIR/as_expr-codegen.fir @@ -0,0 +1,37 @@ +// Test hlfir.as_expr code generation + +// RUN: fir-opt %s -bufferize-hlfir | FileCheck %s + +func.func @char_expr(%addr: !fir.ref>, %len: index) { + %0:2 = hlfir.declare %addr typeparams %len {uniq_name = "c"} : (!fir.ref>, index) -> (!fir.boxchar<1>, !fir.ref>) + %1 = hlfir.as_expr %0#0 : (!fir.boxchar<1>) -> !hlfir.expr> + return +} +// CHECK-LABEL: func.func @char_expr( +// CHECK-SAME: %[[VAL_0:.*]]: !fir.ref>, +// CHECK-SAME: %[[VAL_1:.*]]: index) { +// CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] typeparams %[[VAL_1]] {uniq_name = "c"} : (!fir.ref>, index) -> (!fir.boxchar<1>, !fir.ref>) +// CHECK: %[[VAL_3:.*]] = fir.alloca !fir.char<1,?>(%[[VAL_1]] : index) {bindc_name = ".tmp"} +// CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] typeparams %[[VAL_1]] {uniq_name = ".tmp"} : (!fir.ref>, index) -> (!fir.boxchar<1>, !fir.ref>) +// CHECK: %[[VAL_5:.*]] = arith.constant false +// CHECK: hlfir.assign %[[VAL_2]]#0 to %[[VAL_4]]#0 : !fir.boxchar<1>, !fir.boxchar<1> +// CHECK: %[[VAL_6:.*]] = fir.undefined tuple, i1> +// CHECK: %[[VAL_7:.*]] = fir.insert_value %[[VAL_6]], %[[VAL_5]], [1 : index] : (tuple, i1>, i1) -> tuple, i1> +// CHECK: %[[VAL_8:.*]] = fir.insert_value %[[VAL_7]], %[[VAL_4]]#0, [0 : index] : (tuple, i1>, !fir.boxchar<1>) -> tuple, i1> + +func.func @char_expr_2(%addr: !fir.ref>, %len: index) { + %0:2 = hlfir.declare %addr typeparams %len {uniq_name = "c"} : (!fir.ref>, index) -> (!fir.ref>, !fir.ref>) + %1 = hlfir.as_expr %0#0 : (!fir.ref>) -> !hlfir.expr> + return +} +// CHECK-LABEL: func.func @char_expr_2( +// CHECK-SAME: %[[VAL_0:.*]]: !fir.ref>, +// CHECK-SAME: %[[VAL_1:.*]]: index) { +// CHECK: %[[VAL_2:.*]] = fir.alloca !fir.char<1,10> {bindc_name = ".tmp"} +// CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] typeparams %[[VAL_1]] {uniq_name = "c"} : (!fir.ref>, index) -> (!fir.ref>, !fir.ref>) +// CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_2]] typeparams %[[VAL_1]] {uniq_name = ".tmp"} : (!fir.ref>, index) -> (!fir.ref>, !fir.ref>) +// CHECK: %[[VAL_5:.*]] = arith.constant false +// CHECK: hlfir.assign %[[VAL_3]]#0 to %[[VAL_4]]#0 : !fir.ref>, !fir.ref> +// CHECK: %[[VAL_6:.*]] = fir.undefined tuple>, i1> +// CHECK: %[[VAL_7:.*]] = fir.insert_value %[[VAL_6]], %[[VAL_5]], [1 : index] : (tuple>, i1>, i1) -> tuple>, i1> +// CHECK: %[[VAL_8:.*]] = fir.insert_value %[[VAL_7]], %[[VAL_4]]#0, [0 : index] : (tuple>, i1>, !fir.ref>) -> tuple>, i1>