forked from OSchip/llvm-project
[mlir] Support verification order (1/3)
This CL supports adding dependency between traits verifiers and the dependency will be checked statically. Reviewed By: jpienaar Differential Revision: https://reviews.llvm.org/D115135
This commit is contained in:
parent
efdd0a29b7
commit
91e8a63c20
|
@ -2024,11 +2024,31 @@ class PredAttrTrait<string descr, Pred pred> : PredTrait<descr, pred>;
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// These classes are used to define operation specific traits.
|
||||
class NativeOpTrait<string name> : NativeTrait<name, "Op">;
|
||||
class ParamNativeOpTrait<string prop, string params>
|
||||
: ParamNativeTrait<prop, params, "Op">;
|
||||
class GenInternalOpTrait<string prop> : GenInternalTrait<prop, "Op">;
|
||||
class PredOpTrait<string descr, Pred pred> : PredTrait<descr, pred>;
|
||||
class NativeOpTrait<string name, list<Trait> traits = []>
|
||||
: NativeTrait<name, "Op"> {
|
||||
// Specify the list of traits that need to be verified before the verification
|
||||
// of this NativeOpTrait.
|
||||
list<Trait> dependentTraits = traits;
|
||||
}
|
||||
class ParamNativeOpTrait<string prop, string params,
|
||||
list<Trait> traits = []>
|
||||
: ParamNativeTrait<prop, params, "Op"> {
|
||||
// Specify the list of traits that need to be verified before the verification
|
||||
// of this ParamNativeOpTrait.
|
||||
list<Trait> dependentTraits = traits;
|
||||
}
|
||||
class GenInternalOpTrait<string prop, list<Trait> traits = []>
|
||||
: GenInternalTrait<prop, "Op"> {
|
||||
// Specify the list of traits that need to be verified before the verification
|
||||
// of this GenInternalOpTrait.
|
||||
list<Trait> dependentTraits = traits;
|
||||
}
|
||||
class PredOpTrait<string descr, Pred pred, list<Trait> traits = []>
|
||||
: PredTrait<descr, pred> {
|
||||
// Specify the list of traits that need to be verified before the verification
|
||||
// of this PredOpTrait.
|
||||
list<Trait> dependentTraits = traits;
|
||||
}
|
||||
|
||||
// Op defines an affine scope.
|
||||
def AffineScope : NativeOpTrait<"AffineScope">;
|
||||
|
@ -2164,11 +2184,16 @@ class InterfaceTrait<string name> : NativeTrait<"", ""> {
|
|||
// OpInterfaceTrait corresponds to a specific 'OpInterface' class defined in
|
||||
// C++. The purpose to wrap around C++ symbol string with this class is to make
|
||||
// interfaces specified for ops in TableGen less alien and more integrated.
|
||||
class OpInterfaceTrait<string name, code verifyBody = [{}]>
|
||||
class OpInterfaceTrait<string name, code verifyBody = [{}],
|
||||
list<Trait> traits = []>
|
||||
: InterfaceTrait<name> {
|
||||
// Specify the body of the verification function. `$_op` will be replaced with
|
||||
// the operation being verified.
|
||||
code verify = verifyBody;
|
||||
|
||||
// Specify the list of traits that need to be verified before the verification
|
||||
// of this OpInterfaceTrait.
|
||||
list<Trait> dependentTraits = traits;
|
||||
}
|
||||
|
||||
// This class represents a single, optionally static, interface method.
|
||||
|
|
|
@ -548,6 +548,23 @@ void Operator::populateOpStructure() {
|
|||
SmallPtrSet<const llvm::Init *, 32> traitSet;
|
||||
traits.reserve(traitSet.size());
|
||||
|
||||
// The declaration order of traits imply the verification order of traits.
|
||||
// Some traits may require other traits to be verified first then they can
|
||||
// do further verification based on those verified facts. If you see this
|
||||
// error, fix the traits declaration order by checking the `dependentTraits`
|
||||
// field.
|
||||
auto verifyTraitValidity = [&](Record *trait) {
|
||||
auto *dependentTraits = trait->getValueAsListInit("dependentTraits");
|
||||
for (auto *traitInit : *dependentTraits)
|
||||
if (traitSet.find(traitInit) == traitSet.end())
|
||||
PrintFatalError(
|
||||
def.getLoc(),
|
||||
trait->getValueAsString("trait") + " requires " +
|
||||
cast<DefInit>(traitInit)->getDef()->getValueAsString(
|
||||
"trait") +
|
||||
" to precede it in traits list");
|
||||
};
|
||||
|
||||
std::function<void(llvm::ListInit *)> insert;
|
||||
insert = [&](llvm::ListInit *traitList) {
|
||||
for (auto *traitInit : *traitList) {
|
||||
|
@ -556,6 +573,11 @@ void Operator::populateOpStructure() {
|
|||
insert(def->getValueAsListInit("traits"));
|
||||
continue;
|
||||
}
|
||||
|
||||
// Verify if the trait has all the dependent traits declared before
|
||||
// itself.
|
||||
verifyTraitValidity(def);
|
||||
|
||||
// Keep traits in the same order while skipping over duplicates.
|
||||
if (traitSet.insert(traitInit).second)
|
||||
traits.push_back(Trait::create(traitInit));
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
// RUN: not mlir-tblgen -gen-op-decls -I %S/../../include -DERROR9 %s 2>&1 | FileCheck --check-prefix=ERROR9 %s
|
||||
// RUN: not mlir-tblgen -gen-op-decls -I %S/../../include -DERROR10 %s 2>&1 | FileCheck --check-prefix=ERROR10 %s
|
||||
// RUN: not mlir-tblgen -gen-op-decls -I %S/../../include -DERROR11 %s 2>&1 | FileCheck --check-prefix=ERROR11 %s
|
||||
// RUN: not mlir-tblgen -gen-op-decls -I %S/../../include -DERROR12 %s 2>&1 | FileCheck --check-prefix=ERROR12 %s
|
||||
// RUN: not mlir-tblgen -gen-op-decls -I %S/../../include -DERROR13 %s 2>&1 | FileCheck --check-prefix=ERROR13 %s
|
||||
|
||||
include "mlir/IR/OpBase.td"
|
||||
|
||||
|
@ -104,3 +106,21 @@ def OpWithDuplicatedArgResultNames : Op<Test_Dialect, "default_value"> {
|
|||
let regions = (region AnyRegion:$target);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ERROR12
|
||||
def OpTraitA : NativeOpTrait<"OpTraitA"> {}
|
||||
def OpTraitB : NativeOpTrait<"OpTraitB", [OpTraitA]> {}
|
||||
|
||||
// ERROR12: error: OpTraitB requires OpTraitA to precede it in traits list
|
||||
def OpTraitWithoutDependentTrait : Op<Test_Dialect, "default_value", [OpTraitB]> {}
|
||||
#endif
|
||||
|
||||
#ifdef ERROR13
|
||||
def OpTraitA : NativeOpTrait<"OpTraitA"> {}
|
||||
def OpInterfaceB : OpInterface<"OpInterfaceB"> {
|
||||
let dependentTraits = [OpTraitA];
|
||||
}
|
||||
|
||||
// ERROR13: error: OpInterfaceB::Trait requires OpTraitA to precede it in traits list
|
||||
def OpInterfaceWithoutDependentTrait : Op<Test_Dialect, "default_value", [OpInterfaceB]> {}
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue