ODS: provide a flag to skip generation of default build methods

Some operations need to override the default behavior of builders, in
particular region-holding operations such as affine.for or tf.graph want to
inject default terminators into the region upon construction, which default
builders won't do.  Provide a flag that disables the generation of default
builders so that the custom builders could use the same function signatures.
This is an intentionally low-level and heavy-weight feature that requires the
entire builder to be implemented, and it should be used sparingly.  Injecting
code into the end of a default builder would depend on the naming scheme of the
default builder arguments that is not visible in the ODS.  Checking that the
signature of a custom builder conflicts with that of a default builder to
prevent emission would require teaching ODG to differentiate between types and
(optional) argument names in the generated C++ code.  If this flag ends up
being used a lot, we should consider adding traits that inject specific code
into the default builder.

PiperOrigin-RevId: 256640069
This commit is contained in:
Alex Zinenko 2019-07-05 02:27:39 -07:00 committed by A. Unique TensorFlower
parent 8c6a3ace16
commit ead1acaef2
5 changed files with 34 additions and 2 deletions

View File

@ -1082,8 +1082,9 @@ class Op<Dialect dialect, string mnemonic, list<OpTrait> props = []> {
// Define the hooks used for building, parsing, printing, verification.
// Custom builder.
// In addtion to the custom builder provided here, two default builders
// are generated, with the following signatures:
// In addition to the custom builder provided here, and unless
// skipDefaultBuilders is set, two default builders are generated, with the
// following signatures:
//
// ```c++
// static void build(Builder *, OperationState *tblgen_state,
@ -1101,6 +1102,10 @@ class Op<Dialect dialect, string mnemonic, list<OpTrait> props = []> {
// ```
list<OpBuilder> builders = ?;
// Avoid generating default build functions. Custom builders must be
// provided.
bit skipDefaultBuilders = 0;
// Custom parser.
code parser = ?;

View File

@ -74,6 +74,9 @@ public:
// Returns true if this op has variadic operands or results.
bool isVariadic() const;
// Returns true if default builders should not be generated.
bool skipDefaultBuilders() const;
// Op result iterators.
value_iterator result_begin();
value_iterator result_end();

View File

@ -93,6 +93,10 @@ bool tblgen::Operator::isVariadic() const {
return getNumVariadicOperands() != 0 || getNumVariadicResults() != 0;
}
bool tblgen::Operator::skipDefaultBuilders() const {
return def.getValueAsBit("skipDefaultBuilders");
}
auto tblgen::Operator::result_begin() -> value_iterator {
return results.begin();
}

View File

@ -99,6 +99,19 @@ def NS_DOp : NS_Op<"op_with_two_operands", []> {
// CHECK-LABEL: NS::DOp declarations
// CHECK: OpTrait::NOperands<2>::Impl
// Check that default builders can be suppressed.
// ---
def NS_SkipDefaultBuildersOp : NS_Op<"skip_default_builders", []> {
let skipDefaultBuilders = 1;
let builders = [OpBuilder<"Value *val">];
}
// CHECK-LABEL: NS::SkipDefaultBuildersOp declarations
// CHECK: class SkipDefaultBuildersOp
// CHECK-NOT: static void build(Builder
// CHECK: static void build(Value
// Check leading underscore in op name
// ---

View File

@ -884,6 +884,13 @@ void OpEmitter::genBuilder() {
method.body() << body;
}
}
if (op.skipDefaultBuilders()) {
if (!listInit || listInit->empty())
PrintFatalError(
op.getLoc(),
"default builders are skipped and no custom builders provided");
return;
}
}
int numResults = op.getNumResults();