mirror of https://github.com/llvm/circt.git
[HW] Verify the expression in a hw.param.value is correct.
This commit is contained in:
parent
c3b2b46de8
commit
f0600f06a3
|
@ -74,7 +74,8 @@ def BitcastOp: HWOp<"bitcast", [NoSideEffect]> {
|
|||
}
|
||||
|
||||
def ParamValueOp : HWOp<"param.value",
|
||||
[FirstAttrDerivedResultType, NoSideEffect]> {
|
||||
[FirstAttrDerivedResultType, NoSideEffect,
|
||||
ConstantLike]> {
|
||||
let summary = [{
|
||||
Return the value of a parameter expression as an SSA value that may be used
|
||||
by other ops.
|
||||
|
@ -83,4 +84,5 @@ def ParamValueOp : HWOp<"param.value",
|
|||
let arguments = (ins AnyAttr:$value);
|
||||
let results = (outs HWValueType:$result);
|
||||
let assemblyFormat = "custom<ParamValue>($value, type($result)) attr-dict";
|
||||
let verifier = "return ::verifyParamValueOp(*this);";
|
||||
}
|
||||
|
|
|
@ -111,6 +111,10 @@ void setModuleResultNames(Operation *module, ArrayRef<Attribute> names);
|
|||
/// Return true if the specified operation is a combinational logic op.
|
||||
bool isCombinational(Operation *op);
|
||||
|
||||
/// Return true if the specified attribute tree is made up of nodes that are
|
||||
/// valid in a parameter expression.
|
||||
bool isValidParameterExpression(Attribute attr, Operation *module);
|
||||
|
||||
/// Check parameter specified by `value` to see if it is valid within the scope
|
||||
/// of the specified module `module`. If not, emit an error at the location of
|
||||
/// `usingOp` and return failure, otherwise return success.
|
||||
|
|
|
@ -40,7 +40,8 @@ enum class Delimiter {
|
|||
|
||||
/// Check parameter specified by `value` to see if it is valid within the scope
|
||||
/// of the specified module `module`. If not, emit an error at the location of
|
||||
/// `usingOp` and return failure, otherwise return success.
|
||||
/// `usingOp` and return failure, otherwise return success. If `usingOp` is
|
||||
/// null, then no diagnostic is generated.
|
||||
///
|
||||
/// If `disallowParamRefs` is true, then parameter references are not allowed.
|
||||
LogicalResult hw::checkParameterInContext(Attribute value, Operation *module,
|
||||
|
@ -70,8 +71,9 @@ LogicalResult hw::checkParameterInContext(Attribute value, Operation *module,
|
|||
// Don't allow references to parameters from the default values of a
|
||||
// parameter list.
|
||||
if (disallowParamRefs) {
|
||||
usingOp->emitOpError("parameter ")
|
||||
<< nameAttr << " cannot be used as a default value for a parameter";
|
||||
if (usingOp)
|
||||
usingOp->emitOpError("parameter ")
|
||||
<< nameAttr << " cannot be used as a default value for a parameter";
|
||||
return failure();
|
||||
}
|
||||
|
||||
|
@ -85,19 +87,31 @@ LogicalResult hw::checkParameterInContext(Attribute value, Operation *module,
|
|||
if (paramAttr.getType().getValue() == parameterRef.getType())
|
||||
return success();
|
||||
|
||||
auto diag = usingOp->emitOpError("parameter ")
|
||||
<< nameAttr << " used with type " << parameterRef.getType()
|
||||
<< "; should have type " << paramAttr.getType().getValue();
|
||||
diag.attachNote(module->getLoc()) << "module declared here";
|
||||
if (usingOp) {
|
||||
auto diag = usingOp->emitOpError("parameter ")
|
||||
<< nameAttr << " used with type " << parameterRef.getType()
|
||||
<< "; should have type " << paramAttr.getType().getValue();
|
||||
diag.attachNote(module->getLoc()) << "module declared here";
|
||||
}
|
||||
return failure();
|
||||
}
|
||||
|
||||
auto diag = usingOp->emitOpError("use of unknown parameter ") << nameAttr;
|
||||
diag.attachNote(module->getLoc()) << "module declared here";
|
||||
if (usingOp) {
|
||||
auto diag = usingOp->emitOpError("use of unknown parameter ") << nameAttr;
|
||||
diag.attachNote(module->getLoc()) << "module declared here";
|
||||
}
|
||||
return failure();
|
||||
}
|
||||
|
||||
return usingOp->emitOpError("invalid parameter value ") << value;
|
||||
if (usingOp)
|
||||
usingOp->emitOpError("invalid parameter value ") << value;
|
||||
return failure();
|
||||
}
|
||||
|
||||
/// Return true if the specified attribute tree is made up of nodes that are
|
||||
/// valid in a parameter expression.
|
||||
bool hw::isValidParameterExpression(Attribute attr, Operation *module) {
|
||||
return succeeded(checkParameterInContext(attr, module, nullptr, false));
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -180,7 +194,7 @@ OpFoldResult ConstantOp::fold(ArrayRef<Attribute> constants) {
|
|||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// ConstantOp
|
||||
// ParamValueOp
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
static ParseResult parseParamValue(OpAsmParser &p, Attribute &value,
|
||||
|
@ -197,6 +211,12 @@ static void printParamValue(OpAsmPrinter &p, Operation *, Attribute value,
|
|||
p.printAttributeWithoutType(value);
|
||||
}
|
||||
|
||||
static LogicalResult verifyParamValueOp(ParamValueOp op) {
|
||||
// Check that the attribute expression is valid in this module.
|
||||
return checkParameterInContext(op.value(),
|
||||
op->getParentOfType<hw::HWModuleOp>(), op);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// HWModuleOp
|
||||
//===----------------------------------------------------------------------===/
|
||||
|
|
|
@ -269,3 +269,10 @@ hw.module @Use<xx: i41>() {
|
|||
// expected-error @+1 {{op parameter "p" cannot be used as a default value for a parameter}}
|
||||
hw.module.extern @p<p: i42 = #hw.param.decl.ref<"p">>() -> ()
|
||||
|
||||
// -----
|
||||
|
||||
// expected-note @+1 {{module declared here}}
|
||||
hw.module @Use<xx: i41>() {
|
||||
// expected-error @+1 {{'hw.param.value' op parameter "xx" used with type 'i40'; should have type 'i41'}}
|
||||
%0 = hw.param.value i40 = #hw.param.decl.ref<"xx">
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue