diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp --- a/flang/lib/Lower/Bridge.cpp +++ b/flang/lib/Lower/Bridge.cpp @@ -508,12 +508,16 @@ hlfir::EntityWithAttributes loweredExpr = Fortran::lower::convertExprToHLFIR(loc, *this, expr, localSymbols, context); - if (fir::FortranVariableOpInterface variable = - loweredExpr.getIfVariable()) - if (!variable.isBox()) - return translateToExtendedValue(loc, loweredExpr, context); - TODO(loc, "lower expr that is not a scalar or explicit shape array " - "variable to HLFIR address"); + if (expr.Rank() > 0 && + !Fortran::evaluate::IsSimplyContiguous(expr, getFoldingContext())) + TODO(loc, "genExprAddr of non contiguous variables in HLFIR"); + fir::ExtendedValue exv = + translateToExtendedValue(loc, loweredExpr, context); + if (fir::isa_trivial(fir::getBase(exv).getType())) + TODO(loc, "place trivial in memory"); + if (const auto *mutableBox = exv.getBoxOf()) + exv = fir::factory::genMutableBoxRead(*builder, loc, *mutableBox); + return exv; } return Fortran::lower::createSomeExtendedAddress(loc, *this, expr, localSymbols, context); @@ -564,14 +568,10 @@ hlfir::EntityWithAttributes loweredExpr = Fortran::lower::convertExprToHLFIR(loc, *this, expr, localSymbols, stmtCtx); - if (fir::FortranVariableOpInterface variable = - loweredExpr.getIfVariable()) - if (variable.isBoxValue() || !variable.isBoxAddress()) { - auto exv = translateToExtendedValue(loc, loweredExpr, stmtCtx); - return fir::factory::createBoxValue(getFirOpBuilder(), loc, exv); - } - TODO(loc, - "lower expression value or pointer and allocatable to HLFIR box"); + auto exv = translateToExtendedValue(loc, loweredExpr, stmtCtx); + if (fir::isa_trivial(fir::getBase(exv).getType())) + TODO(loc, "place trivial in memory"); + return fir::factory::createBoxValue(getFirOpBuilder(), loc, exv); } return Fortran::lower::createBoxValue(loc, *this, expr, localSymbols, stmtCtx); diff --git a/flang/lib/Optimizer/Builder/HLFIRTools.cpp b/flang/lib/Optimizer/Builder/HLFIRTools.cpp --- a/flang/lib/Optimizer/Builder/HLFIRTools.cpp +++ b/flang/lib/Optimizer/Builder/HLFIRTools.cpp @@ -76,16 +76,28 @@ if (entity.isVariable()) TODO(loc, "HLFIR variable to fir::ExtendedValue without a " "FortranVariableOpInterface"); - if (entity.getType().isa()) - TODO(loc, "hlfir.expr to fir::ExtendedValue"); // use hlfir.associate + if (entity.getType().isa()) { + hlfir::AssociateOp associate = hlfir::genAssociateExpr( + loc, builder, entity, entity.getType(), "adapt.valuebyref"); + auto *bldr = &builder; + hlfir::CleanupFunction cleanup = [bldr, loc, associate]() -> void { + bldr->create(loc, associate); + }; + hlfir::Entity temp{associate.getBase()}; + return {translateToExtendedValue(loc, builder, temp).first, cleanup}; + } return {{static_cast(entity)}, {}}; } mlir::Value hlfir::Entity::getFirBase() const { - if (fir::FortranVariableOpInterface variable = getIfVariableInterface()) + if (fir::FortranVariableOpInterface variable = getIfVariableInterface()) { if (auto declareOp = mlir::dyn_cast(variable.getOperation())) return declareOp.getOriginalBase(); + if (auto associateOp = + mlir::dyn_cast(variable.getOperation())) + return associateOp.getFirBase(); + } return getBase(); } diff --git a/flang/test/Lower/HLFIR/calls-f77.f90 b/flang/test/Lower/HLFIR/calls-f77.f90 --- a/flang/test/Lower/HLFIR/calls-f77.f90 +++ b/flang/test/Lower/HLFIR/calls-f77.f90 @@ -27,7 +27,7 @@ ! CHECK-LABEL: func.func @_QPcall_int_arg_expr() { ! CHECK: %[[VAL_0:.*]] = arith.constant 42 : i32 ! CHECK: %[[VAL_1:.*]]:3 = hlfir.associate %[[VAL_0]] {uniq_name = "adapt.valuebyref"} : (i32) -> (!fir.ref, !fir.ref, i1) -! CHECK: fir.call @_QPtake_i4(%[[VAL_1]]#0) fastmath : (!fir.ref) -> () +! CHECK: fir.call @_QPtake_i4(%[[VAL_1]]#1) fastmath : (!fir.ref) -> () ! CHECK: hlfir.end_associate %[[VAL_1]]#1, %[[VAL_1]]#2 : !fir.ref, i1 subroutine call_real_arg_expr() @@ -36,7 +36,7 @@ ! CHECK-LABEL: func.func @_QPcall_real_arg_expr() { ! CHECK: %[[VAL_0:.*]] = arith.constant 4.200000e-01 : f32 ! CHECK: %[[VAL_1:.*]]:3 = hlfir.associate %[[VAL_0]] {uniq_name = "adapt.valuebyref"} : (f32) -> (!fir.ref, !fir.ref, i1) -! CHECK: fir.call @_QPtake_r4(%[[VAL_1]]#0) fastmath : (!fir.ref) -> () +! CHECK: fir.call @_QPtake_r4(%[[VAL_1]]#1) fastmath : (!fir.ref) -> () ! CHECK: hlfir.end_associate %[[VAL_1]]#1, %[[VAL_1]]#2 : !fir.ref, i1 subroutine call_real_arg_var(x) @@ -64,7 +64,7 @@ ! CHECK: %[[VAL_0:.*]] = arith.constant true ! CHECK: %[[VAL_1:.*]] = fir.convert %[[VAL_0]] : (i1) -> !fir.logical<4> ! CHECK: %[[VAL_2:.*]]:3 = hlfir.associate %[[VAL_1]] {uniq_name = "adapt.valuebyref"} : (!fir.logical<4>) -> (!fir.ref>, !fir.ref>, i1) -! CHECK: fir.call @_QPtake_l4(%[[VAL_2]]#0) fastmath : (!fir.ref>) -> () +! CHECK: fir.call @_QPtake_l4(%[[VAL_2]]#1) fastmath : (!fir.ref>) -> () ! CHECK: hlfir.end_associate %[[VAL_2]]#1, %[[VAL_2]]#2 : !fir.ref>, i1 subroutine call_logical_arg_expr_2() @@ -74,7 +74,7 @@ ! CHECK: %[[VAL_0:.*]] = arith.constant true ! CHECK: %[[VAL_1:.*]] = fir.convert %[[VAL_0]] : (i1) -> !fir.logical<8> ! CHECK: %[[VAL_2:.*]]:3 = hlfir.associate %[[VAL_1]] {uniq_name = "adapt.valuebyref"} : (!fir.logical<8>) -> (!fir.ref>, !fir.ref>, i1) -! CHECK: fir.call @_QPtake_l8(%[[VAL_2]]#0) fastmath : (!fir.ref>) -> () +! CHECK: fir.call @_QPtake_l8(%[[VAL_2]]#1) fastmath : (!fir.ref>) -> () ! CHECK: hlfir.end_associate %[[VAL_2]]#1, %[[VAL_2]]#2 : !fir.ref>, i1 subroutine call_char_arg_var(x) diff --git a/flang/test/Lower/HLFIR/expr-addr.f90 b/flang/test/Lower/HLFIR/expr-addr.f90 --- a/flang/test/Lower/HLFIR/expr-addr.f90 +++ b/flang/test/Lower/HLFIR/expr-addr.f90 @@ -10,3 +10,16 @@ ! CHECK: %[[x_cast:.*]] = fir.convert %[[x]]#1 : (!fir.ref) -> !fir.ref ! CHECK: fir.call @_FortranAioInputInteger(%{{.*}}, %[[x_cast]], %{{.*}}) {{.*}}: (!fir.ref, !fir.ref, i32) -> i1 end subroutine + +subroutine expr_to_var(c) + character(*) :: c + print *, c//c +end subroutine + +! CHECK-LABEL: func.func @_QPexpr_to_var( +! CHECK: %[[VAL_9:.*]] = hlfir.concat %{{.*}}, %{{.*}} len %[[VAL_8:.*]] : (!fir.boxchar<1>, !fir.boxchar<1>, index) -> !hlfir.expr> +! CHECK: %[[VAL_10:.*]]:3 = hlfir.associate %[[VAL_9]] typeparams %[[VAL_8]] {uniq_name = "adapt.valuebyref"} : (!hlfir.expr>, index) -> (!fir.boxchar<1>, !fir.ref>, i1) +! CHECK: %[[VAL_11:.*]] = fir.convert %[[VAL_10]]#1 : (!fir.ref>) -> !fir.ref +! CHECK: %[[VAL_12:.*]] = fir.convert %[[VAL_8]] : (index) -> i64 +! CHECK: %[[VAL_13:.*]] = fir.call @_FortranAioOutputAscii(%{{.*}}, %[[VAL_11]], %[[VAL_12]]) {{.*}} : (!fir.ref, !fir.ref, i64) -> i1 +! CHECK: hlfir.end_associate %[[VAL_10]]#1, %[[VAL_10]]#2 : !fir.ref>, i1