identifier used as a suffix to these two calls, i.e., `custom<MyDirective>(...)`
would result in calls to `parseMyDirective` and `printMyDirective` wihtin the
parser and printer respectively. `Params` may be any combination of variables
-(i.e. Attribute, Operand, Successor, etc.) and type directives. The type
-directives must refer to a variable, but that variable need not also be a
-parameter to the custom directive.
+(i.e. Attribute, Operand, Successor, etc.), type directives, and `attr-dict`.
+The type directives must refer to a variable, but that variable need not also
+be a parameter to the custom directive.
-The arguments to the `parse<UserDirective>` method is firstly a reference to the
-`OpAsmParser`(`OpAsmParser &`), and secondly a set of output parameters
+The arguments to the `parse<UserDirective>` method are firstly a reference to
+the `OpAsmParser`(`OpAsmParser &`), and secondly a set of output parameters
corresponding to the parameters specified in the format. The mapping of
declarative parameter to `parse` method argument is detailed below:
- Single: `Type`
- Optional: `Type`
- Variadic: `const SmallVectorImpl<Type> &`
+* `attr-dict` Directive: `NamedAttrList &`
When a variable is optional, the value should only be specified if the variable
is present. Otherwise, the value should remain `None` or null.
-The arguments to the `print<UserDirective>` method is firstly a reference to the
-`OpAsmPrinter`(`OpAsmPrinter &`), and secondly a set of output parameters
+The arguments to the `print<UserDirective>` method is firstly a reference to
+the `OpAsmPrinter`(`OpAsmPrinter &`), second the op (e.g. `FooOp op` which
+can be `Operation *op` alternatively), and finally a set of output parameters
corresponding to the parameters specified in the format. The mapping of
declarative parameter to `print` method argument is detailed below:
- Single: `Type`
- Optional: `Type`
- Variadic: `TypeRange`
+* `attr-dict` Directive: `const MutableDictionaryAttr&`
When a variable is optional, the provided value may be null.
return success();
}
-static void printAwaitResultType(OpAsmPrinter &p, Type operandType,
- Type resultType) {
+static void printAwaitResultType(OpAsmPrinter &p, Operation *op,
+ Type operandType, Type resultType) {
p << operandType;
}
argTypes, argAttrs, isVariadic);
}
-static void printLaunchFuncOperands(OpAsmPrinter &printer,
+static void printLaunchFuncOperands(OpAsmPrinter &printer, Operation *,
OperandRange operands, TypeRange types) {
if (operands.empty())
return;
OpAsmParser::Delimiter::OptionalSquare);
}
-static void printAsyncDependencies(OpAsmPrinter &printer, Type asyncTokenType,
+static void printAsyncDependencies(OpAsmPrinter &printer, Operation *op,
+ Type asyncTokenType,
OperandRange asyncDependencies) {
if (asyncTokenType)
printer << "async ";
return success();
}
+static ParseResult parseCustomDirectiveAttrDict(OpAsmParser &parser,
+ NamedAttrList &attrs) {
+ return parser.parseOptionalAttrDict(attrs);
+}
+
//===----------------------------------------------------------------------===//
// Printing
-static void printCustomDirectiveOperands(OpAsmPrinter &printer, Value operand,
- Value optOperand,
+static void printCustomDirectiveOperands(OpAsmPrinter &printer, Operation *,
+ Value operand, Value optOperand,
OperandRange varOperands) {
printer << operand;
if (optOperand)
printer << ", " << optOperand;
printer << " -> (" << varOperands << ")";
}
-static void printCustomDirectiveResults(OpAsmPrinter &printer, Type operandType,
- Type optOperandType,
+static void printCustomDirectiveResults(OpAsmPrinter &printer, Operation *,
+ Type operandType, Type optOperandType,
TypeRange varOperandTypes) {
printer << " : " << operandType;
if (optOperandType)
printer << " -> (" << varOperandTypes << ")";
}
static void printCustomDirectiveWithTypeRefs(OpAsmPrinter &printer,
- Type operandType,
+ Operation *op, Type operandType,
Type optOperandType,
TypeRange varOperandTypes) {
printer << " type_refs_capture ";
- printCustomDirectiveResults(printer, operandType, optOperandType,
+ printCustomDirectiveResults(printer, op, operandType, optOperandType,
varOperandTypes);
}
-static void
-printCustomDirectiveOperandsAndTypes(OpAsmPrinter &printer, Value operand,
- Value optOperand, OperandRange varOperands,
- Type operandType, Type optOperandType,
- TypeRange varOperandTypes) {
- printCustomDirectiveOperands(printer, operand, optOperand, varOperands);
- printCustomDirectiveResults(printer, operandType, optOperandType,
+static void printCustomDirectiveOperandsAndTypes(
+ OpAsmPrinter &printer, Operation *op, Value operand, Value optOperand,
+ OperandRange varOperands, Type operandType, Type optOperandType,
+ TypeRange varOperandTypes) {
+ printCustomDirectiveOperands(printer, op, operand, optOperand, varOperands);
+ printCustomDirectiveResults(printer, op, operandType, optOperandType,
varOperandTypes);
}
-static void printCustomDirectiveRegions(OpAsmPrinter &printer, Region ®ion,
+static void printCustomDirectiveRegions(OpAsmPrinter &printer, Operation *,
+ Region ®ion,
MutableArrayRef<Region> varRegions) {
printer.printRegion(region);
if (!varRegions.empty()) {
printer.printRegion(region);
}
}
-static void printCustomDirectiveSuccessors(OpAsmPrinter &printer,
+static void printCustomDirectiveSuccessors(OpAsmPrinter &printer, Operation *,
Block *successor,
SuccessorRange varSuccessors) {
printer << successor;
if (!varSuccessors.empty())
printer << ", " << varSuccessors.front();
}
-static void printCustomDirectiveAttributes(OpAsmPrinter &printer,
+static void printCustomDirectiveAttributes(OpAsmPrinter &printer, Operation *,
Attribute attribute,
Attribute optAttribute) {
printer << attribute;
printer << ", " << optAttribute;
}
+static void printCustomDirectiveAttrDict(OpAsmPrinter &printer, Operation *op,
+ MutableDictionaryAttr attrs) {
+ printer.printOptionalAttrDict(attrs.getAttrs());
+}
//===----------------------------------------------------------------------===//
// Test IsolatedRegionOp - parse passthrough region arguments.
//===----------------------------------------------------------------------===//
}];
}
+def FormatCustomDirectiveAttrDict
+ : TEST_Op<"format_custom_directive_attrdict"> {
+ let arguments = (ins I64Attr:$attr, OptionalAttr<I64Attr>:$optAttr);
+ let assemblyFormat = [{
+ custom<CustomDirectiveAttrDict>( attr-dict )
+ }];
+}
+
//===----------------------------------------------------------------------===//
// AllTypesMatch type inference
body << ", ";
if (auto *attr = dyn_cast<AttributeVariable>(¶m)) {
body << attr->getVar()->name << "Attr";
-
+ } else if (isa<AttrDictDirective>(¶m)) {
+ body << "result.attributes";
} else if (auto *operand = dyn_cast<OperandVariable>(¶m)) {
StringRef name = operand->getVar()->name;
ArgumentLengthKind lengthKind = getArgumentLengthKind(operand->getVar());
/// Generate the printer for a custom directive.
static void genCustomDirectivePrinter(CustomDirective *customDir,
OpMethodBody &body) {
- body << " print" << customDir->getName() << "(p";
+ body << " print" << customDir->getName() << "(p, *this";
for (Element ¶m : customDir->getArguments()) {
body << ", ";
if (auto *attr = dyn_cast<AttributeVariable>(¶m)) {
body << attr->getVar()->name << "Attr()";
+ } else if (isa<AttrDictDirective>(¶m)) {
+ // Enforce the const-ness since getMutableAttrDict() returns a reference
+ // into the Operations `attr` member.
+ body << "(const "
+ "MutableDictionaryAttr&)getOperation()->getMutableAttrDict()";
+
} else if (auto *operand = dyn_cast<OperandVariable>(¶m)) {
body << operand->getVar()->name << "()";
return ::mlir::failure();
// Verify that the element can be placed within a custom directive.
- if (!isa<TypeRefDirective, TypeDirective, AttributeVariable, OperandVariable,
- RegionVariable, SuccessorVariable>(parameters.back().get())) {
+ if (!isa<TypeRefDirective, TypeDirective, AttrDictDirective,
+ AttributeVariable, OperandVariable, RegionVariable,
+ SuccessorVariable>(parameters.back().get())) {
return emitError(childLoc, "only variables and types may be used as "
"parameters to a custom directive");
}