[flang] Basic local variable lowering

This patch add lowering for simple local variable.

- The signatures in `ConvertType.h` have been simplified to take advantage of the `AbstractConverter`.
- The lowering make use of the `allocateLocal` from the `FirOpBuilder`.

This lowering is used in patch D118982

This patch is part of the upstreaming effort from fir-dev branch.

Reviewed By: kiranchandramohan, jeanPerier, schweitz

Differential Revision: https://reviews.llvm.org/D118978
This commit is contained in:
Valentin Clement 2022-02-07 09:12:17 +01:00
parent 24562babdf
commit 2c2e5a5d0f
No known key found for this signature in database
GPG key ID: 086D54783C928776
7 changed files with 226 additions and 56 deletions

View file

@ -53,6 +53,7 @@ class Symbol;
} // namespace semantics
namespace lower {
class AbstractConverter;
namespace pft {
struct Variable;
}
@ -65,33 +66,24 @@ mlir::Type getFIRType(mlir::MLIRContext *ctxt, common::TypeCategory tc,
int kind);
/// Get a FIR type based on a category.
mlir::Type getFIRType(mlir::MLIRContext *ctxt,
common::IntrinsicTypeDefaultKinds const &defaults,
mlir::Type getFIRType(Fortran::lower::AbstractConverter &,
common::TypeCategory tc);
/// Translate a Fortran::evaluate::DataRef to an mlir::Type.
mlir::Type
translateDataRefToFIRType(mlir::MLIRContext *ctxt,
common::IntrinsicTypeDefaultKinds const &defaults,
const evaluate::DataRef &dataRef);
mlir::Type translateDataRefToFIRType(Fortran::lower::AbstractConverter &,
const evaluate::DataRef &dataRef);
/// Translate a SomeExpr to an mlir::Type.
mlir::Type
translateSomeExprToFIRType(mlir::MLIRContext *ctxt,
common::IntrinsicTypeDefaultKinds const &defaults,
const SomeExpr *expr);
mlir::Type translateSomeExprToFIRType(Fortran::lower::AbstractConverter &,
const SomeExpr *expr);
/// Translate a Fortran::semantics::Symbol to an mlir::Type.
mlir::Type
translateSymbolToFIRType(mlir::MLIRContext *ctxt,
common::IntrinsicTypeDefaultKinds const &defaults,
const SymbolRef symbol);
mlir::Type translateSymbolToFIRType(Fortran::lower::AbstractConverter &,
const SymbolRef symbol);
/// Translate a Fortran::lower::pft::Variable to an mlir::Type.
mlir::Type
translateVariableToFIRType(mlir::MLIRContext *ctxt,
common::IntrinsicTypeDefaultKinds const &defaults,
const pft::Variable &variable);
mlir::Type translateVariableToFIRType(Fortran::lower::AbstractConverter &,
const pft::Variable &variable);
/// Translate a REAL of KIND to the mlir::Type.
mlir::Type convertReal(mlir::MLIRContext *ctxt, int KIND);

View file

@ -0,0 +1,35 @@
//===- Lower/ConvertVariable.h -- lowering of variables to FIR --*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/
//
//===----------------------------------------------------------------------===//
///
/// Instantiation of pft::Variable in FIR/MLIR.
///
//===----------------------------------------------------------------------===//
#ifndef FORTRAN_LOWER_CONVERT_VARIABLE_H
#define FORTRAN_LOWER_CONVERT_VARIABLE_H
namespace Fortran ::lower {
class AbstractConverter;
class SymMap;
namespace pft {
struct Variable;
}
/// Instantiate variable \p var and add it to \p symMap.
/// The AbstractConverter builder must be set.
/// The AbstractConverter own symbol mapping is not used during the
/// instantiation and can be different form \p symMap.
void instantiateVariable(AbstractConverter &, const pft::Variable &var,
SymMap &symMap);
} // namespace Fortran::lower
#endif // FORTRAN_LOWER_CONVERT_VARIABLE_H

View file

@ -15,6 +15,7 @@
#include "flang/Lower/CallInterface.h"
#include "flang/Lower/ConvertExpr.h"
#include "flang/Lower/ConvertType.h"
#include "flang/Lower/ConvertVariable.h"
#include "flang/Lower/Mangler.h"
#include "flang/Lower/PFTBuilder.h"
#include "flang/Lower/Runtime.h"
@ -109,9 +110,8 @@ public:
int kind) override final {
return Fortran::lower::getFIRType(&getMLIRContext(), tc, kind);
}
mlir::Type genType(const Fortran::lower::pft::Variable &) override final {
TODO_NOLOC("Not implemented genType Variable. Needed for more complex "
"expression lowering");
mlir::Type genType(const Fortran::lower::pft::Variable &var) override final {
return Fortran::lower::translateVariableToFIRType(*this, var);
}
void setCurrentPosition(const Fortran::parser::CharBlock &position) {
@ -196,6 +196,12 @@ public:
localSymbols.clear();
}
/// Instantiate variable \p var and add it to the symbol map.
/// See ConvertVariable.cpp.
void instantiateVar(const Fortran::lower::pft::Variable &var) {
Fortran::lower::instantiateVariable(*this, var, localSymbols);
}
/// Prepare to translate a new function
void startNewFunction(Fortran::lower::pft::FunctionLikeUnit &funit) {
assert(!builder && "expected nullptr");
@ -205,6 +211,13 @@ public:
builder = new fir::FirOpBuilder(func, bridge.getKindMap());
assert(builder && "FirOpBuilder did not instantiate");
builder->setInsertionPointToStart(&func.front());
for (const Fortran::lower::pft::Variable &var :
funit.getOrderedSymbolTable()) {
const Fortran::semantics::Symbol &sym = var.getSymbol();
if (!sym.IsFuncResult() || !funit.primaryResult)
instantiateVar(var);
}
}
/// Lower a procedure (nest).

View file

@ -6,6 +6,7 @@ add_flang_library(FortranLower
Coarray.cpp
ConvertExpr.cpp
ConvertType.cpp
ConvertVariable.cpp
Mangler.cpp
OpenACC.cpp
OpenMP.cpp

View file

@ -15,6 +15,7 @@
#include "flang/Evaluate/real.h"
#include "flang/Evaluate/traverse.h"
#include "flang/Lower/AbstractConverter.h"
#include "flang/Lower/SymbolMap.h"
#include "flang/Lower/Todo.h"
#include "flang/Semantics/expression.h"
#include "flang/Semantics/symbol.h"
@ -36,6 +37,32 @@
// to the correct FIR representation in SSA form.
//===----------------------------------------------------------------------===//
/// Generate a load of a value from an address. Beware that this will lose
/// any dynamic type information for polymorphic entities (note that unlimited
/// polymorphic cannot be loaded and must not be provided here).
static fir::ExtendedValue genLoad(fir::FirOpBuilder &builder,
mlir::Location loc,
const fir::ExtendedValue &addr) {
return addr.match(
[](const fir::CharBoxValue &box) -> fir::ExtendedValue { return box; },
[&](const fir::UnboxedValue &v) -> fir::ExtendedValue {
if (fir::unwrapRefType(fir::getBase(v).getType())
.isa<fir::RecordType>())
return v;
return builder.create<fir::LoadOp>(loc, fir::getBase(v));
},
[&](const fir::MutableBoxValue &box) -> fir::ExtendedValue {
TODO(loc, "genLoad for MutableBoxValue");
},
[&](const fir::BoxValue &box) -> fir::ExtendedValue {
TODO(loc, "genLoad for BoxValue");
},
[&](const auto &) -> fir::ExtendedValue {
fir::emitFatalError(
loc, "attempting to load whole array or procedure address");
});
}
namespace {
/// Lowering of Fortran::evaluate::Expr<T> expressions
@ -44,9 +71,10 @@ public:
using ExtValue = fir::ExtendedValue;
explicit ScalarExprLowering(mlir::Location loc,
Fortran::lower::AbstractConverter &converter)
Fortran::lower::AbstractConverter &converter,
Fortran::lower::SymMap &symMap)
: location{loc}, converter{converter},
builder{converter.getFirOpBuilder()} {}
builder{converter.getFirOpBuilder()}, symMap{symMap} {}
mlir::Location getLoc() { return location; }
@ -64,8 +92,26 @@ public:
return builder.createBool(getLoc(), value);
}
/// Returns a reference to a symbol or its box/boxChar descriptor if it has
/// one.
ExtValue gen(Fortran::semantics::SymbolRef sym) {
if (Fortran::lower::SymbolBox val = symMap.lookupSymbol(sym))
return val.match([&val](auto &) { return val.toExtendedValue(); });
LLVM_DEBUG(llvm::dbgs()
<< "unknown symbol: " << sym << "\nmap: " << symMap << '\n');
fir::emitFatalError(getLoc(), "symbol is not mapped to any IR value");
}
ExtValue genLoad(const ExtValue &exv) {
return ::genLoad(builder, getLoc(), exv);
}
ExtValue genval(Fortran::semantics::SymbolRef sym) {
TODO(getLoc(), "genval SymbolRef");
ExtValue var = gen(sym);
if (const fir::UnboxedValue *s = var.getUnboxed())
if (fir::isReferenceLike(s->getType()))
return genLoad(*s);
return var;
}
ExtValue genval(const Fortran::evaluate::BOZLiteralConstant &) {
@ -306,7 +352,7 @@ public:
template <typename A>
ExtValue genval(const Fortran::evaluate::Designator<A> &des) {
TODO(getLoc(), "genval Designator<A>");
return std::visit([&](const auto &x) { return genval(x); }, des.u);
}
template <typename A>
@ -340,12 +386,13 @@ private:
mlir::Location location;
Fortran::lower::AbstractConverter &converter;
fir::FirOpBuilder &builder;
Fortran::lower::SymMap &symMap;
};
} // namespace
fir::ExtendedValue Fortran::lower::createSomeExtendedExpression(
mlir::Location loc, Fortran::lower::AbstractConverter &converter,
const Fortran::lower::SomeExpr &expr, Fortran::lower::SymMap &) {
const Fortran::lower::SomeExpr &expr, Fortran::lower::SymMap &symMap) {
LLVM_DEBUG(expr.AsFortran(llvm::dbgs() << "expr: ") << '\n');
return ScalarExprLowering{loc, converter}.genval(expr);
return ScalarExprLowering{loc, converter, symMap}.genval(expr);
}

View file

@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "flang/Lower/ConvertType.h"
#include "flang/Lower/AbstractConverter.h"
#include "flang/Lower/PFTBuilder.h"
#include "flang/Lower/Utils.h"
#include "flang/Optimizer/Dialect/FIRType.h"
@ -177,11 +178,8 @@ namespace {
/// mlir::Type. The type returned may be an MLIR standard or FIR type.
class TypeBuilder {
public:
/// Constructor.
explicit TypeBuilder(
mlir::MLIRContext *context,
const Fortran::common::IntrinsicTypeDefaultKinds &defaults)
: context{context}, defaults{defaults} {}
TypeBuilder(Fortran::lower::AbstractConverter &converter)
: converter{converter}, context{&converter.getMLIRContext()} {}
//===--------------------------------------------------------------------===//
// Generate type entry points
@ -221,7 +219,7 @@ public:
return genVariant(dref);
}
mlir::Type gen(const Fortran::lower::pft::Variable &var) {
mlir::Type genVariableType(const Fortran::lower::pft::Variable &var) {
return genSymbolHelper(var.getSymbol(), var.isHeapAlloc(), var.isPointer());
}
@ -425,9 +423,7 @@ private:
int defaultKind() {
return defaultKind(TC);
}
int defaultKind(Fortran::common::TypeCategory TC) {
return defaults.GetDefaultKind(TC);
}
int defaultKind(Fortran::common::TypeCategory TC) { return 0; }
fir::SequenceType::Shape seqShapeHelper(Fortran::semantics::SymbolRef symbol,
fir::SequenceType::Shape &bounds) {
@ -469,8 +465,8 @@ private:
//===--------------------------------------------------------------------===//
Fortran::lower::AbstractConverter &converter;
mlir::MLIRContext *context;
const Fortran::common::IntrinsicTypeDefaultKinds &defaults;
};
} // namespace
@ -520,39 +516,32 @@ mlir::Type Fortran::lower::getFIRType(mlir::MLIRContext *context,
return genFIRType(context, tc, kind);
}
mlir::Type Fortran::lower::getFIRType(
mlir::MLIRContext *context,
const Fortran::common::IntrinsicTypeDefaultKinds &defaults,
Fortran::common::TypeCategory tc) {
return TypeBuilder{context, defaults}.genFIRTy(tc);
mlir::Type
Fortran::lower::getFIRType(Fortran::lower::AbstractConverter &converter,
Fortran::common::TypeCategory tc) {
return TypeBuilder{converter}.genFIRTy(tc);
}
mlir::Type Fortran::lower::translateDataRefToFIRType(
mlir::MLIRContext *context,
const Fortran::common::IntrinsicTypeDefaultKinds &defaults,
Fortran::lower::AbstractConverter &converter,
const Fortran::evaluate::DataRef &dataRef) {
return TypeBuilder{context, defaults}.gen(dataRef);
return TypeBuilder{converter}.gen(dataRef);
}
mlir::Type Fortran::lower::translateSomeExprToFIRType(
mlir::MLIRContext *context,
const Fortran::common::IntrinsicTypeDefaultKinds &defaults,
const SomeExpr *expr) {
return TypeBuilder{context, defaults}.gen(*expr);
Fortran::lower::AbstractConverter &converter, const SomeExpr *expr) {
return TypeBuilder{converter}.gen(*expr);
}
mlir::Type Fortran::lower::translateSymbolToFIRType(
mlir::MLIRContext *context,
const Fortran::common::IntrinsicTypeDefaultKinds &defaults,
const SymbolRef symbol) {
return TypeBuilder{context, defaults}.gen(symbol);
Fortran::lower::AbstractConverter &converter, const SymbolRef symbol) {
return TypeBuilder{converter}.gen(symbol);
}
mlir::Type Fortran::lower::translateVariableToFIRType(
mlir::MLIRContext *context,
const Fortran::common::IntrinsicTypeDefaultKinds &defaults,
Fortran::lower::AbstractConverter &converter,
const Fortran::lower::pft::Variable &var) {
return TypeBuilder{context, defaults}.gen(var);
return TypeBuilder{converter}.genVariableType(var);
}
mlir::Type Fortran::lower::convertReal(mlir::MLIRContext *context, int kind) {

View file

@ -0,0 +1,93 @@
//===-- ConvertVariable.cpp -- bridge to lower to MLIR --------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/
//
//===----------------------------------------------------------------------===//
#include "flang/Lower/ConvertVariable.h"
#include "flang/Lower/AbstractConverter.h"
#include "flang/Lower/CallInterface.h"
#include "flang/Lower/ConvertExpr.h"
#include "flang/Lower/Mangler.h"
#include "flang/Lower/PFTBuilder.h"
#include "flang/Lower/Support/Utils.h"
#include "flang/Lower/SymbolMap.h"
#include "flang/Lower/Todo.h"
#include "flang/Optimizer/Builder/Character.h"
#include "flang/Optimizer/Builder/FIRBuilder.h"
#include "flang/Optimizer/Builder/Runtime/Derived.h"
#include "flang/Optimizer/Dialect/FIRAttr.h"
#include "flang/Optimizer/Dialect/FIRDialect.h"
#include "flang/Optimizer/Dialect/FIROps.h"
#include "flang/Optimizer/Support/FIRContext.h"
#include "flang/Optimizer/Support/FatalError.h"
#include "flang/Semantics/tools.h"
#include "llvm/Support/Debug.h"
#define DEBUG_TYPE "flang-lower-variable"
//===----------------------------------------------------------------===//
// Local variables instantiation (not for alias)
//===----------------------------------------------------------------===//
/// Create a stack slot for a local variable. Precondition: the insertion
/// point of the builder must be in the entry block, which is currently being
/// constructed.
static mlir::Value createNewLocal(Fortran::lower::AbstractConverter &converter,
mlir::Location loc,
const Fortran::lower::pft::Variable &var,
mlir::Value preAlloc,
llvm::ArrayRef<mlir::Value> shape = {},
llvm::ArrayRef<mlir::Value> lenParams = {}) {
if (preAlloc)
return preAlloc;
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
std::string nm = Fortran::lower::mangle::mangleName(var.getSymbol());
mlir::Type ty = converter.genType(var);
const Fortran::semantics::Symbol &ultimateSymbol =
var.getSymbol().GetUltimate();
llvm::StringRef symNm = toStringRef(ultimateSymbol.name());
bool isTarg = var.isTarget();
// Let the builder do all the heavy lifting.
return builder.allocateLocal(loc, ty, nm, symNm, shape, lenParams, isTarg);
}
/// Instantiate a local variable. Precondition: Each variable will be visited
/// such that if its properties depend on other variables, the variables upon
/// which its properties depend will already have been visited.
static void instantiateLocal(Fortran::lower::AbstractConverter &converter,
const Fortran::lower::pft::Variable &var,
Fortran::lower::SymMap &symMap) {
assert(!var.isAlias());
const Fortran::semantics::Symbol &sym = var.getSymbol();
if (symMap.lookupSymbol(sym))
return;
const mlir::Location loc = converter.genLocation(sym.name());
mlir::Value local = createNewLocal(converter, loc, var, {});
symMap.addSymbol(sym, local);
}
void Fortran::lower::instantiateVariable(AbstractConverter &converter,
const pft::Variable &var,
SymMap &symMap) {
const Fortran::semantics::Symbol &sym = var.getSymbol();
const mlir::Location loc = converter.genLocation(sym.name());
if (var.isAggregateStore()) {
TODO(loc, "instantiateVariable AggregateStore");
} else if (Fortran::semantics::FindCommonBlockContaining(
var.getSymbol().GetUltimate())) {
TODO(loc, "instantiateVariable Common");
} else if (var.isAlias()) {
TODO(loc, "instantiateVariable Alias");
} else if (var.isGlobal()) {
TODO(loc, "instantiateVariable Global");
} else {
instantiateLocal(converter, var, symMap);
}
}