[flang-commits] [flang] 2c2e5a5 - [flang] Basic local variable lowering

Valentin Clement via flang-commits flang-commits at lists.llvm.org
Mon Feb 7 00:14:16 PST 2022


Author: Valentin Clement
Date: 2022-02-07T09:14:09+01:00
New Revision: 2c2e5a5d0f191027ab447899599baeaf744fc2eb

URL: https://github.com/llvm/llvm-project/commit/2c2e5a5d0f191027ab447899599baeaf744fc2eb
DIFF: https://github.com/llvm/llvm-project/commit/2c2e5a5d0f191027ab447899599baeaf744fc2eb.diff

LOG: [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

Added: 
    flang/include/flang/Lower/ConvertVariable.h
    flang/lib/Lower/ConvertVariable.cpp

Modified: 
    flang/include/flang/Lower/ConvertType.h
    flang/lib/Lower/Bridge.cpp
    flang/lib/Lower/CMakeLists.txt
    flang/lib/Lower/ConvertExpr.cpp
    flang/lib/Lower/ConvertType.cpp

Removed: 
    


################################################################################
diff  --git a/flang/include/flang/Lower/ConvertType.h b/flang/include/flang/Lower/ConvertType.h
index e10772fa5b722..6a815f5affc2e 100644
--- a/flang/include/flang/Lower/ConvertType.h
+++ b/flang/include/flang/Lower/ConvertType.h
@@ -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);

diff  --git a/flang/include/flang/Lower/ConvertVariable.h b/flang/include/flang/Lower/ConvertVariable.h
new file mode 100644
index 0000000000000..011eab6113a6b
--- /dev/null
+++ b/flang/include/flang/Lower/ConvertVariable.h
@@ -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 
diff erent form \p symMap.
+void instantiateVariable(AbstractConverter &, const pft::Variable &var,
+                         SymMap &symMap);
+
+} // namespace Fortran::lower
+#endif // FORTRAN_LOWER_CONVERT_VARIABLE_H

diff  --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index f3e90d69620f1..82666df0b0615 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -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 @@ class FirConverter : public Fortran::lower::AbstractConverter {
                      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 @@ class FirConverter : public Fortran::lower::AbstractConverter {
     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 @@ class FirConverter : public Fortran::lower::AbstractConverter {
     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).

diff  --git a/flang/lib/Lower/CMakeLists.txt b/flang/lib/Lower/CMakeLists.txt
index 025abdcd8d56a..7d72360fce70b 100644
--- a/flang/lib/Lower/CMakeLists.txt
+++ b/flang/lib/Lower/CMakeLists.txt
@@ -6,6 +6,7 @@ add_flang_library(FortranLower
   Coarray.cpp
   ConvertExpr.cpp
   ConvertType.cpp
+  ConvertVariable.cpp
   Mangler.cpp
   OpenACC.cpp
   OpenMP.cpp

diff  --git a/flang/lib/Lower/ConvertExpr.cpp b/flang/lib/Lower/ConvertExpr.cpp
index e77ef422d4340..2f159fe0f3fdd 100644
--- a/flang/lib/Lower/ConvertExpr.cpp
+++ b/flang/lib/Lower/ConvertExpr.cpp
@@ -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 @@ class ScalarExprLowering {
   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 @@ class ScalarExprLowering {
     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 @@ class ScalarExprLowering {
 
   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 @@ class ScalarExprLowering {
   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);
 }

diff  --git a/flang/lib/Lower/ConvertType.cpp b/flang/lib/Lower/ConvertType.cpp
index a411c0fcea5c8..ffff36df41f71 100644
--- a/flang/lib/Lower/ConvertType.cpp
+++ b/flang/lib/Lower/ConvertType.cpp
@@ -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 @@ class TypeBuilder {
     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 @@ class TypeBuilder {
   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 @@ class TypeBuilder {
 
   //===--------------------------------------------------------------------===//
 
+  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) {

diff  --git a/flang/lib/Lower/ConvertVariable.cpp b/flang/lib/Lower/ConvertVariable.cpp
new file mode 100644
index 0000000000000..c207f60437695
--- /dev/null
+++ b/flang/lib/Lower/ConvertVariable.cpp
@@ -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);
+  }
+}


        


More information about the flang-commits mailing list