Add support for generating operation interfaces from the ODS framework.
Operation interfaces generally require a bit of boilerplate code to connect all of the pieces together. This cl introduces mechanisms in the ODS to allow for generating operation interfaces via the 'OpInterface' class.
Providing a definition of the `OpInterface` class will auto-generate the c++
classes for the interface. An `OpInterface` includes a name, for the c++ class,
along with a list of interface methods. There are two types of methods that can be used with an interface, `InterfaceMethod` and `StaticInterfaceMethod`. They are both comprised of the same core components, with the distinction that `StaticInterfaceMethod` models a static method on the derived operation.
An `InterfaceMethod` is comprised of the following components:
* ReturnType
- A string corresponding to the c++ return type of the method.
* MethodName
- A string corresponding to the desired name of the method.
* Arguments
- A dag of strings that correspond to a c++ type and variable name
respectively.
* MethodBody (Optional)
- An optional explicit implementation of the interface method.
def MyInterface : OpInterface<"MyInterface"> {
let methods = [
// A simple non-static method with no inputs.
InterfaceMethod<"unsigned", "foo">,
// A new non-static method accepting an input argument.
InterfaceMethod<"Value *", "bar", (ins "unsigned":$i)>,
// Query a static property of the derived operation.
StaticInterfaceMethod<"unsigned", "fooStatic">,
// Provide the definition of a static interface method.
// Note: `ConcreteOp` corresponds to the derived operation typename.
StaticInterfaceMethod<"Operation *", "create",
(ins "OpBuilder &":$builder, "Location":$loc), [{
return builder.create<ConcreteOp>(loc);
}]>,
// Provide a definition of the non-static method.
// Note: `op` corresponds to the derived operation variable.
InterfaceMethod<"unsigned", "getNumInputsAndOutputs", (ins), [{
return op.getNumInputs() + op.getNumOutputs();
}]>,
];
PiperOrigin-RevId: 264754898
2019-08-22 11:57:23 +08:00
|
|
|
//===- OpInterfacesGen.cpp - MLIR op interface utility generator ----------===//
|
|
|
|
//
|
2020-01-26 11:58:30 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
2019-12-24 01:35:36 +08:00
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
Add support for generating operation interfaces from the ODS framework.
Operation interfaces generally require a bit of boilerplate code to connect all of the pieces together. This cl introduces mechanisms in the ODS to allow for generating operation interfaces via the 'OpInterface' class.
Providing a definition of the `OpInterface` class will auto-generate the c++
classes for the interface. An `OpInterface` includes a name, for the c++ class,
along with a list of interface methods. There are two types of methods that can be used with an interface, `InterfaceMethod` and `StaticInterfaceMethod`. They are both comprised of the same core components, with the distinction that `StaticInterfaceMethod` models a static method on the derived operation.
An `InterfaceMethod` is comprised of the following components:
* ReturnType
- A string corresponding to the c++ return type of the method.
* MethodName
- A string corresponding to the desired name of the method.
* Arguments
- A dag of strings that correspond to a c++ type and variable name
respectively.
* MethodBody (Optional)
- An optional explicit implementation of the interface method.
def MyInterface : OpInterface<"MyInterface"> {
let methods = [
// A simple non-static method with no inputs.
InterfaceMethod<"unsigned", "foo">,
// A new non-static method accepting an input argument.
InterfaceMethod<"Value *", "bar", (ins "unsigned":$i)>,
// Query a static property of the derived operation.
StaticInterfaceMethod<"unsigned", "fooStatic">,
// Provide the definition of a static interface method.
// Note: `ConcreteOp` corresponds to the derived operation typename.
StaticInterfaceMethod<"Operation *", "create",
(ins "OpBuilder &":$builder, "Location":$loc), [{
return builder.create<ConcreteOp>(loc);
}]>,
// Provide a definition of the non-static method.
// Note: `op` corresponds to the derived operation variable.
InterfaceMethod<"unsigned", "getNumInputsAndOutputs", (ins), [{
return op.getNumInputs() + op.getNumOutputs();
}]>,
];
PiperOrigin-RevId: 264754898
2019-08-22 11:57:23 +08:00
|
|
|
//
|
2019-12-24 01:35:36 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
Add support for generating operation interfaces from the ODS framework.
Operation interfaces generally require a bit of boilerplate code to connect all of the pieces together. This cl introduces mechanisms in the ODS to allow for generating operation interfaces via the 'OpInterface' class.
Providing a definition of the `OpInterface` class will auto-generate the c++
classes for the interface. An `OpInterface` includes a name, for the c++ class,
along with a list of interface methods. There are two types of methods that can be used with an interface, `InterfaceMethod` and `StaticInterfaceMethod`. They are both comprised of the same core components, with the distinction that `StaticInterfaceMethod` models a static method on the derived operation.
An `InterfaceMethod` is comprised of the following components:
* ReturnType
- A string corresponding to the c++ return type of the method.
* MethodName
- A string corresponding to the desired name of the method.
* Arguments
- A dag of strings that correspond to a c++ type and variable name
respectively.
* MethodBody (Optional)
- An optional explicit implementation of the interface method.
def MyInterface : OpInterface<"MyInterface"> {
let methods = [
// A simple non-static method with no inputs.
InterfaceMethod<"unsigned", "foo">,
// A new non-static method accepting an input argument.
InterfaceMethod<"Value *", "bar", (ins "unsigned":$i)>,
// Query a static property of the derived operation.
StaticInterfaceMethod<"unsigned", "fooStatic">,
// Provide the definition of a static interface method.
// Note: `ConcreteOp` corresponds to the derived operation typename.
StaticInterfaceMethod<"Operation *", "create",
(ins "OpBuilder &":$builder, "Location":$loc), [{
return builder.create<ConcreteOp>(loc);
}]>,
// Provide a definition of the non-static method.
// Note: `op` corresponds to the derived operation variable.
InterfaceMethod<"unsigned", "getNumInputsAndOutputs", (ins), [{
return op.getNumInputs() + op.getNumOutputs();
}]>,
];
PiperOrigin-RevId: 264754898
2019-08-22 11:57:23 +08:00
|
|
|
//
|
|
|
|
// OpInterfacesGen generates definitions for operation interfaces.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2019-09-25 03:45:11 +08:00
|
|
|
#include "DocGenUtilities.h"
|
2020-01-22 01:40:22 +08:00
|
|
|
#include "mlir/TableGen/Format.h"
|
Add support for generating operation interfaces from the ODS framework.
Operation interfaces generally require a bit of boilerplate code to connect all of the pieces together. This cl introduces mechanisms in the ODS to allow for generating operation interfaces via the 'OpInterface' class.
Providing a definition of the `OpInterface` class will auto-generate the c++
classes for the interface. An `OpInterface` includes a name, for the c++ class,
along with a list of interface methods. There are two types of methods that can be used with an interface, `InterfaceMethod` and `StaticInterfaceMethod`. They are both comprised of the same core components, with the distinction that `StaticInterfaceMethod` models a static method on the derived operation.
An `InterfaceMethod` is comprised of the following components:
* ReturnType
- A string corresponding to the c++ return type of the method.
* MethodName
- A string corresponding to the desired name of the method.
* Arguments
- A dag of strings that correspond to a c++ type and variable name
respectively.
* MethodBody (Optional)
- An optional explicit implementation of the interface method.
def MyInterface : OpInterface<"MyInterface"> {
let methods = [
// A simple non-static method with no inputs.
InterfaceMethod<"unsigned", "foo">,
// A new non-static method accepting an input argument.
InterfaceMethod<"Value *", "bar", (ins "unsigned":$i)>,
// Query a static property of the derived operation.
StaticInterfaceMethod<"unsigned", "fooStatic">,
// Provide the definition of a static interface method.
// Note: `ConcreteOp` corresponds to the derived operation typename.
StaticInterfaceMethod<"Operation *", "create",
(ins "OpBuilder &":$builder, "Location":$loc), [{
return builder.create<ConcreteOp>(loc);
}]>,
// Provide a definition of the non-static method.
// Note: `op` corresponds to the derived operation variable.
InterfaceMethod<"unsigned", "getNumInputsAndOutputs", (ins), [{
return op.getNumInputs() + op.getNumOutputs();
}]>,
];
PiperOrigin-RevId: 264754898
2019-08-22 11:57:23 +08:00
|
|
|
#include "mlir/TableGen/GenInfo.h"
|
2019-10-01 03:42:31 +08:00
|
|
|
#include "mlir/TableGen/OpInterfaces.h"
|
Add support for generating operation interfaces from the ODS framework.
Operation interfaces generally require a bit of boilerplate code to connect all of the pieces together. This cl introduces mechanisms in the ODS to allow for generating operation interfaces via the 'OpInterface' class.
Providing a definition of the `OpInterface` class will auto-generate the c++
classes for the interface. An `OpInterface` includes a name, for the c++ class,
along with a list of interface methods. There are two types of methods that can be used with an interface, `InterfaceMethod` and `StaticInterfaceMethod`. They are both comprised of the same core components, with the distinction that `StaticInterfaceMethod` models a static method on the derived operation.
An `InterfaceMethod` is comprised of the following components:
* ReturnType
- A string corresponding to the c++ return type of the method.
* MethodName
- A string corresponding to the desired name of the method.
* Arguments
- A dag of strings that correspond to a c++ type and variable name
respectively.
* MethodBody (Optional)
- An optional explicit implementation of the interface method.
def MyInterface : OpInterface<"MyInterface"> {
let methods = [
// A simple non-static method with no inputs.
InterfaceMethod<"unsigned", "foo">,
// A new non-static method accepting an input argument.
InterfaceMethod<"Value *", "bar", (ins "unsigned":$i)>,
// Query a static property of the derived operation.
StaticInterfaceMethod<"unsigned", "fooStatic">,
// Provide the definition of a static interface method.
// Note: `ConcreteOp` corresponds to the derived operation typename.
StaticInterfaceMethod<"Operation *", "create",
(ins "OpBuilder &":$builder, "Location":$loc), [{
return builder.create<ConcreteOp>(loc);
}]>,
// Provide a definition of the non-static method.
// Note: `op` corresponds to the derived operation variable.
InterfaceMethod<"unsigned", "getNumInputsAndOutputs", (ins), [{
return op.getNumInputs() + op.getNumOutputs();
}]>,
];
PiperOrigin-RevId: 264754898
2019-08-22 11:57:23 +08:00
|
|
|
#include "llvm/ADT/SmallVector.h"
|
|
|
|
#include "llvm/ADT/StringExtras.h"
|
|
|
|
#include "llvm/Support/FormatVariadic.h"
|
|
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
|
#include "llvm/TableGen/Error.h"
|
|
|
|
#include "llvm/TableGen/Record.h"
|
|
|
|
#include "llvm/TableGen/TableGenBackend.h"
|
|
|
|
|
|
|
|
using namespace llvm;
|
|
|
|
using namespace mlir;
|
2019-10-01 03:42:31 +08:00
|
|
|
using mlir::tblgen::OpInterface;
|
|
|
|
using mlir::tblgen::OpInterfaceMethod;
|
Add support for generating operation interfaces from the ODS framework.
Operation interfaces generally require a bit of boilerplate code to connect all of the pieces together. This cl introduces mechanisms in the ODS to allow for generating operation interfaces via the 'OpInterface' class.
Providing a definition of the `OpInterface` class will auto-generate the c++
classes for the interface. An `OpInterface` includes a name, for the c++ class,
along with a list of interface methods. There are two types of methods that can be used with an interface, `InterfaceMethod` and `StaticInterfaceMethod`. They are both comprised of the same core components, with the distinction that `StaticInterfaceMethod` models a static method on the derived operation.
An `InterfaceMethod` is comprised of the following components:
* ReturnType
- A string corresponding to the c++ return type of the method.
* MethodName
- A string corresponding to the desired name of the method.
* Arguments
- A dag of strings that correspond to a c++ type and variable name
respectively.
* MethodBody (Optional)
- An optional explicit implementation of the interface method.
def MyInterface : OpInterface<"MyInterface"> {
let methods = [
// A simple non-static method with no inputs.
InterfaceMethod<"unsigned", "foo">,
// A new non-static method accepting an input argument.
InterfaceMethod<"Value *", "bar", (ins "unsigned":$i)>,
// Query a static property of the derived operation.
StaticInterfaceMethod<"unsigned", "fooStatic">,
// Provide the definition of a static interface method.
// Note: `ConcreteOp` corresponds to the derived operation typename.
StaticInterfaceMethod<"Operation *", "create",
(ins "OpBuilder &":$builder, "Location":$loc), [{
return builder.create<ConcreteOp>(loc);
}]>,
// Provide a definition of the non-static method.
// Note: `op` corresponds to the derived operation variable.
InterfaceMethod<"unsigned", "getNumInputsAndOutputs", (ins), [{
return op.getNumInputs() + op.getNumOutputs();
}]>,
];
PiperOrigin-RevId: 264754898
2019-08-22 11:57:23 +08:00
|
|
|
|
|
|
|
// Emit the method name and argument list for the given method. If
|
|
|
|
// 'addOperationArg' is true, then an Operation* argument is added to the
|
|
|
|
// beginning of the argument list.
|
|
|
|
static void emitMethodNameAndArgs(const OpInterfaceMethod &method,
|
|
|
|
raw_ostream &os, bool addOperationArg) {
|
|
|
|
os << method.getName() << '(';
|
|
|
|
if (addOperationArg)
|
|
|
|
os << "Operation *tablegen_opaque_op" << (method.arg_empty() ? "" : ", ");
|
2020-04-15 05:53:28 +08:00
|
|
|
llvm::interleaveComma(method.getArguments(), os,
|
|
|
|
[&](const OpInterfaceMethod::Argument &arg) {
|
|
|
|
os << arg.type << " " << arg.name;
|
|
|
|
});
|
Add support for generating operation interfaces from the ODS framework.
Operation interfaces generally require a bit of boilerplate code to connect all of the pieces together. This cl introduces mechanisms in the ODS to allow for generating operation interfaces via the 'OpInterface' class.
Providing a definition of the `OpInterface` class will auto-generate the c++
classes for the interface. An `OpInterface` includes a name, for the c++ class,
along with a list of interface methods. There are two types of methods that can be used with an interface, `InterfaceMethod` and `StaticInterfaceMethod`. They are both comprised of the same core components, with the distinction that `StaticInterfaceMethod` models a static method on the derived operation.
An `InterfaceMethod` is comprised of the following components:
* ReturnType
- A string corresponding to the c++ return type of the method.
* MethodName
- A string corresponding to the desired name of the method.
* Arguments
- A dag of strings that correspond to a c++ type and variable name
respectively.
* MethodBody (Optional)
- An optional explicit implementation of the interface method.
def MyInterface : OpInterface<"MyInterface"> {
let methods = [
// A simple non-static method with no inputs.
InterfaceMethod<"unsigned", "foo">,
// A new non-static method accepting an input argument.
InterfaceMethod<"Value *", "bar", (ins "unsigned":$i)>,
// Query a static property of the derived operation.
StaticInterfaceMethod<"unsigned", "fooStatic">,
// Provide the definition of a static interface method.
// Note: `ConcreteOp` corresponds to the derived operation typename.
StaticInterfaceMethod<"Operation *", "create",
(ins "OpBuilder &":$builder, "Location":$loc), [{
return builder.create<ConcreteOp>(loc);
}]>,
// Provide a definition of the non-static method.
// Note: `op` corresponds to the derived operation variable.
InterfaceMethod<"unsigned", "getNumInputsAndOutputs", (ins), [{
return op.getNumInputs() + op.getNumOutputs();
}]>,
];
PiperOrigin-RevId: 264754898
2019-08-22 11:57:23 +08:00
|
|
|
os << ')';
|
|
|
|
}
|
|
|
|
|
2019-12-14 05:57:49 +08:00
|
|
|
// Get an array of all OpInterface definitions but exclude those subclassing
|
|
|
|
// "DeclareOpInterfaceMethods".
|
|
|
|
static std::vector<Record *>
|
|
|
|
getAllOpInterfaceDefinitions(const RecordKeeper &recordKeeper) {
|
|
|
|
std::vector<Record *> defs =
|
|
|
|
recordKeeper.getAllDerivedDefinitions("OpInterface");
|
|
|
|
|
|
|
|
llvm::erase_if(defs, [](const Record *def) {
|
|
|
|
return def->isSubClassOf("DeclareOpInterfaceMethods");
|
|
|
|
});
|
|
|
|
return defs;
|
|
|
|
}
|
|
|
|
|
2019-09-25 03:45:11 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// GEN: Interface definitions
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
static void emitInterfaceDef(OpInterface &interface, raw_ostream &os) {
|
Add support for generating operation interfaces from the ODS framework.
Operation interfaces generally require a bit of boilerplate code to connect all of the pieces together. This cl introduces mechanisms in the ODS to allow for generating operation interfaces via the 'OpInterface' class.
Providing a definition of the `OpInterface` class will auto-generate the c++
classes for the interface. An `OpInterface` includes a name, for the c++ class,
along with a list of interface methods. There are two types of methods that can be used with an interface, `InterfaceMethod` and `StaticInterfaceMethod`. They are both comprised of the same core components, with the distinction that `StaticInterfaceMethod` models a static method on the derived operation.
An `InterfaceMethod` is comprised of the following components:
* ReturnType
- A string corresponding to the c++ return type of the method.
* MethodName
- A string corresponding to the desired name of the method.
* Arguments
- A dag of strings that correspond to a c++ type and variable name
respectively.
* MethodBody (Optional)
- An optional explicit implementation of the interface method.
def MyInterface : OpInterface<"MyInterface"> {
let methods = [
// A simple non-static method with no inputs.
InterfaceMethod<"unsigned", "foo">,
// A new non-static method accepting an input argument.
InterfaceMethod<"Value *", "bar", (ins "unsigned":$i)>,
// Query a static property of the derived operation.
StaticInterfaceMethod<"unsigned", "fooStatic">,
// Provide the definition of a static interface method.
// Note: `ConcreteOp` corresponds to the derived operation typename.
StaticInterfaceMethod<"Operation *", "create",
(ins "OpBuilder &":$builder, "Location":$loc), [{
return builder.create<ConcreteOp>(loc);
}]>,
// Provide a definition of the non-static method.
// Note: `op` corresponds to the derived operation variable.
InterfaceMethod<"unsigned", "getNumInputsAndOutputs", (ins), [{
return op.getNumInputs() + op.getNumOutputs();
}]>,
];
PiperOrigin-RevId: 264754898
2019-08-22 11:57:23 +08:00
|
|
|
StringRef interfaceName = interface.getName();
|
|
|
|
|
|
|
|
// Insert the method definitions.
|
2019-08-23 02:31:01 +08:00
|
|
|
for (auto &method : interface.getMethods()) {
|
Add support for generating operation interfaces from the ODS framework.
Operation interfaces generally require a bit of boilerplate code to connect all of the pieces together. This cl introduces mechanisms in the ODS to allow for generating operation interfaces via the 'OpInterface' class.
Providing a definition of the `OpInterface` class will auto-generate the c++
classes for the interface. An `OpInterface` includes a name, for the c++ class,
along with a list of interface methods. There are two types of methods that can be used with an interface, `InterfaceMethod` and `StaticInterfaceMethod`. They are both comprised of the same core components, with the distinction that `StaticInterfaceMethod` models a static method on the derived operation.
An `InterfaceMethod` is comprised of the following components:
* ReturnType
- A string corresponding to the c++ return type of the method.
* MethodName
- A string corresponding to the desired name of the method.
* Arguments
- A dag of strings that correspond to a c++ type and variable name
respectively.
* MethodBody (Optional)
- An optional explicit implementation of the interface method.
def MyInterface : OpInterface<"MyInterface"> {
let methods = [
// A simple non-static method with no inputs.
InterfaceMethod<"unsigned", "foo">,
// A new non-static method accepting an input argument.
InterfaceMethod<"Value *", "bar", (ins "unsigned":$i)>,
// Query a static property of the derived operation.
StaticInterfaceMethod<"unsigned", "fooStatic">,
// Provide the definition of a static interface method.
// Note: `ConcreteOp` corresponds to the derived operation typename.
StaticInterfaceMethod<"Operation *", "create",
(ins "OpBuilder &":$builder, "Location":$loc), [{
return builder.create<ConcreteOp>(loc);
}]>,
// Provide a definition of the non-static method.
// Note: `op` corresponds to the derived operation variable.
InterfaceMethod<"unsigned", "getNumInputsAndOutputs", (ins), [{
return op.getNumInputs() + op.getNumOutputs();
}]>,
];
PiperOrigin-RevId: 264754898
2019-08-22 11:57:23 +08:00
|
|
|
os << method.getReturnType() << " " << interfaceName << "::";
|
|
|
|
emitMethodNameAndArgs(method, os, /*addOperationArg=*/false);
|
|
|
|
|
|
|
|
// Forward to the method on the concrete operation type.
|
|
|
|
os << " {\n return getImpl()->" << method.getName() << '(';
|
|
|
|
if (!method.isStatic())
|
|
|
|
os << "getOperation()" << (method.arg_empty() ? "" : ", ");
|
2020-04-15 05:53:28 +08:00
|
|
|
llvm::interleaveComma(
|
2019-10-01 03:42:31 +08:00
|
|
|
method.getArguments(), os,
|
|
|
|
[&](const OpInterfaceMethod::Argument &arg) { os << arg.name; });
|
Add support for generating operation interfaces from the ODS framework.
Operation interfaces generally require a bit of boilerplate code to connect all of the pieces together. This cl introduces mechanisms in the ODS to allow for generating operation interfaces via the 'OpInterface' class.
Providing a definition of the `OpInterface` class will auto-generate the c++
classes for the interface. An `OpInterface` includes a name, for the c++ class,
along with a list of interface methods. There are two types of methods that can be used with an interface, `InterfaceMethod` and `StaticInterfaceMethod`. They are both comprised of the same core components, with the distinction that `StaticInterfaceMethod` models a static method on the derived operation.
An `InterfaceMethod` is comprised of the following components:
* ReturnType
- A string corresponding to the c++ return type of the method.
* MethodName
- A string corresponding to the desired name of the method.
* Arguments
- A dag of strings that correspond to a c++ type and variable name
respectively.
* MethodBody (Optional)
- An optional explicit implementation of the interface method.
def MyInterface : OpInterface<"MyInterface"> {
let methods = [
// A simple non-static method with no inputs.
InterfaceMethod<"unsigned", "foo">,
// A new non-static method accepting an input argument.
InterfaceMethod<"Value *", "bar", (ins "unsigned":$i)>,
// Query a static property of the derived operation.
StaticInterfaceMethod<"unsigned", "fooStatic">,
// Provide the definition of a static interface method.
// Note: `ConcreteOp` corresponds to the derived operation typename.
StaticInterfaceMethod<"Operation *", "create",
(ins "OpBuilder &":$builder, "Location":$loc), [{
return builder.create<ConcreteOp>(loc);
}]>,
// Provide a definition of the non-static method.
// Note: `op` corresponds to the derived operation variable.
InterfaceMethod<"unsigned", "getNumInputsAndOutputs", (ins), [{
return op.getNumInputs() + op.getNumOutputs();
}]>,
];
PiperOrigin-RevId: 264754898
2019-08-22 11:57:23 +08:00
|
|
|
os << ");\n }\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool emitInterfaceDefs(const RecordKeeper &recordKeeper,
|
|
|
|
raw_ostream &os) {
|
|
|
|
llvm::emitSourceFileHeader("Operation Interface Definitions", os);
|
|
|
|
|
2019-12-14 05:57:49 +08:00
|
|
|
for (const auto *def : getAllOpInterfaceDefinitions(recordKeeper)) {
|
2019-09-25 03:45:11 +08:00
|
|
|
OpInterface interface(def);
|
|
|
|
emitInterfaceDef(interface, os);
|
|
|
|
}
|
Add support for generating operation interfaces from the ODS framework.
Operation interfaces generally require a bit of boilerplate code to connect all of the pieces together. This cl introduces mechanisms in the ODS to allow for generating operation interfaces via the 'OpInterface' class.
Providing a definition of the `OpInterface` class will auto-generate the c++
classes for the interface. An `OpInterface` includes a name, for the c++ class,
along with a list of interface methods. There are two types of methods that can be used with an interface, `InterfaceMethod` and `StaticInterfaceMethod`. They are both comprised of the same core components, with the distinction that `StaticInterfaceMethod` models a static method on the derived operation.
An `InterfaceMethod` is comprised of the following components:
* ReturnType
- A string corresponding to the c++ return type of the method.
* MethodName
- A string corresponding to the desired name of the method.
* Arguments
- A dag of strings that correspond to a c++ type and variable name
respectively.
* MethodBody (Optional)
- An optional explicit implementation of the interface method.
def MyInterface : OpInterface<"MyInterface"> {
let methods = [
// A simple non-static method with no inputs.
InterfaceMethod<"unsigned", "foo">,
// A new non-static method accepting an input argument.
InterfaceMethod<"Value *", "bar", (ins "unsigned":$i)>,
// Query a static property of the derived operation.
StaticInterfaceMethod<"unsigned", "fooStatic">,
// Provide the definition of a static interface method.
// Note: `ConcreteOp` corresponds to the derived operation typename.
StaticInterfaceMethod<"Operation *", "create",
(ins "OpBuilder &":$builder, "Location":$loc), [{
return builder.create<ConcreteOp>(loc);
}]>,
// Provide a definition of the non-static method.
// Note: `op` corresponds to the derived operation variable.
InterfaceMethod<"unsigned", "getNumInputsAndOutputs", (ins), [{
return op.getNumInputs() + op.getNumOutputs();
}]>,
];
PiperOrigin-RevId: 264754898
2019-08-22 11:57:23 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-09-25 03:45:11 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// GEN: Interface declarations
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2019-08-23 02:31:01 +08:00
|
|
|
static void emitConceptDecl(OpInterface &interface, raw_ostream &os) {
|
Add support for generating operation interfaces from the ODS framework.
Operation interfaces generally require a bit of boilerplate code to connect all of the pieces together. This cl introduces mechanisms in the ODS to allow for generating operation interfaces via the 'OpInterface' class.
Providing a definition of the `OpInterface` class will auto-generate the c++
classes for the interface. An `OpInterface` includes a name, for the c++ class,
along with a list of interface methods. There are two types of methods that can be used with an interface, `InterfaceMethod` and `StaticInterfaceMethod`. They are both comprised of the same core components, with the distinction that `StaticInterfaceMethod` models a static method on the derived operation.
An `InterfaceMethod` is comprised of the following components:
* ReturnType
- A string corresponding to the c++ return type of the method.
* MethodName
- A string corresponding to the desired name of the method.
* Arguments
- A dag of strings that correspond to a c++ type and variable name
respectively.
* MethodBody (Optional)
- An optional explicit implementation of the interface method.
def MyInterface : OpInterface<"MyInterface"> {
let methods = [
// A simple non-static method with no inputs.
InterfaceMethod<"unsigned", "foo">,
// A new non-static method accepting an input argument.
InterfaceMethod<"Value *", "bar", (ins "unsigned":$i)>,
// Query a static property of the derived operation.
StaticInterfaceMethod<"unsigned", "fooStatic">,
// Provide the definition of a static interface method.
// Note: `ConcreteOp` corresponds to the derived operation typename.
StaticInterfaceMethod<"Operation *", "create",
(ins "OpBuilder &":$builder, "Location":$loc), [{
return builder.create<ConcreteOp>(loc);
}]>,
// Provide a definition of the non-static method.
// Note: `op` corresponds to the derived operation variable.
InterfaceMethod<"unsigned", "getNumInputsAndOutputs", (ins), [{
return op.getNumInputs() + op.getNumOutputs();
}]>,
];
PiperOrigin-RevId: 264754898
2019-08-22 11:57:23 +08:00
|
|
|
os << " class Concept {\n"
|
|
|
|
<< " public:\n"
|
|
|
|
<< " virtual ~Concept() = default;\n";
|
|
|
|
|
2019-08-23 02:31:01 +08:00
|
|
|
// Insert each of the pure virtual concept methods.
|
|
|
|
for (auto &method : interface.getMethods()) {
|
Add support for generating operation interfaces from the ODS framework.
Operation interfaces generally require a bit of boilerplate code to connect all of the pieces together. This cl introduces mechanisms in the ODS to allow for generating operation interfaces via the 'OpInterface' class.
Providing a definition of the `OpInterface` class will auto-generate the c++
classes for the interface. An `OpInterface` includes a name, for the c++ class,
along with a list of interface methods. There are two types of methods that can be used with an interface, `InterfaceMethod` and `StaticInterfaceMethod`. They are both comprised of the same core components, with the distinction that `StaticInterfaceMethod` models a static method on the derived operation.
An `InterfaceMethod` is comprised of the following components:
* ReturnType
- A string corresponding to the c++ return type of the method.
* MethodName
- A string corresponding to the desired name of the method.
* Arguments
- A dag of strings that correspond to a c++ type and variable name
respectively.
* MethodBody (Optional)
- An optional explicit implementation of the interface method.
def MyInterface : OpInterface<"MyInterface"> {
let methods = [
// A simple non-static method with no inputs.
InterfaceMethod<"unsigned", "foo">,
// A new non-static method accepting an input argument.
InterfaceMethod<"Value *", "bar", (ins "unsigned":$i)>,
// Query a static property of the derived operation.
StaticInterfaceMethod<"unsigned", "fooStatic">,
// Provide the definition of a static interface method.
// Note: `ConcreteOp` corresponds to the derived operation typename.
StaticInterfaceMethod<"Operation *", "create",
(ins "OpBuilder &":$builder, "Location":$loc), [{
return builder.create<ConcreteOp>(loc);
}]>,
// Provide a definition of the non-static method.
// Note: `op` corresponds to the derived operation variable.
InterfaceMethod<"unsigned", "getNumInputsAndOutputs", (ins), [{
return op.getNumInputs() + op.getNumOutputs();
}]>,
];
PiperOrigin-RevId: 264754898
2019-08-22 11:57:23 +08:00
|
|
|
os << " virtual " << method.getReturnType() << " ";
|
|
|
|
emitMethodNameAndArgs(method, os, /*addOperationArg=*/!method.isStatic());
|
|
|
|
os << " = 0;\n";
|
|
|
|
}
|
|
|
|
os << " };\n";
|
|
|
|
}
|
|
|
|
|
2019-08-23 02:31:01 +08:00
|
|
|
static void emitModelDecl(OpInterface &interface, raw_ostream &os) {
|
Add support for generating operation interfaces from the ODS framework.
Operation interfaces generally require a bit of boilerplate code to connect all of the pieces together. This cl introduces mechanisms in the ODS to allow for generating operation interfaces via the 'OpInterface' class.
Providing a definition of the `OpInterface` class will auto-generate the c++
classes for the interface. An `OpInterface` includes a name, for the c++ class,
along with a list of interface methods. There are two types of methods that can be used with an interface, `InterfaceMethod` and `StaticInterfaceMethod`. They are both comprised of the same core components, with the distinction that `StaticInterfaceMethod` models a static method on the derived operation.
An `InterfaceMethod` is comprised of the following components:
* ReturnType
- A string corresponding to the c++ return type of the method.
* MethodName
- A string corresponding to the desired name of the method.
* Arguments
- A dag of strings that correspond to a c++ type and variable name
respectively.
* MethodBody (Optional)
- An optional explicit implementation of the interface method.
def MyInterface : OpInterface<"MyInterface"> {
let methods = [
// A simple non-static method with no inputs.
InterfaceMethod<"unsigned", "foo">,
// A new non-static method accepting an input argument.
InterfaceMethod<"Value *", "bar", (ins "unsigned":$i)>,
// Query a static property of the derived operation.
StaticInterfaceMethod<"unsigned", "fooStatic">,
// Provide the definition of a static interface method.
// Note: `ConcreteOp` corresponds to the derived operation typename.
StaticInterfaceMethod<"Operation *", "create",
(ins "OpBuilder &":$builder, "Location":$loc), [{
return builder.create<ConcreteOp>(loc);
}]>,
// Provide a definition of the non-static method.
// Note: `op` corresponds to the derived operation variable.
InterfaceMethod<"unsigned", "getNumInputsAndOutputs", (ins), [{
return op.getNumInputs() + op.getNumOutputs();
}]>,
];
PiperOrigin-RevId: 264754898
2019-08-22 11:57:23 +08:00
|
|
|
os << " template<typename ConcreteOp>\n";
|
|
|
|
os << " class Model : public Concept {\npublic:\n";
|
|
|
|
|
|
|
|
// Insert each of the virtual method overrides.
|
2019-08-23 02:31:01 +08:00
|
|
|
for (auto &method : interface.getMethods()) {
|
Add support for generating operation interfaces from the ODS framework.
Operation interfaces generally require a bit of boilerplate code to connect all of the pieces together. This cl introduces mechanisms in the ODS to allow for generating operation interfaces via the 'OpInterface' class.
Providing a definition of the `OpInterface` class will auto-generate the c++
classes for the interface. An `OpInterface` includes a name, for the c++ class,
along with a list of interface methods. There are two types of methods that can be used with an interface, `InterfaceMethod` and `StaticInterfaceMethod`. They are both comprised of the same core components, with the distinction that `StaticInterfaceMethod` models a static method on the derived operation.
An `InterfaceMethod` is comprised of the following components:
* ReturnType
- A string corresponding to the c++ return type of the method.
* MethodName
- A string corresponding to the desired name of the method.
* Arguments
- A dag of strings that correspond to a c++ type and variable name
respectively.
* MethodBody (Optional)
- An optional explicit implementation of the interface method.
def MyInterface : OpInterface<"MyInterface"> {
let methods = [
// A simple non-static method with no inputs.
InterfaceMethod<"unsigned", "foo">,
// A new non-static method accepting an input argument.
InterfaceMethod<"Value *", "bar", (ins "unsigned":$i)>,
// Query a static property of the derived operation.
StaticInterfaceMethod<"unsigned", "fooStatic">,
// Provide the definition of a static interface method.
// Note: `ConcreteOp` corresponds to the derived operation typename.
StaticInterfaceMethod<"Operation *", "create",
(ins "OpBuilder &":$builder, "Location":$loc), [{
return builder.create<ConcreteOp>(loc);
}]>,
// Provide a definition of the non-static method.
// Note: `op` corresponds to the derived operation variable.
InterfaceMethod<"unsigned", "getNumInputsAndOutputs", (ins), [{
return op.getNumInputs() + op.getNumOutputs();
}]>,
];
PiperOrigin-RevId: 264754898
2019-08-22 11:57:23 +08:00
|
|
|
os << " " << method.getReturnType() << " ";
|
|
|
|
emitMethodNameAndArgs(method, os, /*addOperationArg=*/!method.isStatic());
|
|
|
|
os << " final {\n";
|
|
|
|
|
|
|
|
// Provide a definition of the concrete op if this is non static.
|
|
|
|
if (!method.isStatic()) {
|
|
|
|
os << " auto op = llvm::cast<ConcreteOp>(tablegen_opaque_op);\n"
|
|
|
|
<< " (void)op;\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check for a provided body to the function.
|
|
|
|
if (auto body = method.getBody()) {
|
|
|
|
os << body << "\n }\n";
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Forward to the method on the concrete operation type.
|
|
|
|
os << " return " << (method.isStatic() ? "ConcreteOp::" : "op.");
|
|
|
|
|
|
|
|
// Add the arguments to the call.
|
|
|
|
os << method.getName() << '(';
|
2020-04-15 05:53:28 +08:00
|
|
|
llvm::interleaveComma(
|
2019-10-01 03:42:31 +08:00
|
|
|
method.getArguments(), os,
|
|
|
|
[&](const OpInterfaceMethod::Argument &arg) { os << arg.name; });
|
Add support for generating operation interfaces from the ODS framework.
Operation interfaces generally require a bit of boilerplate code to connect all of the pieces together. This cl introduces mechanisms in the ODS to allow for generating operation interfaces via the 'OpInterface' class.
Providing a definition of the `OpInterface` class will auto-generate the c++
classes for the interface. An `OpInterface` includes a name, for the c++ class,
along with a list of interface methods. There are two types of methods that can be used with an interface, `InterfaceMethod` and `StaticInterfaceMethod`. They are both comprised of the same core components, with the distinction that `StaticInterfaceMethod` models a static method on the derived operation.
An `InterfaceMethod` is comprised of the following components:
* ReturnType
- A string corresponding to the c++ return type of the method.
* MethodName
- A string corresponding to the desired name of the method.
* Arguments
- A dag of strings that correspond to a c++ type and variable name
respectively.
* MethodBody (Optional)
- An optional explicit implementation of the interface method.
def MyInterface : OpInterface<"MyInterface"> {
let methods = [
// A simple non-static method with no inputs.
InterfaceMethod<"unsigned", "foo">,
// A new non-static method accepting an input argument.
InterfaceMethod<"Value *", "bar", (ins "unsigned":$i)>,
// Query a static property of the derived operation.
StaticInterfaceMethod<"unsigned", "fooStatic">,
// Provide the definition of a static interface method.
// Note: `ConcreteOp` corresponds to the derived operation typename.
StaticInterfaceMethod<"Operation *", "create",
(ins "OpBuilder &":$builder, "Location":$loc), [{
return builder.create<ConcreteOp>(loc);
}]>,
// Provide a definition of the non-static method.
// Note: `op` corresponds to the derived operation variable.
InterfaceMethod<"unsigned", "getNumInputsAndOutputs", (ins), [{
return op.getNumInputs() + op.getNumOutputs();
}]>,
];
PiperOrigin-RevId: 264754898
2019-08-22 11:57:23 +08:00
|
|
|
os << ");\n }\n";
|
|
|
|
}
|
|
|
|
os << " };\n";
|
|
|
|
}
|
|
|
|
|
2019-12-19 03:02:35 +08:00
|
|
|
static void emitTraitDecl(OpInterface &interface, raw_ostream &os,
|
|
|
|
StringRef interfaceName,
|
|
|
|
StringRef interfaceTraitsName) {
|
|
|
|
os << " template <typename ConcreteOp>\n "
|
2020-04-30 07:09:43 +08:00
|
|
|
<< llvm::formatv("struct {0}Trait : public OpInterface<{0},"
|
2019-12-19 03:02:35 +08:00
|
|
|
" detail::{1}>::Trait<ConcreteOp> {{\n",
|
|
|
|
interfaceName, interfaceTraitsName);
|
|
|
|
|
|
|
|
// Insert the default implementation for any methods.
|
|
|
|
for (auto &method : interface.getMethods()) {
|
2020-01-22 01:40:22 +08:00
|
|
|
// Flag interface methods named verifyTrait.
|
|
|
|
if (method.getName() == "verifyTrait")
|
|
|
|
PrintFatalError(
|
|
|
|
formatv("'verifyTrait' method cannot be specified as interface "
|
|
|
|
"method for '{0}'; set 'verify' on OpInterfaceTrait instead",
|
|
|
|
interfaceName));
|
2019-12-19 03:02:35 +08:00
|
|
|
auto defaultImpl = method.getDefaultImplementation();
|
|
|
|
if (!defaultImpl)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
os << " " << (method.isStatic() ? "static " : "") << method.getReturnType()
|
|
|
|
<< " ";
|
|
|
|
emitMethodNameAndArgs(method, os, /*addOperationArg=*/false);
|
|
|
|
os << " {\n" << defaultImpl.getValue() << " }\n";
|
|
|
|
}
|
|
|
|
|
2020-01-22 01:40:22 +08:00
|
|
|
tblgen::FmtContext traitCtx;
|
|
|
|
traitCtx.withOp("op");
|
|
|
|
if (auto verify = interface.getVerify()) {
|
2020-04-30 07:09:43 +08:00
|
|
|
os << " static LogicalResult verifyTrait(Operation* op) {\n"
|
2020-01-29 03:23:46 +08:00
|
|
|
<< std::string(tblgen::tgfmt(*verify, &traitCtx)) << "\n }\n";
|
2020-01-22 01:40:22 +08:00
|
|
|
}
|
2020-04-28 03:57:32 +08:00
|
|
|
if (auto extraTraitDecls = interface.getExtraTraitClassDeclaration())
|
|
|
|
os << extraTraitDecls << "\n";
|
2020-01-22 01:40:22 +08:00
|
|
|
|
2019-12-19 03:02:35 +08:00
|
|
|
os << " };\n";
|
2020-04-30 07:09:43 +08:00
|
|
|
|
|
|
|
// Emit a utility using directive for the trait class.
|
|
|
|
os << " template <typename ConcreteOp>\n "
|
|
|
|
<< llvm::formatv("using Trait = {0}Trait<ConcreteOp>;\n", interfaceName);
|
2019-12-19 03:02:35 +08:00
|
|
|
}
|
|
|
|
|
2019-09-25 03:45:11 +08:00
|
|
|
static void emitInterfaceDecl(OpInterface &interface, raw_ostream &os) {
|
Add support for generating operation interfaces from the ODS framework.
Operation interfaces generally require a bit of boilerplate code to connect all of the pieces together. This cl introduces mechanisms in the ODS to allow for generating operation interfaces via the 'OpInterface' class.
Providing a definition of the `OpInterface` class will auto-generate the c++
classes for the interface. An `OpInterface` includes a name, for the c++ class,
along with a list of interface methods. There are two types of methods that can be used with an interface, `InterfaceMethod` and `StaticInterfaceMethod`. They are both comprised of the same core components, with the distinction that `StaticInterfaceMethod` models a static method on the derived operation.
An `InterfaceMethod` is comprised of the following components:
* ReturnType
- A string corresponding to the c++ return type of the method.
* MethodName
- A string corresponding to the desired name of the method.
* Arguments
- A dag of strings that correspond to a c++ type and variable name
respectively.
* MethodBody (Optional)
- An optional explicit implementation of the interface method.
def MyInterface : OpInterface<"MyInterface"> {
let methods = [
// A simple non-static method with no inputs.
InterfaceMethod<"unsigned", "foo">,
// A new non-static method accepting an input argument.
InterfaceMethod<"Value *", "bar", (ins "unsigned":$i)>,
// Query a static property of the derived operation.
StaticInterfaceMethod<"unsigned", "fooStatic">,
// Provide the definition of a static interface method.
// Note: `ConcreteOp` corresponds to the derived operation typename.
StaticInterfaceMethod<"Operation *", "create",
(ins "OpBuilder &":$builder, "Location":$loc), [{
return builder.create<ConcreteOp>(loc);
}]>,
// Provide a definition of the non-static method.
// Note: `op` corresponds to the derived operation variable.
InterfaceMethod<"unsigned", "getNumInputsAndOutputs", (ins), [{
return op.getNumInputs() + op.getNumOutputs();
}]>,
];
PiperOrigin-RevId: 264754898
2019-08-22 11:57:23 +08:00
|
|
|
StringRef interfaceName = interface.getName();
|
|
|
|
auto interfaceTraitsName = (interfaceName + "InterfaceTraits").str();
|
|
|
|
|
|
|
|
// Emit the traits struct containing the concept and model declarations.
|
|
|
|
os << "namespace detail {\n"
|
|
|
|
<< "struct " << interfaceTraitsName << " {\n";
|
2019-08-23 02:31:01 +08:00
|
|
|
emitConceptDecl(interface, os);
|
|
|
|
emitModelDecl(interface, os);
|
Add support for generating operation interfaces from the ODS framework.
Operation interfaces generally require a bit of boilerplate code to connect all of the pieces together. This cl introduces mechanisms in the ODS to allow for generating operation interfaces via the 'OpInterface' class.
Providing a definition of the `OpInterface` class will auto-generate the c++
classes for the interface. An `OpInterface` includes a name, for the c++ class,
along with a list of interface methods. There are two types of methods that can be used with an interface, `InterfaceMethod` and `StaticInterfaceMethod`. They are both comprised of the same core components, with the distinction that `StaticInterfaceMethod` models a static method on the derived operation.
An `InterfaceMethod` is comprised of the following components:
* ReturnType
- A string corresponding to the c++ return type of the method.
* MethodName
- A string corresponding to the desired name of the method.
* Arguments
- A dag of strings that correspond to a c++ type and variable name
respectively.
* MethodBody (Optional)
- An optional explicit implementation of the interface method.
def MyInterface : OpInterface<"MyInterface"> {
let methods = [
// A simple non-static method with no inputs.
InterfaceMethod<"unsigned", "foo">,
// A new non-static method accepting an input argument.
InterfaceMethod<"Value *", "bar", (ins "unsigned":$i)>,
// Query a static property of the derived operation.
StaticInterfaceMethod<"unsigned", "fooStatic">,
// Provide the definition of a static interface method.
// Note: `ConcreteOp` corresponds to the derived operation typename.
StaticInterfaceMethod<"Operation *", "create",
(ins "OpBuilder &":$builder, "Location":$loc), [{
return builder.create<ConcreteOp>(loc);
}]>,
// Provide a definition of the non-static method.
// Note: `op` corresponds to the derived operation variable.
InterfaceMethod<"unsigned", "getNumInputsAndOutputs", (ins), [{
return op.getNumInputs() + op.getNumOutputs();
}]>,
];
PiperOrigin-RevId: 264754898
2019-08-22 11:57:23 +08:00
|
|
|
os << "};\n} // end namespace detail\n";
|
|
|
|
|
|
|
|
// Emit the main interface class declaration.
|
|
|
|
os << llvm::formatv("class {0} : public OpInterface<{1}, detail::{2}> {\n"
|
|
|
|
"public:\n"
|
|
|
|
" using OpInterface<{1}, detail::{2}>::OpInterface;\n",
|
|
|
|
interfaceName, interfaceName, interfaceTraitsName);
|
|
|
|
|
2019-12-19 03:02:35 +08:00
|
|
|
// Emit the derived trait for the interface.
|
|
|
|
emitTraitDecl(interface, os, interfaceName, interfaceTraitsName);
|
|
|
|
|
Add support for generating operation interfaces from the ODS framework.
Operation interfaces generally require a bit of boilerplate code to connect all of the pieces together. This cl introduces mechanisms in the ODS to allow for generating operation interfaces via the 'OpInterface' class.
Providing a definition of the `OpInterface` class will auto-generate the c++
classes for the interface. An `OpInterface` includes a name, for the c++ class,
along with a list of interface methods. There are two types of methods that can be used with an interface, `InterfaceMethod` and `StaticInterfaceMethod`. They are both comprised of the same core components, with the distinction that `StaticInterfaceMethod` models a static method on the derived operation.
An `InterfaceMethod` is comprised of the following components:
* ReturnType
- A string corresponding to the c++ return type of the method.
* MethodName
- A string corresponding to the desired name of the method.
* Arguments
- A dag of strings that correspond to a c++ type and variable name
respectively.
* MethodBody (Optional)
- An optional explicit implementation of the interface method.
def MyInterface : OpInterface<"MyInterface"> {
let methods = [
// A simple non-static method with no inputs.
InterfaceMethod<"unsigned", "foo">,
// A new non-static method accepting an input argument.
InterfaceMethod<"Value *", "bar", (ins "unsigned":$i)>,
// Query a static property of the derived operation.
StaticInterfaceMethod<"unsigned", "fooStatic">,
// Provide the definition of a static interface method.
// Note: `ConcreteOp` corresponds to the derived operation typename.
StaticInterfaceMethod<"Operation *", "create",
(ins "OpBuilder &":$builder, "Location":$loc), [{
return builder.create<ConcreteOp>(loc);
}]>,
// Provide a definition of the non-static method.
// Note: `op` corresponds to the derived operation variable.
InterfaceMethod<"unsigned", "getNumInputsAndOutputs", (ins), [{
return op.getNumInputs() + op.getNumOutputs();
}]>,
];
PiperOrigin-RevId: 264754898
2019-08-22 11:57:23 +08:00
|
|
|
// Insert the method declarations.
|
|
|
|
for (auto &method : interface.getMethods()) {
|
|
|
|
os << " " << method.getReturnType() << " ";
|
|
|
|
emitMethodNameAndArgs(method, os, /*addOperationArg=*/false);
|
|
|
|
os << ";\n";
|
|
|
|
}
|
[mlir] Allow adding extra class declarations to interfaces.
Summary: This matches the similar feature on operation definitions.
Reviewers: jpienaar, antiagainst
Reviewed By: jpienaar, antiagainst
Subscribers: mehdi_amini, burmako, shauheen, antiagainst, nicolasvasilache, arpith-jacob, mgester, lucyrfox, liufengdb, Joonsoo, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D74438
2020-02-16 15:54:28 +08:00
|
|
|
|
|
|
|
// Emit any extra declarations.
|
|
|
|
if (Optional<StringRef> extraDecls = interface.getExtraClassDeclaration())
|
|
|
|
os << *extraDecls << "\n";
|
|
|
|
|
Add support for generating operation interfaces from the ODS framework.
Operation interfaces generally require a bit of boilerplate code to connect all of the pieces together. This cl introduces mechanisms in the ODS to allow for generating operation interfaces via the 'OpInterface' class.
Providing a definition of the `OpInterface` class will auto-generate the c++
classes for the interface. An `OpInterface` includes a name, for the c++ class,
along with a list of interface methods. There are two types of methods that can be used with an interface, `InterfaceMethod` and `StaticInterfaceMethod`. They are both comprised of the same core components, with the distinction that `StaticInterfaceMethod` models a static method on the derived operation.
An `InterfaceMethod` is comprised of the following components:
* ReturnType
- A string corresponding to the c++ return type of the method.
* MethodName
- A string corresponding to the desired name of the method.
* Arguments
- A dag of strings that correspond to a c++ type and variable name
respectively.
* MethodBody (Optional)
- An optional explicit implementation of the interface method.
def MyInterface : OpInterface<"MyInterface"> {
let methods = [
// A simple non-static method with no inputs.
InterfaceMethod<"unsigned", "foo">,
// A new non-static method accepting an input argument.
InterfaceMethod<"Value *", "bar", (ins "unsigned":$i)>,
// Query a static property of the derived operation.
StaticInterfaceMethod<"unsigned", "fooStatic">,
// Provide the definition of a static interface method.
// Note: `ConcreteOp` corresponds to the derived operation typename.
StaticInterfaceMethod<"Operation *", "create",
(ins "OpBuilder &":$builder, "Location":$loc), [{
return builder.create<ConcreteOp>(loc);
}]>,
// Provide a definition of the non-static method.
// Note: `op` corresponds to the derived operation variable.
InterfaceMethod<"unsigned", "getNumInputsAndOutputs", (ins), [{
return op.getNumInputs() + op.getNumOutputs();
}]>,
];
PiperOrigin-RevId: 264754898
2019-08-22 11:57:23 +08:00
|
|
|
os << "};\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool emitInterfaceDecls(const RecordKeeper &recordKeeper,
|
|
|
|
raw_ostream &os) {
|
|
|
|
llvm::emitSourceFileHeader("Operation Interface Declarations", os);
|
|
|
|
|
2019-12-14 05:57:49 +08:00
|
|
|
for (const auto *def : getAllOpInterfaceDefinitions(recordKeeper)) {
|
2019-09-25 03:45:11 +08:00
|
|
|
OpInterface interface(def);
|
|
|
|
emitInterfaceDecl(interface, os);
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// GEN: Interface documentation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
/// Emit a string corresponding to a C++ type, followed by a space if necessary.
|
|
|
|
static raw_ostream &emitCPPType(StringRef type, raw_ostream &os) {
|
|
|
|
type = type.trim();
|
|
|
|
os << type;
|
|
|
|
if (type.back() != '&' && type.back() != '*')
|
|
|
|
os << " ";
|
|
|
|
return os;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void emitInterfaceDoc(const Record &interfaceDef, raw_ostream &os) {
|
|
|
|
OpInterface interface(&interfaceDef);
|
|
|
|
|
|
|
|
// Emit the interface name followed by the description.
|
|
|
|
os << "## " << interface.getName() << " (" << interfaceDef.getName() << ")";
|
|
|
|
if (auto description = interface.getDescription())
|
|
|
|
mlir::tblgen::emitDescription(*description, os);
|
|
|
|
|
|
|
|
// Emit the methods required by the interface.
|
|
|
|
os << "\n### Methods:\n";
|
|
|
|
for (const auto &method : interface.getMethods()) {
|
|
|
|
// Emit the method name.
|
|
|
|
os << "#### `" << method.getName() << "`\n\n```c++\n";
|
|
|
|
|
|
|
|
// Emit the method signature.
|
|
|
|
if (method.isStatic())
|
|
|
|
os << "static ";
|
|
|
|
emitCPPType(method.getReturnType(), os) << method.getName() << '(';
|
2020-04-15 05:53:28 +08:00
|
|
|
llvm::interleaveComma(method.getArguments(), os,
|
|
|
|
[&](const OpInterfaceMethod::Argument &arg) {
|
|
|
|
emitCPPType(arg.type, os) << arg.name;
|
|
|
|
});
|
2019-09-25 03:45:11 +08:00
|
|
|
os << ");\n```\n";
|
|
|
|
|
|
|
|
// Emit the description.
|
|
|
|
if (auto description = method.getDescription())
|
|
|
|
mlir::tblgen::emitDescription(*description, os);
|
|
|
|
|
|
|
|
// If the body is not provided, this method must be provided by the
|
|
|
|
// operation.
|
|
|
|
if (!method.getBody())
|
|
|
|
os << "\nNOTE: This method *must* be implemented by the operation.\n\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool emitInterfaceDocs(const RecordKeeper &recordKeeper,
|
|
|
|
raw_ostream &os) {
|
|
|
|
os << "<!-- Autogenerated by mlir-tblgen; don't manually edit -->\n";
|
|
|
|
os << "# Operation Interface definition\n";
|
|
|
|
|
2019-12-14 05:57:49 +08:00
|
|
|
for (const auto *def : getAllOpInterfaceDefinitions(recordKeeper))
|
2019-09-25 03:45:11 +08:00
|
|
|
emitInterfaceDoc(*def, os);
|
Add support for generating operation interfaces from the ODS framework.
Operation interfaces generally require a bit of boilerplate code to connect all of the pieces together. This cl introduces mechanisms in the ODS to allow for generating operation interfaces via the 'OpInterface' class.
Providing a definition of the `OpInterface` class will auto-generate the c++
classes for the interface. An `OpInterface` includes a name, for the c++ class,
along with a list of interface methods. There are two types of methods that can be used with an interface, `InterfaceMethod` and `StaticInterfaceMethod`. They are both comprised of the same core components, with the distinction that `StaticInterfaceMethod` models a static method on the derived operation.
An `InterfaceMethod` is comprised of the following components:
* ReturnType
- A string corresponding to the c++ return type of the method.
* MethodName
- A string corresponding to the desired name of the method.
* Arguments
- A dag of strings that correspond to a c++ type and variable name
respectively.
* MethodBody (Optional)
- An optional explicit implementation of the interface method.
def MyInterface : OpInterface<"MyInterface"> {
let methods = [
// A simple non-static method with no inputs.
InterfaceMethod<"unsigned", "foo">,
// A new non-static method accepting an input argument.
InterfaceMethod<"Value *", "bar", (ins "unsigned":$i)>,
// Query a static property of the derived operation.
StaticInterfaceMethod<"unsigned", "fooStatic">,
// Provide the definition of a static interface method.
// Note: `ConcreteOp` corresponds to the derived operation typename.
StaticInterfaceMethod<"Operation *", "create",
(ins "OpBuilder &":$builder, "Location":$loc), [{
return builder.create<ConcreteOp>(loc);
}]>,
// Provide a definition of the non-static method.
// Note: `op` corresponds to the derived operation variable.
InterfaceMethod<"unsigned", "getNumInputsAndOutputs", (ins), [{
return op.getNumInputs() + op.getNumOutputs();
}]>,
];
PiperOrigin-RevId: 264754898
2019-08-22 11:57:23 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-09-25 03:45:11 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// GEN: Interface registration hooks
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
Add support for generating operation interfaces from the ODS framework.
Operation interfaces generally require a bit of boilerplate code to connect all of the pieces together. This cl introduces mechanisms in the ODS to allow for generating operation interfaces via the 'OpInterface' class.
Providing a definition of the `OpInterface` class will auto-generate the c++
classes for the interface. An `OpInterface` includes a name, for the c++ class,
along with a list of interface methods. There are two types of methods that can be used with an interface, `InterfaceMethod` and `StaticInterfaceMethod`. They are both comprised of the same core components, with the distinction that `StaticInterfaceMethod` models a static method on the derived operation.
An `InterfaceMethod` is comprised of the following components:
* ReturnType
- A string corresponding to the c++ return type of the method.
* MethodName
- A string corresponding to the desired name of the method.
* Arguments
- A dag of strings that correspond to a c++ type and variable name
respectively.
* MethodBody (Optional)
- An optional explicit implementation of the interface method.
def MyInterface : OpInterface<"MyInterface"> {
let methods = [
// A simple non-static method with no inputs.
InterfaceMethod<"unsigned", "foo">,
// A new non-static method accepting an input argument.
InterfaceMethod<"Value *", "bar", (ins "unsigned":$i)>,
// Query a static property of the derived operation.
StaticInterfaceMethod<"unsigned", "fooStatic">,
// Provide the definition of a static interface method.
// Note: `ConcreteOp` corresponds to the derived operation typename.
StaticInterfaceMethod<"Operation *", "create",
(ins "OpBuilder &":$builder, "Location":$loc), [{
return builder.create<ConcreteOp>(loc);
}]>,
// Provide a definition of the non-static method.
// Note: `op` corresponds to the derived operation variable.
InterfaceMethod<"unsigned", "getNumInputsAndOutputs", (ins), [{
return op.getNumInputs() + op.getNumOutputs();
}]>,
];
PiperOrigin-RevId: 264754898
2019-08-22 11:57:23 +08:00
|
|
|
// Registers the operation interface generator to mlir-tblgen.
|
|
|
|
static mlir::GenRegistration
|
|
|
|
genInterfaceDecls("gen-op-interface-decls",
|
|
|
|
"Generate op interface declarations",
|
|
|
|
[](const RecordKeeper &records, raw_ostream &os) {
|
|
|
|
return emitInterfaceDecls(records, os);
|
|
|
|
});
|
|
|
|
|
|
|
|
// Registers the operation interface generator to mlir-tblgen.
|
|
|
|
static mlir::GenRegistration
|
|
|
|
genInterfaceDefs("gen-op-interface-defs",
|
|
|
|
"Generate op interface definitions",
|
|
|
|
[](const RecordKeeper &records, raw_ostream &os) {
|
|
|
|
return emitInterfaceDefs(records, os);
|
|
|
|
});
|
2019-09-25 03:45:11 +08:00
|
|
|
|
|
|
|
// Registers the operation interface document generator to mlir-tblgen.
|
|
|
|
static mlir::GenRegistration
|
|
|
|
genInterfaceDocs("gen-op-interface-doc",
|
|
|
|
"Generate op interface documentation",
|
|
|
|
[](const RecordKeeper &records, raw_ostream &os) {
|
|
|
|
return emitInterfaceDocs(records, os);
|
|
|
|
});
|