157f536a4SjeanPerier //===-- FIROps.cpp --------------------------------------------------------===//
257f536a4SjeanPerier //
357f536a4SjeanPerier // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
457f536a4SjeanPerier // See https://llvm.org/LICENSE.txt for license information.
557f536a4SjeanPerier // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
657f536a4SjeanPerier //
757f536a4SjeanPerier //===----------------------------------------------------------------------===//
867360decSEric Schweitz //
967360decSEric Schweitz // Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/
1067360decSEric Schweitz //
1167360decSEric Schweitz //===----------------------------------------------------------------------===//
1257f536a4SjeanPerier
1357f536a4SjeanPerier #include "flang/Optimizer/Dialect/FIROps.h"
1457f536a4SjeanPerier #include "flang/Optimizer/Dialect/FIRAttr.h"
1557f536a4SjeanPerier #include "flang/Optimizer/Dialect/FIROpsSupport.h"
1657f536a4SjeanPerier #include "flang/Optimizer/Dialect/FIRType.h"
17f5b970c9SEric Schweitz #include "flang/Optimizer/Support/FIRContext.h"
18f5b970c9SEric Schweitz #include "flang/Optimizer/Support/KindMapping.h"
1934d6c182SEric Schweitz #include "flang/Optimizer/Support/Utils.h"
20bc034238SEric Schweitz #include "mlir/Dialect/CommonFolders.h"
2123aa5a74SRiver Riddle #include "mlir/Dialect/Func/IR/FuncOps.h"
228ec0f221SMehdi Amini #include "mlir/IR/BuiltinAttributes.h"
2365fcddffSRiver Riddle #include "mlir/IR/BuiltinOps.h"
2457f536a4SjeanPerier #include "mlir/IR/Diagnostics.h"
25bc034238SEric Schweitz #include "mlir/IR/Matchers.h"
268ec0f221SMehdi Amini #include "mlir/IR/OpDefinition.h"
270b785a46SEric Schweitz #include "mlir/IR/PatternMatch.h"
288ec0f221SMehdi Amini #include "llvm/ADT/STLExtras.h"
298ec0f221SMehdi Amini #include "llvm/ADT/SmallVector.h"
3057f536a4SjeanPerier #include "llvm/ADT/StringSwitch.h"
31ebf190fcSRiver Riddle #include "llvm/ADT/TypeSwitch.h"
3257f536a4SjeanPerier
33c3abfe42SEric Schweitz namespace {
34d43f779fSValentin Clement #include "flang/Optimizer/Dialect/CanonicalizationPatterns.inc"
35c3abfe42SEric Schweitz } // namespace
3657f536a4SjeanPerier
37bc034238SEric Schweitz /// Return true if a sequence type is of some incomplete size or a record type
38bc034238SEric Schweitz /// is malformed or contains an incomplete sequence type. An incomplete sequence
39bc034238SEric Schweitz /// type is one with more unknown extents in the type than have been provided
40bc034238SEric Schweitz /// via `dynamicExtents`. Sequence types with an unknown rank are incomplete by
41bc034238SEric Schweitz /// definition.
verifyInType(mlir::Type inType,llvm::SmallVectorImpl<llvm::StringRef> & visited,unsigned dynamicExtents=0)4257f536a4SjeanPerier static bool verifyInType(mlir::Type inType,
43bc034238SEric Schweitz llvm::SmallVectorImpl<llvm::StringRef> &visited,
44bc034238SEric Schweitz unsigned dynamicExtents = 0) {
4557f536a4SjeanPerier if (auto st = inType.dyn_cast<fir::SequenceType>()) {
4657f536a4SjeanPerier auto shape = st.getShape();
4757f536a4SjeanPerier if (shape.size() == 0)
4857f536a4SjeanPerier return true;
49de8a65f7SEric Schweitz for (std::size_t i = 0, end = shape.size(); i < end; ++i) {
50bc034238SEric Schweitz if (shape[i] != fir::SequenceType::getUnknownExtent())
51bc034238SEric Schweitz continue;
52bc034238SEric Schweitz if (dynamicExtents-- == 0)
5357f536a4SjeanPerier return true;
54bc034238SEric Schweitz }
5557f536a4SjeanPerier } else if (auto rt = inType.dyn_cast<fir::RecordType>()) {
5657f536a4SjeanPerier // don't recurse if we're already visiting this one
5757f536a4SjeanPerier if (llvm::is_contained(visited, rt.getName()))
5857f536a4SjeanPerier return false;
5957f536a4SjeanPerier // keep track of record types currently being visited
6057f536a4SjeanPerier visited.push_back(rt.getName());
6157f536a4SjeanPerier for (auto &field : rt.getTypeList())
6257f536a4SjeanPerier if (verifyInType(field.second, visited))
6357f536a4SjeanPerier return true;
6457f536a4SjeanPerier visited.pop_back();
6557f536a4SjeanPerier }
6657f536a4SjeanPerier return false;
6757f536a4SjeanPerier }
6857f536a4SjeanPerier
verifyTypeParamCount(mlir::Type inType,unsigned numParams)691f69dc08SValentin Clement static bool verifyTypeParamCount(mlir::Type inType, unsigned numParams) {
701f69dc08SValentin Clement auto ty = fir::unwrapSequenceType(inType);
711f69dc08SValentin Clement if (numParams > 0) {
721f69dc08SValentin Clement if (auto recTy = ty.dyn_cast<fir::RecordType>())
731f69dc08SValentin Clement return numParams != recTy.getNumLenParams();
741f69dc08SValentin Clement if (auto chrTy = ty.dyn_cast<fir::CharacterType>())
751f69dc08SValentin Clement return !(numParams == 1 && chrTy.hasDynamicLen());
761f69dc08SValentin Clement return true;
771f69dc08SValentin Clement }
781f69dc08SValentin Clement if (auto chrTy = ty.dyn_cast<fir::CharacterType>())
791f69dc08SValentin Clement return !chrTy.hasConstantLen();
801f69dc08SValentin Clement return false;
811f69dc08SValentin Clement }
821f69dc08SValentin Clement
831f69dc08SValentin Clement /// Parser shared by Alloca and Allocmem
841f69dc08SValentin Clement ///
851f69dc08SValentin Clement /// operation ::= %res = (`fir.alloca` | `fir.allocmem`) $in_type
861f69dc08SValentin Clement /// ( `(` $typeparams `)` )? ( `,` $shape )?
871f69dc08SValentin Clement /// attr-dict-without-keyword
881f69dc08SValentin Clement template <typename FN>
parseAllocatableOp(FN wrapResultType,mlir::OpAsmParser & parser,mlir::OperationState & result)891f69dc08SValentin Clement static mlir::ParseResult parseAllocatableOp(FN wrapResultType,
901f69dc08SValentin Clement mlir::OpAsmParser &parser,
911f69dc08SValentin Clement mlir::OperationState &result) {
921f69dc08SValentin Clement mlir::Type intype;
931f69dc08SValentin Clement if (parser.parseType(intype))
941f69dc08SValentin Clement return mlir::failure();
951f69dc08SValentin Clement auto &builder = parser.getBuilder();
961f69dc08SValentin Clement result.addAttribute("in_type", mlir::TypeAttr::get(intype));
97e13d23bcSMarkus Böck llvm::SmallVector<mlir::OpAsmParser::UnresolvedOperand> operands;
981f69dc08SValentin Clement llvm::SmallVector<mlir::Type> typeVec;
991f69dc08SValentin Clement bool hasOperands = false;
1001f69dc08SValentin Clement std::int32_t typeparamsSize = 0;
1011f69dc08SValentin Clement if (!parser.parseOptionalLParen()) {
1021f69dc08SValentin Clement // parse the LEN params of the derived type. (<params> : <types>)
1031f69dc08SValentin Clement if (parser.parseOperandList(operands, mlir::OpAsmParser::Delimiter::None) ||
1041f69dc08SValentin Clement parser.parseColonTypeList(typeVec) || parser.parseRParen())
1051f69dc08SValentin Clement return mlir::failure();
1061f69dc08SValentin Clement typeparamsSize = operands.size();
1071f69dc08SValentin Clement hasOperands = true;
1081f69dc08SValentin Clement }
1091f69dc08SValentin Clement std::int32_t shapeSize = 0;
1101f69dc08SValentin Clement if (!parser.parseOptionalComma()) {
1111f69dc08SValentin Clement // parse size to scale by, vector of n dimensions of type index
1121f69dc08SValentin Clement if (parser.parseOperandList(operands, mlir::OpAsmParser::Delimiter::None))
1131f69dc08SValentin Clement return mlir::failure();
1141f69dc08SValentin Clement shapeSize = operands.size() - typeparamsSize;
1151f69dc08SValentin Clement auto idxTy = builder.getIndexType();
1161f69dc08SValentin Clement for (std::int32_t i = typeparamsSize, end = operands.size(); i != end; ++i)
1171f69dc08SValentin Clement typeVec.push_back(idxTy);
1181f69dc08SValentin Clement hasOperands = true;
1191f69dc08SValentin Clement }
1201f69dc08SValentin Clement if (hasOperands &&
1211f69dc08SValentin Clement parser.resolveOperands(operands, typeVec, parser.getNameLoc(),
1221f69dc08SValentin Clement result.operands))
1231f69dc08SValentin Clement return mlir::failure();
1241f69dc08SValentin Clement mlir::Type restype = wrapResultType(intype);
1251f69dc08SValentin Clement if (!restype) {
1261f69dc08SValentin Clement parser.emitError(parser.getNameLoc(), "invalid allocate type: ") << intype;
1271f69dc08SValentin Clement return mlir::failure();
1281f69dc08SValentin Clement }
1291f69dc08SValentin Clement result.addAttribute("operand_segment_sizes",
1301f69dc08SValentin Clement builder.getI32VectorAttr({typeparamsSize, shapeSize}));
1311f69dc08SValentin Clement if (parser.parseOptionalAttrDict(result.attributes) ||
1321f69dc08SValentin Clement parser.addTypeToList(restype, result.types))
1331f69dc08SValentin Clement return mlir::failure();
1341f69dc08SValentin Clement return mlir::success();
1351f69dc08SValentin Clement }
1361f69dc08SValentin Clement
1371f69dc08SValentin Clement template <typename OP>
printAllocatableOp(mlir::OpAsmPrinter & p,OP & op)1381f69dc08SValentin Clement static void printAllocatableOp(mlir::OpAsmPrinter &p, OP &op) {
139149ad3d5SShraiysh Vaishay p << ' ' << op.getInType();
140149ad3d5SShraiysh Vaishay if (!op.getTypeparams().empty()) {
141149ad3d5SShraiysh Vaishay p << '(' << op.getTypeparams() << " : " << op.getTypeparams().getTypes()
142149ad3d5SShraiysh Vaishay << ')';
1431f69dc08SValentin Clement }
1441f69dc08SValentin Clement // print the shape of the allocation (if any); all must be index type
145149ad3d5SShraiysh Vaishay for (auto sh : op.getShape()) {
1461f69dc08SValentin Clement p << ", ";
1471f69dc08SValentin Clement p.printOperand(sh);
1481f69dc08SValentin Clement }
1491f69dc08SValentin Clement p.printOptionalAttrDict(op->getAttrs(), {"in_type", "operand_segment_sizes"});
1501f69dc08SValentin Clement }
1511f69dc08SValentin Clement
15257f536a4SjeanPerier //===----------------------------------------------------------------------===//
15357f536a4SjeanPerier // AllocaOp
15457f536a4SjeanPerier //===----------------------------------------------------------------------===//
15557f536a4SjeanPerier
15657f536a4SjeanPerier /// Create a legal memory reference as return type
wrapAllocaResultType(mlir::Type intype)1578014b28dSEric Schweitz static mlir::Type wrapAllocaResultType(mlir::Type intype) {
15857f536a4SjeanPerier // FIR semantics: memory references to memory references are disallowed
159de8a65f7SEric Schweitz if (intype.isa<fir::ReferenceType>())
16057f536a4SjeanPerier return {};
161de8a65f7SEric Schweitz return fir::ReferenceType::get(intype);
16257f536a4SjeanPerier }
16357f536a4SjeanPerier
getAllocatedType()1648014b28dSEric Schweitz mlir::Type fir::AllocaOp::getAllocatedType() {
165de8a65f7SEric Schweitz return getType().cast<fir::ReferenceType>().getEleTy();
1668014b28dSEric Schweitz }
1678014b28dSEric Schweitz
getRefTy(mlir::Type ty)16857f536a4SjeanPerier mlir::Type fir::AllocaOp::getRefTy(mlir::Type ty) {
169de8a65f7SEric Schweitz return fir::ReferenceType::get(ty);
17057f536a4SjeanPerier }
17157f536a4SjeanPerier
build(mlir::OpBuilder & builder,mlir::OperationState & result,mlir::Type inType,llvm::StringRef uniqName,mlir::ValueRange typeparams,mlir::ValueRange shape,llvm::ArrayRef<mlir::NamedAttribute> attributes)1728014b28dSEric Schweitz void fir::AllocaOp::build(mlir::OpBuilder &builder,
1738014b28dSEric Schweitz mlir::OperationState &result, mlir::Type inType,
1748014b28dSEric Schweitz llvm::StringRef uniqName, mlir::ValueRange typeparams,
1758014b28dSEric Schweitz mlir::ValueRange shape,
1768014b28dSEric Schweitz llvm::ArrayRef<mlir::NamedAttribute> attributes) {
1778014b28dSEric Schweitz auto nameAttr = builder.getStringAttr(uniqName);
1788014b28dSEric Schweitz build(builder, result, wrapAllocaResultType(inType), inType, nameAttr, {},
1794cab4f6bSKiran Chandramohan /*pinned=*/false, typeparams, shape);
1804cab4f6bSKiran Chandramohan result.addAttributes(attributes);
1814cab4f6bSKiran Chandramohan }
1824cab4f6bSKiran Chandramohan
build(mlir::OpBuilder & builder,mlir::OperationState & result,mlir::Type inType,llvm::StringRef uniqName,bool pinned,mlir::ValueRange typeparams,mlir::ValueRange shape,llvm::ArrayRef<mlir::NamedAttribute> attributes)1834cab4f6bSKiran Chandramohan void fir::AllocaOp::build(mlir::OpBuilder &builder,
1844cab4f6bSKiran Chandramohan mlir::OperationState &result, mlir::Type inType,
1854cab4f6bSKiran Chandramohan llvm::StringRef uniqName, bool pinned,
1864cab4f6bSKiran Chandramohan mlir::ValueRange typeparams, mlir::ValueRange shape,
1874cab4f6bSKiran Chandramohan llvm::ArrayRef<mlir::NamedAttribute> attributes) {
1884cab4f6bSKiran Chandramohan auto nameAttr = builder.getStringAttr(uniqName);
1894cab4f6bSKiran Chandramohan build(builder, result, wrapAllocaResultType(inType), inType, nameAttr, {},
1904cab4f6bSKiran Chandramohan pinned, typeparams, shape);
1918014b28dSEric Schweitz result.addAttributes(attributes);
1928014b28dSEric Schweitz }
1938014b28dSEric Schweitz
build(mlir::OpBuilder & builder,mlir::OperationState & result,mlir::Type inType,llvm::StringRef uniqName,llvm::StringRef bindcName,mlir::ValueRange typeparams,mlir::ValueRange shape,llvm::ArrayRef<mlir::NamedAttribute> attributes)1948014b28dSEric Schweitz void fir::AllocaOp::build(mlir::OpBuilder &builder,
1958014b28dSEric Schweitz mlir::OperationState &result, mlir::Type inType,
1968014b28dSEric Schweitz llvm::StringRef uniqName, llvm::StringRef bindcName,
1978014b28dSEric Schweitz mlir::ValueRange typeparams, mlir::ValueRange shape,
1988014b28dSEric Schweitz llvm::ArrayRef<mlir::NamedAttribute> attributes) {
1998014b28dSEric Schweitz auto nameAttr =
2008014b28dSEric Schweitz uniqName.empty() ? mlir::StringAttr{} : builder.getStringAttr(uniqName);
2018014b28dSEric Schweitz auto bindcAttr =
2028014b28dSEric Schweitz bindcName.empty() ? mlir::StringAttr{} : builder.getStringAttr(bindcName);
2038014b28dSEric Schweitz build(builder, result, wrapAllocaResultType(inType), inType, nameAttr,
2044cab4f6bSKiran Chandramohan bindcAttr, /*pinned=*/false, typeparams, shape);
2054cab4f6bSKiran Chandramohan result.addAttributes(attributes);
2064cab4f6bSKiran Chandramohan }
2074cab4f6bSKiran Chandramohan
build(mlir::OpBuilder & builder,mlir::OperationState & result,mlir::Type inType,llvm::StringRef uniqName,llvm::StringRef bindcName,bool pinned,mlir::ValueRange typeparams,mlir::ValueRange shape,llvm::ArrayRef<mlir::NamedAttribute> attributes)2084cab4f6bSKiran Chandramohan void fir::AllocaOp::build(mlir::OpBuilder &builder,
2094cab4f6bSKiran Chandramohan mlir::OperationState &result, mlir::Type inType,
2104cab4f6bSKiran Chandramohan llvm::StringRef uniqName, llvm::StringRef bindcName,
2114cab4f6bSKiran Chandramohan bool pinned, mlir::ValueRange typeparams,
2124cab4f6bSKiran Chandramohan mlir::ValueRange shape,
2134cab4f6bSKiran Chandramohan llvm::ArrayRef<mlir::NamedAttribute> attributes) {
2144cab4f6bSKiran Chandramohan auto nameAttr =
2154cab4f6bSKiran Chandramohan uniqName.empty() ? mlir::StringAttr{} : builder.getStringAttr(uniqName);
2164cab4f6bSKiran Chandramohan auto bindcAttr =
2174cab4f6bSKiran Chandramohan bindcName.empty() ? mlir::StringAttr{} : builder.getStringAttr(bindcName);
2184cab4f6bSKiran Chandramohan build(builder, result, wrapAllocaResultType(inType), inType, nameAttr,
2194cab4f6bSKiran Chandramohan bindcAttr, pinned, typeparams, shape);
2208014b28dSEric Schweitz result.addAttributes(attributes);
2218014b28dSEric Schweitz }
2228014b28dSEric Schweitz
build(mlir::OpBuilder & builder,mlir::OperationState & result,mlir::Type inType,mlir::ValueRange typeparams,mlir::ValueRange shape,llvm::ArrayRef<mlir::NamedAttribute> attributes)2238014b28dSEric Schweitz void fir::AllocaOp::build(mlir::OpBuilder &builder,
2248014b28dSEric Schweitz mlir::OperationState &result, mlir::Type inType,
2258014b28dSEric Schweitz mlir::ValueRange typeparams, mlir::ValueRange shape,
2268014b28dSEric Schweitz llvm::ArrayRef<mlir::NamedAttribute> attributes) {
2278014b28dSEric Schweitz build(builder, result, wrapAllocaResultType(inType), inType, {}, {},
2284cab4f6bSKiran Chandramohan /*pinned=*/false, typeparams, shape);
2294cab4f6bSKiran Chandramohan result.addAttributes(attributes);
2304cab4f6bSKiran Chandramohan }
2314cab4f6bSKiran Chandramohan
build(mlir::OpBuilder & builder,mlir::OperationState & result,mlir::Type inType,bool pinned,mlir::ValueRange typeparams,mlir::ValueRange shape,llvm::ArrayRef<mlir::NamedAttribute> attributes)2324cab4f6bSKiran Chandramohan void fir::AllocaOp::build(mlir::OpBuilder &builder,
2334cab4f6bSKiran Chandramohan mlir::OperationState &result, mlir::Type inType,
2344cab4f6bSKiran Chandramohan bool pinned, mlir::ValueRange typeparams,
2354cab4f6bSKiran Chandramohan mlir::ValueRange shape,
2364cab4f6bSKiran Chandramohan llvm::ArrayRef<mlir::NamedAttribute> attributes) {
2374cab4f6bSKiran Chandramohan build(builder, result, wrapAllocaResultType(inType), inType, {}, {}, pinned,
2388014b28dSEric Schweitz typeparams, shape);
2398014b28dSEric Schweitz result.addAttributes(attributes);
2408014b28dSEric Schweitz }
2418014b28dSEric Schweitz
parse(mlir::OpAsmParser & parser,mlir::OperationState & result)242de8a65f7SEric Schweitz mlir::ParseResult fir::AllocaOp::parse(mlir::OpAsmParser &parser,
243de8a65f7SEric Schweitz mlir::OperationState &result) {
244cc120e36SShraiysh Vaishay return parseAllocatableOp(wrapAllocaResultType, parser, result);
245cc120e36SShraiysh Vaishay }
246cc120e36SShraiysh Vaishay
print(mlir::OpAsmPrinter & p)247de8a65f7SEric Schweitz void fir::AllocaOp::print(mlir::OpAsmPrinter &p) {
248de8a65f7SEric Schweitz printAllocatableOp(p, *this);
249de8a65f7SEric Schweitz }
250cc120e36SShraiysh Vaishay
verify()251cc120e36SShraiysh Vaishay mlir::LogicalResult fir::AllocaOp::verify() {
2528014b28dSEric Schweitz llvm::SmallVector<llvm::StringRef> visited;
253cc120e36SShraiysh Vaishay if (verifyInType(getInType(), visited, numShapeOperands()))
254cc120e36SShraiysh Vaishay return emitOpError("invalid type for allocation");
255cc120e36SShraiysh Vaishay if (verifyTypeParamCount(getInType(), numLenParams()))
256cc120e36SShraiysh Vaishay return emitOpError("LEN params do not correspond to type");
257cc120e36SShraiysh Vaishay mlir::Type outType = getType();
2588014b28dSEric Schweitz if (!outType.isa<fir::ReferenceType>())
259cc120e36SShraiysh Vaishay return emitOpError("must be a !fir.ref type");
2608014b28dSEric Schweitz if (fir::isa_unknown_size_box(fir::dyn_cast_ptrEleTy(outType)))
261cc120e36SShraiysh Vaishay return emitOpError("cannot allocate !fir.box of unknown rank or type");
2628014b28dSEric Schweitz return mlir::success();
2638014b28dSEric Schweitz }
2648014b28dSEric Schweitz
26557f536a4SjeanPerier //===----------------------------------------------------------------------===//
26657f536a4SjeanPerier // AllocMemOp
26757f536a4SjeanPerier //===----------------------------------------------------------------------===//
26857f536a4SjeanPerier
2691f69dc08SValentin Clement /// Create a legal heap reference as return type
wrapAllocMemResultType(mlir::Type intype)2701f69dc08SValentin Clement static mlir::Type wrapAllocMemResultType(mlir::Type intype) {
2711f69dc08SValentin Clement // Fortran semantics: C852 an entity cannot be both ALLOCATABLE and POINTER
2721f69dc08SValentin Clement // 8.5.3 note 1 prohibits ALLOCATABLE procedures as well
2731f69dc08SValentin Clement // FIR semantics: one may not allocate a memory reference value
274de8a65f7SEric Schweitz if (intype.isa<fir::ReferenceType, fir::HeapType, fir::PointerType,
275de8a65f7SEric Schweitz mlir::FunctionType>())
2761f69dc08SValentin Clement return {};
277de8a65f7SEric Schweitz return fir::HeapType::get(intype);
2781f69dc08SValentin Clement }
2791f69dc08SValentin Clement
getAllocatedType()28057f536a4SjeanPerier mlir::Type fir::AllocMemOp::getAllocatedType() {
281de8a65f7SEric Schweitz return getType().cast<fir::HeapType>().getEleTy();
28257f536a4SjeanPerier }
28357f536a4SjeanPerier
getRefTy(mlir::Type ty)28457f536a4SjeanPerier mlir::Type fir::AllocMemOp::getRefTy(mlir::Type ty) {
285de8a65f7SEric Schweitz return fir::HeapType::get(ty);
28657f536a4SjeanPerier }
28757f536a4SjeanPerier
build(mlir::OpBuilder & builder,mlir::OperationState & result,mlir::Type inType,llvm::StringRef uniqName,mlir::ValueRange typeparams,mlir::ValueRange shape,llvm::ArrayRef<mlir::NamedAttribute> attributes)2881f69dc08SValentin Clement void fir::AllocMemOp::build(mlir::OpBuilder &builder,
2891f69dc08SValentin Clement mlir::OperationState &result, mlir::Type inType,
2901f69dc08SValentin Clement llvm::StringRef uniqName,
2911f69dc08SValentin Clement mlir::ValueRange typeparams, mlir::ValueRange shape,
2921f69dc08SValentin Clement llvm::ArrayRef<mlir::NamedAttribute> attributes) {
2931f69dc08SValentin Clement auto nameAttr = builder.getStringAttr(uniqName);
2941f69dc08SValentin Clement build(builder, result, wrapAllocMemResultType(inType), inType, nameAttr, {},
2951f69dc08SValentin Clement typeparams, shape);
2961f69dc08SValentin Clement result.addAttributes(attributes);
2971f69dc08SValentin Clement }
2981f69dc08SValentin Clement
build(mlir::OpBuilder & builder,mlir::OperationState & result,mlir::Type inType,llvm::StringRef uniqName,llvm::StringRef bindcName,mlir::ValueRange typeparams,mlir::ValueRange shape,llvm::ArrayRef<mlir::NamedAttribute> attributes)2991f69dc08SValentin Clement void fir::AllocMemOp::build(mlir::OpBuilder &builder,
3001f69dc08SValentin Clement mlir::OperationState &result, mlir::Type inType,
3011f69dc08SValentin Clement llvm::StringRef uniqName, llvm::StringRef bindcName,
3021f69dc08SValentin Clement mlir::ValueRange typeparams, mlir::ValueRange shape,
3031f69dc08SValentin Clement llvm::ArrayRef<mlir::NamedAttribute> attributes) {
3041f69dc08SValentin Clement auto nameAttr = builder.getStringAttr(uniqName);
3051f69dc08SValentin Clement auto bindcAttr = builder.getStringAttr(bindcName);
3061f69dc08SValentin Clement build(builder, result, wrapAllocMemResultType(inType), inType, nameAttr,
3071f69dc08SValentin Clement bindcAttr, typeparams, shape);
3081f69dc08SValentin Clement result.addAttributes(attributes);
3091f69dc08SValentin Clement }
3101f69dc08SValentin Clement
build(mlir::OpBuilder & builder,mlir::OperationState & result,mlir::Type inType,mlir::ValueRange typeparams,mlir::ValueRange shape,llvm::ArrayRef<mlir::NamedAttribute> attributes)3111f69dc08SValentin Clement void fir::AllocMemOp::build(mlir::OpBuilder &builder,
3121f69dc08SValentin Clement mlir::OperationState &result, mlir::Type inType,
3131f69dc08SValentin Clement mlir::ValueRange typeparams, mlir::ValueRange shape,
3141f69dc08SValentin Clement llvm::ArrayRef<mlir::NamedAttribute> attributes) {
3151f69dc08SValentin Clement build(builder, result, wrapAllocMemResultType(inType), inType, {}, {},
3161f69dc08SValentin Clement typeparams, shape);
3171f69dc08SValentin Clement result.addAttributes(attributes);
3181f69dc08SValentin Clement }
3191f69dc08SValentin Clement
parse(mlir::OpAsmParser & parser,mlir::OperationState & result)320de8a65f7SEric Schweitz mlir::ParseResult fir::AllocMemOp::parse(mlir::OpAsmParser &parser,
321de8a65f7SEric Schweitz mlir::OperationState &result) {
322cc120e36SShraiysh Vaishay return parseAllocatableOp(wrapAllocMemResultType, parser, result);
323cc120e36SShraiysh Vaishay }
324cc120e36SShraiysh Vaishay
print(mlir::OpAsmPrinter & p)325de8a65f7SEric Schweitz void fir::AllocMemOp::print(mlir::OpAsmPrinter &p) {
326de8a65f7SEric Schweitz printAllocatableOp(p, *this);
327de8a65f7SEric Schweitz }
328cc120e36SShraiysh Vaishay
verify()329de8a65f7SEric Schweitz mlir::LogicalResult fir::AllocMemOp::verify() {
3301f69dc08SValentin Clement llvm::SmallVector<llvm::StringRef> visited;
331cc120e36SShraiysh Vaishay if (verifyInType(getInType(), visited, numShapeOperands()))
332cc120e36SShraiysh Vaishay return emitOpError("invalid type for allocation");
333cc120e36SShraiysh Vaishay if (verifyTypeParamCount(getInType(), numLenParams()))
334cc120e36SShraiysh Vaishay return emitOpError("LEN params do not correspond to type");
335cc120e36SShraiysh Vaishay mlir::Type outType = getType();
3361f69dc08SValentin Clement if (!outType.dyn_cast<fir::HeapType>())
337cc120e36SShraiysh Vaishay return emitOpError("must be a !fir.heap type");
3381f69dc08SValentin Clement if (fir::isa_unknown_size_box(fir::dyn_cast_ptrEleTy(outType)))
339cc120e36SShraiysh Vaishay return emitOpError("cannot allocate !fir.box of unknown rank or type");
3401f69dc08SValentin Clement return mlir::success();
34157f536a4SjeanPerier }
34257f536a4SjeanPerier
34357f536a4SjeanPerier //===----------------------------------------------------------------------===//
34467360decSEric Schweitz // ArrayCoorOp
34567360decSEric Schweitz //===----------------------------------------------------------------------===//
34667360decSEric Schweitz
347649439e7SValentin Clement // CHARACTERs and derived types with LEN PARAMETERs are dependent types that
348649439e7SValentin Clement // require runtime values to fully define the type of an object.
validTypeParams(mlir::Type dynTy,mlir::ValueRange typeParams)349649439e7SValentin Clement static bool validTypeParams(mlir::Type dynTy, mlir::ValueRange typeParams) {
350649439e7SValentin Clement dynTy = fir::unwrapAllRefAndSeqType(dynTy);
351649439e7SValentin Clement // A box value will contain type parameter values itself.
352649439e7SValentin Clement if (dynTy.isa<fir::BoxType>())
353649439e7SValentin Clement return typeParams.size() == 0;
354649439e7SValentin Clement // Derived type must have all type parameters satisfied.
355649439e7SValentin Clement if (auto recTy = dynTy.dyn_cast<fir::RecordType>())
356649439e7SValentin Clement return typeParams.size() == recTy.getNumLenParams();
357649439e7SValentin Clement // Characters with non-constant LEN must have a type parameter value.
358649439e7SValentin Clement if (auto charTy = dynTy.dyn_cast<fir::CharacterType>())
359649439e7SValentin Clement if (charTy.hasDynamicLen())
360649439e7SValentin Clement return typeParams.size() == 1;
361649439e7SValentin Clement // Otherwise, any type parameters are invalid.
362649439e7SValentin Clement return typeParams.size() == 0;
363649439e7SValentin Clement }
364649439e7SValentin Clement
verify()365de8a65f7SEric Schweitz mlir::LogicalResult fir::ArrayCoorOp::verify() {
366149ad3d5SShraiysh Vaishay auto eleTy = fir::dyn_cast_ptrOrBoxEleTy(getMemref().getType());
36767360decSEric Schweitz auto arrTy = eleTy.dyn_cast<fir::SequenceType>();
36867360decSEric Schweitz if (!arrTy)
369cc120e36SShraiysh Vaishay return emitOpError("must be a reference to an array");
37067360decSEric Schweitz auto arrDim = arrTy.getDimension();
37167360decSEric Schweitz
372149ad3d5SShraiysh Vaishay if (auto shapeOp = getShape()) {
37367360decSEric Schweitz auto shapeTy = shapeOp.getType();
37467360decSEric Schweitz unsigned shapeTyRank = 0;
37567360decSEric Schweitz if (auto s = shapeTy.dyn_cast<fir::ShapeType>()) {
37667360decSEric Schweitz shapeTyRank = s.getRank();
37767360decSEric Schweitz } else if (auto ss = shapeTy.dyn_cast<fir::ShapeShiftType>()) {
37867360decSEric Schweitz shapeTyRank = ss.getRank();
37967360decSEric Schweitz } else {
38067360decSEric Schweitz auto s = shapeTy.cast<fir::ShiftType>();
38167360decSEric Schweitz shapeTyRank = s.getRank();
382149ad3d5SShraiysh Vaishay if (!getMemref().getType().isa<fir::BoxType>())
383cc120e36SShraiysh Vaishay return emitOpError("shift can only be provided with fir.box memref");
38467360decSEric Schweitz }
38567360decSEric Schweitz if (arrDim && arrDim != shapeTyRank)
386cc120e36SShraiysh Vaishay return emitOpError("rank of dimension mismatched");
387149ad3d5SShraiysh Vaishay if (shapeTyRank != getIndices().size())
388cc120e36SShraiysh Vaishay return emitOpError("number of indices do not match dim rank");
38967360decSEric Schweitz }
39067360decSEric Schweitz
391149ad3d5SShraiysh Vaishay if (auto sliceOp = getSlice()) {
3929daec095SValentin Clement if (auto sl = mlir::dyn_cast_or_null<fir::SliceOp>(sliceOp.getDefiningOp()))
393149ad3d5SShraiysh Vaishay if (!sl.getSubstr().empty())
394cc120e36SShraiysh Vaishay return emitOpError("array_coor cannot take a slice with substring");
39567360decSEric Schweitz if (auto sliceTy = sliceOp.getType().dyn_cast<fir::SliceType>())
39667360decSEric Schweitz if (sliceTy.getRank() != arrDim)
397cc120e36SShraiysh Vaishay return emitOpError("rank of dimension in slice mismatched");
3989daec095SValentin Clement }
399649439e7SValentin Clement if (!validTypeParams(getMemref().getType(), getTypeparams()))
400649439e7SValentin Clement return emitOpError("invalid type parameters");
40167360decSEric Schweitz
40267360decSEric Schweitz return mlir::success();
40367360decSEric Schweitz }
40467360decSEric Schweitz
40567360decSEric Schweitz //===----------------------------------------------------------------------===//
40667360decSEric Schweitz // ArrayLoadOp
40767360decSEric Schweitz //===----------------------------------------------------------------------===//
40867360decSEric Schweitz
adjustedElementType(mlir::Type t)40934d6c182SEric Schweitz static mlir::Type adjustedElementType(mlir::Type t) {
41034d6c182SEric Schweitz if (auto ty = t.dyn_cast<fir::ReferenceType>()) {
41134d6c182SEric Schweitz auto eleTy = ty.getEleTy();
41234d6c182SEric Schweitz if (fir::isa_char(eleTy))
41334d6c182SEric Schweitz return eleTy;
41434d6c182SEric Schweitz if (fir::isa_derived(eleTy))
41534d6c182SEric Schweitz return eleTy;
41634d6c182SEric Schweitz if (eleTy.isa<fir::SequenceType>())
41734d6c182SEric Schweitz return eleTy;
41834d6c182SEric Schweitz }
41934d6c182SEric Schweitz return t;
42034d6c182SEric Schweitz }
42134d6c182SEric Schweitz
getExtents()42267360decSEric Schweitz std::vector<mlir::Value> fir::ArrayLoadOp::getExtents() {
423149ad3d5SShraiysh Vaishay if (auto sh = getShape())
42467360decSEric Schweitz if (auto *op = sh.getDefiningOp()) {
425de8a65f7SEric Schweitz if (auto shOp = mlir::dyn_cast<fir::ShapeOp>(op)) {
4263012f35fSJacques Pienaar auto extents = shOp.getExtents();
4273012f35fSJacques Pienaar return {extents.begin(), extents.end()};
4283012f35fSJacques Pienaar }
429de8a65f7SEric Schweitz return mlir::cast<fir::ShapeShiftOp>(op).getExtents();
43067360decSEric Schweitz }
43167360decSEric Schweitz return {};
43267360decSEric Schweitz }
43367360decSEric Schweitz
verify()434de8a65f7SEric Schweitz mlir::LogicalResult fir::ArrayLoadOp::verify() {
435149ad3d5SShraiysh Vaishay auto eleTy = fir::dyn_cast_ptrOrBoxEleTy(getMemref().getType());
43667360decSEric Schweitz auto arrTy = eleTy.dyn_cast<fir::SequenceType>();
43767360decSEric Schweitz if (!arrTy)
438cc120e36SShraiysh Vaishay return emitOpError("must be a reference to an array");
43967360decSEric Schweitz auto arrDim = arrTy.getDimension();
44067360decSEric Schweitz
441149ad3d5SShraiysh Vaishay if (auto shapeOp = getShape()) {
44267360decSEric Schweitz auto shapeTy = shapeOp.getType();
443de8a65f7SEric Schweitz unsigned shapeTyRank = 0u;
44467360decSEric Schweitz if (auto s = shapeTy.dyn_cast<fir::ShapeType>()) {
44567360decSEric Schweitz shapeTyRank = s.getRank();
44667360decSEric Schweitz } else if (auto ss = shapeTy.dyn_cast<fir::ShapeShiftType>()) {
44767360decSEric Schweitz shapeTyRank = ss.getRank();
44867360decSEric Schweitz } else {
44967360decSEric Schweitz auto s = shapeTy.cast<fir::ShiftType>();
45067360decSEric Schweitz shapeTyRank = s.getRank();
451149ad3d5SShraiysh Vaishay if (!getMemref().getType().isa<fir::BoxType>())
452cc120e36SShraiysh Vaishay return emitOpError("shift can only be provided with fir.box memref");
45367360decSEric Schweitz }
45467360decSEric Schweitz if (arrDim && arrDim != shapeTyRank)
455cc120e36SShraiysh Vaishay return emitOpError("rank of dimension mismatched");
45667360decSEric Schweitz }
45767360decSEric Schweitz
458149ad3d5SShraiysh Vaishay if (auto sliceOp = getSlice()) {
4599daec095SValentin Clement if (auto sl = mlir::dyn_cast_or_null<fir::SliceOp>(sliceOp.getDefiningOp()))
460149ad3d5SShraiysh Vaishay if (!sl.getSubstr().empty())
461cc120e36SShraiysh Vaishay return emitOpError("array_load cannot take a slice with substring");
46267360decSEric Schweitz if (auto sliceTy = sliceOp.getType().dyn_cast<fir::SliceType>())
46367360decSEric Schweitz if (sliceTy.getRank() != arrDim)
464cc120e36SShraiysh Vaishay return emitOpError("rank of dimension in slice mismatched");
4659daec095SValentin Clement }
46667360decSEric Schweitz
467649439e7SValentin Clement if (!validTypeParams(getMemref().getType(), getTypeparams()))
468649439e7SValentin Clement return emitOpError("invalid type parameters");
469649439e7SValentin Clement
47067360decSEric Schweitz return mlir::success();
47167360decSEric Schweitz }
47267360decSEric Schweitz
47367360decSEric Schweitz //===----------------------------------------------------------------------===//
47434d6c182SEric Schweitz // ArrayMergeStoreOp
47534d6c182SEric Schweitz //===----------------------------------------------------------------------===//
47634d6c182SEric Schweitz
verify()477de8a65f7SEric Schweitz mlir::LogicalResult fir::ArrayMergeStoreOp::verify() {
478de8a65f7SEric Schweitz if (!mlir::isa<fir::ArrayLoadOp>(getOriginal().getDefiningOp()))
479cc120e36SShraiysh Vaishay return emitOpError("operand #0 must be result of a fir.array_load op");
480149ad3d5SShraiysh Vaishay if (auto sl = getSlice()) {
4819daec095SValentin Clement if (auto sliceOp =
4829daec095SValentin Clement mlir::dyn_cast_or_null<fir::SliceOp>(sl.getDefiningOp())) {
483149ad3d5SShraiysh Vaishay if (!sliceOp.getSubstr().empty())
484cc120e36SShraiysh Vaishay return emitOpError(
4859daec095SValentin Clement "array_merge_store cannot take a slice with substring");
486149ad3d5SShraiysh Vaishay if (!sliceOp.getFields().empty()) {
48734d6c182SEric Schweitz // This is an intra-object merge, where the slice is projecting the
48834d6c182SEric Schweitz // subfields that are to be overwritten by the merge operation.
489149ad3d5SShraiysh Vaishay auto eleTy = fir::dyn_cast_ptrOrBoxEleTy(getMemref().getType());
49034d6c182SEric Schweitz if (auto seqTy = eleTy.dyn_cast<fir::SequenceType>()) {
49134d6c182SEric Schweitz auto projTy =
492149ad3d5SShraiysh Vaishay fir::applyPathToType(seqTy.getEleTy(), sliceOp.getFields());
493149ad3d5SShraiysh Vaishay if (fir::unwrapSequenceType(getOriginal().getType()) != projTy)
494cc120e36SShraiysh Vaishay return emitOpError(
49534d6c182SEric Schweitz "type of origin does not match sliced memref type");
496149ad3d5SShraiysh Vaishay if (fir::unwrapSequenceType(getSequence().getType()) != projTy)
497cc120e36SShraiysh Vaishay return emitOpError(
49834d6c182SEric Schweitz "type of sequence does not match sliced memref type");
49934d6c182SEric Schweitz return mlir::success();
50034d6c182SEric Schweitz }
501cc120e36SShraiysh Vaishay return emitOpError("referenced type is not an array");
50234d6c182SEric Schweitz }
50334d6c182SEric Schweitz }
50434d6c182SEric Schweitz return mlir::success();
50534d6c182SEric Schweitz }
506149ad3d5SShraiysh Vaishay auto eleTy = fir::dyn_cast_ptrOrBoxEleTy(getMemref().getType());
507149ad3d5SShraiysh Vaishay if (getOriginal().getType() != eleTy)
508cc120e36SShraiysh Vaishay return emitOpError("type of origin does not match memref element type");
509149ad3d5SShraiysh Vaishay if (getSequence().getType() != eleTy)
510cc120e36SShraiysh Vaishay return emitOpError("type of sequence does not match memref element type");
511649439e7SValentin Clement if (!validTypeParams(getMemref().getType(), getTypeparams()))
512649439e7SValentin Clement return emitOpError("invalid type parameters");
51334d6c182SEric Schweitz return mlir::success();
51434d6c182SEric Schweitz }
51534d6c182SEric Schweitz
51634d6c182SEric Schweitz //===----------------------------------------------------------------------===//
51734d6c182SEric Schweitz // ArrayFetchOp
51834d6c182SEric Schweitz //===----------------------------------------------------------------------===//
51934d6c182SEric Schweitz
52034d6c182SEric Schweitz // Template function used for both array_fetch and array_update verification.
52134d6c182SEric Schweitz template <typename A>
validArraySubobject(A op)52234d6c182SEric Schweitz mlir::Type validArraySubobject(A op) {
523149ad3d5SShraiysh Vaishay auto ty = op.getSequence().getType();
524149ad3d5SShraiysh Vaishay return fir::applyPathToType(ty, op.getIndices());
52534d6c182SEric Schweitz }
52634d6c182SEric Schweitz
verify()527de8a65f7SEric Schweitz mlir::LogicalResult fir::ArrayFetchOp::verify() {
528149ad3d5SShraiysh Vaishay auto arrTy = getSequence().getType().cast<fir::SequenceType>();
529149ad3d5SShraiysh Vaishay auto indSize = getIndices().size();
53034d6c182SEric Schweitz if (indSize < arrTy.getDimension())
531cc120e36SShraiysh Vaishay return emitOpError("number of indices != dimension of array");
53234d6c182SEric Schweitz if (indSize == arrTy.getDimension() &&
533149ad3d5SShraiysh Vaishay ::adjustedElementType(getElement().getType()) != arrTy.getEleTy())
534cc120e36SShraiysh Vaishay return emitOpError("return type does not match array");
535cc120e36SShraiysh Vaishay auto ty = validArraySubobject(*this);
536cc120e36SShraiysh Vaishay if (!ty || ty != ::adjustedElementType(getType()))
537cc120e36SShraiysh Vaishay return emitOpError("return type and/or indices do not type check");
538de8a65f7SEric Schweitz if (!mlir::isa<fir::ArrayLoadOp>(getSequence().getDefiningOp()))
539cc120e36SShraiysh Vaishay return emitOpError("argument #0 must be result of fir.array_load");
540649439e7SValentin Clement if (!validTypeParams(arrTy, getTypeparams()))
541649439e7SValentin Clement return emitOpError("invalid type parameters");
54234d6c182SEric Schweitz return mlir::success();
54334d6c182SEric Schweitz }
54434d6c182SEric Schweitz
54534d6c182SEric Schweitz //===----------------------------------------------------------------------===//
546f254a8efSValentin Clement // ArrayAccessOp
547f254a8efSValentin Clement //===----------------------------------------------------------------------===//
548f254a8efSValentin Clement
verify()549de8a65f7SEric Schweitz mlir::LogicalResult fir::ArrayAccessOp::verify() {
550149ad3d5SShraiysh Vaishay auto arrTy = getSequence().getType().cast<fir::SequenceType>();
551149ad3d5SShraiysh Vaishay std::size_t indSize = getIndices().size();
552f254a8efSValentin Clement if (indSize < arrTy.getDimension())
553cc120e36SShraiysh Vaishay return emitOpError("number of indices != dimension of array");
554f254a8efSValentin Clement if (indSize == arrTy.getDimension() &&
555149ad3d5SShraiysh Vaishay getElement().getType() != fir::ReferenceType::get(arrTy.getEleTy()))
556cc120e36SShraiysh Vaishay return emitOpError("return type does not match array");
557cc120e36SShraiysh Vaishay mlir::Type ty = validArraySubobject(*this);
558cc120e36SShraiysh Vaishay if (!ty || fir::ReferenceType::get(ty) != getType())
559cc120e36SShraiysh Vaishay return emitOpError("return type and/or indices do not type check");
560649439e7SValentin Clement if (!validTypeParams(arrTy, getTypeparams()))
561649439e7SValentin Clement return emitOpError("invalid type parameters");
562f254a8efSValentin Clement return mlir::success();
563f254a8efSValentin Clement }
564f254a8efSValentin Clement
565f254a8efSValentin Clement //===----------------------------------------------------------------------===//
56634d6c182SEric Schweitz // ArrayUpdateOp
56734d6c182SEric Schweitz //===----------------------------------------------------------------------===//
56834d6c182SEric Schweitz
verify()569de8a65f7SEric Schweitz mlir::LogicalResult fir::ArrayUpdateOp::verify() {
570149ad3d5SShraiysh Vaishay if (fir::isa_ref_type(getMerge().getType()))
571cc120e36SShraiysh Vaishay return emitOpError("does not support reference type for merge");
572149ad3d5SShraiysh Vaishay auto arrTy = getSequence().getType().cast<fir::SequenceType>();
573149ad3d5SShraiysh Vaishay auto indSize = getIndices().size();
57434d6c182SEric Schweitz if (indSize < arrTy.getDimension())
575cc120e36SShraiysh Vaishay return emitOpError("number of indices != dimension of array");
57634d6c182SEric Schweitz if (indSize == arrTy.getDimension() &&
577149ad3d5SShraiysh Vaishay ::adjustedElementType(getMerge().getType()) != arrTy.getEleTy())
578cc120e36SShraiysh Vaishay return emitOpError("merged value does not have element type");
579cc120e36SShraiysh Vaishay auto ty = validArraySubobject(*this);
580149ad3d5SShraiysh Vaishay if (!ty || ty != ::adjustedElementType(getMerge().getType()))
581cc120e36SShraiysh Vaishay return emitOpError("merged value and/or indices do not type check");
582649439e7SValentin Clement if (!validTypeParams(arrTy, getTypeparams()))
583649439e7SValentin Clement return emitOpError("invalid type parameters");
58434d6c182SEric Schweitz return mlir::success();
58534d6c182SEric Schweitz }
58634d6c182SEric Schweitz
58734d6c182SEric Schweitz //===----------------------------------------------------------------------===//
588dc4d94e6SJean Perier // ArrayModifyOp
589dc4d94e6SJean Perier //===----------------------------------------------------------------------===//
590dc4d94e6SJean Perier
verify()591de8a65f7SEric Schweitz mlir::LogicalResult fir::ArrayModifyOp::verify() {
592149ad3d5SShraiysh Vaishay auto arrTy = getSequence().getType().cast<fir::SequenceType>();
593149ad3d5SShraiysh Vaishay auto indSize = getIndices().size();
594dc4d94e6SJean Perier if (indSize < arrTy.getDimension())
595cc120e36SShraiysh Vaishay return emitOpError("number of indices must match array dimension");
596dc4d94e6SJean Perier return mlir::success();
597dc4d94e6SJean Perier }
598dc4d94e6SJean Perier
599dc4d94e6SJean Perier //===----------------------------------------------------------------------===//
600bc034238SEric Schweitz // BoxAddrOp
601bc034238SEric Schweitz //===----------------------------------------------------------------------===//
602bc034238SEric Schweitz
fold(llvm::ArrayRef<mlir::Attribute> opnds)603bc034238SEric Schweitz mlir::OpFoldResult fir::BoxAddrOp::fold(llvm::ArrayRef<mlir::Attribute> opnds) {
604ab8e1e6eSValentin Clement if (auto *v = getVal().getDefiningOp()) {
605de8a65f7SEric Schweitz if (auto box = mlir::dyn_cast<fir::EmboxOp>(v)) {
606ab8e1e6eSValentin Clement if (!box.getSlice()) // Fold only if not sliced
607149ad3d5SShraiysh Vaishay return box.getMemref();
608ab8e1e6eSValentin Clement }
609de8a65f7SEric Schweitz if (auto box = mlir::dyn_cast<fir::EmboxCharOp>(v))
610149ad3d5SShraiysh Vaishay return box.getMemref();
611bc034238SEric Schweitz }
612bc034238SEric Schweitz return {};
613bc034238SEric Schweitz }
614bc034238SEric Schweitz
615bc034238SEric Schweitz //===----------------------------------------------------------------------===//
616bc034238SEric Schweitz // BoxCharLenOp
617bc034238SEric Schweitz //===----------------------------------------------------------------------===//
618bc034238SEric Schweitz
619bc034238SEric Schweitz mlir::OpFoldResult
fold(llvm::ArrayRef<mlir::Attribute> opnds)620bc034238SEric Schweitz fir::BoxCharLenOp::fold(llvm::ArrayRef<mlir::Attribute> opnds) {
621149ad3d5SShraiysh Vaishay if (auto v = getVal().getDefiningOp()) {
622de8a65f7SEric Schweitz if (auto box = mlir::dyn_cast<fir::EmboxCharOp>(v))
623149ad3d5SShraiysh Vaishay return box.getLen();
624bc034238SEric Schweitz }
625bc034238SEric Schweitz return {};
626bc034238SEric Schweitz }
627bc034238SEric Schweitz
628bc034238SEric Schweitz //===----------------------------------------------------------------------===//
62957f536a4SjeanPerier // BoxDimsOp
63057f536a4SjeanPerier //===----------------------------------------------------------------------===//
63157f536a4SjeanPerier
63257f536a4SjeanPerier /// Get the result types packed in a tuple tuple
getTupleType()63357f536a4SjeanPerier mlir::Type fir::BoxDimsOp::getTupleType() {
63457f536a4SjeanPerier // note: triple, but 4 is nearest power of 2
635067312d2SValentin Clement llvm::SmallVector<mlir::Type> triple{
63657f536a4SjeanPerier getResult(0).getType(), getResult(1).getType(), getResult(2).getType()};
6371b97cdf8SRiver Riddle return mlir::TupleType::get(getContext(), triple);
63857f536a4SjeanPerier }
63957f536a4SjeanPerier
64057f536a4SjeanPerier //===----------------------------------------------------------------------===//
64157f536a4SjeanPerier // CallOp
64257f536a4SjeanPerier //===----------------------------------------------------------------------===//
64357f536a4SjeanPerier
getFunctionType()6440b785a46SEric Schweitz mlir::FunctionType fir::CallOp::getFunctionType() {
6450b785a46SEric Schweitz return mlir::FunctionType::get(getContext(), getOperandTypes(),
6460b785a46SEric Schweitz getResultTypes());
6470b785a46SEric Schweitz }
6480b785a46SEric Schweitz
print(mlir::OpAsmPrinter & p)649cc120e36SShraiysh Vaishay void fir::CallOp::print(mlir::OpAsmPrinter &p) {
650c82fb16fSKazu Hirata bool isDirect = getCallee().has_value();
651c41b16c2SMehdi Amini p << ' ';
65257f536a4SjeanPerier if (isDirect)
653009ab172SKazu Hirata p << *getCallee();
65457f536a4SjeanPerier else
655cc120e36SShraiysh Vaishay p << getOperand(0);
656cc120e36SShraiysh Vaishay p << '(' << (*this)->getOperands().drop_front(isDirect ? 0 : 1) << ')';
657cc120e36SShraiysh Vaishay p.printOptionalAttrDict((*this)->getAttrs(),
6582d4dc1cbSValentin Clement {fir::CallOp::getCalleeAttrNameStr()});
659cc120e36SShraiysh Vaishay auto resultTypes{getResultTypes()};
660de8a65f7SEric Schweitz llvm::SmallVector<mlir::Type> argTypes(
661cc120e36SShraiysh Vaishay llvm::drop_begin(getOperandTypes(), isDirect ? 0 : 1));
662de8a65f7SEric Schweitz p << " : " << mlir::FunctionType::get(getContext(), argTypes, resultTypes);
66357f536a4SjeanPerier }
66457f536a4SjeanPerier
parse(mlir::OpAsmParser & parser,mlir::OperationState & result)665cc120e36SShraiysh Vaishay mlir::ParseResult fir::CallOp::parse(mlir::OpAsmParser &parser,
66657f536a4SjeanPerier mlir::OperationState &result) {
667e13d23bcSMarkus Böck llvm::SmallVector<mlir::OpAsmParser::UnresolvedOperand> operands;
66857f536a4SjeanPerier if (parser.parseOperandList(operands))
66957f536a4SjeanPerier return mlir::failure();
67057f536a4SjeanPerier
6715eae715aSJacques Pienaar mlir::NamedAttrList attrs;
67257f536a4SjeanPerier mlir::SymbolRefAttr funcAttr;
67357f536a4SjeanPerier bool isDirect = operands.empty();
67457f536a4SjeanPerier if (isDirect)
6752d4dc1cbSValentin Clement if (parser.parseAttribute(funcAttr, fir::CallOp::getCalleeAttrNameStr(),
6762d4dc1cbSValentin Clement attrs))
67757f536a4SjeanPerier return mlir::failure();
67857f536a4SjeanPerier
679de8a65f7SEric Schweitz mlir::Type type;
68057f536a4SjeanPerier if (parser.parseOperandList(operands, mlir::OpAsmParser::Delimiter::Paren) ||
68157f536a4SjeanPerier parser.parseOptionalAttrDict(attrs) || parser.parseColon() ||
68257f536a4SjeanPerier parser.parseType(type))
68357f536a4SjeanPerier return mlir::failure();
68457f536a4SjeanPerier
68557f536a4SjeanPerier auto funcType = type.dyn_cast<mlir::FunctionType>();
68657f536a4SjeanPerier if (!funcType)
68757f536a4SjeanPerier return parser.emitError(parser.getNameLoc(), "expected function type");
68857f536a4SjeanPerier if (isDirect) {
68957f536a4SjeanPerier if (parser.resolveOperands(operands, funcType.getInputs(),
69057f536a4SjeanPerier parser.getNameLoc(), result.operands))
69157f536a4SjeanPerier return mlir::failure();
69257f536a4SjeanPerier } else {
69357f536a4SjeanPerier auto funcArgs =
694e13d23bcSMarkus Böck llvm::ArrayRef<mlir::OpAsmParser::UnresolvedOperand>(operands)
695e13d23bcSMarkus Böck .drop_front();
69657f536a4SjeanPerier if (parser.resolveOperand(operands[0], funcType, result.operands) ||
69757f536a4SjeanPerier parser.resolveOperands(funcArgs, funcType.getInputs(),
6980b785a46SEric Schweitz parser.getNameLoc(), result.operands))
69957f536a4SjeanPerier return mlir::failure();
70057f536a4SjeanPerier }
70157f536a4SjeanPerier result.addTypes(funcType.getResults());
70257f536a4SjeanPerier result.attributes = attrs;
70357f536a4SjeanPerier return mlir::success();
70457f536a4SjeanPerier }
70557f536a4SjeanPerier
build(mlir::OpBuilder & builder,mlir::OperationState & result,mlir::func::FuncOp callee,mlir::ValueRange operands)706576301d9SEric Schweitz void fir::CallOp::build(mlir::OpBuilder &builder, mlir::OperationState &result,
70758ceae95SRiver Riddle mlir::func::FuncOp callee, mlir::ValueRange operands) {
708576301d9SEric Schweitz result.addOperands(operands);
709de8a65f7SEric Schweitz result.addAttribute(getCalleeAttrNameStr(), mlir::SymbolRefAttr::get(callee));
7104a3460a7SRiver Riddle result.addTypes(callee.getFunctionType().getResults());
711576301d9SEric Schweitz }
712576301d9SEric Schweitz
build(mlir::OpBuilder & builder,mlir::OperationState & result,mlir::SymbolRefAttr callee,llvm::ArrayRef<mlir::Type> results,mlir::ValueRange operands)713576301d9SEric Schweitz void fir::CallOp::build(mlir::OpBuilder &builder, mlir::OperationState &result,
714576301d9SEric Schweitz mlir::SymbolRefAttr callee,
715576301d9SEric Schweitz llvm::ArrayRef<mlir::Type> results,
716576301d9SEric Schweitz mlir::ValueRange operands) {
717576301d9SEric Schweitz result.addOperands(operands);
718b0eef1eeSValentin Clement if (callee)
7193012f35fSJacques Pienaar result.addAttribute(getCalleeAttrNameStr(), callee);
720576301d9SEric Schweitz result.addTypes(results);
721576301d9SEric Schweitz }
722576301d9SEric Schweitz
72357f536a4SjeanPerier //===----------------------------------------------------------------------===//
724649439e7SValentin Clement // CharConvertOp
725649439e7SValentin Clement //===----------------------------------------------------------------------===//
726649439e7SValentin Clement
verify()727649439e7SValentin Clement mlir::LogicalResult fir::CharConvertOp::verify() {
728649439e7SValentin Clement auto unwrap = [&](mlir::Type t) {
729649439e7SValentin Clement t = fir::unwrapSequenceType(fir::dyn_cast_ptrEleTy(t));
730649439e7SValentin Clement return t.dyn_cast<fir::CharacterType>();
731649439e7SValentin Clement };
732649439e7SValentin Clement auto inTy = unwrap(getFrom().getType());
733649439e7SValentin Clement auto outTy = unwrap(getTo().getType());
734649439e7SValentin Clement if (!(inTy && outTy))
735649439e7SValentin Clement return emitOpError("not a reference to a character");
736649439e7SValentin Clement if (inTy.getFKind() == outTy.getFKind())
737649439e7SValentin Clement return emitOpError("buffers must have different KIND values");
738649439e7SValentin Clement return mlir::success();
739649439e7SValentin Clement }
740649439e7SValentin Clement
741649439e7SValentin Clement //===----------------------------------------------------------------------===//
7422155aa79SValentin Clement // CmpOp
74357f536a4SjeanPerier //===----------------------------------------------------------------------===//
74457f536a4SjeanPerier
74557f536a4SjeanPerier template <typename OPTY>
printCmpOp(mlir::OpAsmPrinter & p,OPTY op)746de8a65f7SEric Schweitz static void printCmpOp(mlir::OpAsmPrinter &p, OPTY op) {
747c41b16c2SMehdi Amini p << ' ';
748a54f4eaeSMogball auto predSym = mlir::arith::symbolizeCmpFPredicate(
749a1eb1544SChristian Sigg op->template getAttrOfType<mlir::IntegerAttr>(
750a1eb1544SChristian Sigg OPTY::getPredicateAttrName())
75157f536a4SjeanPerier .getInt());
752c82fb16fSKazu Hirata assert(predSym.has_value() && "invalid symbol value for predicate");
753*993625beSKazu Hirata p << '"' << mlir::arith::stringifyCmpFPredicate(predSym.value()) << '"'
7543b7c3a65SKazu Hirata << ", ";
755149ad3d5SShraiysh Vaishay p.printOperand(op.getLhs());
75657f536a4SjeanPerier p << ", ";
757149ad3d5SShraiysh Vaishay p.printOperand(op.getRhs());
7585077d42cSEric Schweitz p.printOptionalAttrDict(op->getAttrs(),
75957f536a4SjeanPerier /*elidedAttrs=*/{OPTY::getPredicateAttrName()});
760149ad3d5SShraiysh Vaishay p << " : " << op.getLhs().getType();
76157f536a4SjeanPerier }
76257f536a4SjeanPerier
76357f536a4SjeanPerier template <typename OPTY>
parseCmpOp(mlir::OpAsmParser & parser,mlir::OperationState & result)76457f536a4SjeanPerier static mlir::ParseResult parseCmpOp(mlir::OpAsmParser &parser,
76557f536a4SjeanPerier mlir::OperationState &result) {
766e13d23bcSMarkus Böck llvm::SmallVector<mlir::OpAsmParser::UnresolvedOperand> ops;
7675eae715aSJacques Pienaar mlir::NamedAttrList attrs;
76857f536a4SjeanPerier mlir::Attribute predicateNameAttr;
76957f536a4SjeanPerier mlir::Type type;
77057f536a4SjeanPerier if (parser.parseAttribute(predicateNameAttr, OPTY::getPredicateAttrName(),
77157f536a4SjeanPerier attrs) ||
77257f536a4SjeanPerier parser.parseComma() || parser.parseOperandList(ops, 2) ||
77357f536a4SjeanPerier parser.parseOptionalAttrDict(attrs) || parser.parseColonType(type) ||
77457f536a4SjeanPerier parser.resolveOperands(ops, type, result.operands))
775de8a65f7SEric Schweitz return mlir::failure();
77657f536a4SjeanPerier
77757f536a4SjeanPerier if (!predicateNameAttr.isa<mlir::StringAttr>())
77857f536a4SjeanPerier return parser.emitError(parser.getNameLoc(),
77957f536a4SjeanPerier "expected string comparison predicate attribute");
78057f536a4SjeanPerier
78157f536a4SjeanPerier // Rewrite string attribute to an enum value.
78257f536a4SjeanPerier llvm::StringRef predicateName =
78357f536a4SjeanPerier predicateNameAttr.cast<mlir::StringAttr>().getValue();
7842155aa79SValentin Clement auto predicate = fir::CmpcOp::getPredicateByName(predicateName);
78557f536a4SjeanPerier auto builder = parser.getBuilder();
78657f536a4SjeanPerier mlir::Type i1Type = builder.getI1Type();
7875eae715aSJacques Pienaar attrs.set(OPTY::getPredicateAttrName(),
788de8a65f7SEric Schweitz builder.getI64IntegerAttr(static_cast<std::int64_t>(predicate)));
78957f536a4SjeanPerier result.attributes = attrs;
79057f536a4SjeanPerier result.addTypes({i1Type});
791de8a65f7SEric Schweitz return mlir::success();
79257f536a4SjeanPerier }
79357f536a4SjeanPerier
79457f536a4SjeanPerier //===----------------------------------------------------------------------===//
79557f536a4SjeanPerier // CmpcOp
79657f536a4SjeanPerier //===----------------------------------------------------------------------===//
79757f536a4SjeanPerier
buildCmpCOp(mlir::OpBuilder & builder,mlir::OperationState & result,mlir::arith::CmpFPredicate predicate,mlir::Value lhs,mlir::Value rhs)798de8a65f7SEric Schweitz void fir::buildCmpCOp(mlir::OpBuilder &builder, mlir::OperationState &result,
799de8a65f7SEric Schweitz mlir::arith::CmpFPredicate predicate, mlir::Value lhs,
800de8a65f7SEric Schweitz mlir::Value rhs) {
80157f536a4SjeanPerier result.addOperands({lhs, rhs});
802bb1d976fSAlex Zinenko result.types.push_back(builder.getI1Type());
80357f536a4SjeanPerier result.addAttribute(
80457f536a4SjeanPerier fir::CmpcOp::getPredicateAttrName(),
805de8a65f7SEric Schweitz builder.getI64IntegerAttr(static_cast<std::int64_t>(predicate)));
80657f536a4SjeanPerier }
80757f536a4SjeanPerier
808a54f4eaeSMogball mlir::arith::CmpFPredicate
getPredicateByName(llvm::StringRef name)809a54f4eaeSMogball fir::CmpcOp::getPredicateByName(llvm::StringRef name) {
810a54f4eaeSMogball auto pred = mlir::arith::symbolizeCmpFPredicate(name);
811c82fb16fSKazu Hirata assert(pred.has_value() && "invalid predicate name");
812*993625beSKazu Hirata return pred.value();
8132155aa79SValentin Clement }
8142155aa79SValentin Clement
print(mlir::OpAsmPrinter & p)815de8a65f7SEric Schweitz void fir::CmpcOp::print(mlir::OpAsmPrinter &p) { printCmpOp(p, *this); }
81657f536a4SjeanPerier
parse(mlir::OpAsmParser & parser,mlir::OperationState & result)817de8a65f7SEric Schweitz mlir::ParseResult fir::CmpcOp::parse(mlir::OpAsmParser &parser,
81857f536a4SjeanPerier mlir::OperationState &result) {
81957f536a4SjeanPerier return parseCmpOp<fir::CmpcOp>(parser, result);
82057f536a4SjeanPerier }
82157f536a4SjeanPerier
82257f536a4SjeanPerier //===----------------------------------------------------------------------===//
823633f70f7SValentin Clement // ConstcOp
824633f70f7SValentin Clement //===----------------------------------------------------------------------===//
825633f70f7SValentin Clement
parse(mlir::OpAsmParser & parser,mlir::OperationState & result)826de8a65f7SEric Schweitz mlir::ParseResult fir::ConstcOp::parse(mlir::OpAsmParser &parser,
827633f70f7SValentin Clement mlir::OperationState &result) {
828633f70f7SValentin Clement fir::RealAttr realp;
829633f70f7SValentin Clement fir::RealAttr imagp;
830633f70f7SValentin Clement mlir::Type type;
831633f70f7SValentin Clement if (parser.parseLParen() ||
832be80c6d1SValentin Clement parser.parseAttribute(realp, fir::ConstcOp::getRealAttrName(),
833633f70f7SValentin Clement result.attributes) ||
834633f70f7SValentin Clement parser.parseComma() ||
835be80c6d1SValentin Clement parser.parseAttribute(imagp, fir::ConstcOp::getImagAttrName(),
836633f70f7SValentin Clement result.attributes) ||
837633f70f7SValentin Clement parser.parseRParen() || parser.parseColonType(type) ||
838633f70f7SValentin Clement parser.addTypesToList(type, result.types))
839633f70f7SValentin Clement return mlir::failure();
840633f70f7SValentin Clement return mlir::success();
841633f70f7SValentin Clement }
842633f70f7SValentin Clement
print(mlir::OpAsmPrinter & p)843de8a65f7SEric Schweitz void fir::ConstcOp::print(mlir::OpAsmPrinter &p) {
844ca379554SDiana Picus p << '(';
845be80c6d1SValentin Clement p << getOperation()->getAttr(fir::ConstcOp::getRealAttrName()) << ", ";
846be80c6d1SValentin Clement p << getOperation()->getAttr(fir::ConstcOp::getImagAttrName()) << ") : ";
847cc120e36SShraiysh Vaishay p.printType(getType());
848633f70f7SValentin Clement }
849633f70f7SValentin Clement
verify()850de8a65f7SEric Schweitz mlir::LogicalResult fir::ConstcOp::verify() {
851cc120e36SShraiysh Vaishay if (!getType().isa<fir::ComplexType>())
852cc120e36SShraiysh Vaishay return emitOpError("must be a !fir.complex type");
853633f70f7SValentin Clement return mlir::success();
854633f70f7SValentin Clement }
855633f70f7SValentin Clement
856633f70f7SValentin Clement //===----------------------------------------------------------------------===//
857bc034238SEric Schweitz // ConvertOp
858bc034238SEric Schweitz //===----------------------------------------------------------------------===//
859bc034238SEric Schweitz
getCanonicalizationPatterns(mlir::RewritePatternSet & results,mlir::MLIRContext * context)860de8a65f7SEric Schweitz void fir::ConvertOp::getCanonicalizationPatterns(
861de8a65f7SEric Schweitz mlir::RewritePatternSet &results, mlir::MLIRContext *context) {
8625754bae4SValentin Clement results.insert<ConvertConvertOptPattern, ConvertAscendingIndexOptPattern,
8635754bae4SValentin Clement ConvertDescendingIndexOptPattern, RedundantConvertOptPattern,
8645754bae4SValentin Clement CombineConvertOptPattern, CombineConvertTruncOptPattern,
8655754bae4SValentin Clement ForwardConstantConvertPattern>(context);
866c3abfe42SEric Schweitz }
8670b785a46SEric Schweitz
fold(llvm::ArrayRef<mlir::Attribute> opnds)868bc034238SEric Schweitz mlir::OpFoldResult fir::ConvertOp::fold(llvm::ArrayRef<mlir::Attribute> opnds) {
869149ad3d5SShraiysh Vaishay if (getValue().getType() == getType())
870149ad3d5SShraiysh Vaishay return getValue();
871de8a65f7SEric Schweitz if (matchPattern(getValue(), mlir::m_Op<fir::ConvertOp>())) {
872de8a65f7SEric Schweitz auto inner = mlir::cast<fir::ConvertOp>(getValue().getDefiningOp());
873bc034238SEric Schweitz // (convert (convert 'a : logical -> i1) : i1 -> logical) ==> forward 'a
874bc034238SEric Schweitz if (auto toTy = getType().dyn_cast<fir::LogicalType>())
875149ad3d5SShraiysh Vaishay if (auto fromTy = inner.getValue().getType().dyn_cast<fir::LogicalType>())
876bc034238SEric Schweitz if (inner.getType().isa<mlir::IntegerType>() && (toTy == fromTy))
877149ad3d5SShraiysh Vaishay return inner.getValue();
878bc034238SEric Schweitz // (convert (convert 'a : i1 -> logical) : logical -> i1) ==> forward 'a
879bc034238SEric Schweitz if (auto toTy = getType().dyn_cast<mlir::IntegerType>())
880149ad3d5SShraiysh Vaishay if (auto fromTy =
881149ad3d5SShraiysh Vaishay inner.getValue().getType().dyn_cast<mlir::IntegerType>())
882bc034238SEric Schweitz if (inner.getType().isa<fir::LogicalType>() && (toTy == fromTy) &&
883bc034238SEric Schweitz (fromTy.getWidth() == 1))
884149ad3d5SShraiysh Vaishay return inner.getValue();
885bc034238SEric Schweitz }
886bc034238SEric Schweitz return {};
887bc034238SEric Schweitz }
888bc034238SEric Schweitz
isIntegerCompatible(mlir::Type ty)889bc034238SEric Schweitz bool fir::ConvertOp::isIntegerCompatible(mlir::Type ty) {
890de8a65f7SEric Schweitz return ty.isa<mlir::IntegerType, mlir::IndexType, fir::IntegerType,
891de8a65f7SEric Schweitz fir::LogicalType>();
892bc034238SEric Schweitz }
893bc034238SEric Schweitz
isFloatCompatible(mlir::Type ty)894bc034238SEric Schweitz bool fir::ConvertOp::isFloatCompatible(mlir::Type ty) {
895de8a65f7SEric Schweitz return ty.isa<mlir::FloatType, fir::RealType>();
896bc034238SEric Schweitz }
897bc034238SEric Schweitz
isPointerCompatible(mlir::Type ty)898bc034238SEric Schweitz bool fir::ConvertOp::isPointerCompatible(mlir::Type ty) {
899de8a65f7SEric Schweitz return ty.isa<fir::ReferenceType, fir::PointerType, fir::HeapType,
900de8a65f7SEric Schweitz fir::LLVMPointerType, mlir::MemRefType, mlir::FunctionType,
901de8a65f7SEric Schweitz fir::TypeDescType>();
902bc034238SEric Schweitz }
903bc034238SEric Schweitz
verify()904de8a65f7SEric Schweitz mlir::LogicalResult fir::ConvertOp::verify() {
905149ad3d5SShraiysh Vaishay auto inType = getValue().getType();
906cc120e36SShraiysh Vaishay auto outType = getType();
907633f70f7SValentin Clement if (inType == outType)
908633f70f7SValentin Clement return mlir::success();
909cc120e36SShraiysh Vaishay if ((isPointerCompatible(inType) && isPointerCompatible(outType)) ||
910cc120e36SShraiysh Vaishay (isIntegerCompatible(inType) && isIntegerCompatible(outType)) ||
911cc120e36SShraiysh Vaishay (isIntegerCompatible(inType) && isFloatCompatible(outType)) ||
912cc120e36SShraiysh Vaishay (isFloatCompatible(inType) && isIntegerCompatible(outType)) ||
913cc120e36SShraiysh Vaishay (isFloatCompatible(inType) && isFloatCompatible(outType)) ||
914cc120e36SShraiysh Vaishay (isIntegerCompatible(inType) && isPointerCompatible(outType)) ||
915cc120e36SShraiysh Vaishay (isPointerCompatible(inType) && isIntegerCompatible(outType)) ||
916633f70f7SValentin Clement (inType.isa<fir::BoxType>() && outType.isa<fir::BoxType>()) ||
9175754bae4SValentin Clement (inType.isa<fir::BoxProcType>() && outType.isa<fir::BoxProcType>()) ||
918633f70f7SValentin Clement (fir::isa_complex(inType) && fir::isa_complex(outType)))
919633f70f7SValentin Clement return mlir::success();
920cc120e36SShraiysh Vaishay return emitOpError("invalid type conversion");
921633f70f7SValentin Clement }
922633f70f7SValentin Clement
923bc034238SEric Schweitz //===----------------------------------------------------------------------===//
924bc034238SEric Schweitz // CoordinateOp
925bc034238SEric Schweitz //===----------------------------------------------------------------------===//
926bc034238SEric Schweitz
print(mlir::OpAsmPrinter & p)927de8a65f7SEric Schweitz void fir::CoordinateOp::print(mlir::OpAsmPrinter &p) {
928149ad3d5SShraiysh Vaishay p << ' ' << getRef() << ", " << getCoor();
929cc120e36SShraiysh Vaishay p.printOptionalAttrDict((*this)->getAttrs(), /*elideAttrs=*/{"baseType"});
9300b785a46SEric Schweitz p << " : ";
931cc120e36SShraiysh Vaishay p.printFunctionalType(getOperandTypes(), (*this)->getResultTypes());
9320b785a46SEric Schweitz }
933bc034238SEric Schweitz
parse(mlir::OpAsmParser & parser,mlir::OperationState & result)934de8a65f7SEric Schweitz mlir::ParseResult fir::CoordinateOp::parse(mlir::OpAsmParser &parser,
9350b785a46SEric Schweitz mlir::OperationState &result) {
936e13d23bcSMarkus Böck mlir::OpAsmParser::UnresolvedOperand memref;
9370b785a46SEric Schweitz if (parser.parseOperand(memref) || parser.parseComma())
9380b785a46SEric Schweitz return mlir::failure();
939e13d23bcSMarkus Böck llvm::SmallVector<mlir::OpAsmParser::UnresolvedOperand> coorOperands;
9400b785a46SEric Schweitz if (parser.parseOperandList(coorOperands))
9410b785a46SEric Schweitz return mlir::failure();
942e13d23bcSMarkus Böck llvm::SmallVector<mlir::OpAsmParser::UnresolvedOperand> allOperands;
9430b785a46SEric Schweitz allOperands.push_back(memref);
9440b785a46SEric Schweitz allOperands.append(coorOperands.begin(), coorOperands.end());
945bc034238SEric Schweitz mlir::FunctionType funcTy;
9460b785a46SEric Schweitz auto loc = parser.getCurrentLocation();
9470b785a46SEric Schweitz if (parser.parseOptionalAttrDict(result.attributes) ||
9480b785a46SEric Schweitz parser.parseColonType(funcTy) ||
9490b785a46SEric Schweitz parser.resolveOperands(allOperands, funcTy.getInputs(), loc,
95027478872SChris Lattner result.operands) ||
95127478872SChris Lattner parser.addTypesToList(funcTy.getResults(), result.types))
952de8a65f7SEric Schweitz return mlir::failure();
9530b785a46SEric Schweitz result.addAttribute("baseType", mlir::TypeAttr::get(funcTy.getInput(0)));
9540b785a46SEric Schweitz return mlir::success();
955bc034238SEric Schweitz }
956bc034238SEric Schweitz
verify()957de8a65f7SEric Schweitz mlir::LogicalResult fir::CoordinateOp::verify() {
958c67a8744SValentin Clement const mlir::Type refTy = getRef().getType();
9590b785a46SEric Schweitz if (fir::isa_ref_type(refTy)) {
9600b785a46SEric Schweitz auto eleTy = fir::dyn_cast_ptrEleTy(refTy);
9610b785a46SEric Schweitz if (auto arrTy = eleTy.dyn_cast<fir::SequenceType>()) {
9620b785a46SEric Schweitz if (arrTy.hasUnknownShape())
963cc120e36SShraiysh Vaishay return emitOpError("cannot find coordinate in unknown shape");
9640b785a46SEric Schweitz if (arrTy.getConstantRows() < arrTy.getDimension() - 1)
965cc120e36SShraiysh Vaishay return emitOpError("cannot find coordinate with unknown extents");
966bc034238SEric Schweitz }
9670b785a46SEric Schweitz if (!(fir::isa_aggregate(eleTy) || fir::isa_complex(eleTy) ||
9680b785a46SEric Schweitz fir::isa_char_string(eleTy)))
969c67a8744SValentin Clement return emitOpError("cannot apply to this element type");
970bc034238SEric Schweitz }
971c67a8744SValentin Clement auto eleTy = fir::dyn_cast_ptrOrBoxEleTy(refTy);
972c67a8744SValentin Clement unsigned dimension = 0;
973c67a8744SValentin Clement const unsigned numCoors = getCoor().size();
974c67a8744SValentin Clement for (auto coorOperand : llvm::enumerate(getCoor())) {
975c67a8744SValentin Clement auto co = coorOperand.value();
976c67a8744SValentin Clement if (dimension == 0 && eleTy.isa<fir::SequenceType>()) {
977c67a8744SValentin Clement dimension = eleTy.cast<fir::SequenceType>().getDimension();
978c67a8744SValentin Clement if (dimension == 0)
979c67a8744SValentin Clement return emitOpError("cannot apply to array of unknown rank");
980c67a8744SValentin Clement }
981c67a8744SValentin Clement if (auto *defOp = co.getDefiningOp()) {
982c67a8744SValentin Clement if (auto index = mlir::dyn_cast<fir::LenParamIndexOp>(defOp)) {
983c67a8744SValentin Clement // Recovering a LEN type parameter only makes sense from a boxed
984c67a8744SValentin Clement // value. For a bare reference, the LEN type parameters must be
985c67a8744SValentin Clement // passed as additional arguments to `index`.
986c67a8744SValentin Clement if (refTy.isa<fir::BoxType>()) {
987c67a8744SValentin Clement if (coorOperand.index() != numCoors - 1)
988cc120e36SShraiysh Vaishay return emitOpError("len_param_index must be last argument");
989c67a8744SValentin Clement if (getNumOperands() != 2)
990c67a8744SValentin Clement return emitOpError("too many operands for len_param_index case");
991c67a8744SValentin Clement }
992c67a8744SValentin Clement if (eleTy != index.getOnType())
993c67a8744SValentin Clement emitOpError(
994c67a8744SValentin Clement "len_param_index type not compatible with reference type");
995c67a8744SValentin Clement return mlir::success();
996c67a8744SValentin Clement } else if (auto index = mlir::dyn_cast<fir::FieldIndexOp>(defOp)) {
997c67a8744SValentin Clement if (eleTy != index.getOnType())
998c67a8744SValentin Clement emitOpError("field_index type not compatible with reference type");
999c67a8744SValentin Clement if (auto recTy = eleTy.dyn_cast<fir::RecordType>()) {
1000c67a8744SValentin Clement eleTy = recTy.getType(index.getFieldName());
1001c67a8744SValentin Clement continue;
1002c67a8744SValentin Clement }
1003c67a8744SValentin Clement return emitOpError("field_index not applied to !fir.type");
1004c67a8744SValentin Clement }
1005c67a8744SValentin Clement }
1006c67a8744SValentin Clement if (dimension) {
1007c67a8744SValentin Clement if (--dimension == 0)
1008c67a8744SValentin Clement eleTy = eleTy.cast<fir::SequenceType>().getEleTy();
1009c67a8744SValentin Clement } else {
1010c67a8744SValentin Clement if (auto t = eleTy.dyn_cast<mlir::TupleType>()) {
1011c67a8744SValentin Clement // FIXME: Generally, we don't know which field of the tuple is being
1012c67a8744SValentin Clement // referred to unless the operand is a constant. Just assume everything
1013c67a8744SValentin Clement // is good in the tuple case for now.
1014c67a8744SValentin Clement return mlir::success();
1015c67a8744SValentin Clement } else if (auto t = eleTy.dyn_cast<fir::RecordType>()) {
1016c67a8744SValentin Clement // FIXME: This is the same as the tuple case.
1017c67a8744SValentin Clement return mlir::success();
1018c67a8744SValentin Clement } else if (auto t = eleTy.dyn_cast<fir::ComplexType>()) {
1019c67a8744SValentin Clement eleTy = t.getElementType();
1020c67a8744SValentin Clement } else if (auto t = eleTy.dyn_cast<mlir::ComplexType>()) {
1021c67a8744SValentin Clement eleTy = t.getElementType();
1022c67a8744SValentin Clement } else if (auto t = eleTy.dyn_cast<fir::CharacterType>()) {
1023c67a8744SValentin Clement if (t.getLen() == fir::CharacterType::singleton())
1024c67a8744SValentin Clement return emitOpError("cannot apply to character singleton");
1025c67a8744SValentin Clement eleTy = fir::CharacterType::getSingleton(t.getContext(), t.getFKind());
1026c67a8744SValentin Clement if (fir::unwrapRefType(getType()) != eleTy)
1027c67a8744SValentin Clement return emitOpError("character type mismatch");
1028c67a8744SValentin Clement } else {
1029c67a8744SValentin Clement return emitOpError("invalid parameters (too many)");
1030c67a8744SValentin Clement }
1031c67a8744SValentin Clement }
10320b785a46SEric Schweitz }
10330b785a46SEric Schweitz return mlir::success();
1034bc034238SEric Schweitz }
1035bc034238SEric Schweitz
1036bc034238SEric Schweitz //===----------------------------------------------------------------------===//
103757f536a4SjeanPerier // DispatchOp
103857f536a4SjeanPerier //===----------------------------------------------------------------------===//
103957f536a4SjeanPerier
getFunctionType()104057f536a4SjeanPerier mlir::FunctionType fir::DispatchOp::getFunctionType() {
10410b785a46SEric Schweitz return mlir::FunctionType::get(getContext(), getOperandTypes(),
10420b785a46SEric Schweitz getResultTypes());
104357f536a4SjeanPerier }
104457f536a4SjeanPerier
parse(mlir::OpAsmParser & parser,mlir::OperationState & result)1045de8a65f7SEric Schweitz mlir::ParseResult fir::DispatchOp::parse(mlir::OpAsmParser &parser,
1046633f70f7SValentin Clement mlir::OperationState &result) {
1047633f70f7SValentin Clement mlir::FunctionType calleeType;
1048e13d23bcSMarkus Böck llvm::SmallVector<mlir::OpAsmParser::UnresolvedOperand> operands;
1049633f70f7SValentin Clement auto calleeLoc = parser.getNameLoc();
1050633f70f7SValentin Clement llvm::StringRef calleeName;
1051633f70f7SValentin Clement if (failed(parser.parseOptionalKeyword(&calleeName))) {
1052633f70f7SValentin Clement mlir::StringAttr calleeAttr;
10533012f35fSJacques Pienaar if (parser.parseAttribute(calleeAttr,
10543012f35fSJacques Pienaar fir::DispatchOp::getMethodAttrNameStr(),
1055633f70f7SValentin Clement result.attributes))
1056633f70f7SValentin Clement return mlir::failure();
1057633f70f7SValentin Clement } else {
10583012f35fSJacques Pienaar result.addAttribute(fir::DispatchOp::getMethodAttrNameStr(),
1059633f70f7SValentin Clement parser.getBuilder().getStringAttr(calleeName));
1060633f70f7SValentin Clement }
1061633f70f7SValentin Clement if (parser.parseOperandList(operands, mlir::OpAsmParser::Delimiter::Paren) ||
1062633f70f7SValentin Clement parser.parseOptionalAttrDict(result.attributes) ||
1063633f70f7SValentin Clement parser.parseColonType(calleeType) ||
1064633f70f7SValentin Clement parser.addTypesToList(calleeType.getResults(), result.types) ||
1065633f70f7SValentin Clement parser.resolveOperands(operands, calleeType.getInputs(), calleeLoc,
1066633f70f7SValentin Clement result.operands))
1067633f70f7SValentin Clement return mlir::failure();
1068633f70f7SValentin Clement return mlir::success();
1069633f70f7SValentin Clement }
1070633f70f7SValentin Clement
print(mlir::OpAsmPrinter & p)1071de8a65f7SEric Schweitz void fir::DispatchOp::print(mlir::OpAsmPrinter &p) {
1072cc120e36SShraiysh Vaishay p << ' ' << getMethodAttr() << '(';
1073149ad3d5SShraiysh Vaishay p.printOperand(getObject());
1074149ad3d5SShraiysh Vaishay if (!getArgs().empty()) {
1075633f70f7SValentin Clement p << ", ";
1076149ad3d5SShraiysh Vaishay p.printOperands(getArgs());
1077633f70f7SValentin Clement }
1078633f70f7SValentin Clement p << ") : ";
1079cc120e36SShraiysh Vaishay p.printFunctionalType(getOperation()->getOperandTypes(),
1080cc120e36SShraiysh Vaishay getOperation()->getResultTypes());
1081633f70f7SValentin Clement }
1082633f70f7SValentin Clement
108357f536a4SjeanPerier //===----------------------------------------------------------------------===//
108457f536a4SjeanPerier // DispatchTableOp
108557f536a4SjeanPerier //===----------------------------------------------------------------------===//
108657f536a4SjeanPerier
appendTableEntry(mlir::Operation * op)108757f536a4SjeanPerier void fir::DispatchTableOp::appendTableEntry(mlir::Operation *op) {
108857f536a4SjeanPerier assert(mlir::isa<fir::DTEntryOp>(*op) && "operation must be a DTEntryOp");
108957f536a4SjeanPerier auto &block = getBlock();
109057f536a4SjeanPerier block.getOperations().insert(block.end(), op);
109157f536a4SjeanPerier }
109257f536a4SjeanPerier
parse(mlir::OpAsmParser & parser,mlir::OperationState & result)1093de8a65f7SEric Schweitz mlir::ParseResult fir::DispatchTableOp::parse(mlir::OpAsmParser &parser,
1094633f70f7SValentin Clement mlir::OperationState &result) {
1095633f70f7SValentin Clement // Parse the name as a symbol reference attribute.
1096de8a65f7SEric Schweitz mlir::SymbolRefAttr nameAttr;
1097633f70f7SValentin Clement if (parser.parseAttribute(nameAttr, mlir::SymbolTable::getSymbolAttrName(),
1098633f70f7SValentin Clement result.attributes))
1099de8a65f7SEric Schweitz return mlir::failure();
1100633f70f7SValentin Clement
1101633f70f7SValentin Clement // Convert the parsed name attr into a string attr.
1102633f70f7SValentin Clement result.attributes.set(mlir::SymbolTable::getSymbolAttrName(),
1103633f70f7SValentin Clement nameAttr.getRootReference());
1104633f70f7SValentin Clement
1105633f70f7SValentin Clement // Parse the optional table body.
1106633f70f7SValentin Clement mlir::Region *body = result.addRegion();
1107de8a65f7SEric Schweitz mlir::OptionalParseResult parseResult = parser.parseOptionalRegion(*body);
11083b7c3a65SKazu Hirata if (parseResult.hasValue() && failed(*parseResult))
1109633f70f7SValentin Clement return mlir::failure();
1110633f70f7SValentin Clement
1111633f70f7SValentin Clement fir::DispatchTableOp::ensureTerminator(*body, parser.getBuilder(),
1112633f70f7SValentin Clement result.location);
1113633f70f7SValentin Clement return mlir::success();
1114633f70f7SValentin Clement }
1115633f70f7SValentin Clement
print(mlir::OpAsmPrinter & p)1116de8a65f7SEric Schweitz void fir::DispatchTableOp::print(mlir::OpAsmPrinter &p) {
1117de8a65f7SEric Schweitz auto tableName = getOperation()
1118de8a65f7SEric Schweitz ->getAttrOfType<mlir::StringAttr>(
1119de8a65f7SEric Schweitz mlir::SymbolTable::getSymbolAttrName())
1120633f70f7SValentin Clement .getValue();
1121633f70f7SValentin Clement p << " @" << tableName;
1122633f70f7SValentin Clement
1123de8a65f7SEric Schweitz mlir::Region &body = getOperation()->getRegion(0);
11245c36ee8dSMogball if (!body.empty()) {
11255c36ee8dSMogball p << ' ';
1126633f70f7SValentin Clement p.printRegion(body, /*printEntryBlockArgs=*/false,
1127633f70f7SValentin Clement /*printBlockTerminators=*/false);
1128633f70f7SValentin Clement }
11295c36ee8dSMogball }
1130633f70f7SValentin Clement
verify()1131de8a65f7SEric Schweitz mlir::LogicalResult fir::DispatchTableOp::verify() {
1132cc120e36SShraiysh Vaishay for (auto &op : getBlock())
1133de8a65f7SEric Schweitz if (!mlir::isa<fir::DTEntryOp, fir::FirEndOp>(op))
1134633f70f7SValentin Clement return op.emitOpError("dispatch table must contain dt_entry");
1135633f70f7SValentin Clement return mlir::success();
1136633f70f7SValentin Clement }
1137633f70f7SValentin Clement
113857f536a4SjeanPerier //===----------------------------------------------------------------------===//
113957f536a4SjeanPerier // EmboxOp
114057f536a4SjeanPerier //===----------------------------------------------------------------------===//
114157f536a4SjeanPerier
verify()1142de8a65f7SEric Schweitz mlir::LogicalResult fir::EmboxOp::verify() {
1143149ad3d5SShraiysh Vaishay auto eleTy = fir::dyn_cast_ptrEleTy(getMemref().getType());
11440b785a46SEric Schweitz bool isArray = false;
11450b785a46SEric Schweitz if (auto seqTy = eleTy.dyn_cast<fir::SequenceType>()) {
11460b785a46SEric Schweitz eleTy = seqTy.getEleTy();
11470b785a46SEric Schweitz isArray = true;
114857f536a4SjeanPerier }
1149cc120e36SShraiysh Vaishay if (hasLenParams()) {
1150cc120e36SShraiysh Vaishay auto lenPs = numLenParams();
11510b785a46SEric Schweitz if (auto rt = eleTy.dyn_cast<fir::RecordType>()) {
11520b785a46SEric Schweitz if (lenPs != rt.getNumLenParams())
1153cc120e36SShraiysh Vaishay return emitOpError("number of LEN params does not correspond"
11540b785a46SEric Schweitz " to the !fir.type type");
11550b785a46SEric Schweitz } else if (auto strTy = eleTy.dyn_cast<fir::CharacterType>()) {
11560b785a46SEric Schweitz if (strTy.getLen() != fir::CharacterType::unknownLen())
1157cc120e36SShraiysh Vaishay return emitOpError("CHARACTER already has static LEN");
11580b785a46SEric Schweitz } else {
1159cc120e36SShraiysh Vaishay return emitOpError("LEN parameters require CHARACTER or derived type");
116057f536a4SjeanPerier }
1161149ad3d5SShraiysh Vaishay for (auto lp : getTypeparams())
11620b785a46SEric Schweitz if (!fir::isa_integer(lp.getType()))
1163cc120e36SShraiysh Vaishay return emitOpError("LEN parameters must be integral type");
11640b785a46SEric Schweitz }
1165cc120e36SShraiysh Vaishay if (getShape() && !isArray)
1166cc120e36SShraiysh Vaishay return emitOpError("shape must not be provided for a scalar");
1167cc120e36SShraiysh Vaishay if (getSlice() && !isArray)
1168cc120e36SShraiysh Vaishay return emitOpError("slice must not be provided for a scalar");
116957f536a4SjeanPerier return mlir::success();
117057f536a4SjeanPerier }
117157f536a4SjeanPerier
117257f536a4SjeanPerier //===----------------------------------------------------------------------===//
1173633f70f7SValentin Clement // EmboxCharOp
1174633f70f7SValentin Clement //===----------------------------------------------------------------------===//
1175633f70f7SValentin Clement
verify()1176de8a65f7SEric Schweitz mlir::LogicalResult fir::EmboxCharOp::verify() {
1177149ad3d5SShraiysh Vaishay auto eleTy = fir::dyn_cast_ptrEleTy(getMemref().getType());
1178de8a65f7SEric Schweitz if (!eleTy.dyn_cast_or_null<fir::CharacterType>())
1179633f70f7SValentin Clement return mlir::failure();
1180633f70f7SValentin Clement return mlir::success();
1181633f70f7SValentin Clement }
1182633f70f7SValentin Clement
1183633f70f7SValentin Clement //===----------------------------------------------------------------------===//
1184633f70f7SValentin Clement // EmboxProcOp
1185633f70f7SValentin Clement //===----------------------------------------------------------------------===//
1186633f70f7SValentin Clement
verify()1187de8a65f7SEric Schweitz mlir::LogicalResult fir::EmboxProcOp::verify() {
1188633f70f7SValentin Clement // host bindings (optional) must be a reference to a tuple
1189149ad3d5SShraiysh Vaishay if (auto h = getHost()) {
1190de8a65f7SEric Schweitz if (auto r = h.getType().dyn_cast<fir::ReferenceType>())
1191de8a65f7SEric Schweitz if (r.getEleTy().isa<mlir::TupleType>())
1192fe252f8eSValentin Clement return mlir::success();
1193633f70f7SValentin Clement return mlir::failure();
1194633f70f7SValentin Clement }
1195633f70f7SValentin Clement return mlir::success();
1196633f70f7SValentin Clement }
1197633f70f7SValentin Clement
1198633f70f7SValentin Clement //===----------------------------------------------------------------------===//
119957f536a4SjeanPerier // GenTypeDescOp
120057f536a4SjeanPerier //===----------------------------------------------------------------------===//
120157f536a4SjeanPerier
build(mlir::OpBuilder &,mlir::OperationState & result,mlir::TypeAttr inty)1202de8a65f7SEric Schweitz void fir::GenTypeDescOp::build(mlir::OpBuilder &, mlir::OperationState &result,
120357f536a4SjeanPerier mlir::TypeAttr inty) {
120457f536a4SjeanPerier result.addAttribute("in_type", inty);
120557f536a4SjeanPerier result.addTypes(TypeDescType::get(inty.getValue()));
120657f536a4SjeanPerier }
120757f536a4SjeanPerier
parse(mlir::OpAsmParser & parser,mlir::OperationState & result)1208de8a65f7SEric Schweitz mlir::ParseResult fir::GenTypeDescOp::parse(mlir::OpAsmParser &parser,
1209633f70f7SValentin Clement mlir::OperationState &result) {
1210633f70f7SValentin Clement mlir::Type intype;
1211633f70f7SValentin Clement if (parser.parseType(intype))
1212633f70f7SValentin Clement return mlir::failure();
1213633f70f7SValentin Clement result.addAttribute("in_type", mlir::TypeAttr::get(intype));
1214de8a65f7SEric Schweitz mlir::Type restype = fir::TypeDescType::get(intype);
1215633f70f7SValentin Clement if (parser.addTypeToList(restype, result.types))
1216633f70f7SValentin Clement return mlir::failure();
1217633f70f7SValentin Clement return mlir::success();
1218633f70f7SValentin Clement }
1219633f70f7SValentin Clement
print(mlir::OpAsmPrinter & p)1220de8a65f7SEric Schweitz void fir::GenTypeDescOp::print(mlir::OpAsmPrinter &p) {
1221cc120e36SShraiysh Vaishay p << ' ' << getOperation()->getAttr("in_type");
1222cc120e36SShraiysh Vaishay p.printOptionalAttrDict(getOperation()->getAttrs(), {"in_type"});
1223633f70f7SValentin Clement }
1224633f70f7SValentin Clement
verify()1225de8a65f7SEric Schweitz mlir::LogicalResult fir::GenTypeDescOp::verify() {
1226cc120e36SShraiysh Vaishay mlir::Type resultTy = getType();
1227de8a65f7SEric Schweitz if (auto tdesc = resultTy.dyn_cast<fir::TypeDescType>()) {
1228cc120e36SShraiysh Vaishay if (tdesc.getOfTy() != getInType())
1229cc120e36SShraiysh Vaishay return emitOpError("wrapped type mismatched");
1230633f70f7SValentin Clement return mlir::success();
1231633f70f7SValentin Clement }
1232de8a65f7SEric Schweitz return emitOpError("must be !fir.tdesc type");
1233de8a65f7SEric Schweitz }
1234633f70f7SValentin Clement
123557f536a4SjeanPerier //===----------------------------------------------------------------------===//
123657f536a4SjeanPerier // GlobalOp
123757f536a4SjeanPerier //===----------------------------------------------------------------------===//
123857f536a4SjeanPerier
resultType()123947f75930SValentin Clement mlir::Type fir::GlobalOp::resultType() {
124047f75930SValentin Clement return wrapAllocaResultType(getType());
124147f75930SValentin Clement }
124247f75930SValentin Clement
parse(mlir::OpAsmParser & parser,mlir::OperationState & result)1243de8a65f7SEric Schweitz mlir::ParseResult fir::GlobalOp::parse(mlir::OpAsmParser &parser,
1244de8a65f7SEric Schweitz mlir::OperationState &result) {
1245bc034238SEric Schweitz // Parse the optional linkage
1246bc034238SEric Schweitz llvm::StringRef linkage;
1247bc034238SEric Schweitz auto &builder = parser.getBuilder();
1248bc034238SEric Schweitz if (mlir::succeeded(parser.parseOptionalKeyword(&linkage))) {
1249bc034238SEric Schweitz if (fir::GlobalOp::verifyValidLinkage(linkage))
12500b785a46SEric Schweitz return mlir::failure();
1251bc034238SEric Schweitz mlir::StringAttr linkAttr = builder.getStringAttr(linkage);
1252be80c6d1SValentin Clement result.addAttribute(fir::GlobalOp::getLinkageAttrNameStr(), linkAttr);
1253bc034238SEric Schweitz }
1254bc034238SEric Schweitz
1255bc034238SEric Schweitz // Parse the name as a symbol reference attribute.
1256bc034238SEric Schweitz mlir::SymbolRefAttr nameAttr;
1257be80c6d1SValentin Clement if (parser.parseAttribute(nameAttr, fir::GlobalOp::getSymbolAttrNameStr(),
1258bc034238SEric Schweitz result.attributes))
12590b785a46SEric Schweitz return mlir::failure();
1260bc034238SEric Schweitz result.addAttribute(mlir::SymbolTable::getSymbolAttrName(),
126158e1a5e4SJean Perier nameAttr.getRootReference());
1262bc034238SEric Schweitz
1263bc034238SEric Schweitz bool simpleInitializer = false;
1264bc034238SEric Schweitz if (mlir::succeeded(parser.parseOptionalLParen())) {
1265de8a65f7SEric Schweitz mlir::Attribute attr;
126600c93d88SRiver Riddle if (parser.parseAttribute(attr, "initVal", result.attributes) ||
1267bc034238SEric Schweitz parser.parseRParen())
12680b785a46SEric Schweitz return mlir::failure();
1269bc034238SEric Schweitz simpleInitializer = true;
1270bc034238SEric Schweitz }
1271bc034238SEric Schweitz
1272bc034238SEric Schweitz if (succeeded(parser.parseOptionalKeyword("constant"))) {
1273bc034238SEric Schweitz // if "constant" keyword then mark this as a constant, not a variable
127400c93d88SRiver Riddle result.addAttribute("constant", builder.getUnitAttr());
1275bc034238SEric Schweitz }
1276bc034238SEric Schweitz
1277bc034238SEric Schweitz mlir::Type globalType;
1278bc034238SEric Schweitz if (parser.parseColonType(globalType))
12790b785a46SEric Schweitz return mlir::failure();
1280bc034238SEric Schweitz
1281b077ee92SJacques Pienaar result.addAttribute(fir::GlobalOp::getTypeAttrName(result.name),
1282bc034238SEric Schweitz mlir::TypeAttr::get(globalType));
1283bc034238SEric Schweitz
1284bc034238SEric Schweitz if (simpleInitializer) {
1285bc034238SEric Schweitz result.addRegion();
1286bc034238SEric Schweitz } else {
1287bc034238SEric Schweitz // Parse the optional initializer body.
1288d85eb4e2SChris Lattner auto parseResult =
1289d85eb4e2SChris Lattner parser.parseOptionalRegion(*result.addRegion(), /*arguments=*/{});
12903b7c3a65SKazu Hirata if (parseResult.hasValue() && mlir::failed(*parseResult))
12910b785a46SEric Schweitz return mlir::failure();
1292bc034238SEric Schweitz }
12930b785a46SEric Schweitz return mlir::success();
1294bc034238SEric Schweitz }
1295bc034238SEric Schweitz
print(mlir::OpAsmPrinter & p)1296de8a65f7SEric Schweitz void fir::GlobalOp::print(mlir::OpAsmPrinter &p) {
129786b8c1d9SKazu Hirata if (getLinkName())
1298009ab172SKazu Hirata p << ' ' << *getLinkName();
12993da95b68SValentin Clement p << ' ';
1300cc120e36SShraiysh Vaishay p.printAttributeWithoutType(getSymrefAttr());
1301cc120e36SShraiysh Vaishay if (auto val = getValueOrNull())
13023da95b68SValentin Clement p << '(' << val << ')';
1303cc120e36SShraiysh Vaishay if (getOperation()->getAttr(fir::GlobalOp::getConstantAttrNameStr()))
13043da95b68SValentin Clement p << " constant";
13053da95b68SValentin Clement p << " : ";
1306cc120e36SShraiysh Vaishay p.printType(getType());
1307cc120e36SShraiysh Vaishay if (hasInitializationBody()) {
13085c36ee8dSMogball p << ' ';
1309cc120e36SShraiysh Vaishay p.printRegion(getOperation()->getRegion(0),
13103da95b68SValentin Clement /*printEntryBlockArgs=*/false,
13113da95b68SValentin Clement /*printBlockTerminators=*/true);
13123da95b68SValentin Clement }
13135c36ee8dSMogball }
13143da95b68SValentin Clement
appendInitialValue(mlir::Operation * op)131557f536a4SjeanPerier void fir::GlobalOp::appendInitialValue(mlir::Operation *op) {
131657f536a4SjeanPerier getBlock().getOperations().push_back(op);
131757f536a4SjeanPerier }
131857f536a4SjeanPerier
build(mlir::OpBuilder & builder,mlir::OperationState & result,llvm::StringRef name,bool isConstant,mlir::Type type,mlir::Attribute initialVal,mlir::StringAttr linkage,llvm::ArrayRef<mlir::NamedAttribute> attrs)1319de8a65f7SEric Schweitz void fir::GlobalOp::build(mlir::OpBuilder &builder,
1320de8a65f7SEric Schweitz mlir::OperationState &result, llvm::StringRef name,
1321de8a65f7SEric Schweitz bool isConstant, mlir::Type type,
1322de8a65f7SEric Schweitz mlir::Attribute initialVal, mlir::StringAttr linkage,
1323de8a65f7SEric Schweitz llvm::ArrayRef<mlir::NamedAttribute> attrs) {
1324bc034238SEric Schweitz result.addRegion();
1325b077ee92SJacques Pienaar result.addAttribute(getTypeAttrName(result.name), mlir::TypeAttr::get(type));
1326bc034238SEric Schweitz result.addAttribute(mlir::SymbolTable::getSymbolAttrName(),
1327bb1d976fSAlex Zinenko builder.getStringAttr(name));
1328be80c6d1SValentin Clement result.addAttribute(getSymbolAttrNameStr(),
1329de8a65f7SEric Schweitz mlir::SymbolRefAttr::get(builder.getContext(), name));
1330bc034238SEric Schweitz if (isConstant)
1331149ad3d5SShraiysh Vaishay result.addAttribute(getConstantAttrName(result.name),
1332149ad3d5SShraiysh Vaishay builder.getUnitAttr());
1333bc034238SEric Schweitz if (initialVal)
1334149ad3d5SShraiysh Vaishay result.addAttribute(getInitValAttrName(result.name), initialVal);
1335bc034238SEric Schweitz if (linkage)
1336be80c6d1SValentin Clement result.addAttribute(getLinkageAttrNameStr(), linkage);
1337bc034238SEric Schweitz result.attributes.append(attrs.begin(), attrs.end());
1338bc034238SEric Schweitz }
1339bc034238SEric Schweitz
build(mlir::OpBuilder & builder,mlir::OperationState & result,llvm::StringRef name,mlir::Type type,mlir::Attribute initialVal,mlir::StringAttr linkage,llvm::ArrayRef<mlir::NamedAttribute> attrs)1340de8a65f7SEric Schweitz void fir::GlobalOp::build(mlir::OpBuilder &builder,
1341de8a65f7SEric Schweitz mlir::OperationState &result, llvm::StringRef name,
1342de8a65f7SEric Schweitz mlir::Type type, mlir::Attribute initialVal,
1343de8a65f7SEric Schweitz mlir::StringAttr linkage,
1344de8a65f7SEric Schweitz llvm::ArrayRef<mlir::NamedAttribute> attrs) {
1345bc034238SEric Schweitz build(builder, result, name, /*isConstant=*/false, type, {}, linkage, attrs);
1346bc034238SEric Schweitz }
1347bc034238SEric Schweitz
build(mlir::OpBuilder & builder,mlir::OperationState & result,llvm::StringRef name,bool isConstant,mlir::Type type,mlir::StringAttr linkage,llvm::ArrayRef<mlir::NamedAttribute> attrs)1348de8a65f7SEric Schweitz void fir::GlobalOp::build(mlir::OpBuilder &builder,
1349de8a65f7SEric Schweitz mlir::OperationState &result, llvm::StringRef name,
1350de8a65f7SEric Schweitz bool isConstant, mlir::Type type,
1351de8a65f7SEric Schweitz mlir::StringAttr linkage,
1352de8a65f7SEric Schweitz llvm::ArrayRef<mlir::NamedAttribute> attrs) {
1353bc034238SEric Schweitz build(builder, result, name, isConstant, type, {}, linkage, attrs);
1354bc034238SEric Schweitz }
1355bc034238SEric Schweitz
build(mlir::OpBuilder & builder,mlir::OperationState & result,llvm::StringRef name,mlir::Type type,mlir::StringAttr linkage,llvm::ArrayRef<mlir::NamedAttribute> attrs)1356de8a65f7SEric Schweitz void fir::GlobalOp::build(mlir::OpBuilder &builder,
1357de8a65f7SEric Schweitz mlir::OperationState &result, llvm::StringRef name,
1358de8a65f7SEric Schweitz mlir::Type type, mlir::StringAttr linkage,
1359de8a65f7SEric Schweitz llvm::ArrayRef<mlir::NamedAttribute> attrs) {
1360bc034238SEric Schweitz build(builder, result, name, /*isConstant=*/false, type, {}, linkage, attrs);
1361bc034238SEric Schweitz }
1362bc034238SEric Schweitz
build(mlir::OpBuilder & builder,mlir::OperationState & result,llvm::StringRef name,bool isConstant,mlir::Type type,llvm::ArrayRef<mlir::NamedAttribute> attrs)1363de8a65f7SEric Schweitz void fir::GlobalOp::build(mlir::OpBuilder &builder,
1364de8a65f7SEric Schweitz mlir::OperationState &result, llvm::StringRef name,
1365de8a65f7SEric Schweitz bool isConstant, mlir::Type type,
1366de8a65f7SEric Schweitz llvm::ArrayRef<mlir::NamedAttribute> attrs) {
1367de8a65f7SEric Schweitz build(builder, result, name, isConstant, type, mlir::StringAttr{}, attrs);
1368bc034238SEric Schweitz }
1369bc034238SEric Schweitz
build(mlir::OpBuilder & builder,mlir::OperationState & result,llvm::StringRef name,mlir::Type type,llvm::ArrayRef<mlir::NamedAttribute> attrs)1370de8a65f7SEric Schweitz void fir::GlobalOp::build(mlir::OpBuilder &builder,
1371de8a65f7SEric Schweitz mlir::OperationState &result, llvm::StringRef name,
1372de8a65f7SEric Schweitz mlir::Type type,
1373de8a65f7SEric Schweitz llvm::ArrayRef<mlir::NamedAttribute> attrs) {
1374bc034238SEric Schweitz build(builder, result, name, /*isConstant=*/false, type, attrs);
1375bc034238SEric Schweitz }
1376bc034238SEric Schweitz
verifyValidLinkage(llvm::StringRef linkage)1377de8a65f7SEric Schweitz mlir::ParseResult fir::GlobalOp::verifyValidLinkage(llvm::StringRef linkage) {
1378bc034238SEric Schweitz // Supporting only a subset of the LLVM linkage types for now
137930a0fbf5SJean Perier static const char *validNames[] = {"common", "internal", "linkonce",
138030a0fbf5SJean Perier "linkonce_odr", "weak"};
1381bc034238SEric Schweitz return mlir::success(llvm::is_contained(validNames, linkage));
1382bc034238SEric Schweitz }
1383bc034238SEric Schweitz
1384bd2623b9SV Donaldson //===----------------------------------------------------------------------===//
1385a6fc5552SValentin Clement // GlobalLenOp
1386a6fc5552SValentin Clement //===----------------------------------------------------------------------===//
1387a6fc5552SValentin Clement
parse(mlir::OpAsmParser & parser,mlir::OperationState & result)1388de8a65f7SEric Schweitz mlir::ParseResult fir::GlobalLenOp::parse(mlir::OpAsmParser &parser,
1389a6fc5552SValentin Clement mlir::OperationState &result) {
1390a6fc5552SValentin Clement llvm::StringRef fieldName;
1391a6fc5552SValentin Clement if (failed(parser.parseOptionalKeyword(&fieldName))) {
1392a6fc5552SValentin Clement mlir::StringAttr fieldAttr;
1393be80c6d1SValentin Clement if (parser.parseAttribute(fieldAttr,
1394be80c6d1SValentin Clement fir::GlobalLenOp::getLenParamAttrName(),
1395a6fc5552SValentin Clement result.attributes))
1396a6fc5552SValentin Clement return mlir::failure();
1397a6fc5552SValentin Clement } else {
1398be80c6d1SValentin Clement result.addAttribute(fir::GlobalLenOp::getLenParamAttrName(),
1399a6fc5552SValentin Clement parser.getBuilder().getStringAttr(fieldName));
1400a6fc5552SValentin Clement }
1401a6fc5552SValentin Clement mlir::IntegerAttr constant;
1402a6fc5552SValentin Clement if (parser.parseComma() ||
1403be80c6d1SValentin Clement parser.parseAttribute(constant, fir::GlobalLenOp::getIntAttrName(),
1404a6fc5552SValentin Clement result.attributes))
1405a6fc5552SValentin Clement return mlir::failure();
1406a6fc5552SValentin Clement return mlir::success();
1407a6fc5552SValentin Clement }
1408a6fc5552SValentin Clement
print(mlir::OpAsmPrinter & p)1409de8a65f7SEric Schweitz void fir::GlobalLenOp::print(mlir::OpAsmPrinter &p) {
1410be80c6d1SValentin Clement p << ' ' << getOperation()->getAttr(fir::GlobalLenOp::getLenParamAttrName())
1411be80c6d1SValentin Clement << ", " << getOperation()->getAttr(fir::GlobalLenOp::getIntAttrName());
1412a6fc5552SValentin Clement }
1413a6fc5552SValentin Clement
1414a6fc5552SValentin Clement //===----------------------------------------------------------------------===//
1415220f314fSValentin Clement // FieldIndexOp
1416220f314fSValentin Clement //===----------------------------------------------------------------------===//
1417220f314fSValentin Clement
1418c67a8744SValentin Clement template <typename TY>
parseFieldLikeOp(mlir::OpAsmParser & parser,mlir::OperationState & result)1419c67a8744SValentin Clement mlir::ParseResult parseFieldLikeOp(mlir::OpAsmParser &parser,
1420220f314fSValentin Clement mlir::OperationState &result) {
1421220f314fSValentin Clement llvm::StringRef fieldName;
1422220f314fSValentin Clement auto &builder = parser.getBuilder();
1423220f314fSValentin Clement mlir::Type recty;
1424220f314fSValentin Clement if (parser.parseOptionalKeyword(&fieldName) || parser.parseComma() ||
1425220f314fSValentin Clement parser.parseType(recty))
1426220f314fSValentin Clement return mlir::failure();
1427c67a8744SValentin Clement result.addAttribute(fir::FieldIndexOp::getFieldAttrName(),
1428220f314fSValentin Clement builder.getStringAttr(fieldName));
1429de8a65f7SEric Schweitz if (!recty.dyn_cast<fir::RecordType>())
1430220f314fSValentin Clement return mlir::failure();
1431c67a8744SValentin Clement result.addAttribute(fir::FieldIndexOp::getTypeAttrName(),
1432220f314fSValentin Clement mlir::TypeAttr::get(recty));
1433220f314fSValentin Clement if (!parser.parseOptionalLParen()) {
1434e13d23bcSMarkus Böck llvm::SmallVector<mlir::OpAsmParser::UnresolvedOperand> operands;
1435220f314fSValentin Clement llvm::SmallVector<mlir::Type> types;
1436220f314fSValentin Clement auto loc = parser.getNameLoc();
1437220f314fSValentin Clement if (parser.parseOperandList(operands, mlir::OpAsmParser::Delimiter::None) ||
1438220f314fSValentin Clement parser.parseColonTypeList(types) || parser.parseRParen() ||
1439220f314fSValentin Clement parser.resolveOperands(operands, types, loc, result.operands))
1440220f314fSValentin Clement return mlir::failure();
1441220f314fSValentin Clement }
1442c67a8744SValentin Clement mlir::Type fieldType = TY::get(builder.getContext());
1443220f314fSValentin Clement if (parser.addTypeToList(fieldType, result.types))
1444220f314fSValentin Clement return mlir::failure();
1445220f314fSValentin Clement return mlir::success();
1446220f314fSValentin Clement }
1447220f314fSValentin Clement
parse(mlir::OpAsmParser & parser,mlir::OperationState & result)1448c67a8744SValentin Clement mlir::ParseResult fir::FieldIndexOp::parse(mlir::OpAsmParser &parser,
1449c67a8744SValentin Clement mlir::OperationState &result) {
1450c67a8744SValentin Clement return parseFieldLikeOp<fir::FieldType>(parser, result);
1451c67a8744SValentin Clement }
1452c67a8744SValentin Clement
1453c67a8744SValentin Clement template <typename OP>
printFieldLikeOp(mlir::OpAsmPrinter & p,OP & op)1454c67a8744SValentin Clement void printFieldLikeOp(mlir::OpAsmPrinter &p, OP &op) {
1455220f314fSValentin Clement p << ' '
1456c67a8744SValentin Clement << op.getOperation()
1457c67a8744SValentin Clement ->template getAttrOfType<mlir::StringAttr>(
1458c67a8744SValentin Clement fir::FieldIndexOp::getFieldAttrName())
1459220f314fSValentin Clement .getValue()
1460c67a8744SValentin Clement << ", " << op.getOperation()->getAttr(fir::FieldIndexOp::getTypeAttrName());
1461c67a8744SValentin Clement if (op.getNumOperands()) {
1462220f314fSValentin Clement p << '(';
1463c67a8744SValentin Clement p.printOperands(op.getTypeparams());
1464c67a8744SValentin Clement auto sep = ") : ";
1465c67a8744SValentin Clement for (auto op : op.getTypeparams()) {
1466220f314fSValentin Clement p << sep;
1467220f314fSValentin Clement if (op)
1468220f314fSValentin Clement p.printType(op.getType());
1469220f314fSValentin Clement else
1470220f314fSValentin Clement p << "()";
1471220f314fSValentin Clement sep = ", ";
1472220f314fSValentin Clement }
1473220f314fSValentin Clement }
1474220f314fSValentin Clement }
1475220f314fSValentin Clement
print(mlir::OpAsmPrinter & p)1476c67a8744SValentin Clement void fir::FieldIndexOp::print(mlir::OpAsmPrinter &p) {
1477c67a8744SValentin Clement printFieldLikeOp(p, *this);
1478c67a8744SValentin Clement }
1479c67a8744SValentin Clement
build(mlir::OpBuilder & builder,mlir::OperationState & result,llvm::StringRef fieldName,mlir::Type recTy,mlir::ValueRange operands)1480220f314fSValentin Clement void fir::FieldIndexOp::build(mlir::OpBuilder &builder,
1481220f314fSValentin Clement mlir::OperationState &result,
1482220f314fSValentin Clement llvm::StringRef fieldName, mlir::Type recTy,
1483220f314fSValentin Clement mlir::ValueRange operands) {
1484c67a8744SValentin Clement result.addAttribute(getFieldAttrName(), builder.getStringAttr(fieldName));
1485c67a8744SValentin Clement result.addAttribute(getTypeAttrName(), mlir::TypeAttr::get(recTy));
1486220f314fSValentin Clement result.addOperands(operands);
1487220f314fSValentin Clement }
1488220f314fSValentin Clement
getAttributes()14898c22cb84SValentin Clement llvm::SmallVector<mlir::Attribute> fir::FieldIndexOp::getAttributes() {
14908c22cb84SValentin Clement llvm::SmallVector<mlir::Attribute> attrs;
14918c22cb84SValentin Clement attrs.push_back(getFieldIdAttr());
14928c22cb84SValentin Clement attrs.push_back(getOnTypeAttr());
14938c22cb84SValentin Clement return attrs;
14948c22cb84SValentin Clement }
14958c22cb84SValentin Clement
1496220f314fSValentin Clement //===----------------------------------------------------------------------===//
1497bd2623b9SV Donaldson // InsertOnRangeOp
1498bd2623b9SV Donaldson //===----------------------------------------------------------------------===//
1499bd2623b9SV Donaldson
1500de8a65f7SEric Schweitz static mlir::ParseResult
parseCustomRangeSubscript(mlir::OpAsmParser & parser,mlir::DenseIntElementsAttr & coord)15018ec0f221SMehdi Amini parseCustomRangeSubscript(mlir::OpAsmParser &parser,
15028ec0f221SMehdi Amini mlir::DenseIntElementsAttr &coord) {
1503de8a65f7SEric Schweitz llvm::SmallVector<std::int64_t> lbounds;
1504de8a65f7SEric Schweitz llvm::SmallVector<std::int64_t> ubounds;
15058ec0f221SMehdi Amini if (parser.parseKeyword("from") ||
15068ec0f221SMehdi Amini parser.parseCommaSeparatedList(
1507de8a65f7SEric Schweitz mlir::AsmParser::Delimiter::Paren,
15088ec0f221SMehdi Amini [&] { return parser.parseInteger(lbounds.emplace_back(0)); }) ||
15098ec0f221SMehdi Amini parser.parseKeyword("to") ||
1510de8a65f7SEric Schweitz parser.parseCommaSeparatedList(mlir::AsmParser::Delimiter::Paren, [&] {
15118ec0f221SMehdi Amini return parser.parseInteger(ubounds.emplace_back(0));
15128ec0f221SMehdi Amini }))
1513de8a65f7SEric Schweitz return mlir::failure();
1514de8a65f7SEric Schweitz llvm::SmallVector<std::int64_t> zippedBounds;
15158ec0f221SMehdi Amini for (auto zip : llvm::zip(lbounds, ubounds)) {
15168ec0f221SMehdi Amini zippedBounds.push_back(std::get<0>(zip));
15178ec0f221SMehdi Amini zippedBounds.push_back(std::get<1>(zip));
15188ec0f221SMehdi Amini }
15198ec0f221SMehdi Amini coord = mlir::Builder(parser.getContext()).getIndexTensorAttr(zippedBounds);
1520de8a65f7SEric Schweitz return mlir::success();
15218ec0f221SMehdi Amini }
15228ec0f221SMehdi Amini
printCustomRangeSubscript(mlir::OpAsmPrinter & printer,fir::InsertOnRangeOp op,mlir::DenseIntElementsAttr coord)1523de8a65f7SEric Schweitz static void printCustomRangeSubscript(mlir::OpAsmPrinter &printer,
1524de8a65f7SEric Schweitz fir::InsertOnRangeOp op,
15258ec0f221SMehdi Amini mlir::DenseIntElementsAttr coord) {
15268ec0f221SMehdi Amini printer << "from (";
1527de8a65f7SEric Schweitz auto enumerate = llvm::enumerate(coord.getValues<std::int64_t>());
15288ec0f221SMehdi Amini // Even entries are the lower bounds.
15298ec0f221SMehdi Amini llvm::interleaveComma(
15308ec0f221SMehdi Amini make_filter_range(
15318ec0f221SMehdi Amini enumerate,
15328ec0f221SMehdi Amini [](auto indexed_value) { return indexed_value.index() % 2 == 0; }),
15338ec0f221SMehdi Amini printer, [&](auto indexed_value) { printer << indexed_value.value(); });
15348ec0f221SMehdi Amini printer << ") to (";
15358ec0f221SMehdi Amini // Odd entries are the upper bounds.
15368ec0f221SMehdi Amini llvm::interleaveComma(
15378ec0f221SMehdi Amini make_filter_range(
15388ec0f221SMehdi Amini enumerate,
15398ec0f221SMehdi Amini [](auto indexed_value) { return indexed_value.index() % 2 != 0; }),
15408ec0f221SMehdi Amini printer, [&](auto indexed_value) { printer << indexed_value.value(); });
15418ec0f221SMehdi Amini printer << ")";
15428ec0f221SMehdi Amini }
15438ec0f221SMehdi Amini
1544bd2623b9SV Donaldson /// Range bounds must be nonnegative, and the range must not be empty.
verify()1545de8a65f7SEric Schweitz mlir::LogicalResult fir::InsertOnRangeOp::verify() {
1546149ad3d5SShraiysh Vaishay if (fir::hasDynamicSize(getSeq().getType()))
1547cc120e36SShraiysh Vaishay return emitOpError("must have constant shape and size");
1548149ad3d5SShraiysh Vaishay mlir::DenseIntElementsAttr coorAttr = getCoor();
1549cc120e36SShraiysh Vaishay if (coorAttr.size() < 2 || coorAttr.size() % 2 != 0)
1550cc120e36SShraiysh Vaishay return emitOpError("has uneven number of values in ranges");
1551bd2623b9SV Donaldson bool rangeIsKnownToBeNonempty = false;
1552de8a65f7SEric Schweitz for (auto i = coorAttr.getValues<std::int64_t>().end(),
1553de8a65f7SEric Schweitz b = coorAttr.getValues<std::int64_t>().begin();
15548ec0f221SMehdi Amini i != b;) {
15558ec0f221SMehdi Amini int64_t ub = (*--i);
15568ec0f221SMehdi Amini int64_t lb = (*--i);
1557bd2623b9SV Donaldson if (lb < 0 || ub < 0)
1558cc120e36SShraiysh Vaishay return emitOpError("negative range bound");
1559bd2623b9SV Donaldson if (rangeIsKnownToBeNonempty)
1560bd2623b9SV Donaldson continue;
1561bd2623b9SV Donaldson if (lb > ub)
1562cc120e36SShraiysh Vaishay return emitOpError("empty range");
1563bd2623b9SV Donaldson rangeIsKnownToBeNonempty = lb < ub;
1564bd2623b9SV Donaldson }
1565bd2623b9SV Donaldson return mlir::success();
1566bd2623b9SV Donaldson }
1567bd2623b9SV Donaldson
1568bc034238SEric Schweitz //===----------------------------------------------------------------------===//
15690b785a46SEric Schweitz // InsertValueOp
15700b785a46SEric Schweitz //===----------------------------------------------------------------------===//
15710b785a46SEric Schweitz
checkIsIntegerConstant(mlir::Attribute attr,std::int64_t conVal)1572de8a65f7SEric Schweitz static bool checkIsIntegerConstant(mlir::Attribute attr, std::int64_t conVal) {
15730b785a46SEric Schweitz if (auto iattr = attr.dyn_cast<mlir::IntegerAttr>())
15740b785a46SEric Schweitz return iattr.getInt() == conVal;
15750b785a46SEric Schweitz return false;
15760b785a46SEric Schweitz }
1577de8a65f7SEric Schweitz
isZero(mlir::Attribute a)1578c8f03a7fSEric Schweitz static bool isZero(mlir::Attribute a) { return checkIsIntegerConstant(a, 0); }
isOne(mlir::Attribute a)1579c8f03a7fSEric Schweitz static bool isOne(mlir::Attribute a) { return checkIsIntegerConstant(a, 1); }
15800b785a46SEric Schweitz
15810b785a46SEric Schweitz // Undo some complex patterns created in the front-end and turn them back into
15820b785a46SEric Schweitz // complex ops.
15830b785a46SEric Schweitz template <typename FltOp, typename CpxOp>
15840b785a46SEric Schweitz struct UndoComplexPattern : public mlir::RewritePattern {
UndoComplexPatternUndoComplexPattern15850b785a46SEric Schweitz UndoComplexPattern(mlir::MLIRContext *ctx)
158676f3c2f3SRiver Riddle : mlir::RewritePattern("fir.insert_value", 2, ctx) {}
15870b785a46SEric Schweitz
15880b785a46SEric Schweitz mlir::LogicalResult
matchAndRewriteUndoComplexPattern15890b785a46SEric Schweitz matchAndRewrite(mlir::Operation *op,
15900b785a46SEric Schweitz mlir::PatternRewriter &rewriter) const override {
1591de8a65f7SEric Schweitz auto insval = mlir::dyn_cast_or_null<fir::InsertValueOp>(op);
15920b785a46SEric Schweitz if (!insval || !insval.getType().isa<fir::ComplexType>())
15930b785a46SEric Schweitz return mlir::failure();
1594de8a65f7SEric Schweitz auto insval2 = mlir::dyn_cast_or_null<fir::InsertValueOp>(
1595de8a65f7SEric Schweitz insval.getAdt().getDefiningOp());
15961906188fSValentin Clement if (!insval2)
15970b785a46SEric Schweitz return mlir::failure();
1598de8a65f7SEric Schweitz auto binf = mlir::dyn_cast_or_null<FltOp>(insval.getVal().getDefiningOp());
1599de8a65f7SEric Schweitz auto binf2 =
1600de8a65f7SEric Schweitz mlir::dyn_cast_or_null<FltOp>(insval2.getVal().getDefiningOp());
1601149ad3d5SShraiysh Vaishay if (!binf || !binf2 || insval.getCoor().size() != 1 ||
1602149ad3d5SShraiysh Vaishay !isOne(insval.getCoor()[0]) || insval2.getCoor().size() != 1 ||
1603149ad3d5SShraiysh Vaishay !isZero(insval2.getCoor()[0]))
16040b785a46SEric Schweitz return mlir::failure();
1605de8a65f7SEric Schweitz auto eai = mlir::dyn_cast_or_null<fir::ExtractValueOp>(
1606de8a65f7SEric Schweitz binf.getLhs().getDefiningOp());
1607de8a65f7SEric Schweitz auto ebi = mlir::dyn_cast_or_null<fir::ExtractValueOp>(
1608de8a65f7SEric Schweitz binf.getRhs().getDefiningOp());
1609de8a65f7SEric Schweitz auto ear = mlir::dyn_cast_or_null<fir::ExtractValueOp>(
1610de8a65f7SEric Schweitz binf2.getLhs().getDefiningOp());
1611de8a65f7SEric Schweitz auto ebr = mlir::dyn_cast_or_null<fir::ExtractValueOp>(
1612de8a65f7SEric Schweitz binf2.getRhs().getDefiningOp());
1613149ad3d5SShraiysh Vaishay if (!eai || !ebi || !ear || !ebr || ear.getAdt() != eai.getAdt() ||
1614149ad3d5SShraiysh Vaishay ebr.getAdt() != ebi.getAdt() || eai.getCoor().size() != 1 ||
1615149ad3d5SShraiysh Vaishay !isOne(eai.getCoor()[0]) || ebi.getCoor().size() != 1 ||
1616149ad3d5SShraiysh Vaishay !isOne(ebi.getCoor()[0]) || ear.getCoor().size() != 1 ||
1617149ad3d5SShraiysh Vaishay !isZero(ear.getCoor()[0]) || ebr.getCoor().size() != 1 ||
1618149ad3d5SShraiysh Vaishay !isZero(ebr.getCoor()[0]))
16190b785a46SEric Schweitz return mlir::failure();
1620149ad3d5SShraiysh Vaishay rewriter.replaceOpWithNewOp<CpxOp>(op, ear.getAdt(), ebr.getAdt());
16210b785a46SEric Schweitz return mlir::success();
16220b785a46SEric Schweitz }
16230b785a46SEric Schweitz };
16240b785a46SEric Schweitz
getCanonicalizationPatterns(mlir::RewritePatternSet & results,mlir::MLIRContext * context)16250b785a46SEric Schweitz void fir::InsertValueOp::getCanonicalizationPatterns(
16269f85c198SRiver Riddle mlir::RewritePatternSet &results, mlir::MLIRContext *context) {
1627a54f4eaeSMogball results.insert<UndoComplexPattern<mlir::arith::AddFOp, fir::AddcOp>,
1628a54f4eaeSMogball UndoComplexPattern<mlir::arith::SubFOp, fir::SubcOp>>(context);
16290b785a46SEric Schweitz }
16300b785a46SEric Schweitz
16310b785a46SEric Schweitz //===----------------------------------------------------------------------===//
1632bc034238SEric Schweitz // IterWhileOp
1633bc034238SEric Schweitz //===----------------------------------------------------------------------===//
1634bc034238SEric Schweitz
build(mlir::OpBuilder & builder,mlir::OperationState & result,mlir::Value lb,mlir::Value ub,mlir::Value step,mlir::Value iterate,bool finalCountValue,mlir::ValueRange iterArgs,llvm::ArrayRef<mlir::NamedAttribute> attributes)1635bb1d976fSAlex Zinenko void fir::IterWhileOp::build(mlir::OpBuilder &builder,
1636bc034238SEric Schweitz mlir::OperationState &result, mlir::Value lb,
1637bc034238SEric Schweitz mlir::Value ub, mlir::Value step,
16380b785a46SEric Schweitz mlir::Value iterate, bool finalCountValue,
16390b785a46SEric Schweitz mlir::ValueRange iterArgs,
1640bc034238SEric Schweitz llvm::ArrayRef<mlir::NamedAttribute> attributes) {
1641bc034238SEric Schweitz result.addOperands({lb, ub, step, iterate});
16420b785a46SEric Schweitz if (finalCountValue) {
16430b785a46SEric Schweitz result.addTypes(builder.getIndexType());
16443012f35fSJacques Pienaar result.addAttribute(getFinalValueAttrNameStr(), builder.getUnitAttr());
16450b785a46SEric Schweitz }
1646bc034238SEric Schweitz result.addTypes(iterate.getType());
1647bc034238SEric Schweitz result.addOperands(iterArgs);
1648bc034238SEric Schweitz for (auto v : iterArgs)
1649bc034238SEric Schweitz result.addTypes(v.getType());
1650bc034238SEric Schweitz mlir::Region *bodyRegion = result.addRegion();
1651de8a65f7SEric Schweitz bodyRegion->push_back(new mlir::Block{});
1652e084679fSRiver Riddle bodyRegion->front().addArgument(builder.getIndexType(), result.location);
1653e084679fSRiver Riddle bodyRegion->front().addArgument(iterate.getType(), result.location);
1654e084679fSRiver Riddle bodyRegion->front().addArguments(
1655e084679fSRiver Riddle iterArgs.getTypes(),
1656de8a65f7SEric Schweitz llvm::SmallVector<mlir::Location>(iterArgs.size(), result.location));
1657bc034238SEric Schweitz result.addAttributes(attributes);
1658bc034238SEric Schweitz }
1659bc034238SEric Schweitz
parse(mlir::OpAsmParser & parser,mlir::OperationState & result)1660de8a65f7SEric Schweitz mlir::ParseResult fir::IterWhileOp::parse(mlir::OpAsmParser &parser,
1661bc034238SEric Schweitz mlir::OperationState &result) {
1662bc034238SEric Schweitz auto &builder = parser.getBuilder();
1663d85eb4e2SChris Lattner mlir::OpAsmParser::Argument inductionVariable, iterateVar;
1664d85eb4e2SChris Lattner mlir::OpAsmParser::UnresolvedOperand lb, ub, step, iterateInput;
1665d85eb4e2SChris Lattner if (parser.parseLParen() || parser.parseArgument(inductionVariable) ||
1666bc034238SEric Schweitz parser.parseEqual())
1667bc034238SEric Schweitz return mlir::failure();
1668bc034238SEric Schweitz
1669bc034238SEric Schweitz // Parse loop bounds.
1670bc034238SEric Schweitz auto indexType = builder.getIndexType();
1671bc034238SEric Schweitz auto i1Type = builder.getIntegerType(1);
1672bc034238SEric Schweitz if (parser.parseOperand(lb) ||
1673bc034238SEric Schweitz parser.resolveOperand(lb, indexType, result.operands) ||
1674bc034238SEric Schweitz parser.parseKeyword("to") || parser.parseOperand(ub) ||
1675bc034238SEric Schweitz parser.resolveOperand(ub, indexType, result.operands) ||
1676bc034238SEric Schweitz parser.parseKeyword("step") || parser.parseOperand(step) ||
1677bc034238SEric Schweitz parser.parseRParen() ||
1678d85eb4e2SChris Lattner parser.resolveOperand(step, indexType, result.operands) ||
1679d85eb4e2SChris Lattner parser.parseKeyword("and") || parser.parseLParen() ||
1680d85eb4e2SChris Lattner parser.parseArgument(iterateVar) || parser.parseEqual() ||
1681d85eb4e2SChris Lattner parser.parseOperand(iterateInput) || parser.parseRParen() ||
1682bc034238SEric Schweitz parser.resolveOperand(iterateInput, i1Type, result.operands))
1683bc034238SEric Schweitz return mlir::failure();
1684bc034238SEric Schweitz
1685bc034238SEric Schweitz // Parse the initial iteration arguments.
16860b785a46SEric Schweitz auto prependCount = false;
16870b785a46SEric Schweitz
1688bc034238SEric Schweitz // Induction variable.
1689d85eb4e2SChris Lattner llvm::SmallVector<mlir::OpAsmParser::Argument> regionArgs;
1690bc034238SEric Schweitz regionArgs.push_back(inductionVariable);
1691bc034238SEric Schweitz regionArgs.push_back(iterateVar);
1692bc034238SEric Schweitz
16930b785a46SEric Schweitz if (succeeded(parser.parseOptionalKeyword("iter_args"))) {
1694e13d23bcSMarkus Böck llvm::SmallVector<mlir::OpAsmParser::UnresolvedOperand> operands;
16956e2afdb7SEric Schweitz llvm::SmallVector<mlir::Type> regionTypes;
1696bc034238SEric Schweitz // Parse assignment list and results type list.
1697bc034238SEric Schweitz if (parser.parseAssignmentList(regionArgs, operands) ||
1698bc034238SEric Schweitz parser.parseArrowTypeList(regionTypes))
1699de8a65f7SEric Schweitz return mlir::failure();
17000b785a46SEric Schweitz if (regionTypes.size() == operands.size() + 2)
17010b785a46SEric Schweitz prependCount = true;
17020b785a46SEric Schweitz llvm::ArrayRef<mlir::Type> resTypes = regionTypes;
17030b785a46SEric Schweitz resTypes = prependCount ? resTypes.drop_front(2) : resTypes;
1704bc034238SEric Schweitz // Resolve input operands.
17056e2afdb7SEric Schweitz for (auto operandType : llvm::zip(operands, resTypes))
17066e2afdb7SEric Schweitz if (parser.resolveOperand(std::get<0>(operandType),
17076e2afdb7SEric Schweitz std::get<1>(operandType), result.operands))
1708de8a65f7SEric Schweitz return mlir::failure();
17090b785a46SEric Schweitz if (prependCount) {
1710bc034238SEric Schweitz result.addTypes(regionTypes);
17110b785a46SEric Schweitz } else {
17120b785a46SEric Schweitz result.addTypes(i1Type);
17130b785a46SEric Schweitz result.addTypes(resTypes);
17140b785a46SEric Schweitz }
17150b785a46SEric Schweitz } else if (succeeded(parser.parseOptionalArrow())) {
17166e2afdb7SEric Schweitz llvm::SmallVector<mlir::Type> typeList;
17170b785a46SEric Schweitz if (parser.parseLParen() || parser.parseTypeList(typeList) ||
17180b785a46SEric Schweitz parser.parseRParen())
1719de8a65f7SEric Schweitz return mlir::failure();
17200b785a46SEric Schweitz // Type list must be "(index, i1)".
17210b785a46SEric Schweitz if (typeList.size() != 2 || !typeList[0].isa<mlir::IndexType>() ||
17220b785a46SEric Schweitz !typeList[1].isSignlessInteger(1))
1723de8a65f7SEric Schweitz return mlir::failure();
17240b785a46SEric Schweitz result.addTypes(typeList);
17250b785a46SEric Schweitz prependCount = true;
17260b785a46SEric Schweitz } else {
17270b785a46SEric Schweitz result.addTypes(i1Type);
1728bc034238SEric Schweitz }
1729bc034238SEric Schweitz
1730bc034238SEric Schweitz if (parser.parseOptionalAttrDictWithKeyword(result.attributes))
1731bc034238SEric Schweitz return mlir::failure();
1732bc034238SEric Schweitz
17336e2afdb7SEric Schweitz llvm::SmallVector<mlir::Type> argTypes;
1734bc034238SEric Schweitz // Induction variable (hidden)
17350b785a46SEric Schweitz if (prependCount)
17363012f35fSJacques Pienaar result.addAttribute(IterWhileOp::getFinalValueAttrNameStr(),
17370b785a46SEric Schweitz builder.getUnitAttr());
17380b785a46SEric Schweitz else
1739bc034238SEric Schweitz argTypes.push_back(indexType);
1740bc034238SEric Schweitz // Loop carried variables (including iterate)
1741bc034238SEric Schweitz argTypes.append(result.types.begin(), result.types.end());
1742bc034238SEric Schweitz // Parse the body region.
1743bc034238SEric Schweitz auto *body = result.addRegion();
1744bc034238SEric Schweitz if (regionArgs.size() != argTypes.size())
1745bc034238SEric Schweitz return parser.emitError(
1746bc034238SEric Schweitz parser.getNameLoc(),
1747bc034238SEric Schweitz "mismatch in number of loop-carried values and defined values");
1748bc034238SEric Schweitz
1749d85eb4e2SChris Lattner for (size_t i = 0, e = regionArgs.size(); i != e; ++i)
1750d85eb4e2SChris Lattner regionArgs[i].type = argTypes[i];
1751d85eb4e2SChris Lattner
1752d85eb4e2SChris Lattner if (parser.parseRegion(*body, regionArgs))
1753de8a65f7SEric Schweitz return mlir::failure();
1754bc034238SEric Schweitz
1755bc034238SEric Schweitz fir::IterWhileOp::ensureTerminator(*body, builder, result.location);
1756bc034238SEric Schweitz return mlir::success();
1757bc034238SEric Schweitz }
1758bc034238SEric Schweitz
verify()1759de8a65f7SEric Schweitz mlir::LogicalResult fir::IterWhileOp::verify() {
1760bc034238SEric Schweitz // Check that the body defines as single block argument for the induction
1761bc034238SEric Schweitz // variable.
1762125a4d91SAndrzej Warzynski auto *body = getBody();
1763bc034238SEric Schweitz if (!body->getArgument(1).getType().isInteger(1))
1764125a4d91SAndrzej Warzynski return emitOpError(
1765bc034238SEric Schweitz "expected body second argument to be an index argument for "
1766bc034238SEric Schweitz "the induction variable");
1767bc034238SEric Schweitz if (!body->getArgument(0).getType().isIndex())
1768125a4d91SAndrzej Warzynski return emitOpError(
1769bc034238SEric Schweitz "expected body first argument to be an index argument for "
1770bc034238SEric Schweitz "the induction variable");
1771bc034238SEric Schweitz
1772125a4d91SAndrzej Warzynski auto opNumResults = getNumResults();
1773125a4d91SAndrzej Warzynski if (getFinalValue()) {
17740b785a46SEric Schweitz // Result type must be "(index, i1, ...)".
1775125a4d91SAndrzej Warzynski if (!getResult(0).getType().isa<mlir::IndexType>())
1776125a4d91SAndrzej Warzynski return emitOpError("result #0 expected to be index");
1777125a4d91SAndrzej Warzynski if (!getResult(1).getType().isSignlessInteger(1))
1778125a4d91SAndrzej Warzynski return emitOpError("result #1 expected to be i1");
17790b785a46SEric Schweitz opNumResults--;
17800b785a46SEric Schweitz } else {
17810b785a46SEric Schweitz // iterate_while always returns the early exit induction value.
17820b785a46SEric Schweitz // Result type must be "(i1, ...)"
1783125a4d91SAndrzej Warzynski if (!getResult(0).getType().isSignlessInteger(1))
1784125a4d91SAndrzej Warzynski return emitOpError("result #0 expected to be i1");
17850b785a46SEric Schweitz }
1786bc034238SEric Schweitz if (opNumResults == 0)
1787bc034238SEric Schweitz return mlir::failure();
1788125a4d91SAndrzej Warzynski if (getNumIterOperands() != opNumResults)
1789125a4d91SAndrzej Warzynski return emitOpError(
1790bc034238SEric Schweitz "mismatch in number of loop-carried values and defined values");
1791125a4d91SAndrzej Warzynski if (getNumRegionIterArgs() != opNumResults)
1792125a4d91SAndrzej Warzynski return emitOpError(
1793bc034238SEric Schweitz "mismatch in number of basic block args and defined values");
1794125a4d91SAndrzej Warzynski auto iterOperands = getIterOperands();
1795125a4d91SAndrzej Warzynski auto iterArgs = getRegionIterArgs();
1796125a4d91SAndrzej Warzynski auto opResults = getFinalValue() ? getResults().drop_front() : getResults();
1797de8a65f7SEric Schweitz unsigned i = 0u;
1798bc034238SEric Schweitz for (auto e : llvm::zip(iterOperands, iterArgs, opResults)) {
1799bc034238SEric Schweitz if (std::get<0>(e).getType() != std::get<2>(e).getType())
1800125a4d91SAndrzej Warzynski return emitOpError() << "types mismatch between " << i
1801bc034238SEric Schweitz << "th iter operand and defined value";
1802bc034238SEric Schweitz if (std::get<1>(e).getType() != std::get<2>(e).getType())
1803125a4d91SAndrzej Warzynski return emitOpError() << "types mismatch between " << i
1804bc034238SEric Schweitz << "th iter region arg and defined value";
1805bc034238SEric Schweitz
1806bc034238SEric Schweitz i++;
1807bc034238SEric Schweitz }
1808bc034238SEric Schweitz return mlir::success();
1809bc034238SEric Schweitz }
1810bc034238SEric Schweitz
print(mlir::OpAsmPrinter & p)1811de8a65f7SEric Schweitz void fir::IterWhileOp::print(mlir::OpAsmPrinter &p) {
1812125a4d91SAndrzej Warzynski p << " (" << getInductionVar() << " = " << getLowerBound() << " to "
1813125a4d91SAndrzej Warzynski << getUpperBound() << " step " << getStep() << ") and (";
1814125a4d91SAndrzej Warzynski assert(hasIterOperands());
1815125a4d91SAndrzej Warzynski auto regionArgs = getRegionIterArgs();
1816125a4d91SAndrzej Warzynski auto operands = getIterOperands();
1817bc034238SEric Schweitz p << regionArgs.front() << " = " << *operands.begin() << ")";
1818bc034238SEric Schweitz if (regionArgs.size() > 1) {
1819bc034238SEric Schweitz p << " iter_args(";
1820bc034238SEric Schweitz llvm::interleaveComma(
1821bc034238SEric Schweitz llvm::zip(regionArgs.drop_front(), operands.drop_front()), p,
1822bc034238SEric Schweitz [&](auto it) { p << std::get<0>(it) << " = " << std::get<1>(it); });
182364be3fcbSRiver Riddle p << ") -> (";
182464be3fcbSRiver Riddle llvm::interleaveComma(
1825125a4d91SAndrzej Warzynski llvm::drop_begin(getResultTypes(), getFinalValue() ? 0 : 1), p);
182664be3fcbSRiver Riddle p << ")";
1827125a4d91SAndrzej Warzynski } else if (getFinalValue()) {
1828125a4d91SAndrzej Warzynski p << " -> (" << getResultTypes() << ')';
1829bc034238SEric Schweitz }
1830125a4d91SAndrzej Warzynski p.printOptionalAttrDictWithKeyword((*this)->getAttrs(),
1831125a4d91SAndrzej Warzynski {getFinalValueAttrNameStr()});
18325c36ee8dSMogball p << ' ';
1833125a4d91SAndrzej Warzynski p.printRegion(getRegion(), /*printEntryBlockArgs=*/false,
1834bc034238SEric Schweitz /*printBlockTerminators=*/true);
1835bc034238SEric Schweitz }
1836bc034238SEric Schweitz
getLoopBody()1837149ad3d5SShraiysh Vaishay mlir::Region &fir::IterWhileOp::getLoopBody() { return getRegion(); }
1838bc034238SEric Schweitz
iterArgToBlockArg(mlir::Value iterArg)18390b785a46SEric Schweitz mlir::BlockArgument fir::IterWhileOp::iterArgToBlockArg(mlir::Value iterArg) {
1840149ad3d5SShraiysh Vaishay for (auto i : llvm::enumerate(getInitArgs()))
18410b785a46SEric Schweitz if (iterArg == i.value())
1842149ad3d5SShraiysh Vaishay return getRegion().front().getArgument(i.index() + 1);
18430b785a46SEric Schweitz return {};
18440b785a46SEric Schweitz }
18450b785a46SEric Schweitz
resultToSourceOps(llvm::SmallVectorImpl<mlir::Value> & results,unsigned resultNum)18460b785a46SEric Schweitz void fir::IterWhileOp::resultToSourceOps(
18470b785a46SEric Schweitz llvm::SmallVectorImpl<mlir::Value> &results, unsigned resultNum) {
1848149ad3d5SShraiysh Vaishay auto oper = getFinalValue() ? resultNum + 1 : resultNum;
1849149ad3d5SShraiysh Vaishay auto *term = getRegion().front().getTerminator();
18500b785a46SEric Schweitz if (oper < term->getNumOperands())
18510b785a46SEric Schweitz results.push_back(term->getOperand(oper));
18520b785a46SEric Schweitz }
18530b785a46SEric Schweitz
blockArgToSourceOp(unsigned blockArgNum)18540b785a46SEric Schweitz mlir::Value fir::IterWhileOp::blockArgToSourceOp(unsigned blockArgNum) {
1855149ad3d5SShraiysh Vaishay if (blockArgNum > 0 && blockArgNum <= getInitArgs().size())
1856149ad3d5SShraiysh Vaishay return getInitArgs()[blockArgNum - 1];
18570b785a46SEric Schweitz return {};
18580b785a46SEric Schweitz }
18590b785a46SEric Schweitz
186057f536a4SjeanPerier //===----------------------------------------------------------------------===//
1861633f70f7SValentin Clement // LenParamIndexOp
1862633f70f7SValentin Clement //===----------------------------------------------------------------------===//
1863633f70f7SValentin Clement
parse(mlir::OpAsmParser & parser,mlir::OperationState & result)1864de8a65f7SEric Schweitz mlir::ParseResult fir::LenParamIndexOp::parse(mlir::OpAsmParser &parser,
1865633f70f7SValentin Clement mlir::OperationState &result) {
1866c67a8744SValentin Clement return parseFieldLikeOp<fir::LenType>(parser, result);
1867633f70f7SValentin Clement }
1868633f70f7SValentin Clement
print(mlir::OpAsmPrinter & p)1869de8a65f7SEric Schweitz void fir::LenParamIndexOp::print(mlir::OpAsmPrinter &p) {
1870c67a8744SValentin Clement printFieldLikeOp(p, *this);
1871c67a8744SValentin Clement }
1872c67a8744SValentin Clement
build(mlir::OpBuilder & builder,mlir::OperationState & result,llvm::StringRef fieldName,mlir::Type recTy,mlir::ValueRange operands)1873c67a8744SValentin Clement void fir::LenParamIndexOp::build(mlir::OpBuilder &builder,
1874c67a8744SValentin Clement mlir::OperationState &result,
1875c67a8744SValentin Clement llvm::StringRef fieldName, mlir::Type recTy,
1876c67a8744SValentin Clement mlir::ValueRange operands) {
1877c67a8744SValentin Clement result.addAttribute(getFieldAttrName(), builder.getStringAttr(fieldName));
1878c67a8744SValentin Clement result.addAttribute(getTypeAttrName(), mlir::TypeAttr::get(recTy));
1879c67a8744SValentin Clement result.addOperands(operands);
1880c67a8744SValentin Clement }
1881c67a8744SValentin Clement
getAttributes()1882c67a8744SValentin Clement llvm::SmallVector<mlir::Attribute> fir::LenParamIndexOp::getAttributes() {
1883c67a8744SValentin Clement llvm::SmallVector<mlir::Attribute> attrs;
1884c67a8744SValentin Clement attrs.push_back(getFieldIdAttr());
1885c67a8744SValentin Clement attrs.push_back(getOnTypeAttr());
1886c67a8744SValentin Clement return attrs;
1887633f70f7SValentin Clement }
1888633f70f7SValentin Clement
1889633f70f7SValentin Clement //===----------------------------------------------------------------------===//
189057f536a4SjeanPerier // LoadOp
189157f536a4SjeanPerier //===----------------------------------------------------------------------===//
189257f536a4SjeanPerier
build(mlir::OpBuilder & builder,mlir::OperationState & result,mlir::Value refVal)1893633f70f7SValentin Clement void fir::LoadOp::build(mlir::OpBuilder &builder, mlir::OperationState &result,
1894633f70f7SValentin Clement mlir::Value refVal) {
1895633f70f7SValentin Clement if (!refVal) {
1896633f70f7SValentin Clement mlir::emitError(result.location, "LoadOp has null argument");
1897633f70f7SValentin Clement return;
1898633f70f7SValentin Clement }
1899633f70f7SValentin Clement auto eleTy = fir::dyn_cast_ptrEleTy(refVal.getType());
1900633f70f7SValentin Clement if (!eleTy) {
1901633f70f7SValentin Clement mlir::emitError(result.location, "not a memory reference type");
1902633f70f7SValentin Clement return;
1903633f70f7SValentin Clement }
1904633f70f7SValentin Clement result.addOperands(refVal);
1905633f70f7SValentin Clement result.addTypes(eleTy);
1906633f70f7SValentin Clement }
1907633f70f7SValentin Clement
getElementOf(mlir::Type & ele,mlir::Type ref)190857f536a4SjeanPerier mlir::ParseResult fir::LoadOp::getElementOf(mlir::Type &ele, mlir::Type ref) {
190949c08a22SKiran Chandramohan if ((ele = fir::dyn_cast_ptrEleTy(ref)))
191057f536a4SjeanPerier return mlir::success();
191157f536a4SjeanPerier return mlir::failure();
191257f536a4SjeanPerier }
191357f536a4SjeanPerier
parse(mlir::OpAsmParser & parser,mlir::OperationState & result)1914de8a65f7SEric Schweitz mlir::ParseResult fir::LoadOp::parse(mlir::OpAsmParser &parser,
1915633f70f7SValentin Clement mlir::OperationState &result) {
1916633f70f7SValentin Clement mlir::Type type;
1917e13d23bcSMarkus Böck mlir::OpAsmParser::UnresolvedOperand oper;
1918633f70f7SValentin Clement if (parser.parseOperand(oper) ||
1919633f70f7SValentin Clement parser.parseOptionalAttrDict(result.attributes) ||
1920633f70f7SValentin Clement parser.parseColonType(type) ||
1921633f70f7SValentin Clement parser.resolveOperand(oper, type, result.operands))
1922633f70f7SValentin Clement return mlir::failure();
1923633f70f7SValentin Clement mlir::Type eleTy;
1924633f70f7SValentin Clement if (fir::LoadOp::getElementOf(eleTy, type) ||
1925633f70f7SValentin Clement parser.addTypeToList(eleTy, result.types))
1926633f70f7SValentin Clement return mlir::failure();
1927633f70f7SValentin Clement return mlir::success();
1928633f70f7SValentin Clement }
1929633f70f7SValentin Clement
print(mlir::OpAsmPrinter & p)1930de8a65f7SEric Schweitz void fir::LoadOp::print(mlir::OpAsmPrinter &p) {
1931633f70f7SValentin Clement p << ' ';
1932149ad3d5SShraiysh Vaishay p.printOperand(getMemref());
1933cc120e36SShraiysh Vaishay p.printOptionalAttrDict(getOperation()->getAttrs(), {});
1934149ad3d5SShraiysh Vaishay p << " : " << getMemref().getType();
1935633f70f7SValentin Clement }
1936633f70f7SValentin Clement
193757f536a4SjeanPerier //===----------------------------------------------------------------------===//
19384463e39dSSourabh Singh Tomar // DoLoopOp
193957f536a4SjeanPerier //===----------------------------------------------------------------------===//
194057f536a4SjeanPerier
build(mlir::OpBuilder & builder,mlir::OperationState & result,mlir::Value lb,mlir::Value ub,mlir::Value step,bool unordered,bool finalCountValue,mlir::ValueRange iterArgs,llvm::ArrayRef<mlir::NamedAttribute> attributes)19414463e39dSSourabh Singh Tomar void fir::DoLoopOp::build(mlir::OpBuilder &builder,
19424463e39dSSourabh Singh Tomar mlir::OperationState &result, mlir::Value lb,
19434463e39dSSourabh Singh Tomar mlir::Value ub, mlir::Value step, bool unordered,
19440b785a46SEric Schweitz bool finalCountValue, mlir::ValueRange iterArgs,
1945bc034238SEric Schweitz llvm::ArrayRef<mlir::NamedAttribute> attributes) {
1946bc034238SEric Schweitz result.addOperands({lb, ub, step});
1947bc034238SEric Schweitz result.addOperands(iterArgs);
19480b785a46SEric Schweitz if (finalCountValue) {
19490b785a46SEric Schweitz result.addTypes(builder.getIndexType());
1950149ad3d5SShraiysh Vaishay result.addAttribute(getFinalValueAttrName(result.name),
1951149ad3d5SShraiysh Vaishay builder.getUnitAttr());
19520b785a46SEric Schweitz }
1953bc034238SEric Schweitz for (auto v : iterArgs)
1954bc034238SEric Schweitz result.addTypes(v.getType());
195557f536a4SjeanPerier mlir::Region *bodyRegion = result.addRegion();
1956de8a65f7SEric Schweitz bodyRegion->push_back(new mlir::Block{});
19570b785a46SEric Schweitz if (iterArgs.empty() && !finalCountValue)
1958de8a65f7SEric Schweitz fir::DoLoopOp::ensureTerminator(*bodyRegion, builder, result.location);
1959e084679fSRiver Riddle bodyRegion->front().addArgument(builder.getIndexType(), result.location);
1960e084679fSRiver Riddle bodyRegion->front().addArguments(
1961e084679fSRiver Riddle iterArgs.getTypes(),
1962de8a65f7SEric Schweitz llvm::SmallVector<mlir::Location>(iterArgs.size(), result.location));
1963bc034238SEric Schweitz if (unordered)
1964149ad3d5SShraiysh Vaishay result.addAttribute(getUnorderedAttrName(result.name),
1965149ad3d5SShraiysh Vaishay builder.getUnitAttr());
196657f536a4SjeanPerier result.addAttributes(attributes);
196757f536a4SjeanPerier }
196857f536a4SjeanPerier
parse(mlir::OpAsmParser & parser,mlir::OperationState & result)1969de8a65f7SEric Schweitz mlir::ParseResult fir::DoLoopOp::parse(mlir::OpAsmParser &parser,
197057f536a4SjeanPerier mlir::OperationState &result) {
197157f536a4SjeanPerier auto &builder = parser.getBuilder();
1972d85eb4e2SChris Lattner mlir::OpAsmParser::Argument inductionVariable;
1973d85eb4e2SChris Lattner mlir::OpAsmParser::UnresolvedOperand lb, ub, step;
197457f536a4SjeanPerier // Parse the induction variable followed by '='.
1975d85eb4e2SChris Lattner if (parser.parseArgument(inductionVariable) || parser.parseEqual())
197657f536a4SjeanPerier return mlir::failure();
197757f536a4SjeanPerier
197857f536a4SjeanPerier // Parse loop bounds.
1979bc034238SEric Schweitz auto indexType = builder.getIndexType();
198057f536a4SjeanPerier if (parser.parseOperand(lb) ||
198157f536a4SjeanPerier parser.resolveOperand(lb, indexType, result.operands) ||
198257f536a4SjeanPerier parser.parseKeyword("to") || parser.parseOperand(ub) ||
1983bc034238SEric Schweitz parser.resolveOperand(ub, indexType, result.operands) ||
1984bc034238SEric Schweitz parser.parseKeyword("step") || parser.parseOperand(step) ||
1985bc034238SEric Schweitz parser.resolveOperand(step, indexType, result.operands))
1986de8a65f7SEric Schweitz return mlir::failure();
198757f536a4SjeanPerier
1988bc034238SEric Schweitz if (mlir::succeeded(parser.parseOptionalKeyword("unordered")))
198900c93d88SRiver Riddle result.addAttribute("unordered", builder.getUnitAttr());
1990bc034238SEric Schweitz
1991bc034238SEric Schweitz // Parse the optional initial iteration arguments.
1992d85eb4e2SChris Lattner llvm::SmallVector<mlir::OpAsmParser::Argument> regionArgs;
1993d85eb4e2SChris Lattner llvm::SmallVector<mlir::OpAsmParser::UnresolvedOperand> operands;
1994067312d2SValentin Clement llvm::SmallVector<mlir::Type> argTypes;
1995de8a65f7SEric Schweitz bool prependCount = false;
1996bc034238SEric Schweitz regionArgs.push_back(inductionVariable);
1997bc034238SEric Schweitz
1998bc034238SEric Schweitz if (succeeded(parser.parseOptionalKeyword("iter_args"))) {
1999bc034238SEric Schweitz // Parse assignment list and results type list.
2000bc034238SEric Schweitz if (parser.parseAssignmentList(regionArgs, operands) ||
2001bc034238SEric Schweitz parser.parseArrowTypeList(result.types))
2002de8a65f7SEric Schweitz return mlir::failure();
20030b785a46SEric Schweitz if (result.types.size() == operands.size() + 1)
20040b785a46SEric Schweitz prependCount = true;
2005bc034238SEric Schweitz // Resolve input operands.
20060b785a46SEric Schweitz llvm::ArrayRef<mlir::Type> resTypes = result.types;
20070b785a46SEric Schweitz for (auto operand_type :
20080b785a46SEric Schweitz llvm::zip(operands, prependCount ? resTypes.drop_front() : resTypes))
2009bc034238SEric Schweitz if (parser.resolveOperand(std::get<0>(operand_type),
2010bc034238SEric Schweitz std::get<1>(operand_type), result.operands))
2011de8a65f7SEric Schweitz return mlir::failure();
20120b785a46SEric Schweitz } else if (succeeded(parser.parseOptionalArrow())) {
20130b785a46SEric Schweitz if (parser.parseKeyword("index"))
2014de8a65f7SEric Schweitz return mlir::failure();
20150b785a46SEric Schweitz result.types.push_back(indexType);
20160b785a46SEric Schweitz prependCount = true;
201757f536a4SjeanPerier }
201857f536a4SjeanPerier
2019bc034238SEric Schweitz if (parser.parseOptionalAttrDictWithKeyword(result.attributes))
2020bc034238SEric Schweitz return mlir::failure();
202157f536a4SjeanPerier
2022bc034238SEric Schweitz // Induction variable.
20230b785a46SEric Schweitz if (prependCount)
2024149ad3d5SShraiysh Vaishay result.addAttribute(DoLoopOp::getFinalValueAttrName(result.name),
202500c93d88SRiver Riddle builder.getUnitAttr());
20260b785a46SEric Schweitz else
2027bc034238SEric Schweitz argTypes.push_back(indexType);
2028bc034238SEric Schweitz // Loop carried variables
2029bc034238SEric Schweitz argTypes.append(result.types.begin(), result.types.end());
203057f536a4SjeanPerier // Parse the body region.
2031bc034238SEric Schweitz auto *body = result.addRegion();
2032bc034238SEric Schweitz if (regionArgs.size() != argTypes.size())
2033bc034238SEric Schweitz return parser.emitError(
2034bc034238SEric Schweitz parser.getNameLoc(),
2035bc034238SEric Schweitz "mismatch in number of loop-carried values and defined values");
2036d85eb4e2SChris Lattner for (size_t i = 0, e = regionArgs.size(); i != e; ++i)
2037d85eb4e2SChris Lattner regionArgs[i].type = argTypes[i];
2038bc034238SEric Schweitz
2039d85eb4e2SChris Lattner if (parser.parseRegion(*body, regionArgs))
2040de8a65f7SEric Schweitz return mlir::failure();
204157f536a4SjeanPerier
20420b785a46SEric Schweitz DoLoopOp::ensureTerminator(*body, builder, result.location);
204357f536a4SjeanPerier
204457f536a4SjeanPerier return mlir::success();
204557f536a4SjeanPerier }
204657f536a4SjeanPerier
getForInductionVarOwner(mlir::Value val)20474463e39dSSourabh Singh Tomar fir::DoLoopOp fir::getForInductionVarOwner(mlir::Value val) {
204857f536a4SjeanPerier auto ivArg = val.dyn_cast<mlir::BlockArgument>();
204957f536a4SjeanPerier if (!ivArg)
205057f536a4SjeanPerier return {};
205157f536a4SjeanPerier assert(ivArg.getOwner() && "unlinked block argument");
205257f536a4SjeanPerier auto *containingInst = ivArg.getOwner()->getParentOp();
2053de8a65f7SEric Schweitz return mlir::dyn_cast_or_null<fir::DoLoopOp>(containingInst);
205457f536a4SjeanPerier }
205557f536a4SjeanPerier
2056bc034238SEric Schweitz // Lifted from loop.loop
verify()2057de8a65f7SEric Schweitz mlir::LogicalResult fir::DoLoopOp::verify() {
2058bc034238SEric Schweitz // Check that the body defines as single block argument for the induction
2059bc034238SEric Schweitz // variable.
2060125a4d91SAndrzej Warzynski auto *body = getBody();
2061bc034238SEric Schweitz if (!body->getArgument(0).getType().isIndex())
2062125a4d91SAndrzej Warzynski return emitOpError(
2063bc034238SEric Schweitz "expected body first argument to be an index argument for "
2064bc034238SEric Schweitz "the induction variable");
2065bc034238SEric Schweitz
2066125a4d91SAndrzej Warzynski auto opNumResults = getNumResults();
2067bc034238SEric Schweitz if (opNumResults == 0)
2068de8a65f7SEric Schweitz return mlir::success();
20690b785a46SEric Schweitz
2070125a4d91SAndrzej Warzynski if (getFinalValue()) {
2071125a4d91SAndrzej Warzynski if (getUnordered())
2072125a4d91SAndrzej Warzynski return emitOpError("unordered loop has no final value");
20730b785a46SEric Schweitz opNumResults--;
20740b785a46SEric Schweitz }
2075125a4d91SAndrzej Warzynski if (getNumIterOperands() != opNumResults)
2076125a4d91SAndrzej Warzynski return emitOpError(
2077bc034238SEric Schweitz "mismatch in number of loop-carried values and defined values");
2078125a4d91SAndrzej Warzynski if (getNumRegionIterArgs() != opNumResults)
2079125a4d91SAndrzej Warzynski return emitOpError(
2080bc034238SEric Schweitz "mismatch in number of basic block args and defined values");
2081125a4d91SAndrzej Warzynski auto iterOperands = getIterOperands();
2082125a4d91SAndrzej Warzynski auto iterArgs = getRegionIterArgs();
2083125a4d91SAndrzej Warzynski auto opResults = getFinalValue() ? getResults().drop_front() : getResults();
2084de8a65f7SEric Schweitz unsigned i = 0u;
2085bc034238SEric Schweitz for (auto e : llvm::zip(iterOperands, iterArgs, opResults)) {
2086bc034238SEric Schweitz if (std::get<0>(e).getType() != std::get<2>(e).getType())
2087125a4d91SAndrzej Warzynski return emitOpError() << "types mismatch between " << i
2088bc034238SEric Schweitz << "th iter operand and defined value";
2089bc034238SEric Schweitz if (std::get<1>(e).getType() != std::get<2>(e).getType())
2090125a4d91SAndrzej Warzynski return emitOpError() << "types mismatch between " << i
2091bc034238SEric Schweitz << "th iter region arg and defined value";
2092bc034238SEric Schweitz
2093bc034238SEric Schweitz i++;
2094bc034238SEric Schweitz }
2095de8a65f7SEric Schweitz return mlir::success();
2096bc034238SEric Schweitz }
2097bc034238SEric Schweitz
print(mlir::OpAsmPrinter & p)2098de8a65f7SEric Schweitz void fir::DoLoopOp::print(mlir::OpAsmPrinter &p) {
2099bc034238SEric Schweitz bool printBlockTerminators = false;
2100125a4d91SAndrzej Warzynski p << ' ' << getInductionVar() << " = " << getLowerBound() << " to "
2101125a4d91SAndrzej Warzynski << getUpperBound() << " step " << getStep();
2102125a4d91SAndrzej Warzynski if (getUnordered())
2103bc034238SEric Schweitz p << " unordered";
2104125a4d91SAndrzej Warzynski if (hasIterOperands()) {
2105bc034238SEric Schweitz p << " iter_args(";
2106125a4d91SAndrzej Warzynski auto regionArgs = getRegionIterArgs();
2107125a4d91SAndrzej Warzynski auto operands = getIterOperands();
2108bc034238SEric Schweitz llvm::interleaveComma(llvm::zip(regionArgs, operands), p, [&](auto it) {
2109bc034238SEric Schweitz p << std::get<0>(it) << " = " << std::get<1>(it);
2110bc034238SEric Schweitz });
2111125a4d91SAndrzej Warzynski p << ") -> (" << getResultTypes() << ')';
2112bc034238SEric Schweitz printBlockTerminators = true;
2113125a4d91SAndrzej Warzynski } else if (getFinalValue()) {
2114125a4d91SAndrzej Warzynski p << " -> " << getResultTypes();
21150b785a46SEric Schweitz printBlockTerminators = true;
2116bc034238SEric Schweitz }
2117125a4d91SAndrzej Warzynski p.printOptionalAttrDictWithKeyword((*this)->getAttrs(),
211800c93d88SRiver Riddle {"unordered", "finalValue"});
21195c36ee8dSMogball p << ' ';
2120125a4d91SAndrzej Warzynski p.printRegion(getRegion(), /*printEntryBlockArgs=*/false,
2121bc034238SEric Schweitz printBlockTerminators);
2122bc034238SEric Schweitz }
2123bc034238SEric Schweitz
getLoopBody()2124149ad3d5SShraiysh Vaishay mlir::Region &fir::DoLoopOp::getLoopBody() { return getRegion(); }
2125bc034238SEric Schweitz
21260b785a46SEric Schweitz /// Translate a value passed as an iter_arg to the corresponding block
21270b785a46SEric Schweitz /// argument in the body of the loop.
iterArgToBlockArg(mlir::Value iterArg)21280b785a46SEric Schweitz mlir::BlockArgument fir::DoLoopOp::iterArgToBlockArg(mlir::Value iterArg) {
2129149ad3d5SShraiysh Vaishay for (auto i : llvm::enumerate(getInitArgs()))
21300b785a46SEric Schweitz if (iterArg == i.value())
2131149ad3d5SShraiysh Vaishay return getRegion().front().getArgument(i.index() + 1);
21320b785a46SEric Schweitz return {};
21330b785a46SEric Schweitz }
21340b785a46SEric Schweitz
21350b785a46SEric Schweitz /// Translate the result vector (by index number) to the corresponding value
21360b785a46SEric Schweitz /// to the `fir.result` Op.
resultToSourceOps(llvm::SmallVectorImpl<mlir::Value> & results,unsigned resultNum)21370b785a46SEric Schweitz void fir::DoLoopOp::resultToSourceOps(
21380b785a46SEric Schweitz llvm::SmallVectorImpl<mlir::Value> &results, unsigned resultNum) {
2139149ad3d5SShraiysh Vaishay auto oper = getFinalValue() ? resultNum + 1 : resultNum;
2140149ad3d5SShraiysh Vaishay auto *term = getRegion().front().getTerminator();
21410b785a46SEric Schweitz if (oper < term->getNumOperands())
21420b785a46SEric Schweitz results.push_back(term->getOperand(oper));
21430b785a46SEric Schweitz }
21440b785a46SEric Schweitz
21450b785a46SEric Schweitz /// Translate the block argument (by index number) to the corresponding value
21460b785a46SEric Schweitz /// passed as an iter_arg to the parent DoLoopOp.
blockArgToSourceOp(unsigned blockArgNum)21470b785a46SEric Schweitz mlir::Value fir::DoLoopOp::blockArgToSourceOp(unsigned blockArgNum) {
2148149ad3d5SShraiysh Vaishay if (blockArgNum > 0 && blockArgNum <= getInitArgs().size())
2149149ad3d5SShraiysh Vaishay return getInitArgs()[blockArgNum - 1];
21500b785a46SEric Schweitz return {};
21510b785a46SEric Schweitz }
21520b785a46SEric Schweitz
2153bc034238SEric Schweitz //===----------------------------------------------------------------------===//
2154633f70f7SValentin Clement // DTEntryOp
2155633f70f7SValentin Clement //===----------------------------------------------------------------------===//
2156633f70f7SValentin Clement
parse(mlir::OpAsmParser & parser,mlir::OperationState & result)2157de8a65f7SEric Schweitz mlir::ParseResult fir::DTEntryOp::parse(mlir::OpAsmParser &parser,
2158633f70f7SValentin Clement mlir::OperationState &result) {
2159633f70f7SValentin Clement llvm::StringRef methodName;
2160633f70f7SValentin Clement // allow `methodName` or `"methodName"`
2161633f70f7SValentin Clement if (failed(parser.parseOptionalKeyword(&methodName))) {
2162633f70f7SValentin Clement mlir::StringAttr methodAttr;
21633012f35fSJacques Pienaar if (parser.parseAttribute(methodAttr,
21643012f35fSJacques Pienaar fir::DTEntryOp::getMethodAttrNameStr(),
2165633f70f7SValentin Clement result.attributes))
2166633f70f7SValentin Clement return mlir::failure();
2167633f70f7SValentin Clement } else {
21683012f35fSJacques Pienaar result.addAttribute(fir::DTEntryOp::getMethodAttrNameStr(),
2169633f70f7SValentin Clement parser.getBuilder().getStringAttr(methodName));
2170633f70f7SValentin Clement }
2171633f70f7SValentin Clement mlir::SymbolRefAttr calleeAttr;
2172633f70f7SValentin Clement if (parser.parseComma() ||
21733012f35fSJacques Pienaar parser.parseAttribute(calleeAttr, fir::DTEntryOp::getProcAttrNameStr(),
2174633f70f7SValentin Clement result.attributes))
2175633f70f7SValentin Clement return mlir::failure();
2176633f70f7SValentin Clement return mlir::success();
2177633f70f7SValentin Clement }
2178633f70f7SValentin Clement
print(mlir::OpAsmPrinter & p)2179de8a65f7SEric Schweitz void fir::DTEntryOp::print(mlir::OpAsmPrinter &p) {
2180cc120e36SShraiysh Vaishay p << ' ' << getMethodAttr() << ", " << getProcAttr();
2181633f70f7SValentin Clement }
2182633f70f7SValentin Clement
2183633f70f7SValentin Clement //===----------------------------------------------------------------------===//
21840b785a46SEric Schweitz // ReboxOp
21850b785a46SEric Schweitz //===----------------------------------------------------------------------===//
21860b785a46SEric Schweitz
21870b785a46SEric Schweitz /// Get the scalar type related to a fir.box type.
21880b785a46SEric Schweitz /// Example: return f32 for !fir.box<!fir.heap<!fir.array<?x?xf32>>.
getBoxScalarEleTy(mlir::Type boxTy)21890b785a46SEric Schweitz static mlir::Type getBoxScalarEleTy(mlir::Type boxTy) {
21900b785a46SEric Schweitz auto eleTy = fir::dyn_cast_ptrOrBoxEleTy(boxTy);
21910b785a46SEric Schweitz if (auto seqTy = eleTy.dyn_cast<fir::SequenceType>())
21920b785a46SEric Schweitz return seqTy.getEleTy();
21930b785a46SEric Schweitz return eleTy;
21940b785a46SEric Schweitz }
21950b785a46SEric Schweitz
21960b785a46SEric Schweitz /// Get the rank from a !fir.box type
getBoxRank(mlir::Type boxTy)21970b785a46SEric Schweitz static unsigned getBoxRank(mlir::Type boxTy) {
21980b785a46SEric Schweitz auto eleTy = fir::dyn_cast_ptrOrBoxEleTy(boxTy);
21990b785a46SEric Schweitz if (auto seqTy = eleTy.dyn_cast<fir::SequenceType>())
22000b785a46SEric Schweitz return seqTy.getDimension();
22010b785a46SEric Schweitz return 0;
22020b785a46SEric Schweitz }
22030b785a46SEric Schweitz
22047d52beb2SJean Perier /// Test if \p t1 and \p t2 are compatible character types (if they can
22057d52beb2SJean Perier /// represent the same type at runtime).
areCompatibleCharacterTypes(mlir::Type t1,mlir::Type t2)22067d52beb2SJean Perier static bool areCompatibleCharacterTypes(mlir::Type t1, mlir::Type t2) {
22077d52beb2SJean Perier auto c1 = t1.dyn_cast<fir::CharacterType>();
22087d52beb2SJean Perier auto c2 = t2.dyn_cast<fir::CharacterType>();
22097d52beb2SJean Perier if (!c1 || !c2)
22107d52beb2SJean Perier return false;
22117d52beb2SJean Perier if (c1.hasDynamicLen() || c2.hasDynamicLen())
22127d52beb2SJean Perier return true;
22137d52beb2SJean Perier return c1.getLen() == c2.getLen();
22147d52beb2SJean Perier }
22157d52beb2SJean Perier
verify()2216de8a65f7SEric Schweitz mlir::LogicalResult fir::ReboxOp::verify() {
2217149ad3d5SShraiysh Vaishay auto inputBoxTy = getBox().getType();
22180b785a46SEric Schweitz if (fir::isa_unknown_size_box(inputBoxTy))
2219cc120e36SShraiysh Vaishay return emitOpError("box operand must not have unknown rank or type");
2220cc120e36SShraiysh Vaishay auto outBoxTy = getType();
22210b785a46SEric Schweitz if (fir::isa_unknown_size_box(outBoxTy))
2222cc120e36SShraiysh Vaishay return emitOpError("result type must not have unknown rank or type");
22230b785a46SEric Schweitz auto inputRank = getBoxRank(inputBoxTy);
22240b785a46SEric Schweitz auto inputEleTy = getBoxScalarEleTy(inputBoxTy);
22250b785a46SEric Schweitz auto outRank = getBoxRank(outBoxTy);
22260b785a46SEric Schweitz auto outEleTy = getBoxScalarEleTy(outBoxTy);
22270b785a46SEric Schweitz
2228149ad3d5SShraiysh Vaishay if (auto sliceVal = getSlice()) {
22290b785a46SEric Schweitz // Slicing case
2230cc120e36SShraiysh Vaishay if (sliceVal.getType().cast<fir::SliceType>().getRank() != inputRank)
2231cc120e36SShraiysh Vaishay return emitOpError("slice operand rank must match box operand rank");
2232149ad3d5SShraiysh Vaishay if (auto shapeVal = getShape()) {
2233cc120e36SShraiysh Vaishay if (auto shiftTy = shapeVal.getType().dyn_cast<fir::ShiftType>()) {
22340b785a46SEric Schweitz if (shiftTy.getRank() != inputRank)
2235cc120e36SShraiysh Vaishay return emitOpError("shape operand and input box ranks must match "
22360b785a46SEric Schweitz "when there is a slice");
22370b785a46SEric Schweitz } else {
2238cc120e36SShraiysh Vaishay return emitOpError("shape operand must absent or be a fir.shift "
22390b785a46SEric Schweitz "when there is a slice");
22400b785a46SEric Schweitz }
22410b785a46SEric Schweitz }
2242cc120e36SShraiysh Vaishay if (auto sliceOp = sliceVal.getDefiningOp()) {
22430b785a46SEric Schweitz auto slicedRank = mlir::cast<fir::SliceOp>(sliceOp).getOutRank();
22440b785a46SEric Schweitz if (slicedRank != outRank)
2245cc120e36SShraiysh Vaishay return emitOpError("result type rank and rank after applying slice "
22460b785a46SEric Schweitz "operand must match");
22470b785a46SEric Schweitz }
22480b785a46SEric Schweitz } else {
22490b785a46SEric Schweitz // Reshaping case
22500b785a46SEric Schweitz unsigned shapeRank = inputRank;
2251149ad3d5SShraiysh Vaishay if (auto shapeVal = getShape()) {
2252cc120e36SShraiysh Vaishay auto ty = shapeVal.getType();
22530b785a46SEric Schweitz if (auto shapeTy = ty.dyn_cast<fir::ShapeType>()) {
22540b785a46SEric Schweitz shapeRank = shapeTy.getRank();
22550b785a46SEric Schweitz } else if (auto shapeShiftTy = ty.dyn_cast<fir::ShapeShiftType>()) {
22560b785a46SEric Schweitz shapeRank = shapeShiftTy.getRank();
22570b785a46SEric Schweitz } else {
22580b785a46SEric Schweitz auto shiftTy = ty.cast<fir::ShiftType>();
22590b785a46SEric Schweitz shapeRank = shiftTy.getRank();
22600b785a46SEric Schweitz if (shapeRank != inputRank)
2261cc120e36SShraiysh Vaishay return emitOpError("shape operand and input box ranks must match "
22620b785a46SEric Schweitz "when the shape is a fir.shift");
22630b785a46SEric Schweitz }
22640b785a46SEric Schweitz }
22650b785a46SEric Schweitz if (shapeRank != outRank)
2266cc120e36SShraiysh Vaishay return emitOpError("result type and shape operand ranks must match");
22670b785a46SEric Schweitz }
22680b785a46SEric Schweitz
22697d52beb2SJean Perier if (inputEleTy != outEleTy) {
22700b785a46SEric Schweitz // TODO: check that outBoxTy is a parent type of inputBoxTy for derived
22710b785a46SEric Schweitz // types.
22727d52beb2SJean Perier // Character input and output types with constant length may be different if
22737d52beb2SJean Perier // there is a substring in the slice, otherwise, they must match. If any of
22747d52beb2SJean Perier // the types is a character with dynamic length, the other type can be any
22757d52beb2SJean Perier // character type.
22767d52beb2SJean Perier const bool typeCanMismatch =
22777d52beb2SJean Perier inputEleTy.isa<fir::RecordType>() ||
22787d52beb2SJean Perier (getSlice() && inputEleTy.isa<fir::CharacterType>()) ||
22797d52beb2SJean Perier areCompatibleCharacterTypes(inputEleTy, outEleTy);
22807d52beb2SJean Perier if (!typeCanMismatch)
2281cc120e36SShraiysh Vaishay return emitOpError(
22820b785a46SEric Schweitz "op input and output element types must match for intrinsic types");
22837d52beb2SJean Perier }
22840b785a46SEric Schweitz return mlir::success();
22850b785a46SEric Schweitz }
22860b785a46SEric Schweitz
22870b785a46SEric Schweitz //===----------------------------------------------------------------------===//
2288bc034238SEric Schweitz // ResultOp
2289bc034238SEric Schweitz //===----------------------------------------------------------------------===//
2290bc034238SEric Schweitz
verify()2291de8a65f7SEric Schweitz mlir::LogicalResult fir::ResultOp::verify() {
2292cc120e36SShraiysh Vaishay auto *parentOp = (*this)->getParentOp();
2293bc034238SEric Schweitz auto results = parentOp->getResults();
2294cc120e36SShraiysh Vaishay auto operands = (*this)->getOperands();
2295bc034238SEric Schweitz
2296cc120e36SShraiysh Vaishay if (parentOp->getNumResults() != getNumOperands())
2297cc120e36SShraiysh Vaishay return emitOpError() << "parent of result must have same arity";
22982e046be9SRahul Joshi for (auto e : llvm::zip(results, operands))
2299bc034238SEric Schweitz if (std::get<0>(e).getType() != std::get<1>(e).getType())
2300cc120e36SShraiysh Vaishay return emitOpError() << "types mismatch between result op and its parent";
2301de8a65f7SEric Schweitz return mlir::success();
2302bc034238SEric Schweitz }
2303bc034238SEric Schweitz
230457f536a4SjeanPerier //===----------------------------------------------------------------------===//
23055b5ef2e2SEric Schweitz // SaveResultOp
23065b5ef2e2SEric Schweitz //===----------------------------------------------------------------------===//
23075b5ef2e2SEric Schweitz
verify()2308de8a65f7SEric Schweitz mlir::LogicalResult fir::SaveResultOp::verify() {
2309149ad3d5SShraiysh Vaishay auto resultType = getValue().getType();
2310149ad3d5SShraiysh Vaishay if (resultType != fir::dyn_cast_ptrEleTy(getMemref().getType()))
2311cc120e36SShraiysh Vaishay return emitOpError("value type must match memory reference type");
23125b5ef2e2SEric Schweitz if (fir::isa_unknown_size_box(resultType))
2313cc120e36SShraiysh Vaishay return emitOpError("cannot save !fir.box of unknown rank or type");
23145b5ef2e2SEric Schweitz
23155b5ef2e2SEric Schweitz if (resultType.isa<fir::BoxType>()) {
2316149ad3d5SShraiysh Vaishay if (getShape() || !getTypeparams().empty())
2317cc120e36SShraiysh Vaishay return emitOpError(
23185b5ef2e2SEric Schweitz "must not have shape or length operands if the value is a fir.box");
23195b5ef2e2SEric Schweitz return mlir::success();
23205b5ef2e2SEric Schweitz }
23215b5ef2e2SEric Schweitz
23225b5ef2e2SEric Schweitz // fir.record or fir.array case.
23235b5ef2e2SEric Schweitz unsigned shapeTyRank = 0;
2324149ad3d5SShraiysh Vaishay if (auto shapeVal = getShape()) {
2325cc120e36SShraiysh Vaishay auto shapeTy = shapeVal.getType();
23265b5ef2e2SEric Schweitz if (auto s = shapeTy.dyn_cast<fir::ShapeType>())
23275b5ef2e2SEric Schweitz shapeTyRank = s.getRank();
23285b5ef2e2SEric Schweitz else
23295b5ef2e2SEric Schweitz shapeTyRank = shapeTy.cast<fir::ShapeShiftType>().getRank();
23305b5ef2e2SEric Schweitz }
23315b5ef2e2SEric Schweitz
23325b5ef2e2SEric Schweitz auto eleTy = resultType;
23335b5ef2e2SEric Schweitz if (auto seqTy = resultType.dyn_cast<fir::SequenceType>()) {
23345b5ef2e2SEric Schweitz if (seqTy.getDimension() != shapeTyRank)
2335cc120e36SShraiysh Vaishay emitOpError("shape operand must be provided and have the value rank "
23365b5ef2e2SEric Schweitz "when the value is a fir.array");
23375b5ef2e2SEric Schweitz eleTy = seqTy.getEleTy();
23385b5ef2e2SEric Schweitz } else {
23395b5ef2e2SEric Schweitz if (shapeTyRank != 0)
2340cc120e36SShraiysh Vaishay emitOpError(
23415b5ef2e2SEric Schweitz "shape operand should only be provided if the value is a fir.array");
23425b5ef2e2SEric Schweitz }
23435b5ef2e2SEric Schweitz
23445b5ef2e2SEric Schweitz if (auto recTy = eleTy.dyn_cast<fir::RecordType>()) {
2345149ad3d5SShraiysh Vaishay if (recTy.getNumLenParams() != getTypeparams().size())
2346cc120e36SShraiysh Vaishay emitOpError("length parameters number must match with the value type "
23475b5ef2e2SEric Schweitz "length parameters");
23485b5ef2e2SEric Schweitz } else if (auto charTy = eleTy.dyn_cast<fir::CharacterType>()) {
2349149ad3d5SShraiysh Vaishay if (getTypeparams().size() > 1)
2350cc120e36SShraiysh Vaishay emitOpError("no more than one length parameter must be provided for "
23515b5ef2e2SEric Schweitz "character value");
23525b5ef2e2SEric Schweitz } else {
2353149ad3d5SShraiysh Vaishay if (!getTypeparams().empty())
2354cc120e36SShraiysh Vaishay emitOpError("length parameters must not be provided for this value type");
23555b5ef2e2SEric Schweitz }
23565b5ef2e2SEric Schweitz
23575b5ef2e2SEric Schweitz return mlir::success();
23585b5ef2e2SEric Schweitz }
23595b5ef2e2SEric Schweitz
23605b5ef2e2SEric Schweitz //===----------------------------------------------------------------------===//
2361125a4d91SAndrzej Warzynski // IntegralSwitchTerminator
236257f536a4SjeanPerier //===----------------------------------------------------------------------===//
getCompareOffsetAttr()236357f536a4SjeanPerier static constexpr llvm::StringRef getCompareOffsetAttr() {
236457f536a4SjeanPerier return "compare_operand_offsets";
236557f536a4SjeanPerier }
236657f536a4SjeanPerier
getTargetOffsetAttr()236757f536a4SjeanPerier static constexpr llvm::StringRef getTargetOffsetAttr() {
236857f536a4SjeanPerier return "target_operand_offsets";
236957f536a4SjeanPerier }
237057f536a4SjeanPerier
2371125a4d91SAndrzej Warzynski template <typename OpT>
verifyIntegralSwitchTerminator(OpT op)2372de8a65f7SEric Schweitz static mlir::LogicalResult verifyIntegralSwitchTerminator(OpT op) {
2373de8a65f7SEric Schweitz if (!op.getSelector()
2374de8a65f7SEric Schweitz .getType()
2375de8a65f7SEric Schweitz .template isa<mlir::IntegerType, mlir::IndexType,
2376de8a65f7SEric Schweitz fir::IntegerType>())
2377125a4d91SAndrzej Warzynski return op.emitOpError("must be an integer");
2378125a4d91SAndrzej Warzynski auto cases =
2379125a4d91SAndrzej Warzynski op->template getAttrOfType<mlir::ArrayAttr>(op.getCasesAttr()).getValue();
2380125a4d91SAndrzej Warzynski auto count = op.getNumDest();
2381125a4d91SAndrzej Warzynski if (count == 0)
2382125a4d91SAndrzej Warzynski return op.emitOpError("must have at least one successor");
2383125a4d91SAndrzej Warzynski if (op.getNumConditions() != count)
2384125a4d91SAndrzej Warzynski return op.emitOpError("number of cases and targets don't match");
2385125a4d91SAndrzej Warzynski if (op.targetOffsetSize() != count)
2386125a4d91SAndrzej Warzynski return op.emitOpError("incorrect number of successor operand groups");
2387125a4d91SAndrzej Warzynski for (decltype(count) i = 0; i != count; ++i) {
2388de8a65f7SEric Schweitz if (!cases[i].template isa<mlir::IntegerAttr, mlir::UnitAttr>())
2389125a4d91SAndrzej Warzynski return op.emitOpError("invalid case alternative");
2390125a4d91SAndrzej Warzynski }
2391125a4d91SAndrzej Warzynski return mlir::success();
2392125a4d91SAndrzej Warzynski }
2393125a4d91SAndrzej Warzynski
parseIntegralSwitchTerminator(mlir::OpAsmParser & parser,mlir::OperationState & result,llvm::StringRef casesAttr,llvm::StringRef operandSegmentAttr)2394125a4d91SAndrzej Warzynski static mlir::ParseResult parseIntegralSwitchTerminator(
2395125a4d91SAndrzej Warzynski mlir::OpAsmParser &parser, mlir::OperationState &result,
2396125a4d91SAndrzej Warzynski llvm::StringRef casesAttr, llvm::StringRef operandSegmentAttr) {
2397e13d23bcSMarkus Böck mlir::OpAsmParser::UnresolvedOperand selector;
2398125a4d91SAndrzej Warzynski mlir::Type type;
2399de8a65f7SEric Schweitz if (fir::parseSelector(parser, result, selector, type))
2400125a4d91SAndrzej Warzynski return mlir::failure();
2401125a4d91SAndrzej Warzynski
2402125a4d91SAndrzej Warzynski llvm::SmallVector<mlir::Attribute> ivalues;
2403125a4d91SAndrzej Warzynski llvm::SmallVector<mlir::Block *> dests;
2404125a4d91SAndrzej Warzynski llvm::SmallVector<llvm::SmallVector<mlir::Value>> destArgs;
2405125a4d91SAndrzej Warzynski while (true) {
2406125a4d91SAndrzej Warzynski mlir::Attribute ivalue; // Integer or Unit
2407125a4d91SAndrzej Warzynski mlir::Block *dest;
2408125a4d91SAndrzej Warzynski llvm::SmallVector<mlir::Value> destArg;
2409125a4d91SAndrzej Warzynski mlir::NamedAttrList temp;
2410125a4d91SAndrzej Warzynski if (parser.parseAttribute(ivalue, "i", temp) || parser.parseComma() ||
2411125a4d91SAndrzej Warzynski parser.parseSuccessorAndUseList(dest, destArg))
2412125a4d91SAndrzej Warzynski return mlir::failure();
2413125a4d91SAndrzej Warzynski ivalues.push_back(ivalue);
2414125a4d91SAndrzej Warzynski dests.push_back(dest);
2415125a4d91SAndrzej Warzynski destArgs.push_back(destArg);
2416125a4d91SAndrzej Warzynski if (!parser.parseOptionalRSquare())
2417125a4d91SAndrzej Warzynski break;
2418125a4d91SAndrzej Warzynski if (parser.parseComma())
2419125a4d91SAndrzej Warzynski return mlir::failure();
2420125a4d91SAndrzej Warzynski }
2421125a4d91SAndrzej Warzynski auto &bld = parser.getBuilder();
2422125a4d91SAndrzej Warzynski result.addAttribute(casesAttr, bld.getArrayAttr(ivalues));
2423125a4d91SAndrzej Warzynski llvm::SmallVector<int32_t> argOffs;
2424125a4d91SAndrzej Warzynski int32_t sumArgs = 0;
2425125a4d91SAndrzej Warzynski const auto count = dests.size();
2426125a4d91SAndrzej Warzynski for (std::remove_const_t<decltype(count)> i = 0; i != count; ++i) {
2427125a4d91SAndrzej Warzynski result.addSuccessors(dests[i]);
2428125a4d91SAndrzej Warzynski result.addOperands(destArgs[i]);
2429125a4d91SAndrzej Warzynski auto argSize = destArgs[i].size();
2430125a4d91SAndrzej Warzynski argOffs.push_back(argSize);
2431125a4d91SAndrzej Warzynski sumArgs += argSize;
2432125a4d91SAndrzej Warzynski }
2433125a4d91SAndrzej Warzynski result.addAttribute(operandSegmentAttr,
2434125a4d91SAndrzej Warzynski bld.getI32VectorAttr({1, 0, sumArgs}));
2435125a4d91SAndrzej Warzynski result.addAttribute(getTargetOffsetAttr(), bld.getI32VectorAttr(argOffs));
2436125a4d91SAndrzej Warzynski return mlir::success();
2437125a4d91SAndrzej Warzynski }
2438125a4d91SAndrzej Warzynski
2439125a4d91SAndrzej Warzynski template <typename OpT>
printIntegralSwitchTerminator(OpT op,mlir::OpAsmPrinter & p)2440125a4d91SAndrzej Warzynski static void printIntegralSwitchTerminator(OpT op, mlir::OpAsmPrinter &p) {
2441125a4d91SAndrzej Warzynski p << ' ';
2442125a4d91SAndrzej Warzynski p.printOperand(op.getSelector());
2443125a4d91SAndrzej Warzynski p << " : " << op.getSelector().getType() << " [";
2444125a4d91SAndrzej Warzynski auto cases =
2445125a4d91SAndrzej Warzynski op->template getAttrOfType<mlir::ArrayAttr>(op.getCasesAttr()).getValue();
2446125a4d91SAndrzej Warzynski auto count = op.getNumConditions();
2447125a4d91SAndrzej Warzynski for (decltype(count) i = 0; i != count; ++i) {
2448125a4d91SAndrzej Warzynski if (i)
2449125a4d91SAndrzej Warzynski p << ", ";
2450125a4d91SAndrzej Warzynski auto &attr = cases[i];
2451125a4d91SAndrzej Warzynski if (auto intAttr = attr.template dyn_cast_or_null<mlir::IntegerAttr>())
2452125a4d91SAndrzej Warzynski p << intAttr.getValue();
2453125a4d91SAndrzej Warzynski else
2454125a4d91SAndrzej Warzynski p.printAttribute(attr);
2455125a4d91SAndrzej Warzynski p << ", ";
2456125a4d91SAndrzej Warzynski op.printSuccessorAtIndex(p, i);
2457125a4d91SAndrzej Warzynski }
2458125a4d91SAndrzej Warzynski p << ']';
2459125a4d91SAndrzej Warzynski p.printOptionalAttrDict(
2460125a4d91SAndrzej Warzynski op->getAttrs(), {op.getCasesAttr(), getCompareOffsetAttr(),
2461125a4d91SAndrzej Warzynski getTargetOffsetAttr(), op.getOperandSegmentSizeAttr()});
2462125a4d91SAndrzej Warzynski }
2463125a4d91SAndrzej Warzynski
2464125a4d91SAndrzej Warzynski //===----------------------------------------------------------------------===//
2465125a4d91SAndrzej Warzynski // SelectOp
2466125a4d91SAndrzej Warzynski //===----------------------------------------------------------------------===//
2467125a4d91SAndrzej Warzynski
verify()2468125a4d91SAndrzej Warzynski mlir::LogicalResult fir::SelectOp::verify() {
2469125a4d91SAndrzej Warzynski return verifyIntegralSwitchTerminator(*this);
2470125a4d91SAndrzej Warzynski }
2471125a4d91SAndrzej Warzynski
parse(mlir::OpAsmParser & parser,mlir::OperationState & result)2472125a4d91SAndrzej Warzynski mlir::ParseResult fir::SelectOp::parse(mlir::OpAsmParser &parser,
2473125a4d91SAndrzej Warzynski mlir::OperationState &result) {
2474125a4d91SAndrzej Warzynski return parseIntegralSwitchTerminator(parser, result, getCasesAttr(),
2475125a4d91SAndrzej Warzynski getOperandSegmentSizeAttr());
2476125a4d91SAndrzej Warzynski }
2477125a4d91SAndrzej Warzynski
print(mlir::OpAsmPrinter & p)2478125a4d91SAndrzej Warzynski void fir::SelectOp::print(mlir::OpAsmPrinter &p) {
2479125a4d91SAndrzej Warzynski printIntegralSwitchTerminator(*this, p);
2480125a4d91SAndrzej Warzynski }
2481125a4d91SAndrzej Warzynski
24820752d98cSRiver Riddle template <typename A, typename... AdditionalArgs>
getSubOperands(unsigned pos,A allArgs,mlir::DenseIntElementsAttr ranges,AdditionalArgs &&...additionalArgs)248357f536a4SjeanPerier static A getSubOperands(unsigned pos, A allArgs,
24840752d98cSRiver Riddle mlir::DenseIntElementsAttr ranges,
24850752d98cSRiver Riddle AdditionalArgs &&...additionalArgs) {
248657f536a4SjeanPerier unsigned start = 0;
248757f536a4SjeanPerier for (unsigned i = 0; i < pos; ++i)
248857f536a4SjeanPerier start += (*(ranges.begin() + i)).getZExtValue();
24890752d98cSRiver Riddle return allArgs.slice(start, (*(ranges.begin() + pos)).getZExtValue(),
24900752d98cSRiver Riddle std::forward<AdditionalArgs>(additionalArgs)...);
24910752d98cSRiver Riddle }
24920752d98cSRiver Riddle
24930752d98cSRiver Riddle static mlir::MutableOperandRange
getMutableSuccessorOperands(unsigned pos,mlir::MutableOperandRange operands,llvm::StringRef offsetAttr)24940752d98cSRiver Riddle getMutableSuccessorOperands(unsigned pos, mlir::MutableOperandRange operands,
2495de8a65f7SEric Schweitz llvm::StringRef offsetAttr) {
2496de8a65f7SEric Schweitz mlir::Operation *owner = operands.getOwner();
2497de8a65f7SEric Schweitz mlir::NamedAttribute targetOffsetAttr =
2498fc5cf50eSRiver Riddle *owner->getAttrDictionary().getNamed(offsetAttr);
24990752d98cSRiver Riddle return getSubOperands(
2500de8a65f7SEric Schweitz pos, operands,
2501de8a65f7SEric Schweitz targetOffsetAttr.getValue().cast<mlir::DenseIntElementsAttr>(),
25020752d98cSRiver Riddle mlir::MutableOperandRange::OperandSegment(pos, targetOffsetAttr));
250357f536a4SjeanPerier }
250457f536a4SjeanPerier
denseElementsSize(mlir::DenseIntElementsAttr attr)2505bc034238SEric Schweitz static unsigned denseElementsSize(mlir::DenseIntElementsAttr attr) {
2506bc034238SEric Schweitz return attr.getNumElements();
2507bc034238SEric Schweitz }
2508bc034238SEric Schweitz
getCompareOperands(unsigned)250957f536a4SjeanPerier llvm::Optional<mlir::OperandRange> fir::SelectOp::getCompareOperands(unsigned) {
251057f536a4SjeanPerier return {};
251157f536a4SjeanPerier }
251257f536a4SjeanPerier
251357f536a4SjeanPerier llvm::Optional<llvm::ArrayRef<mlir::Value>>
getCompareOperands(llvm::ArrayRef<mlir::Value>,unsigned)251457f536a4SjeanPerier fir::SelectOp::getCompareOperands(llvm::ArrayRef<mlir::Value>, unsigned) {
251557f536a4SjeanPerier return {};
251657f536a4SjeanPerier }
251757f536a4SjeanPerier
getSuccessorOperands(unsigned oper)25180c789db5SMarkus Böck mlir::SuccessorOperands fir::SelectOp::getSuccessorOperands(unsigned oper) {
25190c789db5SMarkus Böck return mlir::SuccessorOperands(::getMutableSuccessorOperands(
25200c789db5SMarkus Böck oper, getTargetArgsMutable(), getTargetOffsetAttr()));
252157f536a4SjeanPerier }
252257f536a4SjeanPerier
252357f536a4SjeanPerier llvm::Optional<llvm::ArrayRef<mlir::Value>>
getSuccessorOperands(llvm::ArrayRef<mlir::Value> operands,unsigned oper)252457f536a4SjeanPerier fir::SelectOp::getSuccessorOperands(llvm::ArrayRef<mlir::Value> operands,
252557f536a4SjeanPerier unsigned oper) {
2526a1eb1544SChristian Sigg auto a =
2527a1eb1544SChristian Sigg (*this)->getAttrOfType<mlir::DenseIntElementsAttr>(getTargetOffsetAttr());
2528a1eb1544SChristian Sigg auto segments = (*this)->getAttrOfType<mlir::DenseIntElementsAttr>(
2529a1eb1544SChristian Sigg getOperandSegmentSizeAttr());
253057f536a4SjeanPerier return {getSubOperands(oper, getSubOperands(2, operands, segments), a)};
253157f536a4SjeanPerier }
253257f536a4SjeanPerier
25338c239909SValentin Clement llvm::Optional<mlir::ValueRange>
getSuccessorOperands(mlir::ValueRange operands,unsigned oper)25348c239909SValentin Clement fir::SelectOp::getSuccessorOperands(mlir::ValueRange operands, unsigned oper) {
25358c239909SValentin Clement auto a =
25368c239909SValentin Clement (*this)->getAttrOfType<mlir::DenseIntElementsAttr>(getTargetOffsetAttr());
25378c239909SValentin Clement auto segments = (*this)->getAttrOfType<mlir::DenseIntElementsAttr>(
25388c239909SValentin Clement getOperandSegmentSizeAttr());
25398c239909SValentin Clement return {getSubOperands(oper, getSubOperands(2, operands, segments), a)};
25408c239909SValentin Clement }
25418c239909SValentin Clement
targetOffsetSize()2542bc034238SEric Schweitz unsigned fir::SelectOp::targetOffsetSize() {
2543a1eb1544SChristian Sigg return denseElementsSize((*this)->getAttrOfType<mlir::DenseIntElementsAttr>(
2544a1eb1544SChristian Sigg getTargetOffsetAttr()));
2545bc034238SEric Schweitz }
2546bc034238SEric Schweitz
254757f536a4SjeanPerier //===----------------------------------------------------------------------===//
254857f536a4SjeanPerier // SelectCaseOp
254957f536a4SjeanPerier //===----------------------------------------------------------------------===//
255057f536a4SjeanPerier
255157f536a4SjeanPerier llvm::Optional<mlir::OperandRange>
getCompareOperands(unsigned cond)255257f536a4SjeanPerier fir::SelectCaseOp::getCompareOperands(unsigned cond) {
2553a1eb1544SChristian Sigg auto a = (*this)->getAttrOfType<mlir::DenseIntElementsAttr>(
2554a1eb1544SChristian Sigg getCompareOffsetAttr());
2555149ad3d5SShraiysh Vaishay return {getSubOperands(cond, getCompareArgs(), a)};
255657f536a4SjeanPerier }
255757f536a4SjeanPerier
255857f536a4SjeanPerier llvm::Optional<llvm::ArrayRef<mlir::Value>>
getCompareOperands(llvm::ArrayRef<mlir::Value> operands,unsigned cond)255957f536a4SjeanPerier fir::SelectCaseOp::getCompareOperands(llvm::ArrayRef<mlir::Value> operands,
256057f536a4SjeanPerier unsigned cond) {
2561a1eb1544SChristian Sigg auto a = (*this)->getAttrOfType<mlir::DenseIntElementsAttr>(
2562a1eb1544SChristian Sigg getCompareOffsetAttr());
2563a1eb1544SChristian Sigg auto segments = (*this)->getAttrOfType<mlir::DenseIntElementsAttr>(
2564a1eb1544SChristian Sigg getOperandSegmentSizeAttr());
256557f536a4SjeanPerier return {getSubOperands(cond, getSubOperands(1, operands, segments), a)};
256657f536a4SjeanPerier }
256757f536a4SjeanPerier
256839f4ef81SValentin Clement llvm::Optional<mlir::ValueRange>
getCompareOperands(mlir::ValueRange operands,unsigned cond)256939f4ef81SValentin Clement fir::SelectCaseOp::getCompareOperands(mlir::ValueRange operands,
257039f4ef81SValentin Clement unsigned cond) {
257139f4ef81SValentin Clement auto a = (*this)->getAttrOfType<mlir::DenseIntElementsAttr>(
257239f4ef81SValentin Clement getCompareOffsetAttr());
257339f4ef81SValentin Clement auto segments = (*this)->getAttrOfType<mlir::DenseIntElementsAttr>(
257439f4ef81SValentin Clement getOperandSegmentSizeAttr());
257539f4ef81SValentin Clement return {getSubOperands(cond, getSubOperands(1, operands, segments), a)};
257639f4ef81SValentin Clement }
257739f4ef81SValentin Clement
getSuccessorOperands(unsigned oper)25780c789db5SMarkus Böck mlir::SuccessorOperands fir::SelectCaseOp::getSuccessorOperands(unsigned oper) {
25790c789db5SMarkus Böck return mlir::SuccessorOperands(::getMutableSuccessorOperands(
25800c789db5SMarkus Böck oper, getTargetArgsMutable(), getTargetOffsetAttr()));
258157f536a4SjeanPerier }
258257f536a4SjeanPerier
258357f536a4SjeanPerier llvm::Optional<llvm::ArrayRef<mlir::Value>>
getSuccessorOperands(llvm::ArrayRef<mlir::Value> operands,unsigned oper)258457f536a4SjeanPerier fir::SelectCaseOp::getSuccessorOperands(llvm::ArrayRef<mlir::Value> operands,
258557f536a4SjeanPerier unsigned oper) {
2586a1eb1544SChristian Sigg auto a =
2587a1eb1544SChristian Sigg (*this)->getAttrOfType<mlir::DenseIntElementsAttr>(getTargetOffsetAttr());
2588a1eb1544SChristian Sigg auto segments = (*this)->getAttrOfType<mlir::DenseIntElementsAttr>(
2589a1eb1544SChristian Sigg getOperandSegmentSizeAttr());
259057f536a4SjeanPerier return {getSubOperands(oper, getSubOperands(2, operands, segments), a)};
259157f536a4SjeanPerier }
259257f536a4SjeanPerier
259339f4ef81SValentin Clement llvm::Optional<mlir::ValueRange>
getSuccessorOperands(mlir::ValueRange operands,unsigned oper)259439f4ef81SValentin Clement fir::SelectCaseOp::getSuccessorOperands(mlir::ValueRange operands,
259539f4ef81SValentin Clement unsigned oper) {
259639f4ef81SValentin Clement auto a =
259739f4ef81SValentin Clement (*this)->getAttrOfType<mlir::DenseIntElementsAttr>(getTargetOffsetAttr());
259839f4ef81SValentin Clement auto segments = (*this)->getAttrOfType<mlir::DenseIntElementsAttr>(
259939f4ef81SValentin Clement getOperandSegmentSizeAttr());
260039f4ef81SValentin Clement return {getSubOperands(oper, getSubOperands(2, operands, segments), a)};
260139f4ef81SValentin Clement }
260239f4ef81SValentin Clement
260357f536a4SjeanPerier // parser for fir.select_case Op
parse(mlir::OpAsmParser & parser,mlir::OperationState & result)2604de8a65f7SEric Schweitz mlir::ParseResult fir::SelectCaseOp::parse(mlir::OpAsmParser &parser,
260557f536a4SjeanPerier mlir::OperationState &result) {
2606e13d23bcSMarkus Böck mlir::OpAsmParser::UnresolvedOperand selector;
260757f536a4SjeanPerier mlir::Type type;
2608de8a65f7SEric Schweitz if (fir::parseSelector(parser, result, selector, type))
260957f536a4SjeanPerier return mlir::failure();
261057f536a4SjeanPerier
2611067312d2SValentin Clement llvm::SmallVector<mlir::Attribute> attrs;
2612e13d23bcSMarkus Böck llvm::SmallVector<mlir::OpAsmParser::UnresolvedOperand> opers;
2613067312d2SValentin Clement llvm::SmallVector<mlir::Block *> dests;
2614067312d2SValentin Clement llvm::SmallVector<llvm::SmallVector<mlir::Value>> destArgs;
2615de8a65f7SEric Schweitz llvm::SmallVector<std::int32_t> argOffs;
2616de8a65f7SEric Schweitz std::int32_t offSize = 0;
261757f536a4SjeanPerier while (true) {
261857f536a4SjeanPerier mlir::Attribute attr;
261957f536a4SjeanPerier mlir::Block *dest;
2620067312d2SValentin Clement llvm::SmallVector<mlir::Value> destArg;
26215eae715aSJacques Pienaar mlir::NamedAttrList temp;
262257f536a4SjeanPerier if (parser.parseAttribute(attr, "a", temp) || isValidCaseAttr(attr) ||
262357f536a4SjeanPerier parser.parseComma())
262457f536a4SjeanPerier return mlir::failure();
262557f536a4SjeanPerier attrs.push_back(attr);
262657f536a4SjeanPerier if (attr.dyn_cast_or_null<mlir::UnitAttr>()) {
262757f536a4SjeanPerier argOffs.push_back(0);
262857f536a4SjeanPerier } else if (attr.dyn_cast_or_null<fir::ClosedIntervalAttr>()) {
2629e13d23bcSMarkus Böck mlir::OpAsmParser::UnresolvedOperand oper1;
2630e13d23bcSMarkus Böck mlir::OpAsmParser::UnresolvedOperand oper2;
263157f536a4SjeanPerier if (parser.parseOperand(oper1) || parser.parseComma() ||
263257f536a4SjeanPerier parser.parseOperand(oper2) || parser.parseComma())
263357f536a4SjeanPerier return mlir::failure();
263457f536a4SjeanPerier opers.push_back(oper1);
263557f536a4SjeanPerier opers.push_back(oper2);
263657f536a4SjeanPerier argOffs.push_back(2);
263757f536a4SjeanPerier offSize += 2;
263857f536a4SjeanPerier } else {
2639e13d23bcSMarkus Böck mlir::OpAsmParser::UnresolvedOperand oper;
264057f536a4SjeanPerier if (parser.parseOperand(oper) || parser.parseComma())
264157f536a4SjeanPerier return mlir::failure();
264257f536a4SjeanPerier opers.push_back(oper);
264357f536a4SjeanPerier argOffs.push_back(1);
264457f536a4SjeanPerier ++offSize;
264557f536a4SjeanPerier }
264657f536a4SjeanPerier if (parser.parseSuccessorAndUseList(dest, destArg))
264757f536a4SjeanPerier return mlir::failure();
264857f536a4SjeanPerier dests.push_back(dest);
264957f536a4SjeanPerier destArgs.push_back(destArg);
26500b785a46SEric Schweitz if (mlir::succeeded(parser.parseOptionalRSquare()))
265157f536a4SjeanPerier break;
265257f536a4SjeanPerier if (parser.parseComma())
265357f536a4SjeanPerier return mlir::failure();
265457f536a4SjeanPerier }
265557f536a4SjeanPerier result.addAttribute(fir::SelectCaseOp::getCasesAttr(),
265657f536a4SjeanPerier parser.getBuilder().getArrayAttr(attrs));
265757f536a4SjeanPerier if (parser.resolveOperands(opers, type, result.operands))
265857f536a4SjeanPerier return mlir::failure();
2659067312d2SValentin Clement llvm::SmallVector<int32_t> targOffs;
266057f536a4SjeanPerier int32_t toffSize = 0;
266157f536a4SjeanPerier const auto count = dests.size();
266257f536a4SjeanPerier for (std::remove_const_t<decltype(count)> i = 0; i != count; ++i) {
266357f536a4SjeanPerier result.addSuccessors(dests[i]);
266457f536a4SjeanPerier result.addOperands(destArgs[i]);
266557f536a4SjeanPerier auto argSize = destArgs[i].size();
266657f536a4SjeanPerier targOffs.push_back(argSize);
266757f536a4SjeanPerier toffSize += argSize;
266857f536a4SjeanPerier }
266957f536a4SjeanPerier auto &bld = parser.getBuilder();
267057f536a4SjeanPerier result.addAttribute(fir::SelectCaseOp::getOperandSegmentSizeAttr(),
267157f536a4SjeanPerier bld.getI32VectorAttr({1, offSize, toffSize}));
267257f536a4SjeanPerier result.addAttribute(getCompareOffsetAttr(), bld.getI32VectorAttr(argOffs));
267357f536a4SjeanPerier result.addAttribute(getTargetOffsetAttr(), bld.getI32VectorAttr(targOffs));
267457f536a4SjeanPerier return mlir::success();
267557f536a4SjeanPerier }
267657f536a4SjeanPerier
print(mlir::OpAsmPrinter & p)2677de8a65f7SEric Schweitz void fir::SelectCaseOp::print(mlir::OpAsmPrinter &p) {
2678633f70f7SValentin Clement p << ' ';
2679cc120e36SShraiysh Vaishay p.printOperand(getSelector());
2680cc120e36SShraiysh Vaishay p << " : " << getSelector().getType() << " [";
2681cc120e36SShraiysh Vaishay auto cases =
2682cc120e36SShraiysh Vaishay getOperation()->getAttrOfType<mlir::ArrayAttr>(getCasesAttr()).getValue();
2683cc120e36SShraiysh Vaishay auto count = getNumConditions();
2684633f70f7SValentin Clement for (decltype(count) i = 0; i != count; ++i) {
2685633f70f7SValentin Clement if (i)
2686633f70f7SValentin Clement p << ", ";
2687633f70f7SValentin Clement p << cases[i] << ", ";
2688633f70f7SValentin Clement if (!cases[i].isa<mlir::UnitAttr>()) {
2689cc120e36SShraiysh Vaishay auto caseArgs = *getCompareOperands(i);
2690633f70f7SValentin Clement p.printOperand(*caseArgs.begin());
2691633f70f7SValentin Clement p << ", ";
2692633f70f7SValentin Clement if (cases[i].isa<fir::ClosedIntervalAttr>()) {
2693633f70f7SValentin Clement p.printOperand(*(++caseArgs.begin()));
2694633f70f7SValentin Clement p << ", ";
2695633f70f7SValentin Clement }
2696633f70f7SValentin Clement }
2697cc120e36SShraiysh Vaishay printSuccessorAtIndex(p, i);
2698633f70f7SValentin Clement }
2699633f70f7SValentin Clement p << ']';
2700cc120e36SShraiysh Vaishay p.printOptionalAttrDict(getOperation()->getAttrs(),
2701cc120e36SShraiysh Vaishay {getCasesAttr(), getCompareOffsetAttr(),
2702cc120e36SShraiysh Vaishay getTargetOffsetAttr(), getOperandSegmentSizeAttr()});
2703633f70f7SValentin Clement }
2704633f70f7SValentin Clement
compareOffsetSize()2705bc034238SEric Schweitz unsigned fir::SelectCaseOp::compareOffsetSize() {
2706a1eb1544SChristian Sigg return denseElementsSize((*this)->getAttrOfType<mlir::DenseIntElementsAttr>(
2707a1eb1544SChristian Sigg getCompareOffsetAttr()));
2708bc034238SEric Schweitz }
2709bc034238SEric Schweitz
targetOffsetSize()2710bc034238SEric Schweitz unsigned fir::SelectCaseOp::targetOffsetSize() {
2711a1eb1544SChristian Sigg return denseElementsSize((*this)->getAttrOfType<mlir::DenseIntElementsAttr>(
2712a1eb1544SChristian Sigg getTargetOffsetAttr()));
2713bc034238SEric Schweitz }
2714bc034238SEric Schweitz
build(mlir::OpBuilder & builder,mlir::OperationState & result,mlir::Value selector,llvm::ArrayRef<mlir::Attribute> compareAttrs,llvm::ArrayRef<mlir::ValueRange> cmpOperands,llvm::ArrayRef<mlir::Block * > destinations,llvm::ArrayRef<mlir::ValueRange> destOperands,llvm::ArrayRef<mlir::NamedAttribute> attributes)2715bb1d976fSAlex Zinenko void fir::SelectCaseOp::build(mlir::OpBuilder &builder,
2716bc034238SEric Schweitz mlir::OperationState &result,
2717bc034238SEric Schweitz mlir::Value selector,
2718bc034238SEric Schweitz llvm::ArrayRef<mlir::Attribute> compareAttrs,
2719bc034238SEric Schweitz llvm::ArrayRef<mlir::ValueRange> cmpOperands,
2720bc034238SEric Schweitz llvm::ArrayRef<mlir::Block *> destinations,
2721bc034238SEric Schweitz llvm::ArrayRef<mlir::ValueRange> destOperands,
2722bc034238SEric Schweitz llvm::ArrayRef<mlir::NamedAttribute> attributes) {
2723bc034238SEric Schweitz result.addOperands(selector);
2724bb1d976fSAlex Zinenko result.addAttribute(getCasesAttr(), builder.getArrayAttr(compareAttrs));
2725067312d2SValentin Clement llvm::SmallVector<int32_t> operOffs;
2726bc034238SEric Schweitz int32_t operSize = 0;
2727bc034238SEric Schweitz for (auto attr : compareAttrs) {
2728bc034238SEric Schweitz if (attr.isa<fir::ClosedIntervalAttr>()) {
2729bc034238SEric Schweitz operOffs.push_back(2);
2730bc034238SEric Schweitz operSize += 2;
2731bc034238SEric Schweitz } else if (attr.isa<mlir::UnitAttr>()) {
2732bc034238SEric Schweitz operOffs.push_back(0);
2733bc034238SEric Schweitz } else {
2734bc034238SEric Schweitz operOffs.push_back(1);
2735bc034238SEric Schweitz ++operSize;
2736bc034238SEric Schweitz }
2737bc034238SEric Schweitz }
2738bc034238SEric Schweitz for (auto ops : cmpOperands)
2739bc034238SEric Schweitz result.addOperands(ops);
2740bc034238SEric Schweitz result.addAttribute(getCompareOffsetAttr(),
2741bb1d976fSAlex Zinenko builder.getI32VectorAttr(operOffs));
2742bc034238SEric Schweitz const auto count = destinations.size();
2743bc034238SEric Schweitz for (auto d : destinations)
2744bc034238SEric Schweitz result.addSuccessors(d);
2745bc034238SEric Schweitz const auto opCount = destOperands.size();
2746de8a65f7SEric Schweitz llvm::SmallVector<std::int32_t> argOffs;
2747de8a65f7SEric Schweitz std::int32_t sumArgs = 0;
2748bc034238SEric Schweitz for (std::remove_const_t<decltype(count)> i = 0; i != count; ++i) {
2749bc034238SEric Schweitz if (i < opCount) {
2750bc034238SEric Schweitz result.addOperands(destOperands[i]);
2751bc034238SEric Schweitz const auto argSz = destOperands[i].size();
2752bc034238SEric Schweitz argOffs.push_back(argSz);
2753bc034238SEric Schweitz sumArgs += argSz;
2754bc034238SEric Schweitz } else {
2755bc034238SEric Schweitz argOffs.push_back(0);
2756bc034238SEric Schweitz }
2757bc034238SEric Schweitz }
2758bc034238SEric Schweitz result.addAttribute(getOperandSegmentSizeAttr(),
2759bb1d976fSAlex Zinenko builder.getI32VectorAttr({1, operSize, sumArgs}));
2760bb1d976fSAlex Zinenko result.addAttribute(getTargetOffsetAttr(), builder.getI32VectorAttr(argOffs));
2761bc034238SEric Schweitz result.addAttributes(attributes);
2762bc034238SEric Schweitz }
2763bc034238SEric Schweitz
2764bc034238SEric Schweitz /// This builder has a slightly simplified interface in that the list of
2765bc034238SEric Schweitz /// operands need not be partitioned by the builder. Instead the operands are
2766bc034238SEric Schweitz /// partitioned here, before being passed to the default builder. This
2767bc034238SEric Schweitz /// partitioning is unchecked, so can go awry on bad input.
build(mlir::OpBuilder & builder,mlir::OperationState & result,mlir::Value selector,llvm::ArrayRef<mlir::Attribute> compareAttrs,llvm::ArrayRef<mlir::Value> cmpOpList,llvm::ArrayRef<mlir::Block * > destinations,llvm::ArrayRef<mlir::ValueRange> destOperands,llvm::ArrayRef<mlir::NamedAttribute> attributes)2768bb1d976fSAlex Zinenko void fir::SelectCaseOp::build(mlir::OpBuilder &builder,
2769bc034238SEric Schweitz mlir::OperationState &result,
2770bc034238SEric Schweitz mlir::Value selector,
2771bc034238SEric Schweitz llvm::ArrayRef<mlir::Attribute> compareAttrs,
2772bc034238SEric Schweitz llvm::ArrayRef<mlir::Value> cmpOpList,
2773bc034238SEric Schweitz llvm::ArrayRef<mlir::Block *> destinations,
2774bc034238SEric Schweitz llvm::ArrayRef<mlir::ValueRange> destOperands,
2775bc034238SEric Schweitz llvm::ArrayRef<mlir::NamedAttribute> attributes) {
2776067312d2SValentin Clement llvm::SmallVector<mlir::ValueRange> cmpOpers;
2777bc034238SEric Schweitz auto iter = cmpOpList.begin();
2778bc034238SEric Schweitz for (auto &attr : compareAttrs) {
2779bc034238SEric Schweitz if (attr.isa<fir::ClosedIntervalAttr>()) {
2780bc034238SEric Schweitz cmpOpers.push_back(mlir::ValueRange({iter, iter + 2}));
2781bc034238SEric Schweitz iter += 2;
2782de8a65f7SEric Schweitz } else if (attr.isa<mlir::UnitAttr>()) {
2783bc034238SEric Schweitz cmpOpers.push_back(mlir::ValueRange{});
2784bc034238SEric Schweitz } else {
2785bc034238SEric Schweitz cmpOpers.push_back(mlir::ValueRange({iter, iter + 1}));
2786bc034238SEric Schweitz ++iter;
2787bc034238SEric Schweitz }
2788bc034238SEric Schweitz }
2789bc034238SEric Schweitz build(builder, result, selector, compareAttrs, cmpOpers, destinations,
2790bc034238SEric Schweitz destOperands, attributes);
2791bc034238SEric Schweitz }
2792bc034238SEric Schweitz
verify()2793de8a65f7SEric Schweitz mlir::LogicalResult fir::SelectCaseOp::verify() {
2794de8a65f7SEric Schweitz if (!getSelector()
2795de8a65f7SEric Schweitz .getType()
2796de8a65f7SEric Schweitz .isa<mlir::IntegerType, mlir::IndexType, fir::IntegerType,
2797de8a65f7SEric Schweitz fir::LogicalType, fir::CharacterType>())
2798cc120e36SShraiysh Vaishay return emitOpError("must be an integer, character, or logical");
2799cc120e36SShraiysh Vaishay auto cases =
2800cc120e36SShraiysh Vaishay getOperation()->getAttrOfType<mlir::ArrayAttr>(getCasesAttr()).getValue();
2801cc120e36SShraiysh Vaishay auto count = getNumDest();
2802633f70f7SValentin Clement if (count == 0)
2803cc120e36SShraiysh Vaishay return emitOpError("must have at least one successor");
2804cc120e36SShraiysh Vaishay if (getNumConditions() != count)
2805cc120e36SShraiysh Vaishay return emitOpError("number of conditions and successors don't match");
2806cc120e36SShraiysh Vaishay if (compareOffsetSize() != count)
2807cc120e36SShraiysh Vaishay return emitOpError("incorrect number of compare operand groups");
2808cc120e36SShraiysh Vaishay if (targetOffsetSize() != count)
2809cc120e36SShraiysh Vaishay return emitOpError("incorrect number of successor operand groups");
2810633f70f7SValentin Clement for (decltype(count) i = 0; i != count; ++i) {
2811633f70f7SValentin Clement auto &attr = cases[i];
2812633f70f7SValentin Clement if (!(attr.isa<fir::PointIntervalAttr>() ||
2813633f70f7SValentin Clement attr.isa<fir::LowerBoundAttr>() || attr.isa<fir::UpperBoundAttr>() ||
2814633f70f7SValentin Clement attr.isa<fir::ClosedIntervalAttr>() || attr.isa<mlir::UnitAttr>()))
2815cc120e36SShraiysh Vaishay return emitOpError("incorrect select case attribute type");
2816633f70f7SValentin Clement }
2817633f70f7SValentin Clement return mlir::success();
2818633f70f7SValentin Clement }
2819633f70f7SValentin Clement
282057f536a4SjeanPerier //===----------------------------------------------------------------------===//
282157f536a4SjeanPerier // SelectRankOp
282257f536a4SjeanPerier //===----------------------------------------------------------------------===//
282357f536a4SjeanPerier
verify()2824de8a65f7SEric Schweitz mlir::LogicalResult fir::SelectRankOp::verify() {
2825125a4d91SAndrzej Warzynski return verifyIntegralSwitchTerminator(*this);
2826125a4d91SAndrzej Warzynski }
2827125a4d91SAndrzej Warzynski
parse(mlir::OpAsmParser & parser,mlir::OperationState & result)2828125a4d91SAndrzej Warzynski mlir::ParseResult fir::SelectRankOp::parse(mlir::OpAsmParser &parser,
2829125a4d91SAndrzej Warzynski mlir::OperationState &result) {
2830125a4d91SAndrzej Warzynski return parseIntegralSwitchTerminator(parser, result, getCasesAttr(),
2831125a4d91SAndrzej Warzynski getOperandSegmentSizeAttr());
2832125a4d91SAndrzej Warzynski }
2833125a4d91SAndrzej Warzynski
print(mlir::OpAsmPrinter & p)2834125a4d91SAndrzej Warzynski void fir::SelectRankOp::print(mlir::OpAsmPrinter &p) {
2835125a4d91SAndrzej Warzynski printIntegralSwitchTerminator(*this, p);
2836125a4d91SAndrzej Warzynski }
2837125a4d91SAndrzej Warzynski
283857f536a4SjeanPerier llvm::Optional<mlir::OperandRange>
getCompareOperands(unsigned)283957f536a4SjeanPerier fir::SelectRankOp::getCompareOperands(unsigned) {
284057f536a4SjeanPerier return {};
284157f536a4SjeanPerier }
284257f536a4SjeanPerier
284357f536a4SjeanPerier llvm::Optional<llvm::ArrayRef<mlir::Value>>
getCompareOperands(llvm::ArrayRef<mlir::Value>,unsigned)284457f536a4SjeanPerier fir::SelectRankOp::getCompareOperands(llvm::ArrayRef<mlir::Value>, unsigned) {
284557f536a4SjeanPerier return {};
284657f536a4SjeanPerier }
284757f536a4SjeanPerier
getSuccessorOperands(unsigned oper)28480c789db5SMarkus Böck mlir::SuccessorOperands fir::SelectRankOp::getSuccessorOperands(unsigned oper) {
28490c789db5SMarkus Böck return mlir::SuccessorOperands(::getMutableSuccessorOperands(
28500c789db5SMarkus Böck oper, getTargetArgsMutable(), getTargetOffsetAttr()));
285157f536a4SjeanPerier }
285257f536a4SjeanPerier
285357f536a4SjeanPerier llvm::Optional<llvm::ArrayRef<mlir::Value>>
getSuccessorOperands(llvm::ArrayRef<mlir::Value> operands,unsigned oper)285457f536a4SjeanPerier fir::SelectRankOp::getSuccessorOperands(llvm::ArrayRef<mlir::Value> operands,
285557f536a4SjeanPerier unsigned oper) {
2856a1eb1544SChristian Sigg auto a =
2857a1eb1544SChristian Sigg (*this)->getAttrOfType<mlir::DenseIntElementsAttr>(getTargetOffsetAttr());
2858a1eb1544SChristian Sigg auto segments = (*this)->getAttrOfType<mlir::DenseIntElementsAttr>(
2859a1eb1544SChristian Sigg getOperandSegmentSizeAttr());
286057f536a4SjeanPerier return {getSubOperands(oper, getSubOperands(2, operands, segments), a)};
286157f536a4SjeanPerier }
286257f536a4SjeanPerier
28638c239909SValentin Clement llvm::Optional<mlir::ValueRange>
getSuccessorOperands(mlir::ValueRange operands,unsigned oper)28648c239909SValentin Clement fir::SelectRankOp::getSuccessorOperands(mlir::ValueRange operands,
28658c239909SValentin Clement unsigned oper) {
28668c239909SValentin Clement auto a =
28678c239909SValentin Clement (*this)->getAttrOfType<mlir::DenseIntElementsAttr>(getTargetOffsetAttr());
28688c239909SValentin Clement auto segments = (*this)->getAttrOfType<mlir::DenseIntElementsAttr>(
28698c239909SValentin Clement getOperandSegmentSizeAttr());
28708c239909SValentin Clement return {getSubOperands(oper, getSubOperands(2, operands, segments), a)};
28718c239909SValentin Clement }
28728c239909SValentin Clement
targetOffsetSize()2873bc034238SEric Schweitz unsigned fir::SelectRankOp::targetOffsetSize() {
2874a1eb1544SChristian Sigg return denseElementsSize((*this)->getAttrOfType<mlir::DenseIntElementsAttr>(
2875a1eb1544SChristian Sigg getTargetOffsetAttr()));
2876bc034238SEric Schweitz }
2877bc034238SEric Schweitz
287857f536a4SjeanPerier //===----------------------------------------------------------------------===//
287957f536a4SjeanPerier // SelectTypeOp
288057f536a4SjeanPerier //===----------------------------------------------------------------------===//
288157f536a4SjeanPerier
288257f536a4SjeanPerier llvm::Optional<mlir::OperandRange>
getCompareOperands(unsigned)288357f536a4SjeanPerier fir::SelectTypeOp::getCompareOperands(unsigned) {
288457f536a4SjeanPerier return {};
288557f536a4SjeanPerier }
288657f536a4SjeanPerier
288757f536a4SjeanPerier llvm::Optional<llvm::ArrayRef<mlir::Value>>
getCompareOperands(llvm::ArrayRef<mlir::Value>,unsigned)288857f536a4SjeanPerier fir::SelectTypeOp::getCompareOperands(llvm::ArrayRef<mlir::Value>, unsigned) {
288957f536a4SjeanPerier return {};
289057f536a4SjeanPerier }
289157f536a4SjeanPerier
getSuccessorOperands(unsigned oper)28920c789db5SMarkus Böck mlir::SuccessorOperands fir::SelectTypeOp::getSuccessorOperands(unsigned oper) {
28930c789db5SMarkus Böck return mlir::SuccessorOperands(::getMutableSuccessorOperands(
28940c789db5SMarkus Böck oper, getTargetArgsMutable(), getTargetOffsetAttr()));
289557f536a4SjeanPerier }
289657f536a4SjeanPerier
289757f536a4SjeanPerier llvm::Optional<llvm::ArrayRef<mlir::Value>>
getSuccessorOperands(llvm::ArrayRef<mlir::Value> operands,unsigned oper)289857f536a4SjeanPerier fir::SelectTypeOp::getSuccessorOperands(llvm::ArrayRef<mlir::Value> operands,
289957f536a4SjeanPerier unsigned oper) {
2900a1eb1544SChristian Sigg auto a =
2901a1eb1544SChristian Sigg (*this)->getAttrOfType<mlir::DenseIntElementsAttr>(getTargetOffsetAttr());
2902a1eb1544SChristian Sigg auto segments = (*this)->getAttrOfType<mlir::DenseIntElementsAttr>(
2903a1eb1544SChristian Sigg getOperandSegmentSizeAttr());
290457f536a4SjeanPerier return {getSubOperands(oper, getSubOperands(2, operands, segments), a)};
290557f536a4SjeanPerier }
290657f536a4SjeanPerier
parse(mlir::OpAsmParser & parser,mlir::OperationState & result)2907de8a65f7SEric Schweitz mlir::ParseResult fir::SelectTypeOp::parse(mlir::OpAsmParser &parser,
2908de8a65f7SEric Schweitz mlir::OperationState &result) {
2909e13d23bcSMarkus Böck mlir::OpAsmParser::UnresolvedOperand selector;
291057f536a4SjeanPerier mlir::Type type;
2911de8a65f7SEric Schweitz if (fir::parseSelector(parser, result, selector, type))
291257f536a4SjeanPerier return mlir::failure();
291357f536a4SjeanPerier
2914067312d2SValentin Clement llvm::SmallVector<mlir::Attribute> attrs;
2915067312d2SValentin Clement llvm::SmallVector<mlir::Block *> dests;
2916067312d2SValentin Clement llvm::SmallVector<llvm::SmallVector<mlir::Value>> destArgs;
291757f536a4SjeanPerier while (true) {
291857f536a4SjeanPerier mlir::Attribute attr;
291957f536a4SjeanPerier mlir::Block *dest;
2920067312d2SValentin Clement llvm::SmallVector<mlir::Value> destArg;
29215eae715aSJacques Pienaar mlir::NamedAttrList temp;
292257f536a4SjeanPerier if (parser.parseAttribute(attr, "a", temp) || parser.parseComma() ||
292357f536a4SjeanPerier parser.parseSuccessorAndUseList(dest, destArg))
292457f536a4SjeanPerier return mlir::failure();
292557f536a4SjeanPerier attrs.push_back(attr);
292657f536a4SjeanPerier dests.push_back(dest);
292757f536a4SjeanPerier destArgs.push_back(destArg);
29280b785a46SEric Schweitz if (mlir::succeeded(parser.parseOptionalRSquare()))
292957f536a4SjeanPerier break;
293057f536a4SjeanPerier if (parser.parseComma())
293157f536a4SjeanPerier return mlir::failure();
293257f536a4SjeanPerier }
293357f536a4SjeanPerier auto &bld = parser.getBuilder();
293457f536a4SjeanPerier result.addAttribute(fir::SelectTypeOp::getCasesAttr(),
293557f536a4SjeanPerier bld.getArrayAttr(attrs));
2936067312d2SValentin Clement llvm::SmallVector<int32_t> argOffs;
293757f536a4SjeanPerier int32_t offSize = 0;
293857f536a4SjeanPerier const auto count = dests.size();
293957f536a4SjeanPerier for (std::remove_const_t<decltype(count)> i = 0; i != count; ++i) {
294057f536a4SjeanPerier result.addSuccessors(dests[i]);
294157f536a4SjeanPerier result.addOperands(destArgs[i]);
294257f536a4SjeanPerier auto argSize = destArgs[i].size();
294357f536a4SjeanPerier argOffs.push_back(argSize);
294457f536a4SjeanPerier offSize += argSize;
294557f536a4SjeanPerier }
294657f536a4SjeanPerier result.addAttribute(fir::SelectTypeOp::getOperandSegmentSizeAttr(),
294757f536a4SjeanPerier bld.getI32VectorAttr({1, 0, offSize}));
294857f536a4SjeanPerier result.addAttribute(getTargetOffsetAttr(), bld.getI32VectorAttr(argOffs));
294957f536a4SjeanPerier return mlir::success();
295057f536a4SjeanPerier }
295157f536a4SjeanPerier
targetOffsetSize()2952bc034238SEric Schweitz unsigned fir::SelectTypeOp::targetOffsetSize() {
2953a1eb1544SChristian Sigg return denseElementsSize((*this)->getAttrOfType<mlir::DenseIntElementsAttr>(
2954a1eb1544SChristian Sigg getTargetOffsetAttr()));
2955bc034238SEric Schweitz }
2956bc034238SEric Schweitz
print(mlir::OpAsmPrinter & p)2957de8a65f7SEric Schweitz void fir::SelectTypeOp::print(mlir::OpAsmPrinter &p) {
2958633f70f7SValentin Clement p << ' ';
2959cc120e36SShraiysh Vaishay p.printOperand(getSelector());
2960cc120e36SShraiysh Vaishay p << " : " << getSelector().getType() << " [";
2961cc120e36SShraiysh Vaishay auto cases =
2962cc120e36SShraiysh Vaishay getOperation()->getAttrOfType<mlir::ArrayAttr>(getCasesAttr()).getValue();
2963cc120e36SShraiysh Vaishay auto count = getNumConditions();
2964633f70f7SValentin Clement for (decltype(count) i = 0; i != count; ++i) {
2965633f70f7SValentin Clement if (i)
2966633f70f7SValentin Clement p << ", ";
2967633f70f7SValentin Clement p << cases[i] << ", ";
2968cc120e36SShraiysh Vaishay printSuccessorAtIndex(p, i);
2969633f70f7SValentin Clement }
2970633f70f7SValentin Clement p << ']';
2971cc120e36SShraiysh Vaishay p.printOptionalAttrDict(getOperation()->getAttrs(),
2972cc120e36SShraiysh Vaishay {getCasesAttr(), getCompareOffsetAttr(),
2973633f70f7SValentin Clement getTargetOffsetAttr(),
2974633f70f7SValentin Clement fir::SelectTypeOp::getOperandSegmentSizeAttr()});
2975633f70f7SValentin Clement }
2976633f70f7SValentin Clement
verify()2977de8a65f7SEric Schweitz mlir::LogicalResult fir::SelectTypeOp::verify() {
2978cc120e36SShraiysh Vaishay if (!(getSelector().getType().isa<fir::BoxType>()))
2979cc120e36SShraiysh Vaishay return emitOpError("must be a boxed type");
2980cc120e36SShraiysh Vaishay auto cases =
2981cc120e36SShraiysh Vaishay getOperation()->getAttrOfType<mlir::ArrayAttr>(getCasesAttr()).getValue();
2982cc120e36SShraiysh Vaishay auto count = getNumDest();
2983633f70f7SValentin Clement if (count == 0)
2984cc120e36SShraiysh Vaishay return emitOpError("must have at least one successor");
2985cc120e36SShraiysh Vaishay if (getNumConditions() != count)
2986cc120e36SShraiysh Vaishay return emitOpError("number of conditions and successors don't match");
2987cc120e36SShraiysh Vaishay if (targetOffsetSize() != count)
2988cc120e36SShraiysh Vaishay return emitOpError("incorrect number of successor operand groups");
2989633f70f7SValentin Clement for (decltype(count) i = 0; i != count; ++i) {
2990633f70f7SValentin Clement auto &attr = cases[i];
2991633f70f7SValentin Clement if (!(attr.isa<fir::ExactTypeAttr>() || attr.isa<fir::SubclassAttr>() ||
2992633f70f7SValentin Clement attr.isa<mlir::UnitAttr>()))
2993cc120e36SShraiysh Vaishay return emitOpError("invalid type-case alternative");
2994633f70f7SValentin Clement }
2995633f70f7SValentin Clement return mlir::success();
2996633f70f7SValentin Clement }
2997633f70f7SValentin Clement
build(mlir::OpBuilder & builder,mlir::OperationState & result,mlir::Value selector,llvm::ArrayRef<mlir::Attribute> typeOperands,llvm::ArrayRef<mlir::Block * > destinations,llvm::ArrayRef<mlir::ValueRange> destOperands,llvm::ArrayRef<mlir::NamedAttribute> attributes)2998a149b103SValentin Clement void fir::SelectTypeOp::build(mlir::OpBuilder &builder,
2999a149b103SValentin Clement mlir::OperationState &result,
3000a149b103SValentin Clement mlir::Value selector,
3001a149b103SValentin Clement llvm::ArrayRef<mlir::Attribute> typeOperands,
3002a149b103SValentin Clement llvm::ArrayRef<mlir::Block *> destinations,
3003a149b103SValentin Clement llvm::ArrayRef<mlir::ValueRange> destOperands,
3004a149b103SValentin Clement llvm::ArrayRef<mlir::NamedAttribute> attributes) {
3005a149b103SValentin Clement result.addOperands(selector);
3006a149b103SValentin Clement result.addAttribute(getCasesAttr(), builder.getArrayAttr(typeOperands));
3007a149b103SValentin Clement const auto count = destinations.size();
3008a149b103SValentin Clement for (mlir::Block *dest : destinations)
3009a149b103SValentin Clement result.addSuccessors(dest);
3010a149b103SValentin Clement const auto opCount = destOperands.size();
3011a149b103SValentin Clement llvm::SmallVector<int32_t> argOffs;
3012a149b103SValentin Clement int32_t sumArgs = 0;
3013a149b103SValentin Clement for (std::remove_const_t<decltype(count)> i = 0; i != count; ++i) {
3014a149b103SValentin Clement if (i < opCount) {
3015a149b103SValentin Clement result.addOperands(destOperands[i]);
3016a149b103SValentin Clement const auto argSz = destOperands[i].size();
3017a149b103SValentin Clement argOffs.push_back(argSz);
3018a149b103SValentin Clement sumArgs += argSz;
3019a149b103SValentin Clement } else {
3020a149b103SValentin Clement argOffs.push_back(0);
3021a149b103SValentin Clement }
3022a149b103SValentin Clement }
3023a149b103SValentin Clement result.addAttribute(getOperandSegmentSizeAttr(),
3024a149b103SValentin Clement builder.getI32VectorAttr({1, 0, sumArgs}));
3025a149b103SValentin Clement result.addAttribute(getTargetOffsetAttr(), builder.getI32VectorAttr(argOffs));
3026a149b103SValentin Clement result.addAttributes(attributes);
3027a149b103SValentin Clement }
3028a149b103SValentin Clement
3029633f70f7SValentin Clement //===----------------------------------------------------------------------===//
3030afb30fcdSValentin Clement // ShapeOp
3031afb30fcdSValentin Clement //===----------------------------------------------------------------------===//
3032afb30fcdSValentin Clement
verify()3033de8a65f7SEric Schweitz mlir::LogicalResult fir::ShapeOp::verify() {
3034149ad3d5SShraiysh Vaishay auto size = getExtents().size();
3035cc120e36SShraiysh Vaishay auto shapeTy = getType().dyn_cast<fir::ShapeType>();
3036afb30fcdSValentin Clement assert(shapeTy && "must be a shape type");
3037afb30fcdSValentin Clement if (shapeTy.getRank() != size)
3038cc120e36SShraiysh Vaishay return emitOpError("shape type rank mismatch");
3039afb30fcdSValentin Clement return mlir::success();
3040afb30fcdSValentin Clement }
3041afb30fcdSValentin Clement
3042afb30fcdSValentin Clement //===----------------------------------------------------------------------===//
3043633f70f7SValentin Clement // ShapeShiftOp
3044633f70f7SValentin Clement //===----------------------------------------------------------------------===//
3045633f70f7SValentin Clement
verify()3046de8a65f7SEric Schweitz mlir::LogicalResult fir::ShapeShiftOp::verify() {
3047149ad3d5SShraiysh Vaishay auto size = getPairs().size();
3048633f70f7SValentin Clement if (size < 2 || size > 16 * 2)
3049cc120e36SShraiysh Vaishay return emitOpError("incorrect number of args");
3050633f70f7SValentin Clement if (size % 2 != 0)
3051cc120e36SShraiysh Vaishay return emitOpError("requires a multiple of 2 args");
3052cc120e36SShraiysh Vaishay auto shapeTy = getType().dyn_cast<fir::ShapeShiftType>();
3053633f70f7SValentin Clement assert(shapeTy && "must be a shape shift type");
3054633f70f7SValentin Clement if (shapeTy.getRank() * 2 != size)
3055cc120e36SShraiysh Vaishay return emitOpError("shape type rank mismatch");
3056633f70f7SValentin Clement return mlir::success();
3057633f70f7SValentin Clement }
3058633f70f7SValentin Clement
3059633f70f7SValentin Clement //===----------------------------------------------------------------------===//
3060633f70f7SValentin Clement // ShiftOp
3061633f70f7SValentin Clement //===----------------------------------------------------------------------===//
3062633f70f7SValentin Clement
verify()3063de8a65f7SEric Schweitz mlir::LogicalResult fir::ShiftOp::verify() {
3064149ad3d5SShraiysh Vaishay auto size = getOrigins().size();
3065cc120e36SShraiysh Vaishay auto shiftTy = getType().dyn_cast<fir::ShiftType>();
3066633f70f7SValentin Clement assert(shiftTy && "must be a shift type");
3067633f70f7SValentin Clement if (shiftTy.getRank() != size)
3068cc120e36SShraiysh Vaishay return emitOpError("shift type rank mismatch");
3069633f70f7SValentin Clement return mlir::success();
3070633f70f7SValentin Clement }
3071633f70f7SValentin Clement
307257f536a4SjeanPerier //===----------------------------------------------------------------------===//
30730b785a46SEric Schweitz // SliceOp
30740b785a46SEric Schweitz //===----------------------------------------------------------------------===//
30750b785a46SEric Schweitz
build(mlir::OpBuilder & builder,mlir::OperationState & result,mlir::ValueRange trips,mlir::ValueRange path,mlir::ValueRange substr)30767812f510SValentin Clement void fir::SliceOp::build(mlir::OpBuilder &builder, mlir::OperationState &result,
30777812f510SValentin Clement mlir::ValueRange trips, mlir::ValueRange path,
30787812f510SValentin Clement mlir::ValueRange substr) {
30797812f510SValentin Clement const auto rank = trips.size() / 3;
30807812f510SValentin Clement auto sliceTy = fir::SliceType::get(builder.getContext(), rank);
30817812f510SValentin Clement build(builder, result, sliceTy, trips, path, substr);
30827812f510SValentin Clement }
30837812f510SValentin Clement
30840b785a46SEric Schweitz /// Return the output rank of a slice op. The output rank must be between 1 and
30850b785a46SEric Schweitz /// the rank of the array being sliced (inclusive).
getOutputRank(mlir::ValueRange triples)30860b785a46SEric Schweitz unsigned fir::SliceOp::getOutputRank(mlir::ValueRange triples) {
30870b785a46SEric Schweitz unsigned rank = 0;
30880b785a46SEric Schweitz if (!triples.empty()) {
30890b785a46SEric Schweitz for (unsigned i = 1, end = triples.size(); i < end; i += 3) {
30907812f510SValentin Clement auto *op = triples[i].getDefiningOp();
30910b785a46SEric Schweitz if (!mlir::isa_and_nonnull<fir::UndefOp>(op))
30920b785a46SEric Schweitz ++rank;
30930b785a46SEric Schweitz }
30940b785a46SEric Schweitz assert(rank > 0);
30950b785a46SEric Schweitz }
30960b785a46SEric Schweitz return rank;
30970b785a46SEric Schweitz }
30980b785a46SEric Schweitz
verify()3099de8a65f7SEric Schweitz mlir::LogicalResult fir::SliceOp::verify() {
3100149ad3d5SShraiysh Vaishay auto size = getTriples().size();
3101633f70f7SValentin Clement if (size < 3 || size > 16 * 3)
3102cc120e36SShraiysh Vaishay return emitOpError("incorrect number of args for triple");
3103633f70f7SValentin Clement if (size % 3 != 0)
3104cc120e36SShraiysh Vaishay return emitOpError("requires a multiple of 3 args");
3105cc120e36SShraiysh Vaishay auto sliceTy = getType().dyn_cast<fir::SliceType>();
3106633f70f7SValentin Clement assert(sliceTy && "must be a slice type");
3107633f70f7SValentin Clement if (sliceTy.getRank() * 3 != size)
3108cc120e36SShraiysh Vaishay return emitOpError("slice type rank mismatch");
3109633f70f7SValentin Clement return mlir::success();
3110633f70f7SValentin Clement }
3111633f70f7SValentin Clement
31120b785a46SEric Schweitz //===----------------------------------------------------------------------===//
311357f536a4SjeanPerier // StoreOp
311457f536a4SjeanPerier //===----------------------------------------------------------------------===//
311557f536a4SjeanPerier
elementType(mlir::Type refType)311657f536a4SjeanPerier mlir::Type fir::StoreOp::elementType(mlir::Type refType) {
3117ccc0f62dSValentin Clement return fir::dyn_cast_ptrEleTy(refType);
3118ccc0f62dSValentin Clement }
3119ccc0f62dSValentin Clement
parse(mlir::OpAsmParser & parser,mlir::OperationState & result)3120de8a65f7SEric Schweitz mlir::ParseResult fir::StoreOp::parse(mlir::OpAsmParser &parser,
3121ccc0f62dSValentin Clement mlir::OperationState &result) {
3122ccc0f62dSValentin Clement mlir::Type type;
3123e13d23bcSMarkus Böck mlir::OpAsmParser::UnresolvedOperand oper;
3124e13d23bcSMarkus Böck mlir::OpAsmParser::UnresolvedOperand store;
3125ccc0f62dSValentin Clement if (parser.parseOperand(oper) || parser.parseKeyword("to") ||
3126ccc0f62dSValentin Clement parser.parseOperand(store) ||
3127ccc0f62dSValentin Clement parser.parseOptionalAttrDict(result.attributes) ||
3128ccc0f62dSValentin Clement parser.parseColonType(type) ||
3129ccc0f62dSValentin Clement parser.resolveOperand(oper, fir::StoreOp::elementType(type),
3130ccc0f62dSValentin Clement result.operands) ||
3131ccc0f62dSValentin Clement parser.resolveOperand(store, type, result.operands))
3132ccc0f62dSValentin Clement return mlir::failure();
3133ccc0f62dSValentin Clement return mlir::success();
3134ccc0f62dSValentin Clement }
3135ccc0f62dSValentin Clement
print(mlir::OpAsmPrinter & p)3136de8a65f7SEric Schweitz void fir::StoreOp::print(mlir::OpAsmPrinter &p) {
3137ccc0f62dSValentin Clement p << ' ';
3138149ad3d5SShraiysh Vaishay p.printOperand(getValue());
3139ccc0f62dSValentin Clement p << " to ";
3140149ad3d5SShraiysh Vaishay p.printOperand(getMemref());
3141cc120e36SShraiysh Vaishay p.printOptionalAttrDict(getOperation()->getAttrs(), {});
3142149ad3d5SShraiysh Vaishay p << " : " << getMemref().getType();
3143ccc0f62dSValentin Clement }
3144ccc0f62dSValentin Clement
verify()3145de8a65f7SEric Schweitz mlir::LogicalResult fir::StoreOp::verify() {
3146149ad3d5SShraiysh Vaishay if (getValue().getType() != fir::dyn_cast_ptrEleTy(getMemref().getType()))
3147cc120e36SShraiysh Vaishay return emitOpError("store value type must match memory reference type");
3148149ad3d5SShraiysh Vaishay if (fir::isa_unknown_size_box(getValue().getType()))
3149cc120e36SShraiysh Vaishay return emitOpError("cannot store !fir.box of unknown rank or type");
3150ccc0f62dSValentin Clement return mlir::success();
315157f536a4SjeanPerier }
315257f536a4SjeanPerier
315357f536a4SjeanPerier //===----------------------------------------------------------------------===//
315457f536a4SjeanPerier // StringLitOp
315557f536a4SjeanPerier //===----------------------------------------------------------------------===//
315657f536a4SjeanPerier
stringLitOpGetKind(fir::StringLitOp op)3157ae35635fSValentin Clement inline fir::CharacterType::KindTy stringLitOpGetKind(fir::StringLitOp op) {
3158ae35635fSValentin Clement auto eleTy = op.getType().cast<fir::SequenceType>().getEleTy();
3159ae35635fSValentin Clement return eleTy.cast<fir::CharacterType>().getFKind();
316057f536a4SjeanPerier }
316157f536a4SjeanPerier
isWideValue()3162ae35635fSValentin Clement bool fir::StringLitOp::isWideValue() { return stringLitOpGetKind(*this) != 1; }
3163ae35635fSValentin Clement
3164a28896aeSEric Schweitz static mlir::NamedAttribute
mkNamedIntegerAttr(mlir::OpBuilder & builder,llvm::StringRef name,int64_t v)3165a28896aeSEric Schweitz mkNamedIntegerAttr(mlir::OpBuilder &builder, llvm::StringRef name, int64_t v) {
3166a28896aeSEric Schweitz assert(v > 0);
3167a28896aeSEric Schweitz return builder.getNamedAttr(
3168a28896aeSEric Schweitz name, builder.getIntegerAttr(builder.getIntegerType(64), v));
3169a28896aeSEric Schweitz }
3170a28896aeSEric Schweitz
build(mlir::OpBuilder & builder,mlir::OperationState & result,fir::CharacterType inType,llvm::StringRef val,llvm::Optional<int64_t> len)3171de8a65f7SEric Schweitz void fir::StringLitOp::build(mlir::OpBuilder &builder,
3172de8a65f7SEric Schweitz mlir::OperationState &result,
3173a28896aeSEric Schweitz fir::CharacterType inType, llvm::StringRef val,
3174a28896aeSEric Schweitz llvm::Optional<int64_t> len) {
3175a28896aeSEric Schweitz auto valAttr = builder.getNamedAttr(value(), builder.getStringAttr(val));
31760916d96dSKazu Hirata int64_t length = len ? *len : inType.getLen();
3177a28896aeSEric Schweitz auto lenAttr = mkNamedIntegerAttr(builder, size(), length);
3178a28896aeSEric Schweitz result.addAttributes({valAttr, lenAttr});
3179a28896aeSEric Schweitz result.addTypes(inType);
3180a28896aeSEric Schweitz }
3181a28896aeSEric Schweitz
3182a28896aeSEric Schweitz template <typename C>
convertToArrayAttr(mlir::OpBuilder & builder,llvm::ArrayRef<C> xlist)3183a28896aeSEric Schweitz static mlir::ArrayAttr convertToArrayAttr(mlir::OpBuilder &builder,
3184a28896aeSEric Schweitz llvm::ArrayRef<C> xlist) {
3185a28896aeSEric Schweitz llvm::SmallVector<mlir::Attribute> attrs;
3186a28896aeSEric Schweitz auto ty = builder.getIntegerType(8 * sizeof(C));
3187a28896aeSEric Schweitz for (auto ch : xlist)
3188a28896aeSEric Schweitz attrs.push_back(builder.getIntegerAttr(ty, ch));
3189a28896aeSEric Schweitz return builder.getArrayAttr(attrs);
3190a28896aeSEric Schweitz }
3191a28896aeSEric Schweitz
build(mlir::OpBuilder & builder,mlir::OperationState & result,fir::CharacterType inType,llvm::ArrayRef<char> vlist,llvm::Optional<std::int64_t> len)3192de8a65f7SEric Schweitz void fir::StringLitOp::build(mlir::OpBuilder &builder,
3193de8a65f7SEric Schweitz mlir::OperationState &result,
3194a28896aeSEric Schweitz fir::CharacterType inType,
3195a28896aeSEric Schweitz llvm::ArrayRef<char> vlist,
3196de8a65f7SEric Schweitz llvm::Optional<std::int64_t> len) {
3197a28896aeSEric Schweitz auto valAttr =
3198a28896aeSEric Schweitz builder.getNamedAttr(xlist(), convertToArrayAttr(builder, vlist));
31990916d96dSKazu Hirata std::int64_t length = len ? *len : inType.getLen();
3200a28896aeSEric Schweitz auto lenAttr = mkNamedIntegerAttr(builder, size(), length);
3201a28896aeSEric Schweitz result.addAttributes({valAttr, lenAttr});
3202a28896aeSEric Schweitz result.addTypes(inType);
3203a28896aeSEric Schweitz }
3204a28896aeSEric Schweitz
build(mlir::OpBuilder & builder,mlir::OperationState & result,fir::CharacterType inType,llvm::ArrayRef<char16_t> vlist,llvm::Optional<std::int64_t> len)3205de8a65f7SEric Schweitz void fir::StringLitOp::build(mlir::OpBuilder &builder,
3206de8a65f7SEric Schweitz mlir::OperationState &result,
3207a28896aeSEric Schweitz fir::CharacterType inType,
3208a28896aeSEric Schweitz llvm::ArrayRef<char16_t> vlist,
3209de8a65f7SEric Schweitz llvm::Optional<std::int64_t> len) {
3210a28896aeSEric Schweitz auto valAttr =
3211a28896aeSEric Schweitz builder.getNamedAttr(xlist(), convertToArrayAttr(builder, vlist));
32120916d96dSKazu Hirata std::int64_t length = len ? *len : inType.getLen();
3213a28896aeSEric Schweitz auto lenAttr = mkNamedIntegerAttr(builder, size(), length);
3214a28896aeSEric Schweitz result.addAttributes({valAttr, lenAttr});
3215a28896aeSEric Schweitz result.addTypes(inType);
3216a28896aeSEric Schweitz }
3217a28896aeSEric Schweitz
build(mlir::OpBuilder & builder,mlir::OperationState & result,fir::CharacterType inType,llvm::ArrayRef<char32_t> vlist,llvm::Optional<std::int64_t> len)3218de8a65f7SEric Schweitz void fir::StringLitOp::build(mlir::OpBuilder &builder,
3219de8a65f7SEric Schweitz mlir::OperationState &result,
3220a28896aeSEric Schweitz fir::CharacterType inType,
3221a28896aeSEric Schweitz llvm::ArrayRef<char32_t> vlist,
3222de8a65f7SEric Schweitz llvm::Optional<std::int64_t> len) {
3223a28896aeSEric Schweitz auto valAttr =
3224a28896aeSEric Schweitz builder.getNamedAttr(xlist(), convertToArrayAttr(builder, vlist));
32250916d96dSKazu Hirata std::int64_t length = len ? *len : inType.getLen();
3226a28896aeSEric Schweitz auto lenAttr = mkNamedIntegerAttr(builder, size(), length);
3227a28896aeSEric Schweitz result.addAttributes({valAttr, lenAttr});
3228a28896aeSEric Schweitz result.addTypes(inType);
3229a28896aeSEric Schweitz }
3230a28896aeSEric Schweitz
parse(mlir::OpAsmParser & parser,mlir::OperationState & result)3231de8a65f7SEric Schweitz mlir::ParseResult fir::StringLitOp::parse(mlir::OpAsmParser &parser,
3232a28896aeSEric Schweitz mlir::OperationState &result) {
3233a28896aeSEric Schweitz auto &builder = parser.getBuilder();
3234a28896aeSEric Schweitz mlir::Attribute val;
3235a28896aeSEric Schweitz mlir::NamedAttrList attrs;
3236a28896aeSEric Schweitz llvm::SMLoc trailingTypeLoc;
3237a28896aeSEric Schweitz if (parser.parseAttribute(val, "fake", attrs))
3238a28896aeSEric Schweitz return mlir::failure();
3239a28896aeSEric Schweitz if (auto v = val.dyn_cast<mlir::StringAttr>())
3240a28896aeSEric Schweitz result.attributes.push_back(
3241a28896aeSEric Schweitz builder.getNamedAttr(fir::StringLitOp::value(), v));
3242ae35635fSValentin Clement else if (auto v = val.dyn_cast<mlir::DenseElementsAttr>())
3243ae35635fSValentin Clement result.attributes.push_back(
3244ae35635fSValentin Clement builder.getNamedAttr(fir::StringLitOp::xlist(), v));
3245a28896aeSEric Schweitz else if (auto v = val.dyn_cast<mlir::ArrayAttr>())
3246a28896aeSEric Schweitz result.attributes.push_back(
3247a28896aeSEric Schweitz builder.getNamedAttr(fir::StringLitOp::xlist(), v));
3248a28896aeSEric Schweitz else
3249a28896aeSEric Schweitz return parser.emitError(parser.getCurrentLocation(),
3250a28896aeSEric Schweitz "found an invalid constant");
3251a28896aeSEric Schweitz mlir::IntegerAttr sz;
3252a28896aeSEric Schweitz mlir::Type type;
3253a28896aeSEric Schweitz if (parser.parseLParen() ||
3254a28896aeSEric Schweitz parser.parseAttribute(sz, fir::StringLitOp::size(), result.attributes) ||
3255a28896aeSEric Schweitz parser.parseRParen() || parser.getCurrentLocation(&trailingTypeLoc) ||
3256a28896aeSEric Schweitz parser.parseColonType(type))
3257a28896aeSEric Schweitz return mlir::failure();
3258a28896aeSEric Schweitz auto charTy = type.dyn_cast<fir::CharacterType>();
3259a28896aeSEric Schweitz if (!charTy)
3260a28896aeSEric Schweitz return parser.emitError(trailingTypeLoc, "must have character type");
3261a28896aeSEric Schweitz type = fir::CharacterType::get(builder.getContext(), charTy.getFKind(),
3262a28896aeSEric Schweitz sz.getInt());
3263a28896aeSEric Schweitz if (!type || parser.addTypesToList(type, result.types))
3264a28896aeSEric Schweitz return mlir::failure();
3265a28896aeSEric Schweitz return mlir::success();
3266a28896aeSEric Schweitz }
3267a28896aeSEric Schweitz
print(mlir::OpAsmPrinter & p)3268de8a65f7SEric Schweitz void fir::StringLitOp::print(mlir::OpAsmPrinter &p) {
3269cc120e36SShraiysh Vaishay p << ' ' << getValue() << '(';
3270cc120e36SShraiysh Vaishay p << getSize().cast<mlir::IntegerAttr>().getValue() << ") : ";
3271cc120e36SShraiysh Vaishay p.printType(getType());
3272a28896aeSEric Schweitz }
3273a28896aeSEric Schweitz
verify()3274de8a65f7SEric Schweitz mlir::LogicalResult fir::StringLitOp::verify() {
3275cc120e36SShraiysh Vaishay if (getSize().cast<mlir::IntegerAttr>().getValue().isNegative())
3276cc120e36SShraiysh Vaishay return emitOpError("size must be non-negative");
3277cc120e36SShraiysh Vaishay if (auto xl = getOperation()->getAttr(fir::StringLitOp::xlist())) {
3278ae35635fSValentin Clement if (auto xList = xl.dyn_cast<mlir::ArrayAttr>()) {
3279a28896aeSEric Schweitz for (auto a : xList)
3280a28896aeSEric Schweitz if (!a.isa<mlir::IntegerAttr>())
3281ae35635fSValentin Clement return emitOpError("values in initializer must be integers");
3282ae35635fSValentin Clement } else if (xl.isa<mlir::DenseElementsAttr>()) {
3283ae35635fSValentin Clement // do nothing
3284ae35635fSValentin Clement } else {
3285ae35635fSValentin Clement return emitOpError("has unexpected attribute");
3286ae35635fSValentin Clement }
3287a28896aeSEric Schweitz }
3288a28896aeSEric Schweitz return mlir::success();
3289a28896aeSEric Schweitz }
3290a28896aeSEric Schweitz
329157f536a4SjeanPerier //===----------------------------------------------------------------------===//
3292633f70f7SValentin Clement // UnboxProcOp
3293633f70f7SValentin Clement //===----------------------------------------------------------------------===//
3294633f70f7SValentin Clement
verify()3295de8a65f7SEric Schweitz mlir::LogicalResult fir::UnboxProcOp::verify() {
3296149ad3d5SShraiysh Vaishay if (auto eleTy = fir::dyn_cast_ptrEleTy(getRefTuple().getType()))
3297633f70f7SValentin Clement if (eleTy.isa<mlir::TupleType>())
3298633f70f7SValentin Clement return mlir::success();
3299cc120e36SShraiysh Vaishay return emitOpError("second output argument has bad type");
3300633f70f7SValentin Clement }
3301633f70f7SValentin Clement
3302633f70f7SValentin Clement //===----------------------------------------------------------------------===//
3303f47d7c14SEric Schweitz // IfOp
330457f536a4SjeanPerier //===----------------------------------------------------------------------===//
33050b785a46SEric Schweitz
build(mlir::OpBuilder & builder,mlir::OperationState & result,mlir::Value cond,bool withElseRegion)3306de8a65f7SEric Schweitz void fir::IfOp::build(mlir::OpBuilder &builder, mlir::OperationState &result,
330757f536a4SjeanPerier mlir::Value cond, bool withElseRegion) {
33081c93671eSDavid Truby build(builder, result, llvm::None, cond, withElseRegion);
33091c93671eSDavid Truby }
33101c93671eSDavid Truby
build(mlir::OpBuilder & builder,mlir::OperationState & result,mlir::TypeRange resultTypes,mlir::Value cond,bool withElseRegion)3311de8a65f7SEric Schweitz void fir::IfOp::build(mlir::OpBuilder &builder, mlir::OperationState &result,
33121c93671eSDavid Truby mlir::TypeRange resultTypes, mlir::Value cond,
33131c93671eSDavid Truby bool withElseRegion) {
331457f536a4SjeanPerier result.addOperands(cond);
33151c93671eSDavid Truby result.addTypes(resultTypes);
33161c93671eSDavid Truby
331757f536a4SjeanPerier mlir::Region *thenRegion = result.addRegion();
33181c93671eSDavid Truby thenRegion->push_back(new mlir::Block());
33191c93671eSDavid Truby if (resultTypes.empty())
33200b785a46SEric Schweitz IfOp::ensureTerminator(*thenRegion, builder, result.location);
33211c93671eSDavid Truby
33221c93671eSDavid Truby mlir::Region *elseRegion = result.addRegion();
33231c93671eSDavid Truby if (withElseRegion) {
33241c93671eSDavid Truby elseRegion->push_back(new mlir::Block());
33251c93671eSDavid Truby if (resultTypes.empty())
33260b785a46SEric Schweitz IfOp::ensureTerminator(*elseRegion, builder, result.location);
332757f536a4SjeanPerier }
33281c93671eSDavid Truby }
332957f536a4SjeanPerier
parse(mlir::OpAsmParser & parser,mlir::OperationState & result)3330de8a65f7SEric Schweitz mlir::ParseResult fir::IfOp::parse(mlir::OpAsmParser &parser,
3331de8a65f7SEric Schweitz mlir::OperationState &result) {
333257f536a4SjeanPerier result.regions.reserve(2);
333357f536a4SjeanPerier mlir::Region *thenRegion = result.addRegion();
333457f536a4SjeanPerier mlir::Region *elseRegion = result.addRegion();
333557f536a4SjeanPerier
333657f536a4SjeanPerier auto &builder = parser.getBuilder();
3337de8a65f7SEric Schweitz mlir::OpAsmParser::UnresolvedOperand cond;
333857f536a4SjeanPerier mlir::Type i1Type = builder.getIntegerType(1);
333957f536a4SjeanPerier if (parser.parseOperand(cond) ||
334057f536a4SjeanPerier parser.resolveOperand(cond, i1Type, result.operands))
334157f536a4SjeanPerier return mlir::failure();
334257f536a4SjeanPerier
33430b785a46SEric Schweitz if (parser.parseOptionalArrowTypeList(result.types))
33440b785a46SEric Schweitz return mlir::failure();
33450b785a46SEric Schweitz
334657f536a4SjeanPerier if (parser.parseRegion(*thenRegion, {}, {}))
334757f536a4SjeanPerier return mlir::failure();
3348de8a65f7SEric Schweitz fir::IfOp::ensureTerminator(*thenRegion, parser.getBuilder(),
3349de8a65f7SEric Schweitz result.location);
335057f536a4SjeanPerier
33510b785a46SEric Schweitz if (mlir::succeeded(parser.parseOptionalKeyword("else"))) {
335257f536a4SjeanPerier if (parser.parseRegion(*elseRegion, {}, {}))
335357f536a4SjeanPerier return mlir::failure();
3354de8a65f7SEric Schweitz fir::IfOp::ensureTerminator(*elseRegion, parser.getBuilder(),
3355de8a65f7SEric Schweitz result.location);
335657f536a4SjeanPerier }
335757f536a4SjeanPerier
335857f536a4SjeanPerier // Parse the optional attribute list.
335957f536a4SjeanPerier if (parser.parseOptionalAttrDict(result.attributes))
336057f536a4SjeanPerier return mlir::failure();
336157f536a4SjeanPerier return mlir::success();
336257f536a4SjeanPerier }
336357f536a4SjeanPerier
verify()3364de8a65f7SEric Schweitz mlir::LogicalResult fir::IfOp::verify() {
3365125a4d91SAndrzej Warzynski if (getNumResults() != 0 && getElseRegion().empty())
3366125a4d91SAndrzej Warzynski return emitOpError("must have an else block if defining values");
3367bc034238SEric Schweitz
3368bc034238SEric Schweitz return mlir::success();
3369bc034238SEric Schweitz }
3370bc034238SEric Schweitz
print(mlir::OpAsmPrinter & p)3371de8a65f7SEric Schweitz void fir::IfOp::print(mlir::OpAsmPrinter &p) {
3372bc034238SEric Schweitz bool printBlockTerminators = false;
3373125a4d91SAndrzej Warzynski p << ' ' << getCondition();
3374125a4d91SAndrzej Warzynski if (!getResults().empty()) {
3375125a4d91SAndrzej Warzynski p << " -> (" << getResultTypes() << ')';
3376bc034238SEric Schweitz printBlockTerminators = true;
3377bc034238SEric Schweitz }
33785c36ee8dSMogball p << ' ';
3379125a4d91SAndrzej Warzynski p.printRegion(getThenRegion(), /*printEntryBlockArgs=*/false,
3380bc034238SEric Schweitz printBlockTerminators);
3381bc034238SEric Schweitz
3382bc034238SEric Schweitz // Print the 'else' regions if it exists and has a block.
3383125a4d91SAndrzej Warzynski auto &otherReg = getElseRegion();
3384bc034238SEric Schweitz if (!otherReg.empty()) {
3385bc034238SEric Schweitz p << " else ";
3386bc034238SEric Schweitz p.printRegion(otherReg, /*printEntryBlockArgs=*/false,
3387bc034238SEric Schweitz printBlockTerminators);
3388bc034238SEric Schweitz }
3389125a4d91SAndrzej Warzynski p.printOptionalAttrDict((*this)->getAttrs());
3390bc034238SEric Schweitz }
3391bc034238SEric Schweitz
resultToSourceOps(llvm::SmallVectorImpl<mlir::Value> & results,unsigned resultNum)33920b785a46SEric Schweitz void fir::IfOp::resultToSourceOps(llvm::SmallVectorImpl<mlir::Value> &results,
33930b785a46SEric Schweitz unsigned resultNum) {
3394149ad3d5SShraiysh Vaishay auto *term = getThenRegion().front().getTerminator();
33950b785a46SEric Schweitz if (resultNum < term->getNumOperands())
33960b785a46SEric Schweitz results.push_back(term->getOperand(resultNum));
3397149ad3d5SShraiysh Vaishay term = getElseRegion().front().getTerminator();
33980b785a46SEric Schweitz if (resultNum < term->getNumOperands())
33990b785a46SEric Schweitz results.push_back(term->getOperand(resultNum));
34000b785a46SEric Schweitz }
34010b785a46SEric Schweitz
340257f536a4SjeanPerier //===----------------------------------------------------------------------===//
340357f536a4SjeanPerier
isValidCaseAttr(mlir::Attribute attr)340457f536a4SjeanPerier mlir::ParseResult fir::isValidCaseAttr(mlir::Attribute attr) {
3405de8a65f7SEric Schweitz if (attr.isa<mlir::UnitAttr, fir::ClosedIntervalAttr, fir::PointIntervalAttr,
3406de8a65f7SEric Schweitz fir::LowerBoundAttr, fir::UpperBoundAttr>())
340757f536a4SjeanPerier return mlir::success();
340857f536a4SjeanPerier return mlir::failure();
340957f536a4SjeanPerier }
341057f536a4SjeanPerier
getCaseArgumentOffset(llvm::ArrayRef<mlir::Attribute> cases,unsigned dest)341157f536a4SjeanPerier unsigned fir::getCaseArgumentOffset(llvm::ArrayRef<mlir::Attribute> cases,
341257f536a4SjeanPerier unsigned dest) {
341357f536a4SjeanPerier unsigned o = 0;
341457f536a4SjeanPerier for (unsigned i = 0; i < dest; ++i) {
341557f536a4SjeanPerier auto &attr = cases[i];
341657f536a4SjeanPerier if (!attr.dyn_cast_or_null<mlir::UnitAttr>()) {
341757f536a4SjeanPerier ++o;
3418de8a65f7SEric Schweitz if (attr.dyn_cast_or_null<fir::ClosedIntervalAttr>())
341957f536a4SjeanPerier ++o;
342057f536a4SjeanPerier }
342157f536a4SjeanPerier }
342257f536a4SjeanPerier return o;
342357f536a4SjeanPerier }
342457f536a4SjeanPerier
3425e13d23bcSMarkus Böck mlir::ParseResult
parseSelector(mlir::OpAsmParser & parser,mlir::OperationState & result,mlir::OpAsmParser::UnresolvedOperand & selector,mlir::Type & type)3426e13d23bcSMarkus Böck fir::parseSelector(mlir::OpAsmParser &parser, mlir::OperationState &result,
3427e13d23bcSMarkus Böck mlir::OpAsmParser::UnresolvedOperand &selector,
342857f536a4SjeanPerier mlir::Type &type) {
342957f536a4SjeanPerier if (parser.parseOperand(selector) || parser.parseColonType(type) ||
343057f536a4SjeanPerier parser.resolveOperand(selector, type, result.operands) ||
343157f536a4SjeanPerier parser.parseLSquare())
343257f536a4SjeanPerier return mlir::failure();
343357f536a4SjeanPerier return mlir::success();
343457f536a4SjeanPerier }
343557f536a4SjeanPerier
343658ceae95SRiver Riddle mlir::func::FuncOp
createFuncOp(mlir::Location loc,mlir::ModuleOp module,llvm::StringRef name,mlir::FunctionType type,llvm::ArrayRef<mlir::NamedAttribute> attrs)3437de8a65f7SEric Schweitz fir::createFuncOp(mlir::Location loc, mlir::ModuleOp module,
3438de8a65f7SEric Schweitz llvm::StringRef name, mlir::FunctionType type,
343957f536a4SjeanPerier llvm::ArrayRef<mlir::NamedAttribute> attrs) {
344058ceae95SRiver Riddle if (auto f = module.lookupSymbol<mlir::func::FuncOp>(name))
344157f536a4SjeanPerier return f;
344257f536a4SjeanPerier mlir::OpBuilder modBuilder(module.getBodyRegion());
344345503fc0SValentin Clement modBuilder.setInsertionPointToEnd(module.getBody());
344458ceae95SRiver Riddle auto result = modBuilder.create<mlir::func::FuncOp>(loc, name, type, attrs);
34450b785a46SEric Schweitz result.setVisibility(mlir::SymbolTable::Visibility::Private);
34460b785a46SEric Schweitz return result;
344757f536a4SjeanPerier }
344857f536a4SjeanPerier
createGlobalOp(mlir::Location loc,mlir::ModuleOp module,llvm::StringRef name,mlir::Type type,llvm::ArrayRef<mlir::NamedAttribute> attrs)344957f536a4SjeanPerier fir::GlobalOp fir::createGlobalOp(mlir::Location loc, mlir::ModuleOp module,
3450de8a65f7SEric Schweitz llvm::StringRef name, mlir::Type type,
345157f536a4SjeanPerier llvm::ArrayRef<mlir::NamedAttribute> attrs) {
345257f536a4SjeanPerier if (auto g = module.lookupSymbol<fir::GlobalOp>(name))
345357f536a4SjeanPerier return g;
345457f536a4SjeanPerier mlir::OpBuilder modBuilder(module.getBodyRegion());
34550b785a46SEric Schweitz auto result = modBuilder.create<fir::GlobalOp>(loc, name, type, attrs);
34560b785a46SEric Schweitz result.setVisibility(mlir::SymbolTable::Visibility::Private);
34570b785a46SEric Schweitz return result;
345857f536a4SjeanPerier }
345957f536a4SjeanPerier
hasHostAssociationArgument(mlir::func::FuncOp func)346058ceae95SRiver Riddle bool fir::hasHostAssociationArgument(mlir::func::FuncOp func) {
3461beeb86bdSValentin Clement if (auto allArgAttrs = func.getAllArgAttrs())
3462beeb86bdSValentin Clement for (auto attr : allArgAttrs)
3463beeb86bdSValentin Clement if (auto dict = attr.template dyn_cast_or_null<mlir::DictionaryAttr>())
3464beeb86bdSValentin Clement if (dict.get(fir::getHostAssocAttrName()))
3465beeb86bdSValentin Clement return true;
3466beeb86bdSValentin Clement return false;
3467beeb86bdSValentin Clement }
3468beeb86bdSValentin Clement
valueHasFirAttribute(mlir::Value value,llvm::StringRef attributeName)3469ac473bb2SEric Schweitz bool fir::valueHasFirAttribute(mlir::Value value,
3470ac473bb2SEric Schweitz llvm::StringRef attributeName) {
3471ac473bb2SEric Schweitz // If this is a fir.box that was loaded, the fir attributes will be on the
3472ac473bb2SEric Schweitz // related fir.ref<fir.box> creation.
3473ac473bb2SEric Schweitz if (value.getType().isa<fir::BoxType>())
3474ac473bb2SEric Schweitz if (auto definingOp = value.getDefiningOp())
3475ac473bb2SEric Schweitz if (auto loadOp = mlir::dyn_cast<fir::LoadOp>(definingOp))
3476149ad3d5SShraiysh Vaishay value = loadOp.getMemref();
3477ac473bb2SEric Schweitz // If this is a function argument, look in the argument attributes.
3478ac473bb2SEric Schweitz if (auto blockArg = value.dyn_cast<mlir::BlockArgument>()) {
3479ac473bb2SEric Schweitz if (blockArg.getOwner() && blockArg.getOwner()->isEntryBlock())
348058ceae95SRiver Riddle if (auto funcOp = mlir::dyn_cast<mlir::func::FuncOp>(
348158ceae95SRiver Riddle blockArg.getOwner()->getParentOp()))
3482ac473bb2SEric Schweitz if (funcOp.getArgAttr(blockArg.getArgNumber(), attributeName))
3483ac473bb2SEric Schweitz return true;
3484ac473bb2SEric Schweitz return false;
3485ac473bb2SEric Schweitz }
3486ac473bb2SEric Schweitz
3487ac473bb2SEric Schweitz if (auto definingOp = value.getDefiningOp()) {
3488ac473bb2SEric Schweitz // If this is an allocated value, look at the allocation attributes.
3489ac473bb2SEric Schweitz if (mlir::isa<fir::AllocMemOp>(definingOp) ||
3490ac473bb2SEric Schweitz mlir::isa<AllocaOp>(definingOp))
3491ac473bb2SEric Schweitz return definingOp->hasAttr(attributeName);
3492ac473bb2SEric Schweitz // If this is an imported global, look at AddrOfOp and GlobalOp attributes.
3493ac473bb2SEric Schweitz // Both operations are looked at because use/host associated variable (the
3494ac473bb2SEric Schweitz // AddrOfOp) can have ASYNCHRONOUS/VOLATILE attributes even if the ultimate
3495ac473bb2SEric Schweitz // entity (the globalOp) does not have them.
3496ac473bb2SEric Schweitz if (auto addressOfOp = mlir::dyn_cast<fir::AddrOfOp>(definingOp)) {
3497ac473bb2SEric Schweitz if (addressOfOp->hasAttr(attributeName))
3498ac473bb2SEric Schweitz return true;
3499ac473bb2SEric Schweitz if (auto module = definingOp->getParentOfType<mlir::ModuleOp>())
3500ac473bb2SEric Schweitz if (auto globalOp =
3501149ad3d5SShraiysh Vaishay module.lookupSymbol<fir::GlobalOp>(addressOfOp.getSymbol()))
3502ac473bb2SEric Schweitz return globalOp->hasAttr(attributeName);
3503ac473bb2SEric Schweitz }
3504ac473bb2SEric Schweitz }
3505ac473bb2SEric Schweitz // TODO: Construct associated entities attributes. Decide where the fir
3506ac473bb2SEric Schweitz // attributes must be placed/looked for in this case.
3507ac473bb2SEric Schweitz return false;
3508ac473bb2SEric Schweitz }
3509ac473bb2SEric Schweitz
anyFuncArgsHaveAttr(mlir::func::FuncOp func,llvm::StringRef attr)351058ceae95SRiver Riddle bool fir::anyFuncArgsHaveAttr(mlir::func::FuncOp func, llvm::StringRef attr) {
3511d0b70a07SValentin Clement for (unsigned i = 0, end = func.getNumArguments(); i < end; ++i)
3512d0b70a07SValentin Clement if (func.getArgAttr(i, attr))
3513d0b70a07SValentin Clement return true;
3514d0b70a07SValentin Clement return false;
3515d0b70a07SValentin Clement }
3516d0b70a07SValentin Clement
applyPathToType(mlir::Type eleTy,mlir::ValueRange path)351734d6c182SEric Schweitz mlir::Type fir::applyPathToType(mlir::Type eleTy, mlir::ValueRange path) {
351834d6c182SEric Schweitz for (auto i = path.begin(), end = path.end(); eleTy && i < end;) {
351934d6c182SEric Schweitz eleTy = llvm::TypeSwitch<mlir::Type, mlir::Type>(eleTy)
352034d6c182SEric Schweitz .Case<fir::RecordType>([&](fir::RecordType ty) {
352134d6c182SEric Schweitz if (auto *op = (*i++).getDefiningOp()) {
352234d6c182SEric Schweitz if (auto off = mlir::dyn_cast<fir::FieldIndexOp>(op))
352334d6c182SEric Schweitz return ty.getType(off.getFieldName());
3524a54f4eaeSMogball if (auto off = mlir::dyn_cast<mlir::arith::ConstantOp>(op))
352534d6c182SEric Schweitz return ty.getType(fir::toInt(off));
352634d6c182SEric Schweitz }
352734d6c182SEric Schweitz return mlir::Type{};
352834d6c182SEric Schweitz })
352934d6c182SEric Schweitz .Case<fir::SequenceType>([&](fir::SequenceType ty) {
353034d6c182SEric Schweitz bool valid = true;
353134d6c182SEric Schweitz const auto rank = ty.getDimension();
353234d6c182SEric Schweitz for (std::remove_const_t<decltype(rank)> ii = 0;
353334d6c182SEric Schweitz valid && ii < rank; ++ii)
353434d6c182SEric Schweitz valid = i < end && fir::isa_integer((*i++).getType());
353534d6c182SEric Schweitz return valid ? ty.getEleTy() : mlir::Type{};
353634d6c182SEric Schweitz })
353734d6c182SEric Schweitz .Case<mlir::TupleType>([&](mlir::TupleType ty) {
353834d6c182SEric Schweitz if (auto *op = (*i++).getDefiningOp())
3539a54f4eaeSMogball if (auto off = mlir::dyn_cast<mlir::arith::ConstantOp>(op))
354034d6c182SEric Schweitz return ty.getType(fir::toInt(off));
354134d6c182SEric Schweitz return mlir::Type{};
354234d6c182SEric Schweitz })
354334d6c182SEric Schweitz .Case<fir::ComplexType>([&](fir::ComplexType ty) {
3544f5b970c9SEric Schweitz auto x = *i;
3545f5b970c9SEric Schweitz if (auto *op = (*i++).getDefiningOp())
3546f5b970c9SEric Schweitz if (fir::isa_integer(x.getType()))
3547f5b970c9SEric Schweitz return ty.getEleType(fir::getKindMapping(
3548f5b970c9SEric Schweitz op->getParentOfType<mlir::ModuleOp>()));
354934d6c182SEric Schweitz return mlir::Type{};
355034d6c182SEric Schweitz })
355134d6c182SEric Schweitz .Case<mlir::ComplexType>([&](mlir::ComplexType ty) {
355234d6c182SEric Schweitz if (fir::isa_integer((*i++).getType()))
355334d6c182SEric Schweitz return ty.getElementType();
355434d6c182SEric Schweitz return mlir::Type{};
355534d6c182SEric Schweitz })
355634d6c182SEric Schweitz .Default([&](const auto &) { return mlir::Type{}; });
355734d6c182SEric Schweitz }
355834d6c182SEric Schweitz return eleTy;
355934d6c182SEric Schweitz }
356034d6c182SEric Schweitz
356157f536a4SjeanPerier // Tablegen operators
356257f536a4SjeanPerier
356357f536a4SjeanPerier #define GET_OP_CLASSES
356457f536a4SjeanPerier #include "flang/Optimizer/Dialect/FIROps.cpp.inc"
3565