mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-12-26 17:57:07 +00:00
[mlir][ods] ODS ops get an extraClassDefinition
Extra definitions are placed in the generated source file for each op class. The substitution `$cppClass` is replaced by the op's C++ class name. This is useful when declaring but not defining methods in TableGen base classes: ``` class BaseOp<string mnemonic> : Op<MyDialect, mnemonic, [DeclareOpInterfaceMethods<SomeInterface>] { let extraClassDeclaration = [{ // ZOp is declared at at the bottom of the file and is incomplete here ZOp getParent(); }]; let extraClassDefinition = [{ int $cppClass::someInterfaceMethod() { return someUtilityFunction(*this); } ZOp $cppClass::getParent() { return dyn_cast<ZOp>(this->getParentOp()); } }]; } ``` Certain things may prevent defining these functions inline, in the declaration. In this example, `ZOp` in the same dialect is incomplete at the function declaration because ops classes are declared in alphabetical order. Alternatively, functions may be too big to be desired as inlined, or they may require dependencies that create cyclic includes, or they may be calling a templated utility function that one may not want to expose in a header. If the functions are not inlined, then inheriting from the base class N times means that each function will need to be defined N times. With `extraClassDefinitions`, they only need to be defined once. Reviewed By: rriddle Differential Revision: https://reviews.llvm.org/D115783
This commit is contained in:
parent
0f5b718030
commit
b0774e5f50
@ -964,6 +964,16 @@ Note that `extraClassDeclaration` is a mechanism intended for long-tail cases by
|
||||
power users; for not-yet-implemented widely-applicable cases, improving the
|
||||
infrastructure is preferable.
|
||||
|
||||
### Extra definitions
|
||||
|
||||
When defining base op classes in TableGen that are inherited many times by
|
||||
different ops, users may want to provide common definitions of utility and
|
||||
interface functions. However, many of these definitions may not be desirable or
|
||||
possible in `extraClassDeclaration`, which append them to the op's C++ class
|
||||
declaration. In these cases, users can add an `extraClassDefinition` to define
|
||||
code that is added to the generated source file inside the op's C++ namespace.
|
||||
The substitution `$cppClass` is replaced by the op's C++ class name.
|
||||
|
||||
### Generated C++ code
|
||||
|
||||
[OpDefinitionsGen][OpDefinitionsGen] processes the op definition spec file and
|
||||
|
@ -2445,6 +2445,11 @@ class Op<Dialect dialect, string mnemonic, list<OpTrait> props = []> {
|
||||
// Additional code that will be added to the public part of the generated
|
||||
// C++ code of the op declaration.
|
||||
code extraClassDeclaration = ?;
|
||||
|
||||
// Additional code that will be added to the generated source file. The
|
||||
// generated code is placed inside the op's C++ namespace. `$cppClass` is
|
||||
// replaced by the op's C++ class name.
|
||||
code extraClassDefinition = ?;
|
||||
}
|
||||
|
||||
// Base class for ops with static/dynamic offset, sizes and strides
|
||||
|
@ -532,22 +532,32 @@ private:
|
||||
Visibility visibility;
|
||||
};
|
||||
|
||||
/// Unstructured extra class declarations, from TableGen definitions. The
|
||||
/// default visibility of extra class declarations is up to the owning class.
|
||||
/// Unstructured extra class declarations and definitions, from TableGen
|
||||
/// definitions. The default visibility of extra class declarations is up to the
|
||||
/// owning class.
|
||||
class ExtraClassDeclaration
|
||||
: public ClassDeclarationBase<ClassDeclaration::ExtraClassDeclaration> {
|
||||
public:
|
||||
/// Create an extra class declaration.
|
||||
ExtraClassDeclaration(StringRef extraClassDeclaration)
|
||||
: extraClassDeclaration(extraClassDeclaration) {}
|
||||
ExtraClassDeclaration(StringRef extraClassDeclaration,
|
||||
StringRef extraClassDefinition = "")
|
||||
: extraClassDeclaration(extraClassDeclaration),
|
||||
extraClassDefinition(extraClassDefinition) {}
|
||||
|
||||
/// Write the extra class declarations.
|
||||
void writeDeclTo(raw_indented_ostream &os) const override;
|
||||
|
||||
/// Write the extra class definitions.
|
||||
void writeDefTo(raw_indented_ostream &os,
|
||||
StringRef namePrefix) const override;
|
||||
|
||||
private:
|
||||
/// The string of the extra class declarations. It is re-indented before
|
||||
/// printed.
|
||||
StringRef extraClassDeclaration;
|
||||
/// The string of the extra class definitions. It is re-indented before
|
||||
/// printed.
|
||||
StringRef extraClassDefinition;
|
||||
};
|
||||
|
||||
/// A class used to emit C++ classes from Tablegen. Contains a list of public
|
||||
|
@ -235,6 +235,9 @@ public:
|
||||
// Returns this op's extra class declaration code.
|
||||
StringRef getExtraClassDeclaration() const;
|
||||
|
||||
// Returns this op's extra class definition code.
|
||||
StringRef getExtraClassDefinition() const;
|
||||
|
||||
// Returns the Tablegen definition this operator was constructed from.
|
||||
// TODO: do not expose the TableGen record, this is a temporary solution to
|
||||
// OpEmitter requiring a Record because Operator does not provide enough
|
||||
|
@ -260,6 +260,11 @@ void ExtraClassDeclaration::writeDeclTo(raw_indented_ostream &os) const {
|
||||
os.printReindented(extraClassDeclaration);
|
||||
}
|
||||
|
||||
void ExtraClassDeclaration::writeDefTo(raw_indented_ostream &os,
|
||||
StringRef namePrefix) const {
|
||||
os.printReindented(extraClassDefinition);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Class definitions
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -128,6 +128,13 @@ StringRef Operator::getExtraClassDeclaration() const {
|
||||
return def.getValueAsString(attr);
|
||||
}
|
||||
|
||||
StringRef Operator::getExtraClassDefinition() const {
|
||||
constexpr auto attr = "extraClassDefinition";
|
||||
if (def.isValueUnset(attr))
|
||||
return {};
|
||||
return def.getValueAsString(attr);
|
||||
}
|
||||
|
||||
const llvm::Record &Operator::getDef() const { return def; }
|
||||
|
||||
bool Operator::skipDefaultBuilders() const {
|
||||
|
@ -382,7 +382,10 @@ def ConversionCallOp : TEST_Op<"conversion_call_op",
|
||||
|
||||
let extraClassDeclaration = [{
|
||||
/// Return the callee of this operation.
|
||||
::mlir::CallInterfaceCallable getCallableForCallee() {
|
||||
::mlir::CallInterfaceCallable getCallableForCallee();
|
||||
}];
|
||||
let extraClassDefinition = [{
|
||||
::mlir::CallInterfaceCallable $cppClass::getCallableForCallee() {
|
||||
return (*this)->getAttrOfType<::mlir::SymbolRefAttr>("callee");
|
||||
}
|
||||
}];
|
||||
|
@ -15,8 +15,10 @@ using namespace mlir::tblgen;
|
||||
// OpClass definitions
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
OpClass::OpClass(StringRef name, StringRef extraClassDeclaration)
|
||||
OpClass::OpClass(StringRef name, StringRef extraClassDeclaration,
|
||||
std::string extraClassDefinition)
|
||||
: Class(name.str()), extraClassDeclaration(extraClassDeclaration),
|
||||
extraClassDefinition(std::move(extraClassDefinition)),
|
||||
parent(addParent("::mlir::Op")) {
|
||||
parent.addTemplateParam(getClassName().str());
|
||||
declare<VisibilityDeclaration>(Visibility::Public);
|
||||
@ -30,5 +32,5 @@ OpClass::OpClass(StringRef name, StringRef extraClassDeclaration)
|
||||
void OpClass::finalize() {
|
||||
Class::finalize();
|
||||
declare<VisibilityDeclaration>(Visibility::Public);
|
||||
declare<ExtraClassDeclaration>(extraClassDeclaration);
|
||||
declare<ExtraClassDeclaration>(extraClassDeclaration, extraClassDefinition);
|
||||
}
|
||||
|
@ -25,7 +25,8 @@ public:
|
||||
/// - inheritance of `print`
|
||||
/// - a type alias for the associated adaptor class
|
||||
///
|
||||
OpClass(StringRef name, StringRef extraClassDeclaration);
|
||||
OpClass(StringRef name, StringRef extraClassDeclaration,
|
||||
std::string extraClassDefinition);
|
||||
|
||||
/// Add an op trait.
|
||||
void addTrait(Twine trait) { parent.addTemplateParam(trait.str()); }
|
||||
@ -39,6 +40,8 @@ public:
|
||||
private:
|
||||
/// Hand-written extra class declarations.
|
||||
StringRef extraClassDeclaration;
|
||||
/// Hand-written extra class definitions.
|
||||
std::string extraClassDefinition;
|
||||
/// The parent class, which also contains the traits to be inherited.
|
||||
ParentClass &parent;
|
||||
};
|
||||
|
@ -557,10 +557,18 @@ static void genAttributeVerifier(
|
||||
}
|
||||
}
|
||||
|
||||
/// Op extra class definitions have a `$cppClass` substitution that is to be
|
||||
/// replaced by the C++ class name.
|
||||
static std::string formatExtraDefinitions(const Operator &op) {
|
||||
FmtContext ctx = FmtContext().addSubst("cppClass", op.getCppClassName());
|
||||
return tgfmt(op.getExtraClassDefinition(), &ctx).str();
|
||||
}
|
||||
|
||||
OpEmitter::OpEmitter(const Operator &op,
|
||||
const StaticVerifierFunctionEmitter &staticVerifierEmitter)
|
||||
: def(op.getDef()), op(op),
|
||||
opClass(op.getCppClassName(), op.getExtraClassDeclaration()),
|
||||
opClass(op.getCppClassName(), op.getExtraClassDeclaration(),
|
||||
formatExtraDefinitions(op)),
|
||||
staticVerifierEmitter(staticVerifierEmitter) {
|
||||
verifyCtx.withOp("(*this->getOperation())");
|
||||
verifyCtx.addSubst("_ctxt", "this->getOperation()->getContext()");
|
||||
|
Loading…
Reference in New Issue
Block a user