Syntax:
``` {.ebnf}
-string-attribute ::= string-literal
+string-attribute ::= string-literal (`:` type)?
```
A string attribute is an attribute that represents a string literal value.
using Base::Base;
using ValueType = StringRef;
+ /// Get an instance of a StringAttr with the given string.
static StringAttr get(StringRef bytes, MLIRContext *context);
+ /// Get an instance of a StringAttr with the given string and Type.
+ static StringAttr get(StringRef bytes, Type type);
+
StringRef getValue() const;
/// Methods for support type inquiry through isa, cast, and dyn_cast.
FloatAttr getFloatAttr(Type type, double value);
FloatAttr getFloatAttr(Type type, const APFloat &value);
StringAttr getStringAttr(StringRef bytes);
+ StringAttr getStringAttr(StringRef bytes, Type type);
ArrayAttr getArrayAttr(ArrayRef<Attribute> value);
AffineMapAttr getAffineMapAttr(AffineMap map);
IntegerSetAttr getIntegerSetAttr(IntegerSet set);
/// An attribute representing a string value.
struct StringAttributeStorage : public AttributeStorage {
- using KeyTy = StringRef;
+ using KeyTy = std::pair<StringRef, Type>;
- StringAttributeStorage(StringRef value) : value(value) {}
+ StringAttributeStorage(StringRef value, Type type)
+ : AttributeStorage(type), value(value) {}
/// Key equality function.
- bool operator==(const KeyTy &key) const { return key == value; }
+ bool operator==(const KeyTy &key) const {
+ return key == KeyTy(value, getType());
+ }
/// Construct a new storage instance.
static StringAttributeStorage *construct(AttributeStorageAllocator &allocator,
const KeyTy &key) {
return new (allocator.allocate<StringAttributeStorage>())
- StringAttributeStorage(allocator.copyInto(key));
+ StringAttributeStorage(allocator.copyInto(key.first), key.second);
}
StringRef value;
}
FunctionAttr FunctionAttr::get(StringRef value, MLIRContext *ctx) {
- return Base::get(ctx, StandardAttributes::Function, value);
+ return Base::get(ctx, StandardAttributes::Function, value,
+ NoneType::get(ctx));
}
StringRef FunctionAttr::getValue() const { return getImpl()->value; }
//===----------------------------------------------------------------------===//
StringAttr StringAttr::get(StringRef bytes, MLIRContext *context) {
- return Base::get(context, StandardAttributes::String, bytes);
+ return get(bytes, NoneType::get(context));
+}
+
+/// Get an instance of a StringAttr with the given string and Type.
+StringAttr StringAttr::get(StringRef bytes, Type type) {
+ return Base::get(type.getContext(), StandardAttributes::String, bytes, type);
}
StringRef StringAttr::getValue() const { return getImpl()->value; }
return StringAttr::get(bytes, context);
}
+StringAttr Builder::getStringAttr(StringRef bytes, Type type) {
+ return StringAttr::get(bytes, type);
+}
+
ArrayAttr Builder::getArrayAttr(ArrayRef<Attribute> value) {
return ArrayAttr::get(value, context);
}
/// | bool-literal
/// | integer-literal (`:` (index-type | integer-type))?
/// | float-literal (`:` float-type)?
-/// | string-literal
+/// | string-literal (`:` type)?
/// | type
/// | `[` (attribute-value (`,` attribute-value)*)? `]`
/// | `{` (attribute-entry (`,` attribute-entry)*)? `}`
case Token::string: {
auto val = getToken().getStringValue();
consumeToken(Token::string);
+
+ // Parse the optional trailing colon type.
+ if (!type && consumeIf(Token::colon)) {
+ Type stringType = parseType();
+ return stringType ? StringAttr::get(val, stringType) : Attribute();
+ }
+
return builder.getStringAttr(val);
}
Attribute storageClassAttr;
SmallVector<NamedAttribute, 1> storageAttr;
auto loc = parser->getCurrentLocation();
- if (parser->parseAttribute(storageClassAttr, "storage_class", storageAttr)) {
+ if (parser->parseAttribute(storageClassAttr,
+ parser->getBuilder().getNoneType(),
+ "storage_class", storageAttr)) {
return failure();
}
if (!storageClassAttr.isa<StringAttr>()) {
^bb0:
// CHECK: "foo"() {bar = "a\22quoted\22string"} : () -> ()
"foo"(){bar = "a\"quoted\"string"} : () -> ()
+
+ // CHECK-NEXT: "typed_string" : !foo.string
+ "foo"(){bar = "typed_string" : !foo.string} : () -> ()
return
}
func @volatile_load_missing_rbrace() -> () {
%0 = spv.Variable : !spv.ptr<f32, Function>
// expected-error @+1 {{expected ']'}}
- %1 = spv.Load "Function" %0 ["Volatile" : f32
+ %1 = spv.Load "Function" %0 ["Volatile"} : f32
return
}
func @volatile_store_missing_rbrace(%arg0 : f32) -> () {
%0 = spv.Variable : !spv.ptr<f32, Function>
// expected-error @+1 {{expected ']'}}
- spv.Store "Function" %0, %arg0 ["Volatile" : f32
+ spv.Store "Function" %0, %arg0 ["Volatile"} : f32
return
}