1 //===-- HLFIRDialect.cpp --------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/
11 //===----------------------------------------------------------------------===//
13 #include "flang/Optimizer/HLFIR/HLFIRDialect.h"
14 #include "flang/Optimizer/Dialect/FIROps.h"
15 #include "flang/Optimizer/Dialect/FIRType.h"
16 #include "flang/Optimizer/HLFIR/HLFIROps.h"
17 #include "mlir/Dialect/Arith/IR/Arith.h"
18 #include "mlir/IR/Builders.h"
19 #include "mlir/IR/BuiltinTypes.h"
20 #include "mlir/IR/DialectImplementation.h"
21 #include "mlir/IR/Matchers.h"
22 #include "mlir/IR/OpImplementation.h"
23 #include "llvm/ADT/SmallVector.h"
24 #include "llvm/ADT/TypeSwitch.h"
26 #include "flang/Optimizer/HLFIR/HLFIRDialect.cpp.inc"
28 #define GET_TYPEDEF_CLASSES
29 #include "flang/Optimizer/HLFIR/HLFIRTypes.cpp.inc"
31 #define GET_ATTRDEF_CLASSES
32 #include "flang/Optimizer/HLFIR/HLFIRAttributes.cpp.inc"
34 void hlfir::hlfirDialect::initialize() {
36 #define GET_TYPEDEF_LIST
37 #include "flang/Optimizer/HLFIR/HLFIRTypes.cpp.inc"
41 #include "flang/Optimizer/HLFIR/HLFIROps.cpp.inc"
45 // `expr` `<` `*` | bounds (`x` bounds)* `:` type [`?`] `>`
46 // bounds ::= `?` | int-lit
47 mlir::Type
hlfir::ExprType::parse(mlir::AsmParser
&parser
) {
48 if (parser
.parseLess())
50 ExprType::Shape shape
;
51 if (parser
.parseOptionalStar()) {
52 if (parser
.parseDimensionList(shape
, /*allowDynamic=*/true))
54 } else if (parser
.parseColon()) {
58 if (parser
.parseType(eleTy
))
60 const bool polymorphic
= mlir::succeeded(parser
.parseOptionalQuestion());
61 if (parser
.parseGreater())
63 return ExprType::get(parser
.getContext(), shape
, eleTy
, polymorphic
);
66 void hlfir::ExprType::print(mlir::AsmPrinter
&printer
) const {
67 auto shape
= getShape();
70 for (const auto &b
: shape
) {
77 printer
<< getEleTy();
83 bool hlfir::isFortranVariableType(mlir::Type type
) {
84 return llvm::TypeSwitch
<mlir::Type
, bool>(type
)
85 .Case
<fir::ReferenceType
, fir::PointerType
, fir::HeapType
>([](auto p
) {
86 mlir::Type eleType
= p
.getEleTy();
87 return eleType
.isa
<fir::BaseBoxType
>() || !fir::hasDynamicSize(eleType
);
89 .Case
<fir::BaseBoxType
, fir::BoxCharType
>([](auto) { return true; })
90 .Case
<fir::VectorType
>([](auto) { return true; })
91 .Default([](mlir::Type
) { return false; });
94 bool hlfir::isFortranScalarCharacterType(mlir::Type type
) {
95 return isFortranScalarCharacterExprType(type
) ||
96 type
.isa
<fir::BoxCharType
>() ||
97 fir::unwrapPassByRefType(fir::unwrapRefType(type
))
98 .isa
<fir::CharacterType
>();
101 bool hlfir::isFortranScalarCharacterExprType(mlir::Type type
) {
102 if (auto exprType
= type
.dyn_cast
<hlfir::ExprType
>())
103 return exprType
.isScalar() &&
104 exprType
.getElementType().isa
<fir::CharacterType
>();
108 bool hlfir::isFortranArrayCharacterExprType(mlir::Type type
) {
109 if (auto exprType
= mlir::dyn_cast
<hlfir::ExprType
>(type
))
110 return exprType
.isArray() &&
111 mlir::isa
<fir::CharacterType
>(exprType
.getElementType());
116 bool hlfir::isFortranScalarNumericalType(mlir::Type type
) {
117 return fir::isa_integer(type
) || fir::isa_real(type
) ||
118 fir::isa_complex(type
);
121 bool hlfir::isFortranNumericalArrayObject(mlir::Type type
) {
122 if (isBoxAddressType(type
))
125 getFortranElementOrSequenceType(type
).dyn_cast
<fir::SequenceType
>())
126 return isFortranScalarNumericalType(arrayTy
.getEleTy());
130 bool hlfir::isFortranNumericalOrLogicalArrayObject(mlir::Type type
) {
131 if (isBoxAddressType(type
))
134 getFortranElementOrSequenceType(type
).dyn_cast
<fir::SequenceType
>()) {
135 mlir::Type eleTy
= arrayTy
.getEleTy();
136 return isFortranScalarNumericalType(eleTy
) ||
137 mlir::isa
<fir::LogicalType
>(eleTy
);
142 bool hlfir::isFortranArrayObject(mlir::Type type
) {
143 if (isBoxAddressType(type
))
145 return !!getFortranElementOrSequenceType(type
).dyn_cast
<fir::SequenceType
>();
148 bool hlfir::isPassByRefOrIntegerType(mlir::Type type
) {
149 mlir::Type unwrappedType
= fir::unwrapPassByRefType(type
);
150 return fir::isa_integer(unwrappedType
);
153 bool hlfir::isI1Type(mlir::Type type
) {
154 if (mlir::IntegerType integer
= type
.dyn_cast
<mlir::IntegerType
>())
155 if (integer
.getWidth() == 1)
160 bool hlfir::isFortranLogicalArrayObject(mlir::Type type
) {
161 if (isBoxAddressType(type
))
164 getFortranElementOrSequenceType(type
).dyn_cast
<fir::SequenceType
>()) {
165 mlir::Type eleTy
= arrayTy
.getEleTy();
166 return mlir::isa
<fir::LogicalType
>(eleTy
);
171 bool hlfir::isMaskArgument(mlir::Type type
) {
172 if (isBoxAddressType(type
))
175 mlir::Type unwrappedType
= fir::unwrapPassByRefType(fir::unwrapRefType(type
));
176 mlir::Type elementType
= getFortranElementType(unwrappedType
);
177 if (unwrappedType
!= elementType
)
178 // input type is an array
179 return mlir::isa
<fir::LogicalType
>(elementType
);
181 // input is a scalar, so allow i1 too
182 return mlir::isa
<fir::LogicalType
>(elementType
) || isI1Type(elementType
);
185 bool hlfir::isPolymorphicObject(mlir::Type type
) {
186 if (auto exprType
= mlir::dyn_cast
<hlfir::ExprType
>(type
))
187 return exprType
.isPolymorphic();
189 return fir::isPolymorphicType(type
);
192 mlir::Value
hlfir::genExprShape(mlir::OpBuilder
&builder
,
193 const mlir::Location
&loc
,
194 const hlfir::ExprType
&expr
) {
195 mlir::IndexType indexTy
= builder
.getIndexType();
196 llvm::SmallVector
<mlir::Value
> extents
;
197 extents
.reserve(expr
.getRank());
199 for (std::int64_t extent
: expr
.getShape()) {
200 if (extent
== hlfir::ExprType::getUnknownExtent())
202 extents
.emplace_back(builder
.create
<mlir::arith::ConstantOp
>(
203 loc
, indexTy
, builder
.getIntegerAttr(indexTy
, extent
)));
206 fir::ShapeType shapeTy
=
207 fir::ShapeType::get(builder
.getContext(), expr
.getRank());
208 fir::ShapeOp shape
= builder
.create
<fir::ShapeOp
>(loc
, shapeTy
, extents
);
209 return shape
.getResult();
212 bool hlfir::mayHaveAllocatableComponent(mlir::Type ty
) {
213 return fir::isPolymorphicType(ty
) || fir::isUnlimitedPolymorphicType(ty
) ||
214 fir::isRecordWithAllocatableMember(hlfir::getFortranElementType(ty
));