[flang-commits] [flang] c433135 - [flang] Add an enum attribute to carry Fortran attributes

Jean Perier via flang-commits flang-commits at lists.llvm.org
Mon Oct 17 06:43:43 PDT 2022


Author: Jean Perier
Date: 2022-10-17T15:42:42+02:00
New Revision: c4331358fb9de83289b2638a77e8e08e41f56860

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

LOG: [flang] Add an enum attribute to carry Fortran attributes

Currently, Fortran attributes are mostly represented via the presence of
named attribute with special names (fir.target, fir.contiguous,
fir.optional...).

Create an enum so that these attributes can be more easily and safely
manipulated in FIR.

This patch does not add usages for it yet. It is planned to use in it in
the future HLFIR and fir.declare operations. This is added to FIR and
not HLFIR because it is intended to be used on fir.declare that will
be part of FIR, and seems also usefull for FIR operations.

Differential Revision: https://reviews.llvm.org/D135961

Added: 
    flang/include/flang/Optimizer/Dialect/FIRAttr.td

Modified: 
    flang/include/flang/Optimizer/Dialect/CMakeLists.txt
    flang/include/flang/Optimizer/Dialect/FIRAttr.h
    flang/lib/Optimizer/Dialect/FIRAttr.cpp
    flang/test/Fir/fir-ops.fir
    flang/test/Fir/invalid.fir

Removed: 
    


################################################################################
diff  --git a/flang/include/flang/Optimizer/Dialect/CMakeLists.txt b/flang/include/flang/Optimizer/Dialect/CMakeLists.txt
index 19d14b7f89a8b..894685652fbb4 100644
--- a/flang/include/flang/Optimizer/Dialect/CMakeLists.txt
+++ b/flang/include/flang/Optimizer/Dialect/CMakeLists.txt
@@ -1,6 +1,12 @@
 # This replicates part of the add_mlir_dialect cmake function from MLIR that
 # cannot be used her because it expects to be run inside MLIR directory which
 # is not the case for FIR.
+set(LLVM_TARGET_DEFINITIONS FIRAttr.td)
+mlir_tablegen(FIREnumAttr.h.inc -gen-enum-decls)
+mlir_tablegen(FIREnumAttr.cpp.inc -gen-enum-defs)
+mlir_tablegen(FIRAttr.h.inc --gen-attrdef-decls)
+mlir_tablegen(FIRAttr.cpp.inc -gen-attrdef-defs)
+
 set(LLVM_TARGET_DEFINITIONS FIROps.td)
 mlir_tablegen(FIROps.h.inc -gen-op-decls)
 mlir_tablegen(FIROps.cpp.inc -gen-op-defs)

diff  --git a/flang/include/flang/Optimizer/Dialect/FIRAttr.h b/flang/include/flang/Optimizer/Dialect/FIRAttr.h
index 20c82102c207b..92b3f7a8e6f62 100644
--- a/flang/include/flang/Optimizer/Dialect/FIRAttr.h
+++ b/flang/include/flang/Optimizer/Dialect/FIRAttr.h
@@ -142,4 +142,9 @@ void printFirAttribute(FIROpsDialect *dialect, mlir::Attribute attr,
 
 } // namespace fir
 
+#include "flang/Optimizer/Dialect/FIREnumAttr.h.inc"
+
+#define GET_ATTRDEF_CLASSES
+#include "flang/Optimizer/Dialect/FIRAttr.h.inc"
+
 #endif // FORTRAN_OPTIMIZER_DIALECT_FIRATTR_H

diff  --git a/flang/include/flang/Optimizer/Dialect/FIRAttr.td b/flang/include/flang/Optimizer/Dialect/FIRAttr.td
new file mode 100644
index 0000000000000..e6195f8bc1071
--- /dev/null
+++ b/flang/include/flang/Optimizer/Dialect/FIRAttr.td
@@ -0,0 +1,60 @@
+//===- FIRAttr.td - FIR Attributes -------------------------*- tablegen -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the FIR dialect attributes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef FIR_DIALECT_FIR_ATTRS
+#define FIR_DIALECT_FIR_ATTRS
+
+include "flang/Optimizer/Dialect/FIRDialect.td"
+include "mlir/IR/EnumAttr.td"
+
+class fir_Attr<string name> : AttrDef<fir_Dialect, name>;
+
+def FIRnoAttributes  : I32BitEnumAttrCaseNone<"None">;
+def FIRallocatable  : I32BitEnumAttrCaseBit<"allocatable", 0>;
+def FIRasynchronous : I32BitEnumAttrCaseBit<"asynchronous", 1>;
+def FIRbind_c       : I32BitEnumAttrCaseBit<"bind_c", 2>;
+def FIRcontiguous   : I32BitEnumAttrCaseBit<"contiguous", 3>;
+def FIRintent_in    : I32BitEnumAttrCaseBit<"intent_in", 4>;
+def FIRintent_inout : I32BitEnumAttrCaseBit<"intent_inout", 5>;
+def FIRintent_out   : I32BitEnumAttrCaseBit<"intent_out", 6>;
+def FIRoptional     : I32BitEnumAttrCaseBit<"optional", 7>;
+def FIRparameter    : I32BitEnumAttrCaseBit<"parameter", 8>;
+def FIRpointer      : I32BitEnumAttrCaseBit<"pointer", 9>;
+def FIRtarget       : I32BitEnumAttrCaseBit<"target", 10>;
+def FIRvalue        : I32BitEnumAttrCaseBit<"value", 11>;
+def FIRvolatile     : I32BitEnumAttrCaseBit<"fortran_volatile", 12, "volatile">;
+
+def fir_FortranVariableFlagsEnum : I32BitEnumAttr<
+    "FortranVariableFlagsEnum",
+    "Fortran variable attributes",
+    [FIRnoAttributes, FIRallocatable, FIRasynchronous, FIRbind_c, FIRcontiguous,
+     FIRintent_in, FIRintent_inout, FIRintent_out, FIRoptional, FIRparameter,
+     FIRpointer, FIRtarget, FIRvalue, FIRvolatile]> {
+  let separator = ", ";
+  let cppNamespace = "::fir";
+  let printBitEnumPrimaryGroups = 1;
+}
+
+def fir_FortranVariableFlagsAttr : fir_Attr<"FortranVariableFlags"> {
+  let mnemonic = "var_attrs";
+
+  let parameters = (ins
+    "FortranVariableFlagsEnum":$flags
+  );
+  let hasCustomAssemblyFormat = 1;
+  let returnType = "::fir::FortranVariableFlagsEnum";
+  let convertFromStorage = "$_self.getFlags()";
+  let constBuilderCall =
+          "::fir::FortranVariableFlagsAttr::get($_builder.getContext(), $0)";
+}
+
+#endif // FIR_DIALECT_FIR_ATTRS

diff  --git a/flang/lib/Optimizer/Dialect/FIRAttr.cpp b/flang/lib/Optimizer/Dialect/FIRAttr.cpp
index 4474a1e8342e7..655a568382a80 100644
--- a/flang/lib/Optimizer/Dialect/FIRAttr.cpp
+++ b/flang/lib/Optimizer/Dialect/FIRAttr.cpp
@@ -17,6 +17,12 @@
 #include "mlir/IR/BuiltinTypes.h"
 #include "mlir/IR/DialectImplementation.h"
 #include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/TypeSwitch.h"
+
+#include "flang/Optimizer/Dialect/FIREnumAttr.cpp.inc"
+#define GET_ATTRDEF_CLASSES
+#include "flang/Optimizer/Dialect/FIRAttr.cpp.inc"
 
 using namespace fir;
 
@@ -171,15 +177,47 @@ static mlir::Attribute parseFirRealAttr(FIROpsDialect *dialect,
   return RealAttr::get(dialect->getContext(), {kind, value});
 }
 
+mlir::Attribute fir::FortranVariableFlagsAttr::parse(mlir::AsmParser &parser,
+                                                     mlir::Type type) {
+  if (mlir::failed(parser.parseLess()))
+    return {};
+
+  fir::FortranVariableFlagsEnum flags = {};
+  if (mlir::failed(parser.parseOptionalGreater())) {
+    auto parseFlags = [&]() -> mlir::ParseResult {
+      llvm::StringRef elemName;
+      if (mlir::failed(parser.parseKeyword(&elemName)))
+        return mlir::failure();
+
+      auto elem = fir::symbolizeFortranVariableFlagsEnum(elemName);
+      if (!elem)
+        return parser.emitError(parser.getNameLoc(),
+                                "Unknown fortran variable attribute: ")
+               << elemName;
+
+      flags = flags | *elem;
+      return mlir::success();
+    };
+    if (mlir::failed(parser.parseCommaSeparatedList(parseFlags)) ||
+        parser.parseGreater())
+      return {};
+  }
+
+  return FortranVariableFlagsAttr::get(parser.getContext(), flags);
+}
+
 mlir::Attribute fir::parseFirAttribute(FIROpsDialect *dialect,
                                        mlir::DialectAsmParser &parser,
                                        mlir::Type type) {
   auto loc = parser.getNameLoc();
   llvm::StringRef attrName;
-  if (parser.parseKeyword(&attrName)) {
-    parser.emitError(loc, "expected an attribute name");
-    return {};
-  }
+  mlir::Attribute attr;
+  mlir::OptionalParseResult result =
+      generatedAttributeParser(parser, &attrName, type, attr);
+  if (result.has_value())
+    return attr;
+  if (attrName.empty())
+    return {}; // error reported by generatedAttributeParser
 
   if (attrName == ExactTypeAttr::getAttrName()) {
     mlir::Type type;
@@ -216,6 +254,12 @@ mlir::Attribute fir::parseFirAttribute(FIROpsDialect *dialect,
 // FIR attribute pretty printer
 //===----------------------------------------------------------------------===//
 
+void fir::FortranVariableFlagsAttr::print(mlir::AsmPrinter &printer) const {
+  printer << "<";
+  printer << fir::stringifyFortranVariableFlagsEnum(this->getFlags());
+  printer << ">";
+}
+
 void fir::printFirAttribute(FIROpsDialect *dialect, mlir::Attribute attr,
                             mlir::DialectAsmPrinter &p) {
   auto &os = p.getStream();
@@ -240,7 +284,7 @@ void fir::printFirAttribute(FIROpsDialect *dialect, mlir::Attribute attr,
     llvm::SmallString<40> ss;
     a.getValue().bitcastToAPInt().toStringUnsigned(ss, 16);
     os << ss << '>';
-  } else {
+  } else if (mlir::failed(generatedAttributePrinter(attr, p))) {
     // don't know how to print the attribute, so use a default
     os << "<(unknown attribute)>";
   }
@@ -251,6 +295,7 @@ void fir::printFirAttribute(FIROpsDialect *dialect, mlir::Attribute attr,
 //===----------------------------------------------------------------------===//
 
 void FIROpsDialect::registerAttributes() {
-  addAttributes<ClosedIntervalAttr, ExactTypeAttr, LowerBoundAttr,
-                PointIntervalAttr, RealAttr, SubclassAttr, UpperBoundAttr>();
+  addAttributes<ClosedIntervalAttr, ExactTypeAttr, FortranVariableFlagsAttr,
+                LowerBoundAttr, PointIntervalAttr, RealAttr, SubclassAttr,
+                UpperBoundAttr>();
 }

diff  --git a/flang/test/Fir/fir-ops.fir b/flang/test/Fir/fir-ops.fir
index 42d05b2fd9949..5052a06d90bcd 100644
--- a/flang/test/Fir/fir-ops.fir
+++ b/flang/test/Fir/fir-ops.fir
@@ -850,3 +850,35 @@ func.func @embox_tdesc(%arg0: !fir.class<!fir.array<10x!fir.type<derived_poly{a:
   fir.store %4#1 to %0 : !fir.ref<i32>
   return
 }
+
+func.func @test_fortran_var_attrs() {
+  %0 = fir.alloca !fir.heap<f32> {fortran_attrs = #fir.var_attrs<allocatable>}
+  %1 = fir.alloca f32 {fortran_attrs = #fir.var_attrs<asynchronous>}
+  %2 = fir.alloca f32 {fortran_attrs = #fir.var_attrs<bind_c>}
+  %3 = fir.alloca f32 {fortran_attrs = #fir.var_attrs<contiguous>}
+  %4 = fir.alloca f32 {fortran_attrs = #fir.var_attrs<intent_in>}
+  %5 = fir.alloca f32 {fortran_attrs = #fir.var_attrs<intent_inout>}
+  %6 = fir.alloca f32 {fortran_attrs = #fir.var_attrs<intent_out>}
+  %7 = fir.alloca f32 {fortran_attrs = #fir.var_attrs<optional>}
+  %8 = fir.alloca f32 {fortran_attrs = #fir.var_attrs<parameter>}
+  %9 = fir.alloca !fir.ptr<f32> {fortran_attrs = #fir.var_attrs<pointer>}
+  %10 = fir.alloca f32 {fortran_attrs = #fir.var_attrs<target>}
+  %11 = fir.alloca f32 {fortran_attrs = #fir.var_attrs<value>}
+  %12 = fir.alloca f32 {fortran_attrs = #fir.var_attrs<volatile>}
+  %13 = fir.alloca !fir.box<!fir.ptr<!fir.array<?xf32>>> {fortran_attrs = #fir.var_attrs<pointer, contiguous, volatile>}
+  return
+  // CHECK: fir.alloca !fir.heap<f32> {fortran_attrs = #fir.var_attrs<allocatable>}
+  // CHECK: fir.alloca f32 {fortran_attrs = #fir.var_attrs<asynchronous>}
+  // CHECK: fir.alloca f32 {fortran_attrs = #fir.var_attrs<bind_c>}
+  // CHECK: fir.alloca f32 {fortran_attrs = #fir.var_attrs<contiguous>}
+  // CHECK: fir.alloca f32 {fortran_attrs = #fir.var_attrs<intent_in>}
+  // CHECK: fir.alloca f32 {fortran_attrs = #fir.var_attrs<intent_inout>}
+  // CHECK: fir.alloca f32 {fortran_attrs = #fir.var_attrs<intent_out>}
+  // CHECK: fir.alloca f32 {fortran_attrs = #fir.var_attrs<optional>}
+  // CHECK: fir.alloca f32 {fortran_attrs = #fir.var_attrs<parameter>}
+  // CHECK: fir.alloca !fir.ptr<f32> {fortran_attrs = #fir.var_attrs<pointer>}
+  // CHECK: fir.alloca f32 {fortran_attrs = #fir.var_attrs<target>}
+  // CHECK: fir.alloca f32 {fortran_attrs = #fir.var_attrs<value>}
+  // CHECK: fir.alloca f32 {fortran_attrs = #fir.var_attrs<volatile>}
+  // CHECK: fir.alloca !fir.box<!fir.ptr<!fir.array<?xf32>>> {fortran_attrs = #fir.var_attrs<contiguous, pointer, volatile>}
+}

diff  --git a/flang/test/Fir/invalid.fir b/flang/test/Fir/invalid.fir
index a995d86732d4e..f7b23c87b2d2f 100644
--- a/flang/test/Fir/invalid.fir
+++ b/flang/test/Fir/invalid.fir
@@ -802,3 +802,9 @@ func.func private @dispatch(%arg0: !fir.class<!fir.type<derived{a:i32,b:i32}>>,
   fir.dispatch "proc1"(%arg0 : !fir.class<!fir.type<derived{a:i32,b:i32}>>) (%arg0, %arg1 : !fir.class<!fir.type<derived{a:i32,b:i32}>>, i32) {pass_arg_pos = 1 : i32}
   return
 }
+
+// -----
+func.func @test_fortran_var_attrs() {
+  // expected-error at +1 {{Unknown fortran variable attribute: volatypo}}
+  %0 = fir.alloca f32 {fortran_attrs = #fir.var_attrs<volatypo>}
+}


        


More information about the flang-commits mailing list