Allow Builder to create function-type constants

A recent change made ConstantOp::build accept a NumericAttr or assert that a
generic Attribute is in fact a NumericAttr.  The rationale behind the change
was that NumericAttrs have a type that can be used as the result type of the
constant operation.  FunctionAttr also has a type, and it is valid to construct
function-typed constants as exercised by the parser.mlir test.  Relax
ConstantOp::build back to take a generic Attribute.  In the overload that only
takes an attribute, assert that the Attribute is either a NumericAttr or a
FunctionAttr, because it is necessary to extract the type.  In the overload
that takes both type type and the attribute, delegate the attribute type
checking to ConstantOp::verify to prevent non-Builder-based Op construction
mechanisms from creating invalid IR.
PiperOrigin-RevId: 234798569
This commit is contained in:
Alex Zinenko 2019-02-20 08:08:16 -08:00 committed by jpienaar
parent 0cc24bb1af
commit 0a95aac7c7
2 changed files with 25 additions and 10 deletions

View File

@ -227,8 +227,7 @@ public:
/// Builds a constant op with the specified attribute value and the
/// attribute's type.
static void build(Builder *builder, OperationState *result,
NumericAttr value);
static void build(Builder *builder, OperationState *result, Attribute value);
Attribute getValue() const { return getAttr("value"); }

View File

@ -241,19 +241,28 @@ void CondBranchOp::eraseFalseOperand(unsigned index) {
/// Builds a constant op with the specified attribute value and result type.
void ConstantOp::build(Builder *builder, OperationState *result, Type type,
Attribute value) {
auto attr = value.dyn_cast<NumericAttr>();
assert(attr && "expected numeric value");
assert(attr.getType() == type && "value should be of the given type");
(void)attr;
result->addAttribute("value", value);
result->types.push_back(type);
}
// Extracts and returns a type of an attribute if it has one. Returns a null
// type otherwise. Currently, NumericAttrs and FunctionAttrs have types.
static Type getAttributeType(Attribute attr) {
assert(attr && "expected non-null attribute");
if (auto numericAttr = attr.dyn_cast<NumericAttr>())
return numericAttr.getType();
if (auto functionAttr = attr.dyn_cast<FunctionAttr>())
return functionAttr.getType();
return {};
}
/// Builds a constant of with the specified attribute value and type extracted
/// from the attribute. The attribute must have a type.
void ConstantOp::build(Builder *builder, OperationState *result,
NumericAttr value) {
result->addAttribute("value", value);
result->types.push_back(value.getType());
Attribute value) {
Type t = getAttributeType(value);
assert(t && "expected an attribute with a type");
return build(builder, result, t, value);
}
void ConstantOp::print(OpAsmPrinter *p) const {
@ -334,6 +343,13 @@ bool ConstantOp::verify() const {
return false;
}
auto attrType = getAttributeType(value);
if (!attrType)
return emitOpError("requires 'value' attribute to have a type");
if (attrType != type)
return emitOpError("requires the type of the 'value' attribute to match "
"that of the operation result");
return emitOpError(
"requires a result type that aligns with the 'value' attribute");
}