diff --git a/flang/include/flang/Optimizer/Dialect/FIROps.td b/flang/include/flang/Optimizer/Dialect/FIROps.td --- a/flang/include/flang/Optimizer/Dialect/FIROps.td +++ b/flang/include/flang/Optimizer/Dialect/FIROps.td @@ -394,43 +394,11 @@ let arguments = (ins Arg:$memref); - let builders = [OpBuilder<(ins "mlir::Value":$refVal), - [{ - if (!refVal) { - mlir::emitError($_state.location, "LoadOp has null argument"); - return; - } - auto eleTy = fir::dyn_cast_ptrEleTy(refVal.getType()); - if (!eleTy) { - mlir::emitError($_state.location, "not a memory reference type"); - return; - } - $_state.addOperands(refVal); - $_state.addTypes(eleTy); - }] - >]; + let builders = [OpBuilder<(ins "mlir::Value":$refVal)>]; - let parser = [{ - mlir::Type type; - mlir::OpAsmParser::OperandType oper; - if (parser.parseOperand(oper) || - parser.parseOptionalAttrDict(result.attributes) || - parser.parseColonType(type) || - parser.resolveOperand(oper, type, result.operands)) - return mlir::failure(); - mlir::Type eleTy; - if (getElementOf(eleTy, type) || - parser.addTypeToList(eleTy, result.types)) - return mlir::failure(); - return mlir::success(); - }]; + let parser = "return parseLoadOp(parser, result);"; - let printer = [{ - p << ' '; - p.printOperand(memref()); - p.printOptionalAttrDict((*this)->getAttrs(), {}); - p << " : " << memref().getType(); - }]; + let printer = "::print(p, *this);"; let extraClassDeclaration = [{ static mlir::ParseResult getElementOf(mlir::Type &ele, mlir::Type ref); @@ -878,60 +846,9 @@ let parser = "return parseSelectCase(parser, result);"; - let printer = [{ - p << ' '; - p.printOperand(getSelector()); - p << " : " << getSelector().getType() << " ["; - auto cases = (*this)->getAttrOfType(getCasesAttr()).getValue(); - auto count = getNumConditions(); - for (decltype(count) i = 0; i != count; ++i) { - if (i) - p << ", "; - p << cases[i] << ", "; - if (!cases[i].isa()) { - auto caseArgs = *getCompareOperands(i); - p.printOperand(*caseArgs.begin()); - p << ", "; - if (cases[i].isa()) { - p.printOperand(*(++caseArgs.begin())); - p << ", "; - } - } - printSuccessorAtIndex(p, i); - } - p << ']'; - p.printOptionalAttrDict((*this)->getAttrs(), {getCasesAttr(), getCompareOffsetAttr(), - getTargetOffsetAttr(), getOperandSegmentSizeAttr()}); - }]; + let printer = "::print(p, *this);"; - let verifier = [{ - if (!(getSelector().getType().isa() || - getSelector().getType().isa() || - getSelector().getType().isa() || - getSelector().getType().isa() || - getSelector().getType().isa())) - return emitOpError("must be an integer, character, or logical"); - auto cases = (*this)->getAttrOfType(getCasesAttr()).getValue(); - auto count = getNumDest(); - if (count == 0) - return emitOpError("must have at least one successor"); - if (getNumConditions() != count) - return emitOpError("number of conditions and successors don't match"); - if (compareOffsetSize() != count) - return emitOpError("incorrect number of compare operand groups"); - if (targetOffsetSize() != count) - return emitOpError("incorrect number of successor operand groups"); - for (decltype(count) i = 0; i != count; ++i) { - auto &attr = cases[i]; - if (!(attr.isa() || - attr.isa() || - attr.isa() || - attr.isa() || - attr.isa())) - return emitOpError("incorrect select case attribute type"); - } - return mlir::success(); - }]; + let verifier = "return ::verify(*this);"; let extraClassDeclaration = extraSwitchClassDeclaration#[{ unsigned compareOffsetSize(); @@ -994,42 +911,9 @@ let parser = "return parseSelectType(parser, result);"; - let printer = [{ - p << ' '; - p.printOperand(getSelector()); - p << " : " << getSelector().getType() << " ["; - auto cases = (*this)->getAttrOfType(getCasesAttr()).getValue(); - auto count = getNumConditions(); - for (decltype(count) i = 0; i != count; ++i) { - if (i) - p << ", "; - p << cases[i] << ", "; - printSuccessorAtIndex(p, i); - } - p << ']'; - p.printOptionalAttrDict((*this)->getAttrs(), {getCasesAttr(), getCompareOffsetAttr(), - getTargetOffsetAttr(), getOperandSegmentSizeAttr()}); - }]; + let printer = "::print(p, *this);"; - let verifier = [{ - if (!(getSelector().getType().isa())) - return emitOpError("must be a boxed type"); - auto cases = (*this)->getAttrOfType(getCasesAttr()).getValue(); - auto count = getNumDest(); - if (count == 0) - return emitOpError("must have at least one successor"); - if (getNumConditions() != count) - return emitOpError("number of conditions and successors don't match"); - if (targetOffsetSize() != count) - return emitOpError("incorrect number of successor operand groups"); - for (decltype(count) i = 0; i != count; ++i) { - auto &attr = cases[i]; - if (!(attr.isa() || attr.isa() || - attr.isa())) - return emitOpError("invalid type-case alternative"); - } - return mlir::success(); - }]; + let verifier = "return ::verify(*this);"; let extraClassDeclaration = extraSwitchClassDeclaration; } @@ -1201,7 +1085,7 @@ $box (`(` $shape^ `)`)? (`[` $slice^ `]`)? attr-dict `:` functional-type(operands, results) }]; - let verifier = [{ return ::verify(*this); }]; + let verifier = "return ::verify(*this);"; } def fir_EmboxCharOp : fir_Op<"emboxchar", [NoSideEffect]> { @@ -1234,12 +1118,7 @@ $memref `,` $len attr-dict `:` functional-type(operands, results) }]; - let verifier = [{ - auto eleTy = elementTypeOf(memref().getType()); - if (!eleTy.dyn_cast()) - return mlir::failure(); - return mlir::success(); - }]; + let verifier = "return ::verify(*this);"; } def fir_EmboxProcOp : fir_Op<"emboxproc", [NoSideEffect]> { @@ -1271,64 +1150,11 @@ let results = (outs fir_BoxProcType); - let parser = [{ - mlir::SymbolRefAttr procRef; - if (parser.parseAttribute(procRef, "funcname", result.attributes)) - return mlir::failure(); - bool hasTuple = false; - mlir::OpAsmParser::OperandType tupleRef; - if (!parser.parseOptionalComma()) { - if (parser.parseOperand(tupleRef)) - return mlir::failure(); - hasTuple = true; - } - mlir::FunctionType type; - if (parser.parseColon() || - parser.parseLParen() || - parser.parseType(type)) - return mlir::failure(); - result.addAttribute("functype", mlir::TypeAttr::get(type)); - if (hasTuple) { - mlir::Type tupleType; - if (parser.parseComma() || - parser.parseType(tupleType) || - parser.resolveOperand(tupleRef, tupleType, result.operands)) - return mlir::failure(); - } - mlir::Type boxType; - if (parser.parseRParen() || - parser.parseArrow() || - parser.parseType(boxType) || - parser.addTypesToList(boxType, result.types)) - return mlir::failure(); - return mlir::success(); - }]; + let parser = "return parseEmboxProcOp(parser, result);"; - let printer = [{ - p << ' ' << (*this)->getAttr("funcname"); - auto h = host(); - if (h) { - p << ", "; - p.printOperand(h); - } - p << " : (" << (*this)->getAttr("functype"); - if (h) - p << ", " << h.getType(); - p << ") -> " << getType(); - }]; + let printer = "::print(p, *this);"; - let verifier = [{ - // host bindings (optional) must be a reference to a tuple - if (auto h = host()) { - if (auto r = h.getType().dyn_cast()) { - if (!r.getEleTy().dyn_cast()) - return mlir::failure(); - } else { - return mlir::failure(); - } - } - return mlir::success(); - }]; + let verifier = "return ::verify(*this);"; } def fir_UnboxOp : fir_SimpleOp<"unbox", [NoSideEffect]> { @@ -1390,12 +1216,7 @@ ``` }]; - let verifier = [{ - if (auto eleTy = fir::dyn_cast_ptrEleTy(refTuple().getType())) - if (eleTy.isa()) - return mlir::success(); - return emitOpError("second output argument has bad type"); - }]; + let verifier = "return ::verify(*this);"; let arguments = (ins fir_BoxProcType:$boxproc); @@ -1705,7 +1526,7 @@ attr-dict `:` functional-type(operands, results) }]; - let verifier = [{ return ::verify(*this); }]; + let verifier = "return ::verify(*this);"; let extraClassDeclaration = [{ std::vector getExtents(); @@ -1935,9 +1756,9 @@ let results = (outs fir_ReferenceType); - let parser = [{ return parseCoordinateCustom(parser, result); }]; - let printer = [{ ::print(p, *this); }]; - let verifier = [{ return ::verify(*this); }]; + let parser = "return parseCoordinateCustom(parser, result);"; + let printer = "::print(p, *this);"; + let verifier = "return ::verify(*this);"; let builders = [ OpBuilder<(ins "mlir::Type":$resultType, @@ -2141,18 +1962,7 @@ operands attr-dict `:` functional-type(operands, results) }]; - let verifier = [{ - auto size = pairs().size(); - if (size < 2 || size > 16 * 2) - return emitOpError("incorrect number of args"); - if (size % 2 != 0) - return emitOpError("requires a multiple of 2 args"); - auto shapeTy = getType().dyn_cast(); - assert(shapeTy && "must be a shape shift type"); - if (shapeTy.getRank() * 2 != size) - return emitOpError("shape type rank mismatch"); - return mlir::success(); - }]; + let verifier = "return ::verify(*this);"; let extraClassDeclaration = [{ // Logically unzip the origins from the extent values. @@ -2199,14 +2009,7 @@ operands attr-dict `:` functional-type(operands, results) }]; - let verifier = [{ - auto size = origins().size(); - auto shiftTy = getType().dyn_cast(); - assert(shiftTy && "must be a shift type"); - if (shiftTy.getRank() != size) - return emitOpError("shift type rank mismatch"); - return mlir::success(); - }]; + let verifier = "return ::verify(*this);"; let extraClassDeclaration = [{ std::vector getOrigins() { @@ -2253,18 +2056,7 @@ $triples (`path` $fields^)? attr-dict `:` functional-type(operands, results) }]; - let verifier = [{ - auto size = triples().size(); - if (size < 3 || size > 16 * 3) - return emitOpError("incorrect number of args for triple"); - if (size % 3 != 0) - return emitOpError("requires a multiple of 3 args"); - auto sliceTy = getType().dyn_cast(); - assert(sliceTy && "must be a slice type"); - if (sliceTy.getRank() * 3 != size) - return emitOpError("slice type rank mismatch"); - return mlir::success(); - }]; + let verifier = "return ::verify(*this);"; let extraClassDeclaration = [{ unsigned getOutRank() { return getOutputRank(triples()); } @@ -2363,29 +2155,9 @@ let arguments = (ins StrAttr:$field_id, TypeAttr:$on_type); - let parser = [{ - llvm::StringRef fieldName; - auto &builder = parser.getBuilder(); - mlir::Type recty; - if (parser.parseOptionalKeyword(&fieldName) || - parser.parseComma() || - parser.parseType(recty)) - return mlir::failure(); - result.addAttribute(fieldAttrName(), builder.getStringAttr(fieldName)); - if (!recty.dyn_cast()) - return mlir::failure(); - result.addAttribute(typeAttrName(), mlir::TypeAttr::get(recty)); - mlir::Type lenType = fir::LenType::get(builder.getContext()); - if (parser.addTypeToList(lenType, result.types)) - return mlir::failure(); - return mlir::success(); - }]; + let parser = "return parseLenParamIndexOp(parser, result);"; - let printer = [{ - p << ' ' - << (*this)->getAttrOfType(fieldAttrName()).getValue() - << ", " << (*this)->getAttr(typeAttrName()); - }]; + let printer = "::print(p, *this);"; let builders = [OpBuilder<(ins "llvm::StringRef":$fieldName, "mlir::Type":$recTy), @@ -2425,7 +2197,7 @@ let assemblyFormat = "($results^ `:` type($results))? attr-dict"; - let verifier = [{ return ::verify(*this); }]; + let verifier = "return ::verify(*this);"; } def FirRegionTerminator : SingleBlockImplicitTerminator<"ResultOp">; @@ -2433,9 +2205,9 @@ class region_Op traits = []> : fir_Op { - let printer = [{ return ::print(p, *this); }]; - let verifier = [{ return ::verify(*this); }]; - let parser = [{ return ::parse$cppClass(parser, result); }]; + let printer = "return ::print(p, *this);"; + let verifier = "return ::verify(*this);"; + let parser = "return ::parse$cppClass(parser, result);"; } def fir_DoLoopOp : region_Op<"do_loop", @@ -2757,41 +2529,9 @@ let results = (outs Variadic); - let parser = [{ - mlir::FunctionType calleeType; - llvm::SmallVector operands; - auto calleeLoc = parser.getNameLoc(); - llvm::StringRef calleeName; - if (failed(parser.parseOptionalKeyword(&calleeName))) { - mlir::StringAttr calleeAttr; - if (parser.parseAttribute(calleeAttr, "method", result.attributes)) - return mlir::failure(); - } else { - result.addAttribute(methodAttrName(result.name), - parser.getBuilder().getStringAttr(calleeName)); - } - if (parser.parseOperandList(operands, - mlir::OpAsmParser::Delimiter::Paren) || - parser.parseOptionalAttrDict(result.attributes) || - parser.parseColonType(calleeType) || - parser.addTypesToList(calleeType.getResults(), result.types) || - parser.resolveOperands( - operands, calleeType.getInputs(), calleeLoc, result.operands)) - return mlir::failure(); - return mlir::success(); - }]; + let parser = "return parseDispatchOp(parser, result);"; - let printer = [{ - p << ' ' << methodAttr() << '('; - p.printOperand(object()); - if (!args().empty()) { - p << ", "; - p.printOperands(args()); - } - p << ") : "; - p.printFunctionalType((*this)->getOperandTypes(), - (*this)->getResultTypes()); - }]; + let printer = "::print(p, *this);"; let extraClassDeclaration = [{ mlir::FunctionType getFunctionType(); @@ -2804,6 +2544,7 @@ static constexpr llvm::StringRef passArgAttrName() { return "pass_arg_pos"; } + static constexpr llvm::StringRef getMethodAttrName() { return "method"; } unsigned passArgPos(); }]; } @@ -2912,39 +2653,11 @@ let results = (outs fir_ComplexType); - let parser = [{ - fir::RealAttr realp; - fir::RealAttr imagp; - mlir::Type type; - if (parser.parseLParen() || - parser.parseAttribute(realp, realAttrName(), result.attributes) || - parser.parseComma() || - parser.parseAttribute(imagp, imagAttrName(), result.attributes) || - parser.parseRParen() || - parser.parseColonType(type) || - parser.addTypesToList(type, result.types)) - return mlir::failure(); - return mlir::success(); - }]; + let parser = "return parseConstcOp(parser, result);"; - let printer = [{ - p << " (0x"; - auto f1 = (*this)->getAttr(realAttrName()).cast(); - auto i1 = f1.getValue().bitcastToAPInt(); - p.getStream().write_hex(i1.getZExtValue()); - p << ", 0x"; - auto f2 = (*this)->getAttr(imagAttrName()).cast(); - auto i2 = f2.getValue().bitcastToAPInt(); - p.getStream().write_hex(i2.getZExtValue()); - p << ") : "; - p.printType(getType()); - }]; + let printer = "::print(p, *this);"; - let verifier = [{ - if (!getType().isa()) - return emitOpError("must be a !fir.complex type"); - return mlir::success(); - }]; + let verifier = "return ::verify(*this);"; let extraClassDeclaration = [{ static constexpr llvm::StringRef realAttrName() { return "real"; } @@ -3052,23 +2765,7 @@ let hasFolder = 1; - let verifier = [{ - auto inType = value().getType(); - auto outType = getType(); - if (inType == outType) - return mlir::success(); - if ((isPointerCompatible(inType) && isPointerCompatible(outType)) || - (isIntegerCompatible(inType) && isIntegerCompatible(outType)) || - (isIntegerCompatible(inType) && isFloatCompatible(outType)) || - (isFloatCompatible(inType) && isIntegerCompatible(outType)) || - (isFloatCompatible(inType) && isFloatCompatible(outType)) || - (isIntegerCompatible(inType) && isPointerCompatible(outType)) || - (isPointerCompatible(inType) && isIntegerCompatible(outType)) || - (inType.isa() && outType.isa()) || - (fir::isa_complex(inType) && fir::isa_complex(outType))) - return mlir::success(); - return emitOpError("invalid type conversion"); - }]; + let verifier = "return ::verify(*this);"; let extraClassDeclaration = [{ static bool isIntegerCompatible(mlir::Type ty); @@ -3106,34 +2803,13 @@ let arguments = (ins FortranTypeAttr:$in_type); - let parser = [{ - mlir::Type intype; - if (parser.parseType(intype)) - return mlir::failure(); - result.addAttribute("in_type", mlir::TypeAttr::get(intype)); - mlir::Type restype = TypeDescType::get(intype); - if (parser.addTypeToList(restype, result.types)) - return mlir::failure(); - return mlir::success(); - }]; + let parser = "return parseGenTypeDescOp(parser, result);"; - let printer = [{ - p << ' ' << (*this)->getAttr("in_type"); - p.printOptionalAttrDict((*this)->getAttrs(), {"in_type"}); - }]; + let printer = "::print(p, *this);"; let builders = [OpBuilder<(ins "mlir::TypeAttr":$inty)>]; - let verifier = [{ - mlir::Type resultTy = getType(); - if (auto tdesc = resultTy.dyn_cast()) { - if (tdesc.getOfTy() != getInType()) - return emitOpError("wrapped type mismatched"); - } else { - return emitOpError("must be !fir.tdesc type"); - } - return mlir::success(); - }]; + let verifier = "return ::verify(*this);"; let extraClassDeclaration = [{ mlir::Type getInType() { @@ -3355,44 +3031,11 @@ ``` }]; - let parser = [{ - // Parse the name as a symbol reference attribute. - SymbolRefAttr nameAttr; - if (parser.parseAttribute(nameAttr, mlir::SymbolTable::getSymbolAttrName(), - result.attributes)) - return failure(); - - // Convert the parsed name attr into a string attr. - result.attributes.set(mlir::SymbolTable::getSymbolAttrName(), - nameAttr.getRootReference()); - - // Parse the optional table body. - mlir::Region *body = result.addRegion(); - OptionalParseResult parseResult = parser.parseOptionalRegion(*body); - if (parseResult.hasValue() && failed(*parseResult)) - return mlir::failure(); - - ensureTerminator(*body, parser.getBuilder(), result.location); - return mlir::success(); - }]; + let parser = "return parseDispatchTableOp(parser, result);"; - let printer = [{ - auto tableName = (*this)->getAttrOfType( - mlir::SymbolTable::getSymbolAttrName()).getValue(); - p << " @" << tableName; - - Region &body = (*this)->getRegion(0); - if (!body.empty()) - p.printRegion(body, /*printEntryBlockArgs=*/false, - /*printBlockTerminators=*/false); - }]; + let printer = "::print(p, *this);"; - let verifier = [{ - for (auto &op : getBlock()) - if (!(isa(op) || isa(op))) - return emitOpError("dispatch table must contain dt_entry"); - return mlir::success(); - }]; + let verifier = "return ::verify(*this);"; let regions = (region SizedRegion<1>:$region); @@ -3438,28 +3081,13 @@ let arguments = (ins StrAttr:$method, SymbolRefAttr:$proc); - let parser = [{ - llvm::StringRef methodName; - // allow `methodName` or `"methodName"` - if (failed(parser.parseOptionalKeyword(&methodName))) { - mlir::StringAttr methodAttr; - if (parser.parseAttribute(methodAttr, "method", - result.attributes)) - return mlir::failure(); - } else { - result.addAttribute(methodAttrName(result.name), - parser.getBuilder().getStringAttr(methodName)); - } - mlir::SymbolRefAttr calleeAttr; - if (parser.parseComma() || - parser.parseAttribute(calleeAttr, "proc", result.attributes)) - return mlir::failure(); - return mlir::success(); - }]; + let parser = "return parseDTEntryOp(parser, result);"; - let printer = [{ - p << ' ' << methodAttr() << ", " - << procAttr(); + let printer = "::print(p, *this);"; + + let extraClassDeclaration = [{ + static constexpr llvm::StringRef getMethodAttrName() { return "method"; } + static constexpr llvm::StringRef getProcAttrName() { return "proc"; } }]; } diff --git a/flang/lib/Optimizer/Dialect/FIROps.cpp b/flang/lib/Optimizer/Dialect/FIROps.cpp --- a/flang/lib/Optimizer/Dialect/FIROps.cpp +++ b/flang/lib/Optimizer/Dialect/FIROps.cpp @@ -657,6 +657,50 @@ return parseCmpOp(parser, result); } +//===----------------------------------------------------------------------===// +// ConstcOp +//===----------------------------------------------------------------------===// + +static mlir::ParseResult parseConstcOp(mlir::OpAsmParser &parser, + mlir::OperationState &result) { + fir::RealAttr realp; + fir::RealAttr imagp; + mlir::Type type; + if (parser.parseLParen() || + parser.parseAttribute(realp, fir::ConstcOp::realAttrName(), + result.attributes) || + parser.parseComma() || + parser.parseAttribute(imagp, fir::ConstcOp::imagAttrName(), + result.attributes) || + parser.parseRParen() || parser.parseColonType(type) || + parser.addTypesToList(type, result.types)) + return mlir::failure(); + return mlir::success(); +} + +static void print(mlir::OpAsmPrinter &p, fir::ConstcOp &op) { + p << " (0x"; + auto f1 = op.getOperation() + ->getAttr(fir::ConstcOp::realAttrName()) + .cast(); + auto i1 = f1.getValue().bitcastToAPInt(); + p.getStream().write_hex(i1.getZExtValue()); + p << ", 0x"; + auto f2 = op.getOperation() + ->getAttr(fir::ConstcOp::imagAttrName()) + .cast(); + auto i2 = f2.getValue().bitcastToAPInt(); + p.getStream().write_hex(i2.getZExtValue()); + p << ") : "; + p.printType(op.getType()); +} + +static mlir::LogicalResult verify(fir::ConstcOp &op) { + if (!op.getType().isa()) + return op.emitOpError("must be a !fir.complex type"); + return mlir::success(); +} + //===----------------------------------------------------------------------===// // ConvertOp //===----------------------------------------------------------------------===// @@ -699,6 +743,24 @@ ty.isa() || ty.isa(); } +static mlir::LogicalResult verify(fir::ConvertOp &op) { + auto inType = op.value().getType(); + auto outType = op.getType(); + if (inType == outType) + return mlir::success(); + if ((op.isPointerCompatible(inType) && op.isPointerCompatible(outType)) || + (op.isIntegerCompatible(inType) && op.isIntegerCompatible(outType)) || + (op.isIntegerCompatible(inType) && op.isFloatCompatible(outType)) || + (op.isFloatCompatible(inType) && op.isIntegerCompatible(outType)) || + (op.isFloatCompatible(inType) && op.isFloatCompatible(outType)) || + (op.isIntegerCompatible(inType) && op.isPointerCompatible(outType)) || + (op.isPointerCompatible(inType) && op.isIntegerCompatible(outType)) || + (inType.isa() && outType.isa()) || + (fir::isa_complex(inType) && fir::isa_complex(outType))) + return mlir::success(); + return op.emitOpError("invalid type conversion"); +} + //===----------------------------------------------------------------------===// // CoordinateOp //===----------------------------------------------------------------------===// @@ -769,6 +831,44 @@ getResultTypes()); } +static mlir::ParseResult parseDispatchOp(mlir::OpAsmParser &parser, + mlir::OperationState &result) { + mlir::FunctionType calleeType; + llvm::SmallVector operands; + auto calleeLoc = parser.getNameLoc(); + llvm::StringRef calleeName; + if (failed(parser.parseOptionalKeyword(&calleeName))) { + mlir::StringAttr calleeAttr; + if (parser.parseAttribute(calleeAttr, fir::DispatchOp::getMethodAttrName(), + result.attributes)) + return mlir::failure(); + } else { + result.addAttribute(fir::DispatchOp::getMethodAttrName(), + parser.getBuilder().getStringAttr(calleeName)); + } + if (parser.parseOperandList(operands, mlir::OpAsmParser::Delimiter::Paren) || + parser.parseOptionalAttrDict(result.attributes) || + parser.parseColonType(calleeType) || + parser.addTypesToList(calleeType.getResults(), result.types) || + parser.resolveOperands(operands, calleeType.getInputs(), calleeLoc, + result.operands)) + return mlir::failure(); + return mlir::success(); +} + +static void print(mlir::OpAsmPrinter &p, fir::DispatchOp &op) { + p << ' ' << op.getOperation()->getAttr(fir::DispatchOp::getMethodAttrName()) + << '('; + p.printOperand(op.object()); + if (!op.args().empty()) { + p << ", "; + p.printOperands(op.args()); + } + p << ") : "; + p.printFunctionalType(op.getOperation()->getOperandTypes(), + op.getOperation()->getResultTypes()); +} + //===----------------------------------------------------------------------===// // DispatchTableOp //===----------------------------------------------------------------------===// @@ -779,6 +879,49 @@ block.getOperations().insert(block.end(), op); } +static mlir::ParseResult parseDispatchTableOp(mlir::OpAsmParser &parser, + mlir::OperationState &result) { + // Parse the name as a symbol reference attribute. + SymbolRefAttr nameAttr; + if (parser.parseAttribute(nameAttr, mlir::SymbolTable::getSymbolAttrName(), + result.attributes)) + return failure(); + + // Convert the parsed name attr into a string attr. + result.attributes.set(mlir::SymbolTable::getSymbolAttrName(), + nameAttr.getRootReference()); + + // Parse the optional table body. + mlir::Region *body = result.addRegion(); + OptionalParseResult parseResult = parser.parseOptionalRegion(*body); + if (parseResult.hasValue() && failed(*parseResult)) + return mlir::failure(); + + fir::DispatchTableOp::ensureTerminator(*body, parser.getBuilder(), + result.location); + return mlir::success(); +} + +static void print(mlir::OpAsmPrinter &p, fir::DispatchTableOp &op) { + auto tableName = + op.getOperation() + ->getAttrOfType(mlir::SymbolTable::getSymbolAttrName()) + .getValue(); + p << " @" << tableName; + + Region &body = op.getOperation()->getRegion(0); + if (!body.empty()) + p.printRegion(body, /*printEntryBlockArgs=*/false, + /*printBlockTerminators=*/false); +} + +static mlir::LogicalResult verify(fir::DispatchTableOp &op) { + for (auto &op : op.getBlock()) + if (!(isa(op) || isa(op))) + return op.emitOpError("dispatch table must contain dt_entry"); + return mlir::success(); +} + //===----------------------------------------------------------------------===// // EmboxOp //===----------------------------------------------------------------------===// @@ -813,6 +956,76 @@ return mlir::success(); } +//===----------------------------------------------------------------------===// +// EmboxCharOp +//===----------------------------------------------------------------------===// + +static mlir::LogicalResult verify(fir::EmboxCharOp &op) { + auto eleTy = fir::dyn_cast_ptrEleTy(op.memref().getType()); + if (!eleTy.dyn_cast_or_null()) + return mlir::failure(); + return mlir::success(); +} + +//===----------------------------------------------------------------------===// +// EmboxProcOp +//===----------------------------------------------------------------------===// + +static mlir::ParseResult parseEmboxProcOp(mlir::OpAsmParser &parser, + mlir::OperationState &result) { + mlir::SymbolRefAttr procRef; + if (parser.parseAttribute(procRef, "funcname", result.attributes)) + return mlir::failure(); + bool hasTuple = false; + mlir::OpAsmParser::OperandType tupleRef; + if (!parser.parseOptionalComma()) { + if (parser.parseOperand(tupleRef)) + return mlir::failure(); + hasTuple = true; + } + mlir::FunctionType type; + if (parser.parseColon() || parser.parseLParen() || parser.parseType(type)) + return mlir::failure(); + result.addAttribute("functype", mlir::TypeAttr::get(type)); + if (hasTuple) { + mlir::Type tupleType; + if (parser.parseComma() || parser.parseType(tupleType) || + parser.resolveOperand(tupleRef, tupleType, result.operands)) + return mlir::failure(); + } + mlir::Type boxType; + if (parser.parseRParen() || parser.parseArrow() || + parser.parseType(boxType) || parser.addTypesToList(boxType, result.types)) + return mlir::failure(); + return mlir::success(); +} + +static void print(mlir::OpAsmPrinter &p, fir::EmboxProcOp &op) { + p << ' ' << op.getOperation()->getAttr("funcname"); + auto h = op.host(); + if (h) { + p << ", "; + p.printOperand(h); + } + p << " : (" << op.getOperation()->getAttr("functype"); + if (h) + p << ", " << h.getType(); + p << ") -> " << op.getType(); +} + +static mlir::LogicalResult verify(fir::EmboxProcOp &op) { + // host bindings (optional) must be a reference to a tuple + if (auto h = op.host()) { + if (auto r = h.getType().dyn_cast()) { + if (!r.getEleTy().dyn_cast()) + return mlir::failure(); + } else { + return mlir::failure(); + } + } + return mlir::success(); +} + //===----------------------------------------------------------------------===// // GenTypeDescOp //===----------------------------------------------------------------------===// @@ -823,6 +1036,34 @@ result.addTypes(TypeDescType::get(inty.getValue())); } +static mlir::ParseResult parseGenTypeDescOp(mlir::OpAsmParser &parser, + mlir::OperationState &result) { + mlir::Type intype; + if (parser.parseType(intype)) + return mlir::failure(); + result.addAttribute("in_type", mlir::TypeAttr::get(intype)); + mlir::Type restype = TypeDescType::get(intype); + if (parser.addTypeToList(restype, result.types)) + return mlir::failure(); + return mlir::success(); +} + +static void print(mlir::OpAsmPrinter &p, fir::GenTypeDescOp &op) { + p << ' ' << op.getOperation()->getAttr("in_type"); + p.printOptionalAttrDict(op.getOperation()->getAttrs(), {"in_type"}); +} + +static mlir::LogicalResult verify(fir::GenTypeDescOp &op) { + mlir::Type resultTy = op.getType(); + if (auto tdesc = resultTy.dyn_cast()) { + if (tdesc.getOfTy() != op.getInType()) + return op.emitOpError("wrapped type mismatched"); + } else { + return op.emitOpError("must be !fir.tdesc type"); + } + return mlir::success(); +} + //===----------------------------------------------------------------------===// // GlobalOp //===----------------------------------------------------------------------===// @@ -1322,10 +1563,58 @@ return {}; } +//===----------------------------------------------------------------------===// +// LenParamIndexOp +//===----------------------------------------------------------------------===// + +static mlir::ParseResult parseLenParamIndexOp(mlir::OpAsmParser &parser, + mlir::OperationState &result) { + llvm::StringRef fieldName; + auto &builder = parser.getBuilder(); + mlir::Type recty; + if (parser.parseOptionalKeyword(&fieldName) || parser.parseComma() || + parser.parseType(recty)) + return mlir::failure(); + result.addAttribute(fir::LenParamIndexOp::fieldAttrName(), + builder.getStringAttr(fieldName)); + if (!recty.dyn_cast()) + return mlir::failure(); + result.addAttribute(fir::LenParamIndexOp::typeAttrName(), + mlir::TypeAttr::get(recty)); + mlir::Type lenType = fir::LenType::get(builder.getContext()); + if (parser.addTypeToList(lenType, result.types)) + return mlir::failure(); + return mlir::success(); +} + +static void print(mlir::OpAsmPrinter &p, fir::LenParamIndexOp &op) { + p << ' ' + << op.getOperation() + ->getAttrOfType( + fir::LenParamIndexOp::fieldAttrName()) + .getValue() + << ", " << op.getOperation()->getAttr(fir::LenParamIndexOp::typeAttrName()); +} + //===----------------------------------------------------------------------===// // LoadOp //===----------------------------------------------------------------------===// +void fir::LoadOp::build(mlir::OpBuilder &builder, mlir::OperationState &result, + mlir::Value refVal) { + if (!refVal) { + mlir::emitError(result.location, "LoadOp has null argument"); + return; + } + auto eleTy = fir::dyn_cast_ptrEleTy(refVal.getType()); + if (!eleTy) { + mlir::emitError(result.location, "not a memory reference type"); + return; + } + result.addOperands(refVal); + result.addTypes(eleTy); +} + /// Get the element type of a reference like type; otherwise null static mlir::Type elementTypeOf(mlir::Type ref) { return llvm::TypeSwitch(ref) @@ -1340,6 +1629,29 @@ return mlir::failure(); } +static mlir::ParseResult parseLoadOp(mlir::OpAsmParser &parser, + mlir::OperationState &result) { + mlir::Type type; + mlir::OpAsmParser::OperandType oper; + if (parser.parseOperand(oper) || + parser.parseOptionalAttrDict(result.attributes) || + parser.parseColonType(type) || + parser.resolveOperand(oper, type, result.operands)) + return mlir::failure(); + mlir::Type eleTy; + if (fir::LoadOp::getElementOf(eleTy, type) || + parser.addTypeToList(eleTy, result.types)) + return mlir::failure(); + return mlir::success(); +} + +static void print(mlir::OpAsmPrinter &p, fir::LoadOp &op) { + p << ' '; + p.printOperand(op.memref()); + p.printOptionalAttrDict(op.getOperation()->getAttrs(), {}); + p << " : " << op.memref().getType(); +} + //===----------------------------------------------------------------------===// // DoLoopOp //===----------------------------------------------------------------------===// @@ -1559,6 +1871,36 @@ return {}; } +//===----------------------------------------------------------------------===// +// DTEntryOp +//===----------------------------------------------------------------------===// + +static mlir::ParseResult parseDTEntryOp(mlir::OpAsmParser &parser, + mlir::OperationState &result) { + llvm::StringRef methodName; + // allow `methodName` or `"methodName"` + if (failed(parser.parseOptionalKeyword(&methodName))) { + mlir::StringAttr methodAttr; + if (parser.parseAttribute(methodAttr, fir::DTEntryOp::getMethodAttrName(), + result.attributes)) + return mlir::failure(); + } else { + result.addAttribute(fir::DTEntryOp::getMethodAttrName(), + parser.getBuilder().getStringAttr(methodName)); + } + mlir::SymbolRefAttr calleeAttr; + if (parser.parseComma() || + parser.parseAttribute(calleeAttr, fir::DTEntryOp::getProcAttrName(), + result.attributes)) + return mlir::failure(); + return mlir::success(); +} + +static void print(mlir::OpAsmPrinter &p, fir::DTEntryOp &op) { + p << ' ' << op.getOperation()->getAttr(fir::DTEntryOp::getMethodAttrName()) + << ", " << op.getOperation()->getAttr(fir::DTEntryOp::getProcAttrName()); +} + //===----------------------------------------------------------------------===// // ReboxOp //===----------------------------------------------------------------------===// @@ -1896,6 +2238,36 @@ return mlir::success(); } +static void print(mlir::OpAsmPrinter &p, fir::SelectCaseOp &op) { + p << ' '; + p.printOperand(op.getSelector()); + p << " : " << op.getSelector().getType() << " ["; + auto cases = op.getOperation() + ->getAttrOfType(op.getCasesAttr()) + .getValue(); + auto count = op.getNumConditions(); + for (decltype(count) i = 0; i != count; ++i) { + if (i) + p << ", "; + p << cases[i] << ", "; + if (!cases[i].isa()) { + auto caseArgs = *op.getCompareOperands(i); + p.printOperand(*caseArgs.begin()); + p << ", "; + if (cases[i].isa()) { + p.printOperand(*(++caseArgs.begin())); + p << ", "; + } + } + op.printSuccessorAtIndex(p, i); + } + p << ']'; + p.printOptionalAttrDict(op.getOperation()->getAttrs(), + {op.getCasesAttr(), getCompareOffsetAttr(), + getTargetOffsetAttr(), + op.getOperandSegmentSizeAttr()}); +} + unsigned fir::SelectCaseOp::compareOffsetSize() { return denseElementsSize((*this)->getAttrOfType( getCompareOffsetAttr())); @@ -1984,6 +2356,35 @@ destOperands, attributes); } +static mlir::LogicalResult verify(fir::SelectCaseOp &op) { + if (!(op.getSelector().getType().isa() || + op.getSelector().getType().isa() || + op.getSelector().getType().isa() || + op.getSelector().getType().isa() || + op.getSelector().getType().isa())) + return op.emitOpError("must be an integer, character, or logical"); + auto cases = op.getOperation() + ->getAttrOfType(op.getCasesAttr()) + .getValue(); + auto count = op.getNumDest(); + if (count == 0) + return op.emitOpError("must have at least one successor"); + if (op.getNumConditions() != count) + return op.emitOpError("number of conditions and successors don't match"); + if (op.compareOffsetSize() != count) + return op.emitOpError("incorrect number of compare operand groups"); + if (op.targetOffsetSize() != count) + return op.emitOpError("incorrect number of successor operand groups"); + for (decltype(count) i = 0; i != count; ++i) { + auto &attr = cases[i]; + if (!(attr.isa() || + attr.isa() || attr.isa() || + attr.isa() || attr.isa())) + return op.emitOpError("incorrect select case attribute type"); + } + return mlir::success(); +} + //===----------------------------------------------------------------------===// // SelectRankOp //===----------------------------------------------------------------------===// @@ -2099,6 +2500,79 @@ getTargetOffsetAttr())); } +static void print(mlir::OpAsmPrinter &p, fir::SelectTypeOp &op) { + p << ' '; + p.printOperand(op.getSelector()); + p << " : " << op.getSelector().getType() << " ["; + auto cases = op.getOperation() + ->getAttrOfType(op.getCasesAttr()) + .getValue(); + auto count = op.getNumConditions(); + for (decltype(count) i = 0; i != count; ++i) { + if (i) + p << ", "; + p << cases[i] << ", "; + op.printSuccessorAtIndex(p, i); + } + p << ']'; + p.printOptionalAttrDict(op.getOperation()->getAttrs(), + {op.getCasesAttr(), getCompareOffsetAttr(), + getTargetOffsetAttr(), + fir::SelectTypeOp::getOperandSegmentSizeAttr()}); +} + +static mlir::LogicalResult verify(fir::SelectTypeOp &op) { + if (!(op.getSelector().getType().isa())) + return op.emitOpError("must be a boxed type"); + auto cases = op.getOperation() + ->getAttrOfType(op.getCasesAttr()) + .getValue(); + auto count = op.getNumDest(); + if (count == 0) + return op.emitOpError("must have at least one successor"); + if (op.getNumConditions() != count) + return op.emitOpError("number of conditions and successors don't match"); + if (op.targetOffsetSize() != count) + return op.emitOpError("incorrect number of successor operand groups"); + for (decltype(count) i = 0; i != count; ++i) { + auto &attr = cases[i]; + if (!(attr.isa() || attr.isa() || + attr.isa())) + return op.emitOpError("invalid type-case alternative"); + } + return mlir::success(); +} + +//===----------------------------------------------------------------------===// +// ShapeShiftOp +//===----------------------------------------------------------------------===// + +static mlir::LogicalResult verify(fir::ShapeShiftOp &op) { + auto size = op.pairs().size(); + if (size < 2 || size > 16 * 2) + return op.emitOpError("incorrect number of args"); + if (size % 2 != 0) + return op.emitOpError("requires a multiple of 2 args"); + auto shapeTy = op.getType().dyn_cast(); + assert(shapeTy && "must be a shape shift type"); + if (shapeTy.getRank() * 2 != size) + return op.emitOpError("shape type rank mismatch"); + return mlir::success(); +} + +//===----------------------------------------------------------------------===// +// ShiftOp +//===----------------------------------------------------------------------===// + +static mlir::LogicalResult verify(fir::ShiftOp &op) { + auto size = op.origins().size(); + auto shiftTy = op.getType().dyn_cast(); + assert(shiftTy && "must be a shift type"); + if (shiftTy.getRank() != size) + return op.emitOpError("shift type rank mismatch"); + return mlir::success(); +} + //===----------------------------------------------------------------------===// // SliceOp //===----------------------------------------------------------------------===// @@ -2118,6 +2592,19 @@ return rank; } +static mlir::LogicalResult verify(fir::SliceOp &op) { + auto size = op.triples().size(); + if (size < 3 || size > 16 * 3) + return op.emitOpError("incorrect number of args for triple"); + if (size % 3 != 0) + return op.emitOpError("requires a multiple of 3 args"); + auto sliceTy = op.getType().dyn_cast(); + assert(sliceTy && "must be a slice type"); + if (sliceTy.getRank() * 3 != size) + return op.emitOpError("slice type rank mismatch"); + return mlir::success(); +} + //===----------------------------------------------------------------------===// // StoreOp //===----------------------------------------------------------------------===// @@ -2256,6 +2743,17 @@ return mlir::success(); } +//===----------------------------------------------------------------------===// +// UnboxProcOp +//===----------------------------------------------------------------------===// + +static mlir::LogicalResult verify(fir::UnboxProcOp &op) { + if (auto eleTy = fir::dyn_cast_ptrEleTy(op.refTuple().getType())) + if (eleTy.isa()) + return mlir::success(); + return op.emitOpError("second output argument has bad type"); +} + //===----------------------------------------------------------------------===// // IfOp //===----------------------------------------------------------------------===//