let arguments = (ins Arg<AnyReferenceLike, "", [MemRead]>:$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);
let parser = "return parseSelectCase(parser, result);";
- let printer = [{
- p << ' ';
- p.printOperand(getSelector());
- p << " : " << getSelector().getType() << " [";
- auto cases = (*this)->getAttrOfType<mlir::ArrayAttr>(getCasesAttr()).getValue();
- auto count = getNumConditions();
- for (decltype(count) i = 0; i != count; ++i) {
- if (i)
- p << ", ";
- p << cases[i] << ", ";
- if (!cases[i].isa<mlir::UnitAttr>()) {
- auto caseArgs = *getCompareOperands(i);
- p.printOperand(*caseArgs.begin());
- p << ", ";
- if (cases[i].isa<fir::ClosedIntervalAttr>()) {
- 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<mlir::IntegerType>() ||
- getSelector().getType().isa<mlir::IndexType>() ||
- getSelector().getType().isa<fir::IntegerType>() ||
- getSelector().getType().isa<fir::LogicalType>() ||
- getSelector().getType().isa<fir::CharacterType>()))
- return emitOpError("must be an integer, character, or logical");
- auto cases = (*this)->getAttrOfType<mlir::ArrayAttr>(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<fir::PointIntervalAttr>() ||
- attr.isa<fir::LowerBoundAttr>() ||
- attr.isa<fir::UpperBoundAttr>() ||
- attr.isa<fir::ClosedIntervalAttr>() ||
- attr.isa<mlir::UnitAttr>()))
- return emitOpError("incorrect select case attribute type");
- }
- return mlir::success();
- }];
+ let verifier = "return ::verify(*this);";
let extraClassDeclaration = extraSwitchClassDeclaration#[{
unsigned compareOffsetSize();
let parser = "return parseSelectType(parser, result);";
- let printer = [{
- p << ' ';
- p.printOperand(getSelector());
- p << " : " << getSelector().getType() << " [";
- auto cases = (*this)->getAttrOfType<mlir::ArrayAttr>(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<fir::BoxType>()))
- return emitOpError("must be a boxed type");
- auto cases = (*this)->getAttrOfType<mlir::ArrayAttr>(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<fir::ExactTypeAttr>() || attr.isa<fir::SubclassAttr>() ||
- attr.isa<mlir::UnitAttr>()))
- return emitOpError("invalid type-case alternative");
- }
- return mlir::success();
- }];
+ let verifier = "return ::verify(*this);";
let extraClassDeclaration = extraSwitchClassDeclaration;
}
$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]> {
$memref `,` $len attr-dict `:` functional-type(operands, results)
}];
- let verifier = [{
- auto eleTy = elementTypeOf(memref().getType());
- if (!eleTy.dyn_cast<CharacterType>())
- return mlir::failure();
- return mlir::success();
- }];
+ let verifier = "return ::verify(*this);";
}
def fir_EmboxProcOp : fir_Op<"emboxproc", [NoSideEffect]> {
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<ReferenceType>()) {
- if (!r.getEleTy().dyn_cast<mlir::TupleType>())
- return mlir::failure();
- } else {
- return mlir::failure();
- }
- }
- return mlir::success();
- }];
+ let verifier = "return ::verify(*this);";
}
def fir_UnboxOp : fir_SimpleOp<"unbox", [NoSideEffect]> {
```
}];
- let verifier = [{
- if (auto eleTy = fir::dyn_cast_ptrEleTy(refTuple().getType()))
- if (eleTy.isa<mlir::TupleType>())
- return mlir::success();
- return emitOpError("second output argument has bad type");
- }];
+ let verifier = "return ::verify(*this);";
let arguments = (ins fir_BoxProcType:$boxproc);
attr-dict `:` functional-type(operands, results)
}];
- let verifier = [{ return ::verify(*this); }];
+ let verifier = "return ::verify(*this);";
let extraClassDeclaration = [{
std::vector<mlir::Value> getExtents();
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,
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<fir::ShapeShiftType>();
- 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.
operands attr-dict `:` functional-type(operands, results)
}];
- let verifier = [{
- auto size = origins().size();
- auto shiftTy = getType().dyn_cast<fir::ShiftType>();
- 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<mlir::Value> getOrigins() {
$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<fir::SliceType>();
- 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()); }
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<RecordType>())
- 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<mlir::StringAttr>(fieldAttrName()).getValue()
- << ", " << (*this)->getAttr(typeAttrName());
- }];
+ let printer = "::print(p, *this);";
let builders = [OpBuilder<(ins "llvm::StringRef":$fieldName,
"mlir::Type":$recTy),
let assemblyFormat = "($results^ `:` type($results))? attr-dict";
- let verifier = [{ return ::verify(*this); }];
+ let verifier = "return ::verify(*this);";
}
def FirRegionTerminator : SingleBlockImplicitTerminator<"ResultOp">;
class region_Op<string mnemonic, list<OpTrait> traits = []> :
fir_Op<mnemonic,
!listconcat(traits, [FirRegionTerminator, RecursiveSideEffects])> {
- 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",
let results = (outs Variadic<AnyType>);
- let parser = [{
- mlir::FunctionType calleeType;
- llvm::SmallVector<mlir::OpAsmParser::OperandType, 4> 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();
static constexpr llvm::StringRef passArgAttrName() {
return "pass_arg_pos";
}
+ static constexpr llvm::StringRef getMethodAttrName() { return "method"; }
unsigned passArgPos();
}];
}
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<mlir::FloatAttr>();
- auto i1 = f1.getValue().bitcastToAPInt();
- p.getStream().write_hex(i1.getZExtValue());
- p << ", 0x";
- auto f2 = (*this)->getAttr(imagAttrName()).cast<mlir::FloatAttr>();
- 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<fir::ComplexType>())
- 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"; }
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<fir::BoxType>() && outType.isa<fir::BoxType>()) ||
- (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);
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<TypeDescType>()) {
- 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() {
```
}];
- 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<StringAttr>(
- 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<fir::DTEntryOp>(op) || isa<fir::FirEndOp>(op)))
- return emitOpError("dispatch table must contain dt_entry");
- return mlir::success();
- }];
+ let verifier = "return ::verify(*this);";
let regions = (region SizedRegion<1>:$region);
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"; }
}];
}
}
//===----------------------------------------------------------------------===//
+// 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<mlir::FloatAttr>();
+ auto i1 = f1.getValue().bitcastToAPInt();
+ p.getStream().write_hex(i1.getZExtValue());
+ p << ", 0x";
+ auto f2 = op.getOperation()
+ ->getAttr(fir::ConstcOp::imagAttrName())
+ .cast<mlir::FloatAttr>();
+ 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<fir::ComplexType>())
+ return op.emitOpError("must be a !fir.complex type");
+ return mlir::success();
+}
+
+//===----------------------------------------------------------------------===//
// ConvertOp
//===----------------------------------------------------------------------===//
ty.isa<mlir::FunctionType>() || ty.isa<fir::TypeDescType>();
}
+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<fir::BoxType>() && outType.isa<fir::BoxType>()) ||
+ (fir::isa_complex(inType) && fir::isa_complex(outType)))
+ return mlir::success();
+ return op.emitOpError("invalid type conversion");
+}
+
//===----------------------------------------------------------------------===//
// CoordinateOp
//===----------------------------------------------------------------------===//
getResultTypes());
}
+static mlir::ParseResult parseDispatchOp(mlir::OpAsmParser &parser,
+ mlir::OperationState &result) {
+ mlir::FunctionType calleeType;
+ llvm::SmallVector<mlir::OpAsmParser::OperandType> 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
//===----------------------------------------------------------------------===//
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<StringAttr>(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<fir::DTEntryOp>(op) || isa<fir::FirEndOp>(op)))
+ return op.emitOpError("dispatch table must contain dt_entry");
+ return mlir::success();
+}
+
//===----------------------------------------------------------------------===//
// EmboxOp
//===----------------------------------------------------------------------===//
}
//===----------------------------------------------------------------------===//
+// EmboxCharOp
+//===----------------------------------------------------------------------===//
+
+static mlir::LogicalResult verify(fir::EmboxCharOp &op) {
+ auto eleTy = fir::dyn_cast_ptrEleTy(op.memref().getType());
+ if (!eleTy.dyn_cast_or_null<CharacterType>())
+ 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<ReferenceType>()) {
+ if (!r.getEleTy().dyn_cast<mlir::TupleType>())
+ return mlir::failure();
+ } else {
+ return mlir::failure();
+ }
+ }
+ return mlir::success();
+}
+
+//===----------------------------------------------------------------------===//
// GenTypeDescOp
//===----------------------------------------------------------------------===//
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<TypeDescType>()) {
+ if (tdesc.getOfTy() != op.getInType())
+ return op.emitOpError("wrapped type mismatched");
+ } else {
+ return op.emitOpError("must be !fir.tdesc type");
+ }
+ return mlir::success();
+}
+
//===----------------------------------------------------------------------===//
// GlobalOp
//===----------------------------------------------------------------------===//
}
//===----------------------------------------------------------------------===//
+// 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<RecordType>())
+ 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<mlir::StringAttr>(
+ 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<mlir::Type, mlir::Type>(ref)
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
//===----------------------------------------------------------------------===//
}
//===----------------------------------------------------------------------===//
+// 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
//===----------------------------------------------------------------------===//
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<mlir::ArrayAttr>(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<mlir::UnitAttr>()) {
+ auto caseArgs = *op.getCompareOperands(i);
+ p.printOperand(*caseArgs.begin());
+ p << ", ";
+ if (cases[i].isa<fir::ClosedIntervalAttr>()) {
+ 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<mlir::DenseIntElementsAttr>(
getCompareOffsetAttr()));
destOperands, attributes);
}
+static mlir::LogicalResult verify(fir::SelectCaseOp &op) {
+ if (!(op.getSelector().getType().isa<mlir::IntegerType>() ||
+ op.getSelector().getType().isa<mlir::IndexType>() ||
+ op.getSelector().getType().isa<fir::IntegerType>() ||
+ op.getSelector().getType().isa<fir::LogicalType>() ||
+ op.getSelector().getType().isa<fir::CharacterType>()))
+ return op.emitOpError("must be an integer, character, or logical");
+ auto cases = op.getOperation()
+ ->getAttrOfType<mlir::ArrayAttr>(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<fir::PointIntervalAttr>() ||
+ attr.isa<fir::LowerBoundAttr>() || attr.isa<fir::UpperBoundAttr>() ||
+ attr.isa<fir::ClosedIntervalAttr>() || attr.isa<mlir::UnitAttr>()))
+ return op.emitOpError("incorrect select case attribute type");
+ }
+ return mlir::success();
+}
+
//===----------------------------------------------------------------------===//
// SelectRankOp
//===----------------------------------------------------------------------===//
getTargetOffsetAttr()));
}
+static void print(mlir::OpAsmPrinter &p, fir::SelectTypeOp &op) {
+ p << ' ';
+ p.printOperand(op.getSelector());
+ p << " : " << op.getSelector().getType() << " [";
+ auto cases = op.getOperation()
+ ->getAttrOfType<mlir::ArrayAttr>(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<fir::BoxType>()))
+ return op.emitOpError("must be a boxed type");
+ auto cases = op.getOperation()
+ ->getAttrOfType<mlir::ArrayAttr>(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<fir::ExactTypeAttr>() || attr.isa<fir::SubclassAttr>() ||
+ attr.isa<mlir::UnitAttr>()))
+ 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<fir::ShapeShiftType>();
+ 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<fir::ShiftType>();
+ assert(shiftTy && "must be a shift type");
+ if (shiftTy.getRank() != size)
+ return op.emitOpError("shift type rank mismatch");
+ return mlir::success();
+}
+
//===----------------------------------------------------------------------===//
// SliceOp
//===----------------------------------------------------------------------===//
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<fir::SliceType>();
+ assert(sliceTy && "must be a slice type");
+ if (sliceTy.getRank() * 3 != size)
+ return op.emitOpError("slice type rank mismatch");
+ return mlir::success();
+}
+
//===----------------------------------------------------------------------===//
// StoreOp
//===----------------------------------------------------------------------===//
}
//===----------------------------------------------------------------------===//
+// UnboxProcOp
+//===----------------------------------------------------------------------===//
+
+static mlir::LogicalResult verify(fir::UnboxProcOp &op) {
+ if (auto eleTy = fir::dyn_cast_ptrEleTy(op.refTuple().getType()))
+ if (eleTy.isa<mlir::TupleType>())
+ return mlir::success();
+ return op.emitOpError("second output argument has bad type");
+}
+
+//===----------------------------------------------------------------------===//
// IfOp
//===----------------------------------------------------------------------===//