InterfaceMethod<"Prints the type name.",
"void", "printTypeC", (ins "Location":$loc)
>,
+ // It should be possible to use the interface type name as result type
+ // as well as in the implementation.
+ InterfaceMethod<"Prints the type name and returns the type as interface.",
+ "TestTypeInterface", "printTypeRet", (ins "Location":$loc),
+ [{}], /*defaultImplementation=*/[{
+ emitRemark(loc) << $_type << " - TestRet";
+ return $_type;
+ }]
+ >,
];
let extraClassDeclaration = [{
/// Prints the type name.
// DECL-LABEL: TestOpInterfaceInterfaceTraits
// DECL: class TestOpInterface : public ::mlir::OpInterface<TestOpInterface, detail::TestOpInterfaceInterfaceTraits>
+
// DECL: int foo(int input);
-// DECL-NOT: TestOpInterface
+// DECL: template<typename ConcreteOp>
+// DECL: int detail::TestOpInterfaceInterfaceTraits::Model<ConcreteOp>::foo
// OP_DECL-LABEL: class DeclareMethodsOp : public
// OP_DECL: int foo(int input);
void emitConceptDecl(Interface &interface);
void emitModelDecl(Interface &interface);
+ void emitModelMethodsDef(Interface &interface);
void emitTraitDecl(Interface &interface, StringRef interfaceName,
StringRef interfaceTraitsName);
void emitInterfaceDecl(Interface interface);
// Insert each of the virtual method overrides.
for (auto &method : interface.getMethods()) {
- emitCPPType(method.getReturnType(), os << " static ");
+ emitCPPType(method.getReturnType(), os << " static inline ");
emitMethodNameAndArgs(method, os, valueType,
/*addThisArg=*/!method.isStatic(),
/*addConst=*/false);
- os << " {\n ";
+ os << ";\n";
+ }
+ os << " };\n";
+}
+
+void InterfaceGenerator::emitModelMethodsDef(Interface &interface) {
+ for (auto &method : interface.getMethods()) {
+ os << "template<typename " << valueTemplate << ">\n";
+ emitCPPType(method.getReturnType(), os);
+ os << "detail::" << interface.getName() << "InterfaceTraits::Model<"
+ << valueTemplate << ">::";
+ emitMethodNameAndArgs(method, os, valueType,
+ /*addThisArg=*/!method.isStatic(),
+ /*addConst=*/false);
+ os << " {\n ";
// Check for a provided body to the function.
if (Optional<StringRef> body = method.getBody()) {
os << body->trim();
else
os << tblgen::tgfmt(body->trim(), &nonStaticMethodFmt);
- os << "\n }\n";
+ os << "\n}\n";
continue;
}
llvm::interleaveComma(
method.getArguments(), os,
[&](const InterfaceMethod::Argument &arg) { os << arg.name; });
- os << ");\n }\n";
+ os << ");\n}\n";
}
- os << " };\n";
}
void InterfaceGenerator::emitTraitDecl(Interface &interface,
StringRef interfaceName = interface.getName();
auto interfaceTraitsName = (interfaceName + "InterfaceTraits").str();
+ // Emit a forward declaration of the interface class so that it becomes usable
+ // in the signature of its methods.
+ os << "class " << interfaceName << ";\n";
+
// Emit the traits struct containing the concept and model declarations.
os << "namespace detail {\n"
<< "struct " << interfaceTraitsName << " {\n";
os << "};\n";
+ emitModelMethodsDef(interface);
+
for (StringRef ns : llvm::reverse(namespaces))
os << "} // namespace " << ns << "\n";
}