Skip to content

Commit c14ef2d

Browse files
committed
[flang] Add kernel to lower expressions to HLFIR
This patch adds the kernel to lower evaluate::Expr to HLFIR to a hlfir::FortranEntity (a single mlir::Value that can be interpreted as a Fortran variable or the value of a Fortram expression). It implements lowering of simple name designators ("x") and starts adding a translation layer in AbstractConverter::genExprBox and AbstractConverter::genExprAddr so that the new expression lowering can be used without any changes for now in the current statement and construct lowering. Differential Revision: https://reviews.llvm.org/D136453
1 parent b7c9226 commit c14ef2d

File tree

11 files changed

+340
-10
lines changed

11 files changed

+340
-10
lines changed
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
//===-- Lower/ConvertExprToHLFIR.h -- lowering of expressions ----*- C++-*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/
10+
//
11+
//===----------------------------------------------------------------------===//
12+
///
13+
/// Implements the conversion from Fortran::evaluate::Expr trees to HLFIR.
14+
///
15+
//===----------------------------------------------------------------------===//
16+
17+
#ifndef FORTRAN_LOWER_CONVERTEXPRTOHLFIR_H
18+
#define FORTRAN_LOWER_CONVERTEXPRTOHLFIR_H
19+
20+
#include "flang/Lower/Support/Utils.h"
21+
#include "flang/Optimizer/Builder/FIRBuilder.h"
22+
#include "flang/Optimizer/Builder/HLFIRTools.h"
23+
#include "flang/Optimizer/Dialect/FIRDialect.h"
24+
25+
namespace mlir {
26+
class Location;
27+
} // namespace mlir
28+
29+
namespace Fortran::lower {
30+
31+
class AbstractConverter;
32+
class StatementContext;
33+
class SymMap;
34+
35+
hlfir::FortranEntity convertExprToHLFIR(mlir::Location loc,
36+
Fortran::lower::AbstractConverter &,
37+
const Fortran::lower::SomeExpr &,
38+
Fortran::lower::SymMap &,
39+
Fortran::lower::StatementContext &);
40+
} // namespace Fortran::lower
41+
42+
#endif // FORTRAN_LOWER_CONVERTEXPRTOHLFIR_H

flang/include/flang/Lower/SymbolMap.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,9 @@ class SymMap {
348348
symbolMapStack.back().try_emplace(sym, definingOp);
349349
}
350350

351+
llvm::Optional<fir::FortranVariableOpInterface>
352+
lookupVariableDefinition(semantics::SymbolRef sym);
353+
351354
private:
352355
/// Add `symbol` to the current map and bind a `box`.
353356
void makeSym(semantics::SymbolRef symRef, const SymbolBox &box,

flang/include/flang/Optimizer/Builder/FIRBuilder.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,10 @@ mlir::Value genMaxWithZero(fir::FirOpBuilder &builder, mlir::Location loc,
561561
mlir::Value genCPtrOrCFunptrAddr(fir::FirOpBuilder &builder, mlir::Location loc,
562562
mlir::Value cPtr, mlir::Type ty);
563563

564+
/// Create a fir.box from a fir::ExtendedValue and wrap it in a fir::BoxValue
565+
/// to keep all the lower bound and explicit parameter information.
566+
fir::BoxValue createBoxValue(fir::FirOpBuilder &builder, mlir::Location loc,
567+
const fir::ExtendedValue &exv);
564568
} // namespace fir::factory
565569

566570
#endif // FORTRAN_OPTIMIZER_BUILDER_FIRBUILDER_H

flang/lib/Lower/Bridge.cpp

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "flang/Lower/CallInterface.h"
1616
#include "flang/Lower/Coarray.h"
1717
#include "flang/Lower/ConvertExpr.h"
18+
#include "flang/Lower/ConvertExprToHLFIR.h"
1819
#include "flang/Lower/ConvertType.h"
1920
#include "flang/Lower/ConvertVariable.h"
2021
#include "flang/Lower/HostAssociations.h"
@@ -416,16 +417,35 @@ class FirConverter : public Fortran::lower::AbstractConverter {
416417
return iter->second;
417418
}
418419

420+
fir::ExtendedValue
421+
translateToExtendedValue(mlir::Location loc, hlfir::FortranEntity entity,
422+
Fortran::lower::StatementContext &context) {
423+
auto [exv, exvCleanup] =
424+
hlfir::translateToExtendedValue(loc, getFirOpBuilder(), entity);
425+
if (exvCleanup)
426+
context.attachCleanup(*exvCleanup);
427+
return exv;
428+
}
429+
419430
fir::ExtendedValue
420431
genExprAddr(const Fortran::lower::SomeExpr &expr,
421432
Fortran::lower::StatementContext &context,
422433
mlir::Location *locPtr = nullptr) override final {
423434
mlir::Location loc = locPtr ? *locPtr : toLocation();
424-
if (bridge.getLoweringOptions().getLowerToHighLevelFIR())
425-
TODO(loc, "lower expr to HLFIR address");
435+
if (bridge.getLoweringOptions().getLowerToHighLevelFIR()) {
436+
hlfir::FortranEntity loweredExpr = Fortran::lower::convertExprToHLFIR(
437+
loc, *this, expr, localSymbols, context);
438+
if (fir::FortranVariableOpInterface variable =
439+
loweredExpr.getIfVariable())
440+
if (!variable.isBox())
441+
return translateToExtendedValue(loc, loweredExpr, context);
442+
TODO(loc, "lower expr that is not a scalar or explicit shape array "
443+
"variable to HLFIR address");
444+
}
426445
return Fortran::lower::createSomeExtendedAddress(loc, *this, expr,
427446
localSymbols, context);
428447
}
448+
429449
fir::ExtendedValue
430450
genExprValue(const Fortran::lower::SomeExpr &expr,
431451
Fortran::lower::StatementContext &context,
@@ -440,8 +460,18 @@ class FirConverter : public Fortran::lower::AbstractConverter {
440460
fir::ExtendedValue
441461
genExprBox(mlir::Location loc, const Fortran::lower::SomeExpr &expr,
442462
Fortran::lower::StatementContext &stmtCtx) override final {
443-
if (bridge.getLoweringOptions().getLowerToHighLevelFIR())
444-
TODO(loc, "lower expr to HLFIR box");
463+
if (bridge.getLoweringOptions().getLowerToHighLevelFIR()) {
464+
hlfir::FortranEntity loweredExpr = Fortran::lower::convertExprToHLFIR(
465+
loc, *this, expr, localSymbols, stmtCtx);
466+
if (fir::FortranVariableOpInterface variable =
467+
loweredExpr.getIfVariable())
468+
if (variable.isBoxValue() || !variable.isBoxAddress()) {
469+
auto exv = translateToExtendedValue(loc, loweredExpr, stmtCtx);
470+
return fir::factory::createBoxValue(getFirOpBuilder(), loc, exv);
471+
}
472+
TODO(loc,
473+
"lower expression value or pointer and allocatable to HLFIR box");
474+
}
445475
return Fortran::lower::createBoxValue(loc, *this, expr, localSymbols,
446476
stmtCtx);
447477
}

flang/lib/Lower/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ add_flang_library(FortranLower
66
CallInterface.cpp
77
Coarray.cpp
88
ConvertExpr.cpp
9+
ConvertExprToHLFIR.cpp
910
ConvertType.cpp
1011
ConvertVariable.cpp
1112
ComponentPath.cpp
@@ -28,13 +29,15 @@ add_flang_library(FortranLower
2829
FIRBuilder
2930
FIRSupport
3031
FIRTransforms
32+
HLFIRDialect
3133
${dialect_libs}
3234

3335
LINK_LIBS
3436
FIRDialect
3537
FIRBuilder
3638
FIRSupport
3739
FIRTransforms
40+
HLFIRDialect
3841
${dialect_libs}
3942
FortranCommon
4043
FortranParser
Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
//===-- ConvertExprToHLFIR.cpp --------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#include "flang/Lower/ConvertExprToHLFIR.h"
14+
#include "flang/Lower/AbstractConverter.h"
15+
#include "flang/Lower/StatementContext.h"
16+
#include "flang/Lower/SymbolMap.h"
17+
#include "flang/Optimizer/Builder/Todo.h"
18+
19+
namespace {
20+
21+
/// Lower Designators to HLFIR.
22+
class HlfirDesignatorBuilder {
23+
public:
24+
HlfirDesignatorBuilder(mlir::Location loc,
25+
Fortran::lower::AbstractConverter &converter,
26+
Fortran::lower::SymMap &symMap,
27+
Fortran::lower::StatementContext &stmtCtx)
28+
: converter{converter}, symMap{symMap}, stmtCtx{stmtCtx}, loc{loc} {}
29+
30+
// Character designators variant contains substrings
31+
using CharacterDesignators =
32+
decltype(Fortran::evaluate::Designator<Fortran::evaluate::Type<
33+
Fortran::evaluate::TypeCategory::Character, 1>>::u);
34+
hlfir::FortranEntity gen(const CharacterDesignators &designatorVariant) {
35+
return std::visit([&](const auto &x) { return gen(x); }, designatorVariant);
36+
}
37+
// Character designators variant contains complex parts
38+
using RealDesignators =
39+
decltype(Fortran::evaluate::Designator<Fortran::evaluate::Type<
40+
Fortran::evaluate::TypeCategory::Real, 4>>::u);
41+
hlfir::FortranEntity gen(const RealDesignators &designatorVariant) {
42+
return std::visit([&](const auto &x) { return gen(x); }, designatorVariant);
43+
}
44+
// All other designators are similar
45+
using OtherDesignators =
46+
decltype(Fortran::evaluate::Designator<Fortran::evaluate::Type<
47+
Fortran::evaluate::TypeCategory::Integer, 4>>::u);
48+
hlfir::FortranEntity gen(const OtherDesignators &designatorVariant) {
49+
return std::visit([&](const auto &x) { return gen(x); }, designatorVariant);
50+
}
51+
52+
private:
53+
hlfir::FortranEntity gen(const Fortran::evaluate::SymbolRef &symbolRef) {
54+
if (llvm::Optional<fir::FortranVariableOpInterface> varDef =
55+
getSymMap().lookupVariableDefinition(symbolRef))
56+
return *varDef;
57+
TODO(getLoc(), "lowering symbol to HLFIR");
58+
}
59+
hlfir::FortranEntity gen(const Fortran::evaluate::Component &component) {
60+
TODO(getLoc(), "lowering component to HLFIR");
61+
}
62+
hlfir::FortranEntity gen(const Fortran::evaluate::ArrayRef &arrayRef) {
63+
TODO(getLoc(), "lowering ArrayRef to HLFIR");
64+
}
65+
hlfir::FortranEntity gen(const Fortran::evaluate::CoarrayRef &coarrayRef) {
66+
TODO(getLoc(), "lowering CoarrayRef to HLFIR");
67+
}
68+
hlfir::FortranEntity gen(const Fortran::evaluate::ComplexPart &complexPart) {
69+
TODO(getLoc(), "lowering complex part to HLFIR");
70+
}
71+
hlfir::FortranEntity gen(const Fortran::evaluate::Substring &substring) {
72+
TODO(getLoc(), "lowering substrings to HLFIR");
73+
}
74+
75+
mlir::Location getLoc() const { return loc; }
76+
Fortran::lower::AbstractConverter &getConverter() { return converter; }
77+
fir::FirOpBuilder &getBuilder() { return converter.getFirOpBuilder(); }
78+
Fortran::lower::SymMap &getSymMap() { return symMap; }
79+
Fortran::lower::StatementContext &getStmtCtx() { return stmtCtx; }
80+
81+
Fortran::lower::AbstractConverter &converter;
82+
Fortran::lower::SymMap &symMap;
83+
Fortran::lower::StatementContext &stmtCtx;
84+
mlir::Location loc;
85+
};
86+
87+
/// Lower Expr to HLFIR.
88+
class HlfirBuilder {
89+
public:
90+
HlfirBuilder(mlir::Location loc, Fortran::lower::AbstractConverter &converter,
91+
Fortran::lower::SymMap &symMap,
92+
Fortran::lower::StatementContext &stmtCtx)
93+
: converter{converter}, symMap{symMap}, stmtCtx{stmtCtx}, loc{loc} {}
94+
95+
template <typename T>
96+
hlfir::FortranEntity gen(const Fortran::evaluate::Expr<T> &expr) {
97+
return std::visit([&](const auto &x) { return gen(x); }, expr.u);
98+
}
99+
100+
private:
101+
hlfir::FortranEntity gen(const Fortran::evaluate::BOZLiteralConstant &expr) {
102+
fir::emitFatalError(loc, "BOZ literal must be replaced by semantics");
103+
}
104+
hlfir::FortranEntity gen(const Fortran::evaluate::NullPointer &expr) {
105+
TODO(getLoc(), "lowering NullPointer to HLFIR");
106+
}
107+
hlfir::FortranEntity gen(const Fortran::evaluate::ProcedureDesignator &expr) {
108+
TODO(getLoc(), "lowering ProcDes to HLFIR");
109+
}
110+
hlfir::FortranEntity gen(const Fortran::evaluate::ProcedureRef &expr) {
111+
TODO(getLoc(), "lowering ProcRef to HLFIR");
112+
}
113+
114+
template <typename T>
115+
hlfir::FortranEntity gen(const Fortran::evaluate::Designator<T> &designator) {
116+
return HlfirDesignatorBuilder(getLoc(), getConverter(), getSymMap(),
117+
getStmtCtx())
118+
.gen(designator.u);
119+
}
120+
121+
template <typename T>
122+
hlfir::FortranEntity gen(const Fortran::evaluate::FunctionRef<T> &expr) {
123+
TODO(getLoc(), "lowering funcRef to HLFIR");
124+
}
125+
126+
template <typename T>
127+
hlfir::FortranEntity gen(const Fortran::evaluate::Constant<T> &expr) {
128+
TODO(getLoc(), "lowering constant to HLFIR");
129+
}
130+
131+
template <typename T>
132+
hlfir::FortranEntity gen(const Fortran::evaluate::ArrayConstructor<T> &expr) {
133+
TODO(getLoc(), "lowering ArrayCtor to HLFIR");
134+
}
135+
136+
template <Fortran::common::TypeCategory TC1, int KIND,
137+
Fortran::common::TypeCategory TC2>
138+
hlfir::FortranEntity
139+
gen(const Fortran::evaluate::Convert<Fortran::evaluate::Type<TC1, KIND>, TC2>
140+
&convert) {
141+
TODO(getLoc(), "lowering convert to HLFIR");
142+
}
143+
144+
template <typename D, typename R, typename O>
145+
hlfir::FortranEntity gen(const Fortran::evaluate::Operation<D, R, O> &op) {
146+
TODO(getLoc(), "lowering unary op to HLFIR");
147+
}
148+
149+
template <typename D, typename R, typename LO, typename RO>
150+
hlfir::FortranEntity
151+
gen(const Fortran::evaluate::Operation<D, R, LO, RO> &op) {
152+
TODO(getLoc(), "lowering binary op to HLFIR");
153+
}
154+
155+
hlfir::FortranEntity
156+
gen(const Fortran::evaluate::Relational<Fortran::evaluate::SomeType> &op) {
157+
return std::visit([&](const auto &x) { return gen(x); }, op.u);
158+
}
159+
160+
hlfir::FortranEntity gen(const Fortran::evaluate::TypeParamInquiry &) {
161+
TODO(getLoc(), "lowering type parameter inquiry to HLFIR");
162+
}
163+
164+
hlfir::FortranEntity gen(const Fortran::evaluate::DescriptorInquiry &desc) {
165+
TODO(getLoc(), "lowering descriptor inquiry to HLFIR");
166+
}
167+
168+
hlfir::FortranEntity gen(const Fortran::evaluate::ImpliedDoIndex &var) {
169+
TODO(getLoc(), "lowering implied do index to HLFIR");
170+
}
171+
172+
hlfir::FortranEntity gen(const Fortran::evaluate::StructureConstructor &var) {
173+
TODO(getLoc(), "lowering structure constructor to HLFIR");
174+
}
175+
176+
mlir::Location getLoc() const { return loc; }
177+
Fortran::lower::AbstractConverter &getConverter() { return converter; }
178+
fir::FirOpBuilder &getBuilder() { return converter.getFirOpBuilder(); }
179+
Fortran::lower::SymMap &getSymMap() { return symMap; }
180+
Fortran::lower::StatementContext &getStmtCtx() { return stmtCtx; }
181+
182+
Fortran::lower::AbstractConverter &converter;
183+
Fortran::lower::SymMap &symMap;
184+
Fortran::lower::StatementContext &stmtCtx;
185+
mlir::Location loc;
186+
};
187+
188+
} // namespace
189+
190+
hlfir::FortranEntity Fortran::lower::convertExprToHLFIR(
191+
mlir::Location loc, Fortran::lower::AbstractConverter &converter,
192+
const Fortran::lower::SomeExpr &expr, Fortran::lower::SymMap &symMap,
193+
Fortran::lower::StatementContext &stmtCtx) {
194+
return HlfirBuilder(loc, converter, symMap, stmtCtx).gen(expr);
195+
}

flang/lib/Lower/ConvertVariable.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1359,7 +1359,7 @@ static void genDeclareSymbol(Fortran::lower::AbstractConverter &converter,
13591359
auto newBase = builder.create<fir::DeclareOp>(
13601360
loc, base.getType(), base, shapeOrShift, lenParams, name, attributes);
13611361
base = newBase;
1362-
symMap.addVariableDefinition(sym, newBase);
1362+
symMap.addVariableDefinition(sym, newBase, force);
13631363
return;
13641364
}
13651365

flang/lib/Lower/SymbolMap.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,22 @@ Fortran::lower::SymMap::lookupImpliedDo(Fortran::lower::SymMap::AcDoVar var) {
9090
return {};
9191
}
9292

93+
llvm::Optional<fir::FortranVariableOpInterface>
94+
Fortran::lower::SymMap::lookupVariableDefinition(semantics::SymbolRef sym) {
95+
for (auto jmap = symbolMapStack.rbegin(), jend = symbolMapStack.rend();
96+
jmap != jend; ++jmap) {
97+
auto iter = jmap->find(&*sym);
98+
if (iter != jmap->end()) {
99+
if (const auto *varDef =
100+
std::get_if<fir::FortranVariableOpInterface>(&iter->second))
101+
return *varDef;
102+
else
103+
return llvm::None;
104+
}
105+
}
106+
return llvm::None;
107+
}
108+
93109
llvm::raw_ostream &
94110
Fortran::lower::operator<<(llvm::raw_ostream &os,
95111
const Fortran::lower::SymbolBox &symBox) {

0 commit comments

Comments
 (0)