# 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)
} // 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
--- /dev/null
+//===- 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
#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;
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;
// 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();
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)>";
}
//===----------------------------------------------------------------------===//
void FIROpsDialect::registerAttributes() {
- addAttributes<ClosedIntervalAttr, ExactTypeAttr, LowerBoundAttr,
- PointIntervalAttr, RealAttr, SubclassAttr, UpperBoundAttr>();
+ addAttributes<ClosedIntervalAttr, ExactTypeAttr, FortranVariableFlagsAttr,
+ LowerBoundAttr, PointIntervalAttr, RealAttr, SubclassAttr,
+ UpperBoundAttr>();
}
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>}
+}
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@+1 {{Unknown fortran variable attribute: volatypo}}
+ %0 = fir.alloca f32 {fortran_attrs = #fir.var_attrs<volatypo>}
+}