From 4e78f88561af26c74b4b7fa2a017cd836a9f9bf4 Mon Sep 17 00:00:00 2001 From: Jean Perier Date: Tue, 10 Jan 2023 09:28:08 +0100 Subject: [PATCH] [flang] Lower addresses inside global initializers in HLFIR Move the code to lower an expression to address or a box in HLFIR from Bridge.cpp to ConvertExpr.cpp so that it can be used inside ConvertVariable.cpp (that needs to use a different symbol map that the one held in the bridge). Lower NULL to hlfir.null. This allows lowering derived type constant structure constructors with pointer components into fir.global. Differential Revision: https://reviews.llvm.org/D141276 --- flang/include/flang/Lower/ConvertExprToHLFIR.h | 26 ++++++++++++++- flang/include/flang/Lower/StatementContext.h | 1 + flang/lib/Lower/Bridge.cpp | 45 +++++--------------------- flang/lib/Lower/ConvertExprToHLFIR.cpp | 38 +++++++++++++++++++++- flang/lib/Lower/ConvertVariable.cpp | 29 ++++++++++------- flang/test/Lower/HLFIR/constant-derived.f90 | 35 +++++++++++++++++++- 6 files changed, 123 insertions(+), 51 deletions(-) diff --git a/flang/include/flang/Lower/ConvertExprToHLFIR.h b/flang/include/flang/Lower/ConvertExprToHLFIR.h index abcab29..fb70166 100644 --- a/flang/include/flang/Lower/ConvertExprToHLFIR.h +++ b/flang/include/flang/Lower/ConvertExprToHLFIR.h @@ -17,6 +17,7 @@ #ifndef FORTRAN_LOWER_CONVERTEXPRTOHLFIR_H #define FORTRAN_LOWER_CONVERTEXPRTOHLFIR_H +#include "flang/Lower/StatementContext.h" #include "flang/Lower/Support/Utils.h" #include "flang/Optimizer/Builder/FIRBuilder.h" #include "flang/Optimizer/Builder/HLFIRTools.h" @@ -29,13 +30,36 @@ class Location; namespace Fortran::lower { class AbstractConverter; -class StatementContext; class SymMap; hlfir::EntityWithAttributes convertExprToHLFIR(mlir::Location loc, Fortran::lower::AbstractConverter &, const Fortran::lower::SomeExpr &, Fortran::lower::SymMap &, Fortran::lower::StatementContext &); + +inline fir::ExtendedValue +translateToExtendedValue(mlir::Location loc, fir::FirOpBuilder &builder, + hlfir::EntityWithAttributes entity, + Fortran::lower::StatementContext &context) { + auto [exv, exvCleanup] = + hlfir::translateToExtendedValue(loc, builder, entity); + if (exvCleanup) + context.attachCleanup(*exvCleanup); + return exv; +} + +fir::BoxValue convertExprToBox(mlir::Location loc, + Fortran::lower::AbstractConverter &, + const Fortran::lower::SomeExpr &, + Fortran::lower::SymMap &, + Fortran::lower::StatementContext &); + +// Probably not what you think. +fir::ExtendedValue convertExprToAddress(mlir::Location loc, + Fortran::lower::AbstractConverter &, + const Fortran::lower::SomeExpr &, + Fortran::lower::SymMap &, + Fortran::lower::StatementContext &); } // namespace Fortran::lower #endif // FORTRAN_LOWER_CONVERTEXPRTOHLFIR_H diff --git a/flang/include/flang/Lower/StatementContext.h b/flang/include/flang/Lower/StatementContext.h index ed8bdc2..9ee304a 100644 --- a/flang/include/flang/Lower/StatementContext.h +++ b/flang/include/flang/Lower/StatementContext.h @@ -13,6 +13,7 @@ #ifndef FORTRAN_LOWER_STATEMENTCONTEXT_H #define FORTRAN_LOWER_STATEMENTCONTEXT_H +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include #include diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp index 9f10ec5..5bddf95 100644 --- a/flang/lib/Lower/Bridge.cpp +++ b/flang/lib/Lower/Bridge.cpp @@ -473,36 +473,13 @@ public: } fir::ExtendedValue - translateToExtendedValue(mlir::Location loc, - hlfir::EntityWithAttributes entity, - Fortran::lower::StatementContext &context) { - auto [exv, exvCleanup] = - hlfir::translateToExtendedValue(loc, getFirOpBuilder(), entity); - if (exvCleanup) - context.attachCleanup(*exvCleanup); - return exv; - } - - fir::ExtendedValue genExprAddr(const Fortran::lower::SomeExpr &expr, Fortran::lower::StatementContext &context, mlir::Location *locPtr = nullptr) override final { mlir::Location loc = locPtr ? *locPtr : toLocation(); - if (bridge.getLoweringOptions().getLowerToHighLevelFIR()) { - hlfir::EntityWithAttributes loweredExpr = - Fortran::lower::convertExprToHLFIR(loc, *this, expr, localSymbols, - context); - 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; - } + if (bridge.getLoweringOptions().getLowerToHighLevelFIR()) + return Fortran::lower::convertExprToAddress(loc, *this, expr, + localSymbols, context); return Fortran::lower::createSomeExtendedAddress(loc, *this, expr, localSymbols, context); } @@ -516,8 +493,8 @@ public: hlfir::EntityWithAttributes loweredExpr = Fortran::lower::convertExprToHLFIR(loc, *this, expr, localSymbols, context); - fir::ExtendedValue exv = - translateToExtendedValue(loc, loweredExpr, context); + fir::ExtendedValue exv = Fortran::lower::translateToExtendedValue( + loc, getFirOpBuilder(), loweredExpr, context); // 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 no needed or create a copy into contiguous memory. @@ -548,15 +525,9 @@ public: fir::ExtendedValue genExprBox(mlir::Location loc, const Fortran::lower::SomeExpr &expr, Fortran::lower::StatementContext &stmtCtx) override final { - if (bridge.getLoweringOptions().getLowerToHighLevelFIR()) { - hlfir::EntityWithAttributes loweredExpr = - Fortran::lower::convertExprToHLFIR(loc, *this, expr, localSymbols, - stmtCtx); - 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); - } + if (bridge.getLoweringOptions().getLowerToHighLevelFIR()) + return Fortran::lower::convertExprToBox(loc, *this, expr, localSymbols, + stmtCtx); return Fortran::lower::createBoxValue(loc, *this, expr, localSymbols, stmtCtx); } diff --git a/flang/lib/Lower/ConvertExprToHLFIR.cpp b/flang/lib/Lower/ConvertExprToHLFIR.cpp index 4b1a542..034ee2a 100644 --- a/flang/lib/Lower/ConvertExprToHLFIR.cpp +++ b/flang/lib/Lower/ConvertExprToHLFIR.cpp @@ -21,6 +21,7 @@ #include "flang/Lower/StatementContext.h" #include "flang/Lower/SymbolMap.h" #include "flang/Optimizer/Builder/Complex.h" +#include "flang/Optimizer/Builder/MutableBox.h" #include "flang/Optimizer/Builder/Runtime/Character.h" #include "flang/Optimizer/Builder/Todo.h" #include "flang/Optimizer/HLFIR/HLFIROps.h" @@ -797,9 +798,12 @@ private: gen(const Fortran::evaluate::BOZLiteralConstant &expr) { fir::emitFatalError(loc, "BOZ literal must be replaced by semantics"); } + hlfir::EntityWithAttributes gen(const Fortran::evaluate::NullPointer &expr) { - TODO(getLoc(), "lowering NullPointer to HLFIR"); + auto nullop = getBuilder().create(getLoc()); + return mlir::cast(nullop.getOperation()); } + hlfir::EntityWithAttributes gen(const Fortran::evaluate::ProcedureDesignator &expr) { TODO(getLoc(), "lowering ProcDes to HLFIR"); @@ -1024,3 +1028,35 @@ hlfir::EntityWithAttributes Fortran::lower::convertExprToHLFIR( Fortran::lower::StatementContext &stmtCtx) { return HlfirBuilder(loc, converter, symMap, stmtCtx).gen(expr); } + +fir::BoxValue Fortran::lower::convertExprToBox( + mlir::Location loc, Fortran::lower::AbstractConverter &converter, + const Fortran::lower::SomeExpr &expr, Fortran::lower::SymMap &symMap, + Fortran::lower::StatementContext &stmtCtx) { + hlfir::EntityWithAttributes loweredExpr = + HlfirBuilder(loc, converter, symMap, stmtCtx).gen(expr); + auto exv = Fortran::lower::translateToExtendedValue( + loc, converter.getFirOpBuilder(), loweredExpr, stmtCtx); + if (fir::isa_trivial(fir::getBase(exv).getType())) + TODO(loc, "place trivial in memory"); + return fir::factory::createBoxValue(converter.getFirOpBuilder(), loc, exv); +} + +fir::ExtendedValue Fortran::lower::convertExprToAddress( + mlir::Location loc, Fortran::lower::AbstractConverter &converter, + const Fortran::lower::SomeExpr &expr, Fortran::lower::SymMap &symMap, + Fortran::lower::StatementContext &stmtCtx) { + hlfir::EntityWithAttributes loweredExpr = + HlfirBuilder(loc, converter, symMap, stmtCtx).gen(expr); + if (expr.Rank() > 0 && !Fortran::evaluate::IsSimplyContiguous( + expr, converter.getFoldingContext())) + TODO(loc, "genExprAddr of non contiguous variables in HLFIR"); + fir::ExtendedValue exv = Fortran::lower::translateToExtendedValue( + loc, converter.getFirOpBuilder(), loweredExpr, stmtCtx); + if (fir::isa_trivial(fir::getBase(exv).getType())) + TODO(loc, "place trivial in memory"); + if (const auto *mutableBox = exv.getBoxOf()) + exv = fir::factory::genMutableBoxRead(converter.getFirOpBuilder(), loc, + *mutableBox); + return exv; +} diff --git a/flang/lib/Lower/ConvertVariable.cpp b/flang/lib/Lower/ConvertVariable.cpp index 084221f..8cb6dea 100644 --- a/flang/lib/Lower/ConvertVariable.cpp +++ b/flang/lib/Lower/ConvertVariable.cpp @@ -163,8 +163,6 @@ hasDerivedTypeWithLengthParameters(const Fortran::semantics::Symbol &sym) { fir::ExtendedValue Fortran::lower::genExtAddrInInitializer( Fortran::lower::AbstractConverter &converter, mlir::Location loc, const Fortran::lower::SomeExpr &addr) { - if (converter.getLoweringOptions().getLowerToHighLevelFIR()) - TODO(loc, "generate initializer address in HLFIR"); Fortran::lower::SymMap globalOpSymMap; Fortran::lower::AggregateStoreMap storeMap; Fortran::lower::StatementContext stmtCtx; @@ -179,6 +177,10 @@ fir::ExtendedValue Fortran::lower::genExtAddrInInitializer( Fortran::lower::instantiateVariable(converter, var, globalOpSymMap, storeMap); } + + if (converter.getLoweringOptions().getLowerToHighLevelFIR()) + return Fortran::lower::convertExprToAddress(loc, converter, addr, + globalOpSymMap, stmtCtx); return Fortran::lower::createInitializerAddress(loc, converter, addr, globalOpSymMap, stmtCtx); } @@ -188,8 +190,6 @@ mlir::Value Fortran::lower::genInitialDataTarget( Fortran::lower::AbstractConverter &converter, mlir::Location loc, mlir::Type boxType, const Fortran::lower::SomeExpr &initialTarget, bool couldBeInEquivalence) { - if (converter.getLoweringOptions().getLowerToHighLevelFIR()) - TODO(loc, "initial data target in HLFIR"); Fortran::lower::SymMap globalOpSymMap; Fortran::lower::AggregateStoreMap storeMap; Fortran::lower::StatementContext stmtCtx; @@ -248,16 +248,23 @@ mlir::Value Fortran::lower::genInitialDataTarget( mlir::Value targetBox; mlir::Value targetShift; - if (initialTarget.Rank() > 0) { - auto target = Fortran::lower::createSomeArrayBox(converter, initialTarget, - globalOpSymMap, stmtCtx); + if (converter.getLoweringOptions().getLowerToHighLevelFIR()) { + auto target = Fortran::lower::convertExprToBox( + loc, converter, initialTarget, globalOpSymMap, stmtCtx); targetBox = fir::getBase(target); targetShift = builder.createShape(loc, target); } else { - fir::ExtendedValue addr = Fortran::lower::createInitializerAddress( - loc, converter, initialTarget, globalOpSymMap, stmtCtx); - targetBox = builder.createBox(loc, addr); - // Nothing to do for targetShift, the target is a scalar. + if (initialTarget.Rank() > 0) { + auto target = Fortran::lower::createSomeArrayBox(converter, initialTarget, + globalOpSymMap, stmtCtx); + targetBox = fir::getBase(target); + targetShift = builder.createShape(loc, target); + } else { + fir::ExtendedValue addr = Fortran::lower::createInitializerAddress( + loc, converter, initialTarget, globalOpSymMap, stmtCtx); + targetBox = builder.createBox(loc, addr); + // Nothing to do for targetShift, the target is a scalar. + } } // The targetBox is a fir.box, not a fir.box> as it should for // pointers (this matters to get the POINTER attribute correctly inside the diff --git a/flang/test/Lower/HLFIR/constant-derived.f90 b/flang/test/Lower/HLFIR/constant-derived.f90 index 4da714e..62d5079 100644 --- a/flang/test/Lower/HLFIR/constant-derived.f90 +++ b/flang/test/Lower/HLFIR/constant-derived.f90 @@ -1,5 +1,4 @@ ! Test lowering of Constant. -! TODO: remove "-I nowhere" once derived type descriptor can be lowered. ! RUN: bbc -hlfir -emit-fir -o - -I nowhere %s 2>&1 | FileCheck %s subroutine test_constant_scalar() @@ -14,6 +13,17 @@ subroutine test_constant_scalar() ! CHECK: fir.address_of(@[[CST:_QQro._QFtest_constant_scalarTmyderived..*]]) end subroutine +subroutine test_constant_scalar_ptr_component() + type myderived + real, pointer :: x + real, pointer :: y(:) + end type + real, target, save :: targ(100) + call test(myderived(NULL(), targ(1:50:5))) +! CHECK-LABEL: func.func @_QPtest_constant_scalar_ptr_component() { +! CHECK: fir.address_of(@[[CST_TARGET:_QQro._QFtest_constant_scalar_ptr_componentTmyderived..*]]) +end subroutine + ! CHECK: fir.global internal @[[CST]] constant : !fir.type<[[DERIVED:_QFtest_constant_scalarTmyderived{i:i32,j:i32,x:!fir.array<2xf32>,c:!fir.char<1,10>}]]> { ! CHECK: %[[VAL_0:.*]] = fir.undefined !fir.type<[[DERIVED]]> ! CHECK: %[[VAL_1:.*]] = fir.field_index i, !fir.type<[[DERIVED]]> @@ -36,3 +46,26 @@ end subroutine ! CHECK: %[[VAL_18:.*]] = fir.insert_value %[[VAL_14]], %[[VAL_16]], ["c", !fir.type<[[DERIVED]]>] : (!fir.type<[[DERIVED]]>, !fir.char<1,10>) -> !fir.type<[[DERIVED]]> ! CHECK: fir.has_value %[[VAL_18]] : !fir.type<[[DERIVED]]> ! CHECK: } + +! CHECK: fir.global internal @[[CST_TARGET]] constant : +! CHECK-SAME: !fir.type<[[DERIVED_2:_QFtest_constant_scalar_ptr_componentTmyderived{x:!fir.box>,y:!fir.box>>}]]> { +! CHECK: %[[VAL_0:.*]] = fir.undefined !fir.type<[[DERIVED_2]]> +! CHECK: %[[VAL_1:.*]] = fir.field_index x, !fir.type<[[DERIVED_2]]> +! CHECK: %[[VAL_2:.*]] = fir.zero_bits !fir.ptr +! CHECK: %[[VAL_3:.*]] = fir.embox %[[VAL_2]] : (!fir.ptr) -> !fir.box> +! CHECK: %[[VAL_4:.*]] = fir.insert_value %[[VAL_0]], %[[VAL_3]], ["x", !fir.type<[[DERIVED_2]]>] : (!fir.type<[[DERIVED_2]]>, !fir.box>) -> !fir.type<[[DERIVED_2]]> +! CHECK: %[[VAL_5:.*]] = fir.field_index y, !fir.type<[[DERIVED_2]]> +! CHECK: %[[VAL_6:.*]] = fir.address_of(@_QFtest_constant_scalar_ptr_componentEtarg) : !fir.ref> +! CHECK: %[[VAL_7:.*]] = arith.constant 100 : index +! CHECK: %[[VAL_8:.*]] = fir.shape %[[VAL_7]] : (index) -> !fir.shape<1> +! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_6]](%[[VAL_8]]) +! CHECK: %[[VAL_11:.*]] = arith.constant 1 : index +! CHECK: %[[VAL_13:.*]] = arith.constant 50 : index +! CHECK: %[[VAL_15:.*]] = arith.constant 5 : index +! CHECK: %[[VAL_16:.*]] = arith.constant 10 : index +! CHECK: %[[VAL_17:.*]] = fir.shape %[[VAL_16]] : (index) -> !fir.shape<1> +! CHECK: %[[VAL_18:.*]] = hlfir.designate %[[VAL_9]]#0 (%[[VAL_11]]:%[[VAL_13]]:%[[VAL_15]]) shape %[[VAL_17]] : (!fir.ref>, index, index, index, !fir.shape<1>) -> !fir.box> +! CHECK: %[[VAL_19:.*]] = fir.rebox %[[VAL_18]] : (!fir.box>) -> !fir.box>> +! CHECK: %[[VAL_20:.*]] = fir.insert_value %[[VAL_4]], %[[VAL_19]], ["y", !fir.type<[[DERIVED_2]]>] : (!fir.type<[[DERIVED_2]]>, !fir.box>>) -> !fir.type<[[DERIVED_2]]> +! CHECK: fir.has_value %[[VAL_20]] : !fir.type<[[DERIVED_2]]> +! CHECK: } -- 2.7.4