diff --git a/flang/lib/Optimizer/Dialect/FIRType.cpp b/flang/lib/Optimizer/Dialect/FIRType.cpp --- a/flang/lib/Optimizer/Dialect/FIRType.cpp +++ b/flang/lib/Optimizer/Dialect/FIRType.cpp @@ -749,14 +749,17 @@ return {}; } mlir::Type eleTy; - if (parser.parseType(eleTy) || parser.parseGreater()) + if (parser.parseType(eleTy)) return {}; mlir::AffineMapAttr map; - if (!parser.parseOptionalComma()) + if (!parser.parseOptionalComma()) { if (parser.parseAttribute(map)) { parser.emitError(parser.getNameLoc(), "expecting affine map"); return {}; } + } + if (parser.parseGreater()) + return {}; return SequenceType::get(parser.getContext(), shape, eleTy, map); } diff --git a/mlir/docs/LangRef.md b/mlir/docs/LangRef.md --- a/mlir/docs/LangRef.md +++ b/mlir/docs/LangRef.md @@ -685,55 +685,46 @@ ``` dialect-namespace ::= bare-id -opaque-dialect-item ::= dialect-namespace '<' string-literal '>' +dialect-type ::= '!' (opaque-dialect-type | pretty-dialect-type) +opaque-dialect-type ::= dialect-namespace dialect-type-body +pretty-dialect-type ::= dialect-namespace '.' pretty-dialect-type-lead-ident + dialect-type-body? +pretty-dialect-type-lead-ident ::= '[A-Za-z][A-Za-z0-9._]*' -pretty-dialect-item ::= dialect-namespace '.' pretty-dialect-item-lead-ident - pretty-dialect-item-body? - -pretty-dialect-item-lead-ident ::= '[A-Za-z][A-Za-z0-9._]*' -pretty-dialect-item-body ::= '<' pretty-dialect-item-contents+ '>' -pretty-dialect-item-contents ::= pretty-dialect-item-body - | '(' pretty-dialect-item-contents+ ')' - | '[' pretty-dialect-item-contents+ ']' - | '{' pretty-dialect-item-contents+ '}' - | '[^\[<({\]>)}\0]+' - -dialect-type ::= '!' (opaque-dialect-item | pretty-dialect-item) +dialect-type-body ::= '<' dialect-type-contents+ '>' +dialect-type-contents ::= dialect-type-body + | '(' dialect-type-contents+ ')' + | '[' dialect-type-contents+ ']' + | '{' dialect-type-contents+ '}' + | '[^\[<({\]>)}\0]+' ``` -Dialect types can be specified in a verbose form, e.g. like this: +Dialect types are generally specified in an opaque form, where the contents +of the type are defined within a body wrapped with the dialect namespace +and `<>`. Consider the following examples: ```mlir -// LLVM type that wraps around llvm IR types. -!llvm<"i32*"> +// A tensorflow string type. +!tf -// Tensor flow string type. -!tf.string +// A type with complex components. +!foo> -// Complex type -!foo<"something"> - -// Even more complex type -!foo<"something>>"> +// An even more complex type. +!foo<"a123^^^" + bar> ``` -Dialect types that are simple enough can use the pretty format, which is a -lighter weight syntax that is equivalent to the above forms: +Dialect types that are simple enough may use a prettier format, which unwraps +part of the syntax into an equivalent, but lighter weight form: ```mlir -// Tensor flow string type. +// A tensorflow string type. !tf.string -// Complex type +// A type with complex components. !foo.something ``` -Sufficiently complex dialect types are required to use the verbose form for -generality. For example, the more complex type shown above wouldn't be valid in -the lighter syntax: `!foo.something>>` because it contains characters -that are not allowed in the lighter syntax, as well as unbalanced `<>` -characters. - See [here](AttributesAndTypes.md) to learn how to define dialect types. ### Builtin Types @@ -807,40 +798,45 @@ ### Dialect Attribute Values -Similarly to operations, dialects may define custom attribute values. The -syntactic structure of these values is identical to custom dialect type values, -except that dialect attribute values are distinguished with a leading '#', while -dialect types are distinguished with a leading '!'. +Similarly to operations, dialects may define custom attribute values. ``` -dialect-attribute-value ::= '#' opaque-dialect-item -dialect-attribute-value ::= '#' pretty-dialect-item +dialect-namespace ::= bare-id + +dialect-attribute ::= '#' (opaque-dialect-attribute | pretty-dialect-attribute) +opaque-dialect-attribute ::= dialect-namespace dialect-attribute-body +pretty-dialect-attribute ::= dialect-namespace '.' pretty-dialect-attribute-lead-ident + dialect-attribute-body? +pretty-dialect-attribute-lead-ident ::= '[A-Za-z][A-Za-z0-9._]*' + +dialect-attribute-body ::= '<' dialect-attribute-contents+ '>' +dialect-attribute-contents ::= dialect-attribute-body + | '(' dialect-attribute-contents+ ')' + | '[' dialect-attribute-contents+ ']' + | '{' dialect-attribute-contents+ '}' + | '[^\[<({\]>)}\0]+' ``` -Dialect attribute values can be specified in a verbose form, e.g. like this: +Dialect attributes are generally specified in an opaque form, where the contents +of the attribute are defined within a body wrapped with the dialect namespace +and `<>`. Consider the following examples: ```mlir -// Complex attribute value. -#foo<"something"> +// A string attribute. +#foo> -// Even more complex attribute value. -#foo<"something>>"> +// A complex attribute. +#foo<"a123^^^" + bar> ``` -Dialect attribute values that are simple enough can use the pretty format, which -is a lighter weight syntax that is equivalent to the above forms: +Dialect attributes that are simple enough may use a prettier format, which unwraps +part of the syntax into an equivalent, but lighter weight form: ```mlir -// Complex attribute -#foo.something +// A string attribute. +#foo.string<""> ``` -Sufficiently complex dialect attribute values are required to use the verbose -form for generality. For example, the more complex type shown above would not be -valid in the lighter syntax: `#foo.something>>` because it contains -characters that are not allowed in the lighter syntax, as well as unbalanced -`<>` characters. - See [here](AttributesAndTypes.md) on how to define dialect attribute values. ### Builtin Attribute Values diff --git a/mlir/lib/IR/AsmPrinter.cpp b/mlir/lib/IR/AsmPrinter.cpp --- a/mlir/lib/IR/AsmPrinter.cpp +++ b/mlir/lib/IR/AsmPrinter.cpp @@ -1601,7 +1601,7 @@ } /// Returns true if the given dialect symbol data is simple enough to print in -/// the pretty form, i.e. without the enclosing "". +/// the pretty form. static bool isDialectSymbolSimpleEnoughForPrettyForm(StringRef symName) { // The name must start with an identifier. if (symName.empty() || !isalpha(symName.front())) @@ -1614,64 +1614,9 @@ if (symName.empty()) return true; - // If we got to an unexpected character, then it must be a <>. Check those - // recursively. - if (symName.front() != '<' || symName.back() != '>') - return false; - - SmallVector nestedPunctuation; - do { - // If we ran out of characters, then we had a punctuation mismatch. - if (symName.empty()) - return false; - - auto c = symName.front(); - symName = symName.drop_front(); - - switch (c) { - // We never allow null characters. This is an EOF indicator for the lexer - // which we could handle, but isn't important for any known dialect. - case '\0': - return false; - case '<': - case '[': - case '(': - case '{': - nestedPunctuation.push_back(c); - continue; - case '-': - // Treat `->` as a special token. - if (!symName.empty() && symName.front() == '>') { - symName = symName.drop_front(); - continue; - } - break; - // Reject types with mismatched brackets. - case '>': - if (nestedPunctuation.pop_back_val() != '<') - return false; - break; - case ']': - if (nestedPunctuation.pop_back_val() != '[') - return false; - break; - case ')': - if (nestedPunctuation.pop_back_val() != '(') - return false; - break; - case '}': - if (nestedPunctuation.pop_back_val() != '{') - return false; - break; - default: - continue; - } - - // We're done when the punctuation is fully matched. - } while (!nestedPunctuation.empty()); - - // If there were extra characters, then we failed. - return symName.empty(); + // If we got to an unexpected character, then it must be a <>. Check that the + // rest of the symbol is wrapped within <>. + return symName.front() == '<' && symName.back() == '>'; } /// Print the given dialect symbol to the stream. @@ -1686,9 +1631,7 @@ return; } - os << "<\""; - llvm::printEscapedString(symString, os); - os << "\">"; + os << '<' << symString << '>'; } /// Returns true if the given string can be represented as a bare identifier. diff --git a/mlir/lib/Parser/DialectSymbolParser.cpp b/mlir/lib/Parser/DialectSymbolParser.cpp --- a/mlir/lib/Parser/DialectSymbolParser.cpp +++ b/mlir/lib/Parser/DialectSymbolParser.cpp @@ -43,9 +43,9 @@ }; } // namespace -/// Parse the body of a pretty dialect symbol, which starts and ends with <>'s, -/// and may be recursive. Return with the 'prettyName' StringRef encompassing -/// the entire pretty name. +/// Parse the body of a dialect symbol, which starts and ends with <>'s, and may +/// be recursive. Return with the 'body' StringRef encompassing the entire +/// body. /// /// pretty-dialect-sym-body ::= '<' pretty-dialect-sym-contents+ '>' /// pretty-dialect-sym-contents ::= pretty-dialect-sym-body @@ -54,24 +54,26 @@ /// | '{' pretty-dialect-sym-contents+ '}' /// | '[^[<({>\])}\0]+' /// -ParseResult Parser::parsePrettyDialectSymbolName(StringRef &prettyName) { - // Pretty symbol names are a relatively unstructured format that contains a - // series of properly nested punctuation, with anything else in the middle. - // Scan ahead to find it and consume it if successful, otherwise emit an - // error. - auto *curPtr = getTokenSpelling().data(); - - SmallVector nestedPunctuation; +ParseResult Parser::parseDialectSymbolBody(StringRef &body) { + // Symbol bodies are a relatively unstructured format that contains a series + // of properly nested punctuation, with anything else in the middle. Scan + // ahead to find it and consume it if successful, otherwise emit an error. + const char *curPtr = getTokenSpelling().data(); // Scan over the nested punctuation, bailing out on error and consuming until - // we find the end. We know that we're currently looking at the '<', so we - // can go until we find the matching '>' character. + // we find the end. We know that we're currently looking at the '<', so we can + // go until we find the matching '>' character. assert(*curPtr == '<'); + SmallVector nestedPunctuation; do { char c = *curPtr++; switch (c) { case '\0': // This also handles the EOF case. + if (!nestedPunctuation.empty()) { + return emitError() << "unbalanced '" << nestedPunctuation.back() + << "' character in pretty dialect name"; + } return emitError("unexpected nul or EOF in pretty dialect name"); case '<': case '[': @@ -102,6 +104,14 @@ if (nestedPunctuation.pop_back_val() != '{') return emitError("unbalanced '}' character in pretty dialect name"); break; + case '"': { + // Dispatch to the lexer to lex past strings. + resetToken(curPtr - 1); + if (state.curToken.isNot(Token::string)) + return failure(); + curPtr = state.curToken.getEndLoc().getPointer(); + break; + } default: continue; @@ -110,11 +120,10 @@ // Ok, we succeeded, remember where we stopped, reset the lexer to know it is // consuming all this stuff, and return. - state.lex.resetPointer(curPtr); + resetToken(curPtr); - unsigned length = curPtr - prettyName.begin(); - prettyName = StringRef(prettyName.begin(), length); - consumeToken(); + unsigned length = curPtr - body.begin(); + body = StringRef(body.data(), length); return success(); } @@ -125,12 +134,24 @@ CreateFn &&createSymbol) { // Parse the dialect namespace. StringRef identifier = p.getTokenSpelling().drop_front(); - auto loc = p.getToken().getLoc(); + SMLoc loc = p.getToken().getLoc(); p.consumeToken(identifierTok); + // Check to see if this is a pretty name. + StringRef dialectName; + StringRef symbolData; + std::tie(dialectName, symbolData) = identifier.split('.'); + bool isPrettyName = !symbolData.empty(); + + // Check to see if the symbol has trailing data, i.e. has an immediately + // following '<'. + bool hasTrailingData = + p.getToken().is(Token::less) && + identifier.bytes_end() == p.getTokenSpelling().bytes_begin(); + // If there is no '<' token following this, and if the typename contains no // dot, then we are parsing a symbol alias. - if (p.getToken().isNot(Token::less) && !identifier.contains('.')) { + if (!hasTrailingData && !isPrettyName) { // Check for an alias for this type. auto aliasIt = aliases.find(identifier); if (aliasIt == aliases.end()) @@ -140,93 +161,25 @@ return aliasIt->second; } - // Otherwise, we are parsing a dialect-specific symbol. If the name contains - // a dot, then this is the "pretty" form. If not, it is the verbose form that - // looks like <"...">. - std::string symbolData; - auto dialectName = identifier; - - // Handle the verbose form, where "identifier" is a simple dialect name. - if (!identifier.contains('.')) { - // Consume the '<'. - if (p.parseToken(Token::less, "expected '<' in dialect type")) - return nullptr; - - // Parse the symbol specific data. - if (p.getToken().isNot(Token::string)) - return (p.emitWrongTokenError( - "expected string literal data in dialect symbol"), - nullptr); - symbolData = p.getToken().getStringValue(); - loc = SMLoc::getFromPointer(p.getToken().getLoc().getPointer() + 1); - p.consumeToken(Token::string); - - // Consume the '>'. - if (p.parseToken(Token::greater, "expected '>' in dialect symbol")) + // If this isn't an alias, we are parsing a dialect-specific symbol. If the + // name contains a dot, then this is the "pretty" form. If not, it is the + // verbose form that looks like <...>. + if (!isPrettyName) { + // Point the symbol data to the end of the dialect name to start. + symbolData = StringRef(dialectName.end(), 0); + if (p.parseDialectSymbolBody(symbolData)) return nullptr; + symbolData = symbolData.drop_front().drop_back(); } else { - // Ok, the dialect name is the part of the identifier before the dot, the - // part after the dot is the dialect's symbol, or the start thereof. - auto dotHalves = identifier.split('.'); - dialectName = dotHalves.first; - auto prettyName = dotHalves.second; - loc = SMLoc::getFromPointer(prettyName.data()); + loc = SMLoc::getFromPointer(symbolData.data()); // If the dialect's symbol is followed immediately by a <, then lex the body // of it into prettyName. - if (p.getToken().is(Token::less) && - prettyName.bytes_end() == p.getTokenSpelling().bytes_begin()) { - if (p.parsePrettyDialectSymbolName(prettyName)) - return nullptr; - } - - symbolData = prettyName.str(); + if (hasTrailingData && p.parseDialectSymbolBody(symbolData)) + return nullptr; } - // Record the name location of the type remapped to the top level buffer. - SMLoc locInTopLevelBuffer = p.remapLocationToTopLevelBuffer(loc); - p.getState().symbols.nestedParserLocs.push_back(locInTopLevelBuffer); - - // Call into the provided symbol construction function. - Symbol sym = createSymbol(dialectName, symbolData, loc); - - // Pop the last parser location. - p.getState().symbols.nestedParserLocs.pop_back(); - return sym; -} - -/// Parses a symbol, of type 'T', and returns it if parsing was successful. If -/// parsing failed, nullptr is returned. The number of bytes read from the input -/// string is returned in 'numRead'. -template -static T parseSymbol(StringRef inputStr, MLIRContext *context, - SymbolState &symbolState, ParserFn &&parserFn, - size_t *numRead = nullptr) { - SourceMgr sourceMgr; - auto memBuffer = MemoryBuffer::getMemBuffer( - inputStr, /*BufferName=*/"", - /*RequiresNullTerminator=*/false); - sourceMgr.AddNewSourceBuffer(std::move(memBuffer), SMLoc()); - ParserState state(sourceMgr, context, symbolState, /*asmState=*/nullptr); - Parser parser(state); - - Token startTok = parser.getToken(); - T symbol = parserFn(parser); - if (!symbol) - return T(); - - // If 'numRead' is valid, then provide the number of bytes that were read. - Token endTok = parser.getToken(); - if (numRead) { - *numRead = static_cast(endTok.getLoc().getPointer() - - startTok.getLoc().getPointer()); - - // Otherwise, ensure that all of the tokens were parsed. - } else if (startTok.getLoc() != endTok.getLoc() && endTok.isNot(Token::eof)) { - parser.emitError(endTok.getLoc(), "encountered unexpected token"); - return T(); - } - return symbol; + return createSymbol(dialectName, symbolData, loc); } /// Parse an extended attribute. @@ -239,8 +192,7 @@ Attribute Parser::parseExtendedAttr(Type type) { Attribute attr = parseExtendedSymbol( *this, Token::hash_identifier, state.symbols.attributeAliasDefinitions, - [&](StringRef dialectName, StringRef symbolData, - SMLoc loc) -> Attribute { + [&](StringRef dialectName, StringRef symbolData, SMLoc loc) -> Attribute { // Parse an optional trailing colon type. Type attrType = type; if (consumeIf(Token::colon) && !(attrType = parseType())) @@ -249,11 +201,15 @@ // If we found a registered dialect, then ask it to parse the attribute. if (Dialect *dialect = builder.getContext()->getOrLoadDialect(dialectName)) { - return parseSymbol( - symbolData, state.context, state.symbols, [&](Parser &parser) { - CustomDialectAsmParser customParser(symbolData, parser); - return dialect->parseAttribute(customParser, attrType); - }); + // Temporarily reset the lexer to let the dialect parse the attribute. + const char *curLexerPos = getToken().getLoc().getPointer(); + resetToken(symbolData.data()); + + // Parse the attribute. + CustomDialectAsmParser customParser(symbolData, *this); + Attribute attr = dialect->parseAttribute(customParser, attrType); + resetToken(curLexerPos); + return attr; } // Otherwise, form a new opaque attribute. @@ -282,17 +238,18 @@ Type Parser::parseExtendedType() { return parseExtendedSymbol( *this, Token::exclamation_identifier, state.symbols.typeAliasDefinitions, - [&](StringRef dialectName, StringRef symbolData, - SMLoc loc) -> Type { + [&](StringRef dialectName, StringRef symbolData, SMLoc loc) -> Type { // If we found a registered dialect, then ask it to parse the type. - auto *dialect = state.context->getOrLoadDialect(dialectName); - - if (dialect) { - return parseSymbol( - symbolData, state.context, state.symbols, [&](Parser &parser) { - CustomDialectAsmParser customParser(symbolData, parser); - return dialect->parseType(customParser); - }); + if (auto *dialect = state.context->getOrLoadDialect(dialectName)) { + // Temporarily reset the lexer to let the dialect parse the type. + const char *curLexerPos = getToken().getLoc().getPointer(); + resetToken(symbolData.data()); + + // Parse the type. + CustomDialectAsmParser customParser(symbolData, *this); + Type type = dialect->parseType(customParser); + resetToken(curLexerPos); + return type; } // Otherwise, form a new opaque type. @@ -312,16 +269,28 @@ template static T parseSymbol(StringRef inputStr, MLIRContext *context, size_t &numRead, ParserFn &&parserFn) { + SourceMgr sourceMgr; + auto memBuffer = MemoryBuffer::getMemBuffer( + inputStr, /*BufferName=*/"", + /*RequiresNullTerminator=*/false); + sourceMgr.AddNewSourceBuffer(std::move(memBuffer), SMLoc()); SymbolState aliasState; - return parseSymbol( - inputStr, context, aliasState, - [&](Parser &parser) { - SourceMgrDiagnosticHandler handler( - const_cast(parser.getSourceMgr()), - parser.getContext()); - return parserFn(parser); - }, - &numRead); + ParserState state(sourceMgr, context, aliasState, /*asmState=*/nullptr); + Parser parser(state); + + SourceMgrDiagnosticHandler handler( + const_cast(parser.getSourceMgr()), + parser.getContext()); + Token startTok = parser.getToken(); + T symbol = parserFn(parser); + if (!symbol) + return T(); + + // Provide the number of bytes that were read. + Token endTok = parser.getToken(); + numRead = static_cast(endTok.getLoc().getPointer() - + startTok.getLoc().getPointer()); + return symbol; } Attribute mlir::parseAttribute(StringRef attrStr, MLIRContext *context) { diff --git a/mlir/lib/Parser/Parser.h b/mlir/lib/Parser/Parser.h --- a/mlir/lib/Parser/Parser.h +++ b/mlir/lib/Parser/Parser.h @@ -56,7 +56,7 @@ return parseCommaSeparatedList(Delimiter::None, parseElementFn); } - ParseResult parsePrettyDialectSymbolName(StringRef &prettyName); + ParseResult parseDialectSymbolBody(StringRef &body); // We have two forms of parsing methods - those that return a non-null // pointer on success, and those that return a ParseResult to indicate whether @@ -80,32 +80,7 @@ /// Encode the specified source location information into an attribute for /// attachment to the IR. Location getEncodedSourceLocation(SMLoc loc) { - // If there are no active nested parsers, we can get the encoded source - // location directly. - if (state.parserDepth == 0) - return state.lex.getEncodedSourceLocation(loc); - // Otherwise, we need to re-encode it to point to the top level buffer. - return state.symbols.topLevelLexer->getEncodedSourceLocation( - remapLocationToTopLevelBuffer(loc)); - } - - /// Remaps the given SMLoc to the top level lexer of the parser. This is used - /// to adjust locations of potentially nested parsers to ensure that they can - /// be emitted properly as diagnostics. - SMLoc remapLocationToTopLevelBuffer(SMLoc loc) { - // If there are no active nested parsers, we can return location directly. - SymbolState &symbols = state.symbols; - if (state.parserDepth == 0) - return loc; - assert(symbols.topLevelLexer && "expected valid top-level lexer"); - - // Otherwise, we need to remap the location to the main parser. This is - // simply offseting the location onto the location of the last nested - // parser. - size_t offset = loc.getPointer() - state.lex.getBufferBegin(); - auto *rawLoc = - symbols.nestedParserLocs[state.parserDepth - 1].getPointer() + offset; - return SMLoc::getFromPointer(rawLoc); + return state.lex.getEncodedSourceLocation(loc); } //===--------------------------------------------------------------------===// @@ -140,6 +115,12 @@ consumeToken(); } + /// Reset the parser to the given lexer position. + void resetToken(const char *tokPos) { + state.lex.resetPointer(tokPos); + state.curToken = state.lex.lexToken(); + } + /// Consume the specified token if present and return success. On failure, /// output a diagnostic and return failure. ParseResult parseToken(Token::Kind expectedToken, const Twine &message); diff --git a/mlir/lib/Parser/ParserState.h b/mlir/lib/Parser/ParserState.h --- a/mlir/lib/Parser/ParserState.h +++ b/mlir/lib/Parser/ParserState.h @@ -27,17 +27,6 @@ // A map from type alias identifier to Type. llvm::StringMap typeAliasDefinitions; - - /// A set of locations into the main parser memory buffer for each of the - /// active nested parsers. Given that some nested parsers, i.e. custom dialect - /// parsers, operate on a temporary memory buffer, this provides an anchor - /// point for emitting diagnostics. - SmallVector nestedParserLocs; - - /// The top-level lexer that contains the original memory buffer provided by - /// the user. This is used by nested parsers to get a properly encoded source - /// location. - Lexer *topLevelLexer = nullptr; }; //===----------------------------------------------------------------------===// @@ -50,17 +39,7 @@ ParserState(const llvm::SourceMgr &sourceMgr, MLIRContext *ctx, SymbolState &symbols, AsmParserState *asmState) : context(ctx), lex(sourceMgr, ctx), curToken(lex.lexToken()), - symbols(symbols), parserDepth(symbols.nestedParserLocs.size()), - asmState(asmState) { - // Set the top level lexer for the symbol state if one doesn't exist. - if (!symbols.topLevelLexer) - symbols.topLevelLexer = &lex; - } - ~ParserState() { - // Reset the top level lexer if it refers the lexer in our state. - if (symbols.topLevelLexer == &lex) - symbols.topLevelLexer = nullptr; - } + symbols(symbols), asmState(asmState) {} ParserState(const ParserState &) = delete; void operator=(const ParserState &) = delete; @@ -76,9 +55,6 @@ /// The current state for symbol parsing. SymbolState &symbols; - /// The depth of this parser in the nested parsing stack. - size_t parserDepth; - /// An optional pointer to a struct containing high level parser state to be /// populated during parsing. AsmParserState *asmState; diff --git a/mlir/test/Dialect/EmitC/types.mlir b/mlir/test/Dialect/EmitC/types.mlir --- a/mlir/test/Dialect/EmitC/types.mlir +++ b/mlir/test/Dialect/EmitC/types.mlir @@ -5,13 +5,13 @@ // CHECK-LABEL: func @opaque_types() { func.func @opaque_types() { // CHECK-NEXT: !emitc.opaque<"int"> - emitc.call "f"() {template_args = [!emitc<"opaque<\"int\">">]} : () -> () + emitc.call "f"() {template_args = [!emitc>]} : () -> () // CHECK-NEXT: !emitc.opaque<"byte"> - emitc.call "f"() {template_args = [!emitc<"opaque<\"byte\">">]} : () -> () + emitc.call "f"() {template_args = [!emitc>]} : () -> () // CHECK-NEXT: !emitc.opaque<"unsigned"> - emitc.call "f"() {template_args = [!emitc<"opaque<\"unsigned\">">]} : () -> () + emitc.call "f"() {template_args = [!emitc>]} : () -> () // CHECK-NEXT: !emitc.opaque<"status_t"> - emitc.call "f"() {template_args = [!emitc<"opaque<\"status_t\">">]} : () -> () + emitc.call "f"() {template_args = [!emitc>]} : () -> () // CHECK-NEXT: !emitc.opaque<"std::vector"> emitc.call "f"() {template_args = [!emitc.opaque<"std::vector">]} : () -> () // CHECK-NEXT: !emitc.opaque<"SmallVector"> @@ -23,11 +23,11 @@ // CHECK-LABEL: func @pointer_types() { func.func @pointer_types() { // CHECK-NEXT: !emitc.ptr - emitc.call "f"() {template_args = [!emitc<"ptr">]} : () -> () + emitc.call "f"() {template_args = [!emitc.ptr]} : () -> () // CHECK-NEXT: !emitc.ptr emitc.call "f"() {template_args = [!emitc.ptr]} : () -> () // CHECK-NEXT: !emitc.ptr - emitc.call "f"() {template_args = [!emitc<"ptr">]} : () -> () + emitc.call "f"() {template_args = [!emitc.ptr]} : () -> () // CHECK-NEXT: !emitc.ptr emitc.call "f"() {template_args = [!emitc.ptr]} : () -> () // CHECK-NEXT: !emitc.ptr diff --git a/mlir/test/Dialect/GPU/invalid.mlir b/mlir/test/Dialect/GPU/invalid.mlir --- a/mlir/test/Dialect/GPU/invalid.mlir +++ b/mlir/test/Dialect/GPU/invalid.mlir @@ -223,7 +223,7 @@ %res = "gpu.all_reduce"(%arg0) ({ ^bb(%lhs : f32, %rhs : f32): "gpu.yield"(%lhs) : (f32) -> () - }) {op = #gpu<"all_reduce_op add">} : (f32) -> (f32) + }) {op = #gpu} : (f32) -> (f32) return } @@ -303,7 +303,7 @@ func.func @shuffle_mismatching_type(%arg0 : f32, %arg1 : i32, %arg2 : i32) { // expected-error@+1 {{op failed to verify that all of {value, result} have same type}} - %shfl, %pred = "gpu.shuffle"(%arg0, %arg1, %arg2) { mode = #gpu<"shuffle_mode xor"> } : (f32, i32, i32) -> (i32, i1) + %shfl, %pred = "gpu.shuffle"(%arg0, %arg1, %arg2) { mode = #gpu } : (f32, i32, i32) -> (i32, i1) return } diff --git a/mlir/test/Dialect/OpenACC/ops.mlir b/mlir/test/Dialect/OpenACC/ops.mlir --- a/mlir/test/Dialect/OpenACC/ops.mlir +++ b/mlir/test/Dialect/OpenACC/ops.mlir @@ -376,9 +376,9 @@ acc.parallel private(%a: memref<10xf32>, %c: memref<10x10xf32>) firstprivate(%b: memref<10xf32>) { } acc.parallel { - } attributes {defaultAttr = #acc<"defaultvalue none">} + } attributes {defaultAttr = #acc} acc.parallel { - } attributes {defaultAttr = #acc<"defaultvalue present">} + } attributes {defaultAttr = #acc} acc.parallel { } attributes {asyncAttr} acc.parallel { @@ -441,9 +441,9 @@ // CHECK: acc.parallel private([[ARGA]]: memref<10xf32>, [[ARGC]]: memref<10x10xf32>) firstprivate([[ARGB]]: memref<10xf32>) { // CHECK-NEXT: } // CHECK: acc.parallel { -// CHECK-NEXT: } attributes {defaultAttr = #acc<"defaultvalue none">} +// CHECK-NEXT: } attributes {defaultAttr = #acc} // CHECK: acc.parallel { -// CHECK-NEXT: } attributes {defaultAttr = #acc<"defaultvalue present">} +// CHECK-NEXT: } attributes {defaultAttr = #acc} // CHECK: acc.parallel { // CHECK-NEXT: } attributes {asyncAttr} // CHECK: acc.parallel { @@ -482,11 +482,11 @@ acc.data copyin(%b: memref<10xf32>) copyout(%c: memref<10x10xf32>) present(%a: memref<10xf32>) { } acc.data present(%a : memref<10xf32>) { - } attributes { defaultAttr = #acc<"defaultvalue none"> } + } attributes { defaultAttr = #acc } acc.data present(%a : memref<10xf32>) { - } attributes { defaultAttr = #acc<"defaultvalue present"> } + } attributes { defaultAttr = #acc } acc.data { - } attributes { defaultAttr = #acc<"defaultvalue none"> } + } attributes { defaultAttr = #acc } return } @@ -519,11 +519,11 @@ // CHECK: acc.data copyin([[ARGB]] : memref<10xf32>) copyout([[ARGC]] : memref<10x10xf32>) present([[ARGA]] : memref<10xf32>) { // CHECK-NEXT: } // CHECK: acc.data present([[ARGA]] : memref<10xf32>) { -// CHECK-NEXT: } attributes {defaultAttr = #acc<"defaultvalue none">} +// CHECK-NEXT: } attributes {defaultAttr = #acc} // CHECK: acc.data present([[ARGA]] : memref<10xf32>) { -// CHECK-NEXT: } attributes {defaultAttr = #acc<"defaultvalue present">} +// CHECK-NEXT: } attributes {defaultAttr = #acc} // CHECK: acc.data { -// CHECK-NEXT: } attributes {defaultAttr = #acc<"defaultvalue none">} +// CHECK-NEXT: } attributes {defaultAttr = #acc} // ----- diff --git a/mlir/test/Dialect/OpenMP/ops.mlir b/mlir/test/Dialect/OpenMP/ops.mlir --- a/mlir/test/Dialect/OpenMP/ops.mlir +++ b/mlir/test/Dialect/OpenMP/ops.mlir @@ -77,7 +77,7 @@ }) {operand_segment_sizes = dense<[1,1,0,0,0]> : vector<5xi32>} : (i1, i32) -> () omp.terminator - }) {operand_segment_sizes = dense<[1,1,1,1,0]> : vector<5xi32>, proc_bind_val = #omp<"procbindkind spread">} : (i1, i32, memref, memref) -> () + }) {operand_segment_sizes = dense<[1,1,1,1,0]> : vector<5xi32>, proc_bind_val = #omp} : (i1, i32, memref, memref) -> () // test with multiple parameters for single variadic argument // CHECK: omp.parallel allocate(%{{.*}} : memref -> %{{.*}} : memref) @@ -149,7 +149,7 @@ "omp.wsloop" (%lb, %ub, %step, %data_var, %linear_var) ({ ^bb0(%iv: index): omp.yield - }) {operand_segment_sizes = dense<[1,1,1,1,1,0,0]> : vector<7xi32>, schedule_val = #omp<"schedulekind static">} : + }) {operand_segment_sizes = dense<[1,1,1,1,1,0,0]> : vector<7xi32>, schedule_val = #omp} : (index, index, index, memref, i32) -> () // CHECK: omp.wsloop linear(%{{.*}} = %{{.*}} : memref, %{{.*}} = %{{.*}} : memref) schedule(static) @@ -157,7 +157,7 @@ "omp.wsloop" (%lb, %ub, %step, %data_var, %data_var, %linear_var, %linear_var) ({ ^bb0(%iv: index): omp.yield - }) {operand_segment_sizes = dense<[1,1,1,2,2,0,0]> : vector<7xi32>, schedule_val = #omp<"schedulekind static">} : + }) {operand_segment_sizes = dense<[1,1,1,2,2,0,0]> : vector<7xi32>, schedule_val = #omp} : (index, index, index, memref, memref, i32, i32) -> () // CHECK: omp.wsloop linear(%{{.*}} = %{{.*}} : memref) schedule(dynamic = %{{.*}}) ordered(2) @@ -165,7 +165,7 @@ "omp.wsloop" (%lb, %ub, %step, %data_var, %linear_var, %chunk_var) ({ ^bb0(%iv: index): omp.yield - }) {operand_segment_sizes = dense<[1,1,1,1,1,0,1]> : vector<7xi32>, schedule_val = #omp<"schedulekind dynamic">, ordered_val = 2} : + }) {operand_segment_sizes = dense<[1,1,1,1,1,0,1]> : vector<7xi32>, schedule_val = #omp, ordered_val = 2} : (index, index, index, memref, i32, i32) -> () // CHECK: omp.wsloop schedule(auto) nowait @@ -173,7 +173,7 @@ "omp.wsloop" (%lb, %ub, %step) ({ ^bb0(%iv: index): omp.yield - }) {operand_segment_sizes = dense<[1,1,1,0,0,0,0]> : vector<7xi32>, nowait, schedule_val = #omp<"schedulekind auto">} : + }) {operand_segment_sizes = dense<[1,1,1,0,0,0,0]> : vector<7xi32>, nowait, schedule_val = #omp} : (index, index, index) -> () return diff --git a/mlir/test/Dialect/Quant/parse-any-invalid.mlir b/mlir/test/Dialect/Quant/parse-any-invalid.mlir --- a/mlir/test/Dialect/Quant/parse-any-invalid.mlir +++ b/mlir/test/Dialect/Quant/parse-any-invalid.mlir @@ -7,8 +7,8 @@ // ----- // Unrecognized token: missing closing angle bracket -// expected-error@+1 {{expected '>'}} -!qalias = !quant<"any"> +// expected-error@+1 {{unbalanced '<' character in pretty dialect name}} +!qalias = !quant> // ----- // Unrecognized token: missing type colon diff --git a/mlir/test/Dialect/Quant/parse-calibrated-invalid.mlir b/mlir/test/Dialect/Quant/parse-calibrated-invalid.mlir --- a/mlir/test/Dialect/Quant/parse-calibrated-invalid.mlir +++ b/mlir/test/Dialect/Quant/parse-calibrated-invalid.mlir @@ -8,8 +8,8 @@ // ----- // Unrecognized token: missing closing angle bracket -// expected-error@+1 {{expected '>'}} -!qalias = !quant<"calibrated"> +// expected-error@+1 {{unbalanced '<' character in pretty dialect name}} +!qalias = !quant.calibrated // ----- // Unrecognized expressed type: integer type diff --git a/mlir/test/Dialect/Quant/parse-uniform-invalid.mlir b/mlir/test/Dialect/Quant/parse-uniform-invalid.mlir --- a/mlir/test/Dialect/Quant/parse-uniform-invalid.mlir +++ b/mlir/test/Dialect/Quant/parse-uniform-invalid.mlir @@ -22,8 +22,8 @@ // ----- // Unrecognized token: missing closing angle bracket -// expected-error@+1 {{expected '>'}} -!qalias = !quant<"uniform"> +// expected-error@+1 {{unbalanced '<' character in pretty dialect name}} +!qalias = !quant> // ----- // Unrecognized token: missing type colon diff --git a/mlir/test/IR/enum-attr-invalid.mlir b/mlir/test/IR/enum-attr-invalid.mlir --- a/mlir/test/IR/enum-attr-invalid.mlir +++ b/mlir/test/IR/enum-attr-invalid.mlir @@ -3,7 +3,7 @@ func.func @test_invalid_enum_case() -> () { // expected-error@+2 {{expected test::TestEnum to be one of: first, second, third}} // expected-error@+1 {{failed to parse TestEnumAttr}} - test.op_with_enum #test<"enum fourth"> + test.op_with_enum #test } // ----- diff --git a/mlir/test/IR/enum-attr-roundtrip.mlir b/mlir/test/IR/enum-attr-roundtrip.mlir --- a/mlir/test/IR/enum-attr-roundtrip.mlir +++ b/mlir/test/IR/enum-attr-roundtrip.mlir @@ -2,12 +2,12 @@ // CHECK-LABEL: @test_enum_attr_roundtrip func.func @test_enum_attr_roundtrip() -> () { - // CHECK: value = #test<"enum first"> - "test.op"() {value = #test<"enum first">} : () -> () - // CHECK: value = #test<"enum second"> - "test.op"() {value = #test<"enum second">} : () -> () - // CHECK: value = #test<"enum third"> - "test.op"() {value = #test<"enum third">} : () -> () + // CHECK: value = #test + "test.op"() {value = #test} : () -> () + // CHECK: value = #test + "test.op"() {value = #test} : () -> () + // CHECK: value = #test + "test.op"() {value = #test} : () -> () return } diff --git a/mlir/test/IR/invalid.mlir b/mlir/test/IR/invalid.mlir --- a/mlir/test/IR/invalid.mlir +++ b/mlir/test/IR/invalid.mlir @@ -858,15 +858,8 @@ // ----- -func.func @dialect_type_no_string_type_data(!foo<>) -> () { // expected-error {{expected string literal data in dialect symbol}} +func.func @dialect_type_missing_greater(!foo<) -> () { // expected-error {{unbalanced ')' character in pretty dialect name}} return -} - -// ----- - -func.func @dialect_type_missing_greater(!foo<"") -> () { // expected-error {{expected '>' in dialect symbol}} - return -} // ----- diff --git a/mlir/test/IR/parser.mlir b/mlir/test/IR/parser.mlir --- a/mlir/test/IR/parser.mlir +++ b/mlir/test/IR/parser.mlir @@ -790,10 +790,10 @@ // CHECK: "foof321"() {bar = sparse<> : tensor} : () -> () "foof321"(){bar = sparse<> : tensor} : () -> () -// CHECK: "foostr"() {bar = sparse<0, "foo"> : tensor<1x1x1x!unknown<"">>} : () -> () - "foostr"(){bar = sparse<0, "foo"> : tensor<1x1x1x!unknown<"">>} : () -> () -// CHECK: "foostr"() {bar = sparse<{{\[\[}}1, 1, 0], {{\[}}0, 1, 0], {{\[}}0, 0, 1]], {{\[}}"a", "b", "c"]> : tensor<2x2x2x!unknown<"">>} : () -> () - "foostr"(){bar = sparse<[[1, 1, 0], [0, 1, 0], [0, 0, 1]], ["a", "b", "c"]> : tensor<2x2x2x!unknown<"">>} : () -> () +// CHECK: "foostr"() {bar = sparse<0, "foo"> : tensor<1x1x1x!unknown<>>} : () -> () + "foostr"(){bar = sparse<0, "foo"> : tensor<1x1x1x!unknown<>>} : () -> () +// CHECK: "foostr"() {bar = sparse<{{\[\[}}1, 1, 0], {{\[}}0, 1, 0], {{\[}}0, 0, 1]], {{\[}}"a", "b", "c"]> : tensor<2x2x2x!unknown<>>} : () -> () + "foostr"(){bar = sparse<[[1, 1, 0], [0, 1, 0], [0, 0, 1]], ["a", "b", "c"]> : tensor<2x2x2x!unknown<>>} : () -> () return } @@ -819,16 +819,16 @@ return } -// CHECK-LABEL: func @unknown_dialect_type() -> !bar<""> { -func.func @unknown_dialect_type() -> !bar<""> { +// CHECK-LABEL: func @unknown_dialect_type() -> !bar<> { +func.func @unknown_dialect_type() -> !bar<> { // Unregistered dialect 'bar'. - // CHECK: "foo"() : () -> !bar<""> - %0 = "foo"() : () -> !bar<""> + // CHECK: "foo"() : () -> !bar<> + %0 = "foo"() : () -> !bar<> // CHECK: "foo"() : () -> !bar.baz - %1 = "foo"() : () -> !bar<"baz"> + %1 = "foo"() : () -> !bar - return %0 : !bar<""> + return %0 : !bar<> } // CHECK-LABEL: func @type_alias() -> i32 { @@ -953,10 +953,6 @@ // CHECK: "foo.unknown_op"() {foo = #foo.dialect} : () -> () "foo.unknown_op"() {foo = #foo.dialect} : () -> () - // Extraneous extra > character can't use the pretty syntax. - // CHECK: "foo.unknown_op"() {foo = #foo<"dialect>">} : () -> () - "foo.unknown_op"() {foo = #foo<"dialect>">} : () -> () - return } @@ -978,10 +974,6 @@ // CHECK: %{{.*}} = "foo.unknown_op"() : () -> !foo.dialect %4 = "foo.unknown_op"() : () -> !foo.dialect - // Extraneous extra > character can't use the pretty syntax. - // CHECK: %{{.*}} = "foo.unknown_op"() : () -> !foo<"dialect>"> - %5 = "foo.unknown_op"() : () -> !foo<"dialect>"> - return } @@ -1202,7 +1194,7 @@ // CHECK-LABEL: func private @parse_opaque_attr_escape func.func private @parse_opaque_attr_escape() { - // CHECK: value = #foo<"\22escaped\\\0A\22"> + // CHECK: value = #foo<"\"escaped\\\n\""> "foo.constant"() {value = #foo<"\"escaped\\\n\"">} : () -> () } diff --git a/mlir/test/Target/Cpp/types.mlir b/mlir/test/Target/Cpp/types.mlir --- a/mlir/test/Target/Cpp/types.mlir +++ b/mlir/test/Target/Cpp/types.mlir @@ -3,13 +3,13 @@ // CHECK-LABEL: void opaque_types() { func.func @opaque_types() { // CHECK-NEXT: f(); - emitc.call "f"() {template_args = [!emitc<"opaque<\"int\">">]} : () -> () + emitc.call "f"() {template_args = [!emitc>]} : () -> () // CHECK-NEXT: f(); - emitc.call "f"() {template_args = [!emitc<"opaque<\"byte\">">]} : () -> () + emitc.call "f"() {template_args = [!emitc>]} : () -> () // CHECK-NEXT: f(); - emitc.call "f"() {template_args = [!emitc<"opaque<\"unsigned\">">]} : () -> () + emitc.call "f"() {template_args = [!emitc>]} : () -> () // CHECK-NEXT: f(); - emitc.call "f"() {template_args = [!emitc<"opaque<\"status_t\">">]} : () -> () + emitc.call "f"() {template_args = [!emitc>]} : () -> () // CHECK-NEXT: f>(); emitc.call "f"() {template_args = [!emitc.opaque<"std::vector">]} : () -> () @@ -19,11 +19,11 @@ // CHECK-LABEL: void ptr_types() { func.func @ptr_types() { // CHECK-NEXT: f(); - emitc.call "f"() {template_args = [!emitc<"ptr">]} : () -> () + emitc.call "f"() {template_args = [!emitc.ptr]} : () -> () // CHECK-NEXT: f(); emitc.call "f"() {template_args = [!emitc.ptr]} : () -> () // CHECK-NEXT: f(); - emitc.call "f"() {template_args = [!emitc<"ptr">]} : () -> () + emitc.call "f"() {template_args = [!emitc.ptr]} : () -> () // CHECK-NEXT: f(); emitc.call "f"() {template_args = [!emitc.ptr]} : () -> () // CHECK-NEXT: int32_t* [[V0:[^ ]*]] = f(); diff --git a/mlir/test/mlir-tblgen/attr-or-type-format-roundtrip.mlir b/mlir/test/mlir-tblgen/attr-or-type-format-roundtrip.mlir --- a/mlir/test/mlir-tblgen/attr-or-type-format-roundtrip.mlir +++ b/mlir/test/mlir-tblgen/attr-or-type-format-roundtrip.mlir @@ -1,16 +1,16 @@ // RUN: mlir-opt %s | mlir-opt | FileCheck %s // CHECK-LABEL: @test_roundtrip_parameter_parsers -// CHECK: !test.type_with_format<111, three = #test<"attr_ugly begin 5 : index end">, two = "foo"> +// CHECK: !test.type_with_format<111, three = #test, two = "foo"> // CHECK: !test.type_with_format<2147, three = "hi", two = "hi"> -func.func private @test_roundtrip_parameter_parsers(!test.type_with_format<111, three = #test<"attr_ugly begin 5 : index end">, two = "foo">) -> !test.type_with_format<2147, two = "hi", three = "hi"> +func.func private @test_roundtrip_parameter_parsers(!test.type_with_format<111, three = #test, two = "foo">) -> !test.type_with_format<2147, two = "hi", three = "hi"> attributes { // CHECK: #test.attr_with_format<3 : two = "hello", four = [1, 2, 3] : 42 : i64, [ 10 : i16] attr0 = #test.attr_with_format<3 : two = "hello", four = [1, 2, 3] : 42 : i64, [10 : i16]>, // CHECK: #test.attr_with_format<5 : two = "a_string", four = [4, 5, 6, 7, 8] : 8 : i8, [ 10 : i16]>, attr1 = #test.attr_with_format<5 : two = "a_string", four = [4, 5, 6, 7, 8] : 8 : i8, [10 : i16]>, - // CHECK: #test<"attr_ugly begin 5 : index end"> - attr2 = #test<"attr_ugly begin 5 : index end">, + // CHECK: #test + attr2 = #test, // CHECK: #test.attr_params<42, 24> attr3 = #test.attr_params<42, 24>, // CHECK: #test.attr_with_type> diff --git a/mlir/test/mlir-tblgen/attr-or-type-format.mlir b/mlir/test/mlir-tblgen/attr-or-type-format.mlir --- a/mlir/test/mlir-tblgen/attr-or-type-format.mlir +++ b/mlir/test/mlir-tblgen/attr-or-type-format.mlir @@ -1,22 +1,22 @@ // RUN: mlir-opt --split-input-file %s --verify-diagnostics func.func private @test_ugly_attr_cannot_be_pretty() -> () attributes { - // expected-error@+1 {{expected 'begin'}} - attr = #test.attr_ugly + // expected-error@below {{expected 'begin'}} + attr = #test.attr_ugly, } // ----- func.func private @test_ugly_attr_no_mnemonic() -> () attributes { // expected-error@+1 {{expected valid keyword}} - attr = #test<""> + attr = #test<> } // ----- func.func private @test_ugly_attr_parser_dispatch() -> () attributes { // expected-error@+1 {{expected 'begin'}} - attr = #test<"attr_ugly"> + attr = #test } // ----- @@ -24,21 +24,21 @@ func.func private @test_ugly_attr_missing_parameter() -> () attributes { // expected-error@+2 {{failed to parse TestAttrUgly parameter 'attr'}} // expected-error@+1 {{expected attribute value}} - attr = #test<"attr_ugly begin"> + attr = #test } // ----- func.func private @test_ugly_attr_missing_literal() -> () attributes { // expected-error@+1 {{expected 'end'}} - attr = #test<"attr_ugly begin \"string_attr\""> + attr = #test } // ----- func.func private @test_pretty_attr_expects_less() -> () attributes { // expected-error@+1 {{expected '<'}} - attr = #test.attr_with_format + attr = #test.attr_with_format, } // ----- @@ -55,7 +55,7 @@ // Test parameter parser failure is propagated // expected-error@+2 {{expected integer value}} // expected-error@+1 {{failed to parse TestAttrWithFormat parameter 'one'}} - attr = #test.attr_with_format<"hi"> + attr = #test.attr_with_format } // ----- @@ -105,7 +105,7 @@ // ----- // expected-error@+1 {{expected '<'}} -func.func private @test_invalid_type() -> !test.type_with_format +func.func private @test_invalid_type() -> !test.type_with_format, // ----- diff --git a/mlir/test/mlir-tblgen/testdialect-attrdefs.mlir b/mlir/test/mlir-tblgen/testdialect-attrdefs.mlir --- a/mlir/test/mlir-tblgen/testdialect-attrdefs.mlir +++ b/mlir/test/mlir-tblgen/testdialect-attrdefs.mlir @@ -7,8 +7,8 @@ // CHECK: test.result_has_same_type_as_attr #test.attr_with_self_type_param : i32 -> i32 %a = test.result_has_same_type_as_attr #test.attr_with_self_type_param : i32 -> i32 -// CHECK: test.result_has_same_type_as_attr #test<"attr_with_type_builder 10 : i16"> : i16 -> i16 -%b = test.result_has_same_type_as_attr #test<"attr_with_type_builder 10 : i16"> -> i16 +// CHECK: test.result_has_same_type_as_attr #test : i16 -> i16 +%b = test.result_has_same_type_as_attr #test -> i16 // CHECK-LABEL: @qualifiedAttr() // CHECK-SAME: #test.cmpnd_nested_outer_qual>> diff --git a/mlir/test/python/ir/attributes.py b/mlir/test/python/ir/attributes.py --- a/mlir/test/python/ir/attributes.py +++ b/mlir/test/python/ir/attributes.py @@ -248,7 +248,7 @@ print("oattr value:", oattr.data) # Test factory methods. - # CHECK: default_get: #foobar<"123"> + # CHECK: default_get: #foobar<123> print( "default_get:", OpaqueAttr.get("foobar", bytes("123", "utf-8"), NoneType.get()))