diff --git a/flang/include/flang/Optimizer/Builder/HLFIRTools.h b/flang/include/flang/Optimizer/Builder/HLFIRTools.h --- a/flang/include/flang/Optimizer/Builder/HLFIRTools.h +++ b/flang/include/flang/Optimizer/Builder/HLFIRTools.h @@ -339,6 +339,17 @@ hlfir::ElementalOp elemental, mlir::ValueRange oneBasedIndices); +std::pair> +convertToValue(mlir::Location loc, fir::FirOpBuilder &builder, + const hlfir::Entity &entity); + +std::pair> +convertToAddress(mlir::Location loc, fir::FirOpBuilder &builder, + const hlfir::Entity &entity, mlir::Type targetType); + +std::pair> +convertToBox(mlir::Location loc, fir::FirOpBuilder &builder, + const hlfir::Entity &entity, mlir::Type targetType); } // namespace hlfir #endif // FORTRAN_OPTIMIZER_BUILDER_HLFIRTOOLS_H diff --git a/flang/lib/Lower/ConvertExprToHLFIR.cpp b/flang/lib/Lower/ConvertExprToHLFIR.cpp --- a/flang/lib/Lower/ConvertExprToHLFIR.cpp +++ b/flang/lib/Lower/ConvertExprToHLFIR.cpp @@ -1254,25 +1254,15 @@ return HlfirBuilder(loc, converter, symMap, stmtCtx).gen(expr); } -static fir::ExtendedValue placeTrivialInMemory(mlir::Location loc, - fir::FirOpBuilder &builder, - mlir::Value val, - mlir::Type fortranType) { - auto temp = builder.createTemporary(loc, fortranType); - builder.createStoreWithConvert(loc, val, temp); - return temp; -} - fir::BoxValue Fortran::lower::convertToBox( mlir::Location loc, Fortran::lower::AbstractConverter &converter, hlfir::Entity entity, Fortran::lower::StatementContext &stmtCtx, mlir::Type fortranType) { - auto exv = Fortran::lower::translateToExtendedValue( - loc, converter.getFirOpBuilder(), entity, stmtCtx); - if (fir::isa_trivial(fir::getBase(exv).getType())) - exv = placeTrivialInMemory(loc, converter.getFirOpBuilder(), - fir::getBase(exv), fortranType); - return fir::factory::createBoxValue(converter.getFirOpBuilder(), loc, exv); + fir::FirOpBuilder &builder = converter.getFirOpBuilder(); + auto [exv, cleanup] = hlfir::convertToBox(loc, builder, entity, fortranType); + if (cleanup) + stmtCtx.attachCleanup(*cleanup); + return exv; } fir::BoxValue Fortran::lower::convertExprToBox( mlir::Location loc, Fortran::lower::AbstractConverter &converter, @@ -1289,11 +1279,10 @@ hlfir::Entity entity, Fortran::lower::StatementContext &stmtCtx, mlir::Type fortranType) { fir::FirOpBuilder &builder = converter.getFirOpBuilder(); - entity = hlfir::derefPointersAndAllocatables(loc, builder, entity); - fir::ExtendedValue exv = - Fortran::lower::translateToExtendedValue(loc, builder, entity, stmtCtx); - if (fir::isa_trivial(fir::getBase(exv).getType())) - return placeTrivialInMemory(loc, builder, fir::getBase(exv), fortranType); + auto [exv, cleanup] = + hlfir::convertToAddress(loc, builder, entity, fortranType); + if (cleanup) + stmtCtx.attachCleanup(*cleanup); return exv; } @@ -1311,26 +1300,10 @@ mlir::Location loc, Fortran::lower::AbstractConverter &converter, hlfir::Entity entity, Fortran::lower::StatementContext &stmtCtx) { auto &builder = converter.getFirOpBuilder(); - fir::ExtendedValue exv = - Fortran::lower::translateToExtendedValue(loc, builder, entity, stmtCtx); - // Load scalar references to integer, logical, real, or complex value - // to an mlir value, dereference allocatable and pointers, and get rid - // of fir.box that are not needed or create a copy into contiguous memory. - return exv.match( - [&](const fir::UnboxedValue &box) -> fir::ExtendedValue { - if (mlir::Type elementType = fir::dyn_cast_ptrEleTy(box.getType())) - if (fir::isa_trivial(elementType)) - return builder.create(loc, box); - return box; - }, - [&](const fir::CharBoxValue &box) -> fir::ExtendedValue { return box; }, - [&](const fir::ArrayBoxValue &box) -> fir::ExtendedValue { return box; }, - [&](const fir::CharArrayBoxValue &box) -> fir::ExtendedValue { - return box; - }, - [&](const auto &) -> fir::ExtendedValue { - TODO(loc, "lower descriptor designator to HLFIR value"); - }); + auto [exv, cleanup] = hlfir::convertToValue(loc, builder, entity); + if (cleanup) + stmtCtx.attachCleanup(*cleanup); + return exv; } fir::ExtendedValue Fortran::lower::convertExprToValue( 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 @@ -760,3 +760,64 @@ } return {{static_cast(entity)}, {}}; } + +std::pair> +hlfir::convertToValue(mlir::Location loc, fir::FirOpBuilder &builder, + const hlfir::Entity &entity) { + auto [exv, cleanup] = translateToExtendedValue(loc, builder, entity); + // Load scalar references to integer, logical, real, or complex value + // to an mlir value, dereference allocatable and pointers, and get rid + // of fir.box that are not needed or create a copy into contiguous memory. + exv = exv.match( + [&](const fir::UnboxedValue &box) -> fir::ExtendedValue { + if (mlir::Type elementType = fir::dyn_cast_ptrEleTy(box.getType())) + if (fir::isa_trivial(elementType)) + return builder.create(loc, box); + return box; + }, + [&](const fir::CharBoxValue &box) -> fir::ExtendedValue { return box; }, + [&](const fir::ArrayBoxValue &box) -> fir::ExtendedValue { return box; }, + [&](const fir::CharArrayBoxValue &box) -> fir::ExtendedValue { + return box; + }, + [&](const auto &) -> fir::ExtendedValue { + TODO(loc, "lower descriptor designator to HLFIR value"); + }); + return {exv, cleanup}; +} + +static fir::ExtendedValue placeTrivialInMemory(mlir::Location loc, + fir::FirOpBuilder &builder, + mlir::Value val, + mlir::Type targetType) { + auto temp = builder.createTemporary(loc, targetType); + if (targetType != val.getType()) + builder.createStoreWithConvert(loc, val, temp); + else + builder.create(loc, val, temp); + return temp; +} + +std::pair> +hlfir::convertToBox(mlir::Location loc, fir::FirOpBuilder &builder, + const hlfir::Entity &entity, mlir::Type targetType) { + auto [exv, cleanup] = translateToExtendedValue(loc, builder, entity); + mlir::Value base = fir::getBase(exv); + if (fir::isa_trivial(base.getType())) + exv = placeTrivialInMemory(loc, builder, base, targetType); + fir::BoxValue box = fir::factory::createBoxValue(builder, loc, exv); + return {box, cleanup}; +} + +std::pair> +hlfir::convertToAddress(mlir::Location loc, fir::FirOpBuilder &builder, + const hlfir::Entity &entity, mlir::Type targetType) { + hlfir::Entity derefedEntity = + hlfir::derefPointersAndAllocatables(loc, builder, entity); + auto [exv, cleanup] = + hlfir::translateToExtendedValue(loc, builder, derefedEntity); + mlir::Value base = fir::getBase(exv); + if (fir::isa_trivial(base.getType())) + exv = placeTrivialInMemory(loc, builder, base, targetType); + return {exv, cleanup}; +}