Skip to content

Commit d2f3e5f

Browse files
committed
[mlir] Add support for non-identifier attribute names.
Summary: In some situations the name of the attribute is not representable as a bare-identifier, this revision adds support for those cases by formatting the name as a string instead. This has the added benefit of removing the identifier regex from the verifier. Differential Revision: https://reviews.llvm.org/D75973
1 parent c5c487f commit d2f3e5f

File tree

5 files changed

+37
-37
lines changed

5 files changed

+37
-37
lines changed

mlir/docs/LangRef.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1156,7 +1156,8 @@ attribute-dict ::= `{` `}`
11561156
attribute-entry ::= dialect-attribute-entry | dependent-attribute-entry
11571157
dialect-attribute-entry ::= dialect-namespace `.` bare-id `=` attribute-value
11581158
dependent-attribute-entry ::= dependent-attribute-name `=` attribute-value
1159-
dependent-attribute-name ::= (letter|[_]) (letter|digit|[_$])*
1159+
dependent-attribute-name ::= ((letter|[_]) (letter|digit|[_$])*)
1160+
| string-literal
11601161
```
11611162

11621163
Attributes are the mechanism for specifying constant data on operations in

mlir/lib/Analysis/Verifier.cpp

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,7 @@ namespace {
4040
/// This class encapsulates all the state used to verify an operation region.
4141
class OperationVerifier {
4242
public:
43-
explicit OperationVerifier(MLIRContext *ctx)
44-
: ctx(ctx), identifierRegex("^[a-zA-Z_][a-zA-Z_0-9\\.\\$]*$") {}
43+
explicit OperationVerifier(MLIRContext *ctx) : ctx(ctx) {}
4544

4645
/// Verify the given operation.
4746
LogicalResult verify(Operation &op);
@@ -53,9 +52,6 @@ class OperationVerifier {
5352
return ctx->getRegisteredDialect(dialectNamePair.first);
5453
}
5554

56-
/// Returns if the given string is valid to use as an identifier name.
57-
bool isValidName(StringRef name) { return identifierRegex.match(name); }
58-
5955
private:
6056
/// Verify the given potentially nested region or block.
6157
LogicalResult verifyRegion(Region &region);
@@ -82,9 +78,6 @@ class OperationVerifier {
8278
/// Dominance information for this operation, when checking dominance.
8379
DominanceInfo *domInfo = nullptr;
8480

85-
/// Regex checker for attribute names.
86-
llvm::Regex identifierRegex;
87-
8881
/// Mapping between dialect namespace and if that dialect supports
8982
/// unregistered operations.
9083
llvm::StringMap<bool> dialectAllowsUnknownOps;
@@ -172,9 +165,6 @@ LogicalResult OperationVerifier::verifyOperation(Operation &op) {
172165

173166
/// Verify that all of the attributes are okay.
174167
for (auto attr : op.getAttrs()) {
175-
if (!identifierRegex.match(attr.first))
176-
return op.emitError("invalid attribute name '") << attr.first << "'";
177-
178168
// Check for any optional dialect specific attributes.
179169
if (!attr.first.strref().contains('.'))
180170
continue;

mlir/lib/IR/AsmPrinter.cpp

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -892,6 +892,7 @@ class ModulePrinter {
892892
void printOptionalAttrDict(ArrayRef<NamedAttribute> attrs,
893893
ArrayRef<StringRef> elidedAttrs = {},
894894
bool withKeyword = false);
895+
void printNamedAttribute(NamedAttribute attr);
895896
void printTrailingLocation(Location loc);
896897
void printLocationInternal(LocationAttr loc, bool pretty = false);
897898

@@ -1244,16 +1245,7 @@ void ModulePrinter::printAttribute(Attribute attr,
12441245
case StandardAttributes::Dictionary:
12451246
os << '{';
12461247
interleaveComma(attr.cast<DictionaryAttr>().getValue(),
1247-
[&](NamedAttribute attr) {
1248-
os << attr.first;
1249-
1250-
// The value of a UnitAttr is elided within a dictionary.
1251-
if (attr.second.isa<UnitAttr>())
1252-
return;
1253-
1254-
os << " = ";
1255-
printAttribute(attr.second);
1256-
});
1248+
[&](NamedAttribute attr) { printNamedAttribute(attr); });
12571249
os << '}';
12581250
break;
12591251
case StandardAttributes::Integer: {
@@ -1618,17 +1610,26 @@ void ModulePrinter::printOptionalAttrDict(ArrayRef<NamedAttribute> attrs,
16181610

16191611
// Otherwise, print them all out in braces.
16201612
os << " {";
1621-
interleaveComma(filteredAttrs, [&](NamedAttribute attr) {
1613+
interleaveComma(filteredAttrs,
1614+
[&](NamedAttribute attr) { printNamedAttribute(attr); });
1615+
os << '}';
1616+
}
1617+
1618+
void ModulePrinter::printNamedAttribute(NamedAttribute attr) {
1619+
if (isBareIdentifier(attr.first)) {
16221620
os << attr.first;
1621+
} else {
1622+
os << '"';
1623+
printEscapedString(attr.first.strref(), os);
1624+
os << '"';
1625+
}
16231626

1624-
// Pretty printing elides the attribute value for unit attributes.
1625-
if (attr.second.isa<UnitAttr>())
1626-
return;
1627+
// Pretty printing elides the attribute value for unit attributes.
1628+
if (attr.second.isa<UnitAttr>())
1629+
return;
16271630

1628-
os << " = ";
1629-
printAttribute(attr.second);
1630-
});
1631-
os << '}';
1631+
os << " = ";
1632+
printAttribute(attr.second);
16321633
}
16331634

16341635
//===----------------------------------------------------------------------===//

mlir/lib/Parser/Parser.cpp

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1642,33 +1642,37 @@ Attribute Parser::parseAttribute(Type type) {
16421642
///
16431643
/// attribute-dict ::= `{` `}`
16441644
/// | `{` attribute-entry (`,` attribute-entry)* `}`
1645-
/// attribute-entry ::= bare-id `=` attribute-value
1645+
/// attribute-entry ::= (bare-id | string-literal) `=` attribute-value
16461646
///
16471647
ParseResult
16481648
Parser::parseAttributeDict(SmallVectorImpl<NamedAttribute> &attributes) {
16491649
if (parseToken(Token::l_brace, "expected '{' in attribute dictionary"))
16501650
return failure();
16511651

16521652
auto parseElt = [&]() -> ParseResult {
1653-
// We allow keywords as attribute names.
1654-
if (getToken().isNot(Token::bare_identifier, Token::inttype) &&
1655-
!getToken().isKeyword())
1653+
// The name of an attribute can either be a bare identifier, or a string.
1654+
Optional<Identifier> nameId;
1655+
if (getToken().is(Token::string))
1656+
nameId = builder.getIdentifier(getToken().getStringValue());
1657+
else if (getToken().isAny(Token::bare_identifier, Token::inttype) ||
1658+
getToken().isKeyword())
1659+
nameId = builder.getIdentifier(getTokenSpelling());
1660+
else
16561661
return emitError("expected attribute name");
1657-
Identifier nameId = builder.getIdentifier(getTokenSpelling());
16581662
consumeToken();
16591663

16601664
// Try to parse the '=' for the attribute value.
16611665
if (!consumeIf(Token::equal)) {
16621666
// If there is no '=', we treat this as a unit attribute.
1663-
attributes.push_back({nameId, builder.getUnitAttr()});
1667+
attributes.push_back({*nameId, builder.getUnitAttr()});
16641668
return success();
16651669
}
16661670

16671671
auto attr = parseAttribute();
16681672
if (!attr)
16691673
return failure();
16701674

1671-
attributes.push_back({nameId, attr});
1675+
attributes.push_back({*nameId, attr});
16721676
return success();
16731677
};
16741678

mlir/test/IR/parser.mlir

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1163,6 +1163,10 @@ func @"\"_string_symbol_reference\""() {
11631163
return
11641164
}
11651165

1166+
// CHECK-LABEL: func @string_attr_name
1167+
// CHECK-SAME: {"0 . 0", nested = {"0 . 0"}}
1168+
func @string_attr_name() attributes {"0 . 0", nested = {"0 . 0"}}
1169+
11661170
// CHECK-LABEL: func @nested_reference
11671171
// CHECK: ref = @some_symbol::@some_nested_symbol
11681172
func @nested_reference() attributes {test.ref = @some_symbol::@some_nested_symbol }

0 commit comments

Comments
 (0)