Skip to content

Commit bb49640

Browse files
committed
Turn on the assertion to check that the Value bound to a Symbol in the
lowering symbol table has a legal type. Corrects a number of bugs associated with fixing the symbol table, etc.
1 parent 590cd50 commit bb49640

File tree

8 files changed

+160
-83
lines changed

8 files changed

+160
-83
lines changed

flang/include/flang/Evaluate/expression.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "flang/Common/indirection.h"
2727
#include "flang/Common/template.h"
2828
#include "flang/Parser/char-block.h"
29+
#include "llvm/Support/Compiler.h"
2930
#include <algorithm>
3031
#include <list>
3132
#include <tuple>
@@ -93,6 +94,9 @@ template <typename RESULT> class ExpressionBase {
9394
std::optional<DynamicType> GetType() const;
9495
int Rank() const;
9596
std::string AsFortran() const;
97+
LLVM_DUMP_METHOD void dump() const {
98+
llvm::errs() << "Ev::Expr is <{" << AsFortran() << "}>\n";
99+
}
96100
llvm::raw_ostream &AsFortran(llvm::raw_ostream &) const;
97101
static Derived Rewrite(FoldingContext &, Derived &&);
98102
};
@@ -129,8 +133,8 @@ class Operation {
129133

130134
public:
131135
CLASS_BOILERPLATE(Operation)
132-
explicit Operation(const Expr<OPERANDS> &...x) : operand_{x...} {}
133-
explicit Operation(Expr<OPERANDS> &&...x) : operand_{std::move(x)...} {}
136+
explicit Operation(const Expr<OPERANDS> &... x) : operand_{x...} {}
137+
explicit Operation(Expr<OPERANDS> &&... x) : operand_{std::move(x)...} {}
134138

135139
Derived &derived() { return *static_cast<Derived *>(this); }
136140
const Derived &derived() const { return *static_cast<const Derived *>(this); }

flang/include/flang/Lower/Support/BoxValue.h

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#define LOWER_SUPPORT_BOXVALUE_H
1515

1616
#include "flang/Optimizer/Dialect/FIRType.h"
17+
#include "flang/Optimizer/Support/Matcher.h"
1718
#include "mlir/IR/Value.h"
1819
#include "llvm/ADT/SmallVector.h"
1920
#include "llvm/Support/Compiler.h"
@@ -53,8 +54,8 @@ class AbstractBox {
5354
public:
5455
AbstractBox() = delete;
5556
AbstractBox(mlir::Value addr) : addr{addr} {
56-
// FIXME: enable the assert!
57-
// assert(fir::isa_passbyref_type(addr.getType()));
57+
assert(isa_passbyref_type(addr.getType()) &&
58+
"box values must be references");
5859
}
5960

6061
/// An abstract box always contains a memory reference to a value.
@@ -219,17 +220,25 @@ ExtendedValue substBase(const ExtendedValue &exv, mlir::Value base);
219220
/// example, an entity may have an address in memory that contains its value(s)
220221
/// as well as various attribute values that describe the shape and starting
221222
/// indices if it is an array entity.
222-
class ExtendedValue {
223+
class ExtendedValue : public details::matcher<ExtendedValue> {
223224
public:
225+
using VT = std::variant<UnboxedValue, CharBoxValue, ArrayBoxValue,
226+
CharArrayBoxValue, BoxValue, ProcBoxValue>;
227+
224228
template <typename A>
225229
constexpr ExtendedValue(A &&box) : box{std::forward<A>(box)} {}
226230

231+
template <typename A>
232+
constexpr const A *getBoxOf() const {
233+
return std::get_if<A>(&box);
234+
}
235+
227236
constexpr const CharBoxValue *getCharBox() const {
228-
return std::get_if<CharBoxValue>(&box);
237+
return getBoxOf<CharBoxValue>();
229238
}
230239

231240
constexpr const UnboxedValue *getUnboxed() const {
232-
return std::get_if<UnboxedValue>(&box);
241+
return getBoxOf<UnboxedValue>();
233242
}
234243

235244
/// LLVM style debugging of extended values
@@ -241,10 +250,10 @@ class ExtendedValue {
241250
friend mlir::Value getLen(const ExtendedValue &exv);
242251
friend ExtendedValue substBase(const ExtendedValue &exv, mlir::Value base);
243252

253+
const VT &matchee() const { return box; }
254+
244255
private:
245-
std::variant<UnboxedValue, CharBoxValue, ArrayBoxValue, CharArrayBoxValue,
246-
BoxValue, ProcBoxValue>
247-
box;
256+
VT box;
248257
};
249258
} // namespace fir
250259

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
//===-- Optimizer/Support/Matcher.h -----------------------------*- 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+
#ifndef OPTIMIZER_SUPPORT_MATCHER_H
14+
#define OPTIMIZER_SUPPORT_MATCHER_H
15+
16+
#include <variant>
17+
18+
// Boilerplate CRTP class for a simplified type-casing syntactic sugar.
19+
namespace fir::details {
20+
// clang-format off
21+
template<class... Ts> struct matches : Ts... { using Ts::operator()...; };
22+
template<class... Ts> matches(Ts...) -> matches<Ts...>;
23+
template<typename N> struct matcher {
24+
template<typename... Ts> auto match(Ts... ts) {
25+
return std::visit(matches{ts...}, static_cast<N*>(this)->matchee());
26+
}
27+
template<typename... Ts> auto match(Ts... ts) const {
28+
return std::visit(matches{ts...}, static_cast<N const*>(this)->matchee());
29+
}
30+
};
31+
// clang-format on
32+
} // namespace fir::details
33+
34+
#endif // OPTIMIZER_SUPPORT_MATCHER_H

flang/lib/Lower/ConvertExpr.cpp

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -844,6 +844,8 @@ class ExprLowering {
844844
&con) {
845845
// TODO:
846846
// - derived type constant
847+
// ?? derived type cannot match the above template, can it? looks like it
848+
// would have to be Constant<SomeType<TC::Derived>> instead
847849
if (con.Rank() > 0)
848850
return genArrayLit(con);
849851
auto opt = con.GetScalarValue();
@@ -1263,16 +1265,16 @@ class ExprLowering {
12631265
return std::visit([&](const auto &x) { return genval(x); }, des.u);
12641266
}
12651267

1266-
// call a function
12671268
template <typename A>
1268-
fir::ExtendedValue gen(const Fortran::evaluate::FunctionRef<A> &funRef) {
1269-
TODO();
1270-
}
1271-
template <typename A>
1272-
fir::ExtendedValue genval(const Fortran::evaluate::FunctionRef<A> &funRef) {
1273-
TODO(); // Derived type functions (user + intrinsics)
1269+
fir::ExtendedValue gen(const Fortran::evaluate::FunctionRef<A> &func) {
1270+
auto resTy = converter.genType(*func.proc().GetSymbol());
1271+
auto retVal = genProcedureRef(func, llvm::ArrayRef<mlir::Type>{resTy});
1272+
auto mem = builder.create<fir::AllocaOp>(getLoc(), resTy);
1273+
builder.create<fir::StoreOp>(getLoc(), fir::getBase(retVal), mem);
1274+
return mem.getResult();
12741275
}
12751276

1277+
/// Generate a call to an intrinsic function.
12761278
fir::ExtendedValue
12771279
genIntrinsicRef(const Fortran::evaluate::ProcedureRef &procRef,
12781280
const Fortran::evaluate::SpecificIntrinsic &intrinsic,
@@ -1289,11 +1291,10 @@ class ExprLowering {
12891291
// lowering facility should control argument lowering.
12901292
for (const auto &arg : procRef.arguments()) {
12911293
if (auto *expr = Fortran::evaluate::UnwrapExpr<
1292-
Fortran::evaluate::Expr<Fortran::evaluate::SomeType>>(arg)) {
1294+
Fortran::evaluate::Expr<Fortran::evaluate::SomeType>>(arg))
12931295
operands.emplace_back(genval(*expr));
1294-
} else {
1295-
operands.emplace_back(mlir::Value{}); // absent optional
1296-
}
1296+
else
1297+
operands.emplace_back(fir::UnboxedValue{}); // absent optional
12971298
}
12981299
// Let the intrinsic library lower the intrinsic procedure call
12991300
llvm::StringRef name = intrinsic.name;
@@ -1340,15 +1341,9 @@ class ExprLowering {
13401341
// allowed, probably because nobody thought of restricting this usage.
13411342
// gfortran/ifort compiles this.
13421343
assert(expr && "assumed type used as statement function argument");
1343-
auto argVal = genval(*expr);
1344-
if (auto *charBox = argVal.getCharBox()) {
1345-
symMap.addCharSymbol(dummySymbol, charBox->getBuffer(),
1346-
charBox->getLen());
1347-
} else {
1348-
// As per Fortran 2018 C1580, statement function arguments can only be
1349-
// scalars, so just pass the base address.
1350-
symMap.addSymbol(dummySymbol, fir::getBase(argVal));
1351-
}
1344+
// As per Fortran 2018 C1580, statement function arguments can only be
1345+
// scalars, so just pass the box with the address.
1346+
symMap.addSymbol(dummySymbol, genExtAddr(*expr));
13521347
}
13531348
auto result = genval(details.stmtFunction().value());
13541349
LLVM_DEBUG(llvm::errs() << "stmt-function: " << result << '\n');
@@ -1565,7 +1560,12 @@ class ExprLowering {
15651560
if constexpr (inRefSet<std::decay_t<decltype(a)>>) {
15661561
return gen(a);
15671562
} else {
1568-
llvm_unreachable("expression error");
1563+
// Since `a` is not itself a valid referent, determine its value and
1564+
// create a temporary location for referencing.
1565+
auto val = fir::getBase(genval(a));
1566+
auto mem = builder.create<fir::AllocaOp>(getLoc(), val.getType());
1567+
builder.create<fir::StoreOp>(getLoc(), val, mem);
1568+
return mem.getResult();
15691569
}
15701570
}
15711571

flang/lib/Lower/IntrinsicCall.cpp

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
#include <string_view>
2929
#include <utility>
3030

31+
#define DEBUG_TYPE "flang-lower-intrinsic"
32+
3133
#define PGMATH_DECLARE
3234
#include "../runtime/pgmath.h.inc"
3335

@@ -1072,7 +1074,6 @@ mlir::Value IntrinsicLibrary::genFloor(mlir::Type resultType,
10721074
mlir::Value IntrinsicLibrary::genIAnd(mlir::Type resultType,
10731075
llvm::ArrayRef<mlir::Value> args) {
10741076
assert(args.size() == 2);
1075-
10761077
return builder.create<mlir::AndOp>(loc, args[0], args[1]);
10771078
}
10781079

@@ -1083,22 +1084,29 @@ mlir::Value IntrinsicLibrary::genIchar(mlir::Type resultType,
10831084
assert(args.size() >= 1 && args.size() <= 2);
10841085

10851086
auto arg = args[0];
1086-
assert(Fortran::lower::CharacterExprHelper::isCharacter(arg.getType()) &&
1087+
auto argTy = arg.getType();
1088+
assert(Fortran::lower::CharacterExprHelper::isCharacter(argTy) &&
10871089
"Error: Unhandled type passed to ICHAR");
1088-
Fortran::lower::CharacterExprHelper helper{builder, loc};
1089-
auto dataAndLen = helper.createUnboxChar(arg);
1090-
auto charType = helper.getCharacterType(arg.getType());
10911090
mlir::Value charVal;
1092-
if (fir::isa_ref_type(dataAndLen.first.getType())) {
1093-
auto refType = builder.getRefType(charType);
1094-
auto charAddr = builder.createConvert(loc, refType, dataAndLen.first);
1095-
charVal = builder.create<fir::LoadOp>(loc, charType, charAddr);
1091+
if (auto charTy = argTy.dyn_cast<fir::CharacterType>()) {
1092+
assert(charTy.singleton());
1093+
charVal = arg;
1094+
} else if (auto seqTy = argTy.dyn_cast<fir::SequenceType>()) {
1095+
auto zero =
1096+
builder.createIntegerConstant(loc, builder.getIntegerType(32), 0);
1097+
charVal = builder.create<fir::ExtractValueOp>(loc, seqTy.getEleTy(), arg,
1098+
mlir::ValueRange{zero});
10961099
} else {
1097-
charVal = builder.create<fir::ExtractValueOp>(
1098-
loc, charType, dataAndLen.first,
1099-
llvm::ArrayRef<mlir::Value>{
1100-
builder.createIntegerConstant(loc, builder.getIntegerType(32), 0)});
1100+
using H = Fortran::lower::CharacterExprHelper;
1101+
H helper{builder, loc};
1102+
auto dataAndLen = helper.createUnboxChar(arg);
1103+
// Strip away any sequence type residual.
1104+
auto toTy =
1105+
builder.getRefType(H::getCharacterType(dataAndLen.first.getType()));
1106+
auto cast = builder.createConvert(loc, toTy, dataAndLen.first);
1107+
charVal = builder.create<fir::LoadOp>(loc, cast);
11011108
}
1109+
LLVM_DEBUG(llvm::errs() << "ichar(" << charVal << ")\n");
11021110
return builder.createConvert(loc, resultType, charVal);
11031111
}
11041112

flang/lib/Lower/SymbolMap.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,20 @@ struct SymbolBox {
172172
/// etc.
173173
class SymMap {
174174
public:
175+
/// Add an extended value to the symbol table.
176+
void addSymbol(semantics::SymbolRef sym, const fir::ExtendedValue &ext,
177+
bool force = false) {
178+
ext.match([&](const fir::UnboxedValue &v) { addSymbol(sym, v, force); },
179+
[&](const fir::CharBoxValue &v) { makeSym(sym, v, force); },
180+
[&](const fir::ArrayBoxValue &v) { makeSym(sym, v, force); },
181+
[&](const fir::CharArrayBoxValue &v) { makeSym(sym, v, force); },
182+
[&](const fir::BoxValue &v) { makeSym(sym, v, force); },
183+
[](auto) {
184+
llvm::report_fatal_error(
185+
"box value should not be added to symbol table");
186+
});
187+
}
188+
175189
/// Add a trivial symbol mapping to an address.
176190
void addSymbol(semantics::SymbolRef sym, mlir::Value value,
177191
bool force = false) {

flang/lib/Optimizer/Dialect/FIRType.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -984,7 +984,8 @@ bool isa_box_type(mlir::Type t) {
984984
}
985985

986986
bool isa_passbyref_type(mlir::Type t) {
987-
return t.isa<ReferenceType>() || isa_box_type(t);
987+
return t.isa<ReferenceType>() || isa_box_type(t) ||
988+
t.isa<mlir::FunctionType>();
988989
}
989990

990991
bool isa_aggregate(mlir::Type t) {

0 commit comments

Comments
 (0)