18#include <mlir/TableGen/GenInfo.h>
19#include <mlir/TableGen/Operator.h>
21#include <llvm/Support/CommandLine.h>
22#include <llvm/Support/FormatVariadic.h>
23#include <llvm/TableGen/Error.h>
24#include <llvm/TableGen/Record.h>
25#include <llvm/TableGen/TableGenBackend.h>
39 name.empty() ? llvm::formatv(
"Result{0}", resultIndex).str() :
toPascalCase(name);
43 name.empty() ? llvm::formatv(
"Region{0}", regionIndex).str() :
toPascalCase(name);
55 using HeaderGenerator::HeaderGenerator;
59 static constexpr char fmt[] = R
"(
61MLIR_CAPI_EXPORTED MlirOperation {0}{1}_{2}Build(MlirOpBuilder builder, MlirLocation location{3});
63 assert(!
className.empty() &&
"className must be set");
75 static constexpr char fmt[] = R
"(
77MLIR_CAPI_EXPORTED MlirValue {0}{1}_{2}Get{3}(MlirOperation op);
79 assert(!
className.empty() &&
"className must be set");
92 static constexpr char fmt[] = R
"(
94MLIR_CAPI_EXPORTED void {0}{1}_{2}Set{3}(MlirOperation op, MlirValue value);
96 assert(!
className.empty() &&
"className must be set");
109 static constexpr char fmt[] = R
"(
111MLIR_CAPI_EXPORTED intptr_t {0}{1}_{2}Get{3}Count(MlirOperation op);
114MLIR_CAPI_EXPORTED MlirValue {0}{1}_{2}Get{3}At(MlirOperation op, intptr_t index);
116 assert(!
className.empty() &&
"className must be set");
130 static constexpr char fmt[] = R
"(
132MLIR_CAPI_EXPORTED void {0}{1}_{2}Set{3}(MlirOperation op, intptr_t count, MlirValue const *values);
134 assert(!
className.empty() &&
"className must be set");
148 static constexpr char fmt[] = R
"(
152MLIR_CAPI_EXPORTED void {0}{1}_{2}Set{3}(MlirOperation op, intptr_t groupCount, MlirValueRange const *groups);
154 assert(!
className.empty() &&
"className must be set");
167 static constexpr char fmt[] = R
"(
169MLIR_CAPI_EXPORTED MlirAttribute {0}{1}_{2}Get{3}(MlirOperation op);
184 static constexpr char fmt[] = R
"(
186MLIR_CAPI_EXPORTED void {0}{1}_{2}Set{3}(MlirOperation op, MlirAttribute attr);
188 assert(!
className.empty() &&
"className must be set");
201 static constexpr char fmt[] = R
"(
203MLIR_CAPI_EXPORTED MlirValue {0}{1}_{2}Get{3}(MlirOperation op);
205 assert(!
className.empty() &&
"className must be set");
218 static constexpr char fmt[] = R
"(
220MLIR_CAPI_EXPORTED intptr_t {0}{1}_{2}Get{3}Count(MlirOperation op);
223MLIR_CAPI_EXPORTED MlirValue {0}{1}_{2}Get{3}At(MlirOperation op, intptr_t index);
225 assert(!
className.empty() &&
"className must be set");
238 static constexpr char fmt[] = R
"(
240MLIR_CAPI_EXPORTED MlirRegion {0}{1}_{2}Get{3}(MlirOperation op);
242 assert(!
className.empty() &&
"className must be set");
255 static constexpr char fmt[] = R
"(
257MLIR_CAPI_EXPORTED intptr_t {0}{1}_{2}Get{3}Count(MlirOperation op);
260MLIR_CAPI_EXPORTED MlirRegion {0}{1}_{2}Get{3}At(MlirOperation op, intptr_t index);
262 assert(!
className.empty() &&
"className must be set");
280static std::string generateCAPIBuildParams(
const Operator &op) {
283 llvm::raw_ostream &os,
const NamedTypeConstraint &result,
const std::string &resultName
285 if (result.isVariadic()) {
286 os << llvm::formatv(
", intptr_t {0}Size, MlirType const *{0}Types", resultName);
288 os << llvm::formatv(
", MlirType {0}Type", resultName);
291 void genOperand(llvm::raw_ostream &os,
const NamedTypeConstraint &operand)
override {
292 if (operand.isVariadic()) {
293 os << llvm::formatv(
", intptr_t {0}Size, MlirValue const *{0}", operand.name);
295 os << llvm::formatv(
", MlirValue {0}", operand.name);
298 void genAttribute(llvm::raw_ostream &os,
const NamedAttribute &attr)
override {
300 os << llvm::formatv(
", {0} {1}", attrType.value_or(
"MlirAttribute"), attr.name);
302 void genRegion(llvm::raw_ostream &os,
const mlir::tblgen::NamedRegion ®ion)
override {
303 if (region.isVariadic()) {
304 os << llvm::formatv(
", unsigned {0}Count", region.name);
307 } paramStringGenerator;
308 return paramStringGenerator.gen(op);
312static bool emitOpCAPIHeader(
const llvm::RecordKeeper &records, raw_ostream &os) {
313 emitSourceFileHeader(
"Op C API Declarations", os, records);
316 generator.genPrologue();
318 for (
const auto *def : records.getAllDerivedDefinitions(
"Op")) {
319 const Operator op(def);
320 const Dialect &dialect = op.getDialect();
327 generator.setNamespaceAndClassName(dialect, op.getCppClassName());
331 generator.genOpBuildDecl(generateCAPIBuildParams(op));
336 generator.genIsADecl();
340 for (
int i = 0, e = op.getNumOperands(); i < e; ++i) {
341 const auto &operand = op.getOperand(i);
342 generator.setOperandName(operand.name);
343 if (operand.isVariadic()) {
345 generator.genVariadicOperandGetterDecl();
348 if (operand.isVariadicOfVariadic()) {
349 generator.genVariadicOfVariadicOperandSetterDecl();
351 generator.genVariadicOperandSetterDecl();
356 generator.genOperandGetterDecl();
359 generator.genOperandSetterDecl();
365 for (
const auto &namedAttr : op.getAttributes()) {
366 generator.setAttributeName(namedAttr.name);
368 generator.genAttributeGetterDecl();
371 generator.genAttributeSetterDecl();
377 for (
int i = 0, e = op.getNumResults(); i < e; ++i) {
378 const auto &result = op.getResult(i);
379 generator.setResultName(result.name, i);
380 if (result.isVariadic()) {
381 generator.genVariadicResultGetterDecl();
383 generator.genResultGetterDecl();
390 for (
unsigned i = 0, e = op.getNumRegions(); i < e; ++i) {
391 const auto ®ion = op.getRegion(i);
392 generator.setRegionName(region.name, i);
393 if (region.isVariadic()) {
394 generator.genVariadicRegionGetterDecl();
396 generator.genRegionGetterDecl();
404 generator.genExtraMethod(method);
409 generator.genEpilogue();
415 using ImplementationGenerator::ImplementationGenerator;
432 const std::string &operationName,
const std::string ¶ms,
const std::string &assignments
434 static constexpr char fmt[] = R
"(
435MlirOperation {0}{1}_{2}Build(MlirOpBuilder builder, MlirLocation location{3}) {{
436 MlirOperationState state = mlirOperationStateGet(mlirStringRefCreateFromCString("{4}"), location);
438 return mlirOpBuilderInsert(builder, mlirOperationCreate(&state));
441 assert(!className.empty() && "className must be set");
454 static constexpr char fmt[] = R
"(
455MlirValue {0}{1}_{2}Get{3}(MlirOperation op) {{
456 auto range = llvm::cast<{2}>(unwrap(op)).getODSOperandIndexAndLength({4});
457 assert(range.second == 1 && "expected fixed operand segment size");
459 static_cast<uintptr_t>(range.first) <= static_cast<uintptr_t>(std::numeric_limits<intptr_t>::max()) &&
460 "operand index exceeds intptr_t range"
462 return mlirOperationGetOperand(op, static_cast<intptr_t>(range.first));
465 assert(!className.empty() && "className must be set");
478 static constexpr char fmt[] = R
"(
479void {0}{1}_{2}Set{3}(MlirOperation op, MlirValue value) {{
480 auto range = llvm::cast<{2}>(unwrap(op)).getODSOperandIndexAndLength({4});
481 assert(range.second == 1 && "expected fixed operand segment size");
483 static_cast<uintptr_t>(range.first) <= static_cast<uintptr_t>(std::numeric_limits<intptr_t>::max()) &&
484 "operand index exceeds intptr_t range"
486 mlirOperationSetOperand(op, static_cast<intptr_t>(range.first), value);
489 assert(!className.empty() && "className must be set");
502 static constexpr char fmt[] = R
"(
503intptr_t {0}{1}_{2}Get{3}Count(MlirOperation op) {{
504 auto range = llvm::cast<{2}>(unwrap(op)).getODSOperandIndexAndLength({4});
508MlirValue {0}{1}_{2}Get{3}At(MlirOperation op, intptr_t index) {{
509 auto range = llvm::cast<{2}>(unwrap(op)).getODSOperandIndexAndLength({4});
510 assert(index >= 0 && index < range.second && "variadic operand index out of range");
512 static_cast<uintptr_t>(range.first) <= static_cast<uintptr_t>(std::numeric_limits<intptr_t>::max()) &&
513 "operand index exceeds intptr_t range"
515 return mlirOperationGetOperand(op, static_cast<intptr_t>(range.first) + index);
518 assert(!className.empty() && "className must be set");
533 static constexpr char fmt[] = R
"(
534void {0}{1}_{2}Set{3}(MlirOperation op, intptr_t count, MlirValue const *values) {{
537 ::llvm::SmallVector<::mlir::Value> vals;
538 vals.reserve(static_cast<size_t>(count));
539 for (intptr_t i = 0; i < count; ++i)
540 vals.push_back(unwrap(values[i]));
541 ::llvm::cast<{2}>(unwrap(op)).get{3}Mutable().assign(vals);
544 assert(!className.empty() && "className must be set");
560 static constexpr char fmt[] = R
"(
561void {0}{1}_{2}Set{3}(MlirOperation op, intptr_t groupCount, MlirValueRange const *groups) {{
565 ::llvm::SmallVector<::mlir::Value> vals;
566 for (intptr_t g = 0; g < groupCount; ++g) {{
567 assert(groups[g].size >= 0 && "group size must be non-negative");
568 for (intptr_t i = 0; i < groups[g].size; ++i) {{
569 vals.push_back(unwrap(groups[g].values[i]));
572 ::llvm::cast<{2}>(unwrap(op)).get{3}Mutable().join().assign(vals);
574 ::llvm::SmallVector<int32_t> newGroupSizes;
575 newGroupSizes.reserve(static_cast<size_t>(groupCount));
576 for (intptr_t g = 0; g < groupCount; ++g) {{
578 groups[g].size <= static_cast<intptr_t>(std::numeric_limits<int32_t>::max()) &&
579 "group size exceeds int32_t range"
581 newGroupSizes.push_back(static_cast<int32_t>(groups[g].size));
583 MlirContext ctx = mlirOperationGetContext(op);
585 newGroupSizes.size() <= static_cast<size_t>(std::numeric_limits<intptr_t>::max()) &&
586 "group count exceeds intptr_t range"
588 mlirOperationSetAttributeByName(
589 op, mlirStringRefCreateFromCString("{4}"),
590 mlirDenseI32ArrayGet(ctx, static_cast<intptr_t>(newGroupSizes.size()), newGroupSizes.data())
594 assert(!className.empty() && "className must be set");
607 static constexpr char fmt[] = R
"(
608MlirAttribute {0}{1}_{2}Get{3}(MlirOperation op) {{
609 return mlirOperationGetAttributeByName(op, mlirStringRefCreateFromCString("{4}"));
612 assert(!className.empty() && "className must be set");
625 static constexpr char fmt[] = R
"(
626void {0}{1}_{2}Set{3}(MlirOperation op, MlirAttribute attr) {{
627 mlirOperationSetAttributeByName(op, mlirStringRefCreateFromCString("{4}"), attr);
630 assert(!className.empty() && "className must be set");
643 static constexpr char fmt[] = R
"(
644MlirValue {0}{1}_{2}Get{3}(MlirOperation op) {{
645 return mlirOperationGetResult(op, {4});
648 assert(!className.empty() && "className must be set");
661 static constexpr char fmt[] = R
"(
662intptr_t {0}{1}_{2}Get{3}Count(MlirOperation op) {{
663 intptr_t count = mlirOperationGetNumResults(op);
664 assert(count >= {4} && "result count less than start index");
668MlirValue {0}{1}_{2}Get{3}At(MlirOperation op, intptr_t index) {{
669 return mlirOperationGetResult(op, {4} + index);
672 assert(!className.empty() && "className must be set");
685 static constexpr char fmt[] = R
"(
686MlirRegion {0}{1}_{2}Get{3}(MlirOperation op) {{
687 return mlirOperationGetRegion(op, {4});
690 assert(!className.empty() && "className must be set");
703 static constexpr char fmt[] = R
"(
704intptr_t {0}{1}_{2}Get{3}Count(MlirOperation op) {{
705 intptr_t count = mlirOperationGetNumRegions(op);
706 assert(count >= {4} && "region count less than start index");
710MlirRegion {0}{1}_{2}Get{3}At(MlirOperation op, intptr_t index) {{
711 return mlirOperationGetRegion(op, {4} + index);
714 assert(!className.empty() && "className must be set");
732static std::string generateCAPIAssignments(
const Operator &op) {
739 void genResultInferred(llvm::raw_ostream &os)
override {
740 os <<
" mlirOperationStateEnableResultTypeInference(&state);\n";
743 llvm::raw_ostream &os,
const NamedTypeConstraint &result,
const std::string &resultName
745 if (result.isVariadic()) {
747 " mlirOperationStateAddResults(&state, {0}Size, {0}Types);\n", resultName
750 os << llvm::formatv(
" mlirOperationStateAddResults(&state, 1, &{0}Type);\n", resultName);
753 void genOperand(llvm::raw_ostream &os,
const NamedTypeConstraint &operand)
override {
754 if (operand.isVariadic()) {
756 " mlirOperationStateAddOperands(&state, {0}Size, {0});\n", operand.name
759 os << llvm::formatv(
" mlirOperationStateAddOperands(&state, 1, &{0});\n", operand.name);
762 void genAttributesPrefix(llvm::raw_ostream &os,
const mlir::tblgen::Operator &op)
override {
763 os <<
" MlirContext ctx = mlirOpBuilderGetContext(builder);\n";
764 os <<
" llvm::SmallVector<MlirNamedAttribute, " << op.getNumAttributes()
765 <<
"> attributes;\n";
767 void genAttribute(llvm::raw_ostream &os,
const NamedAttribute &attr)
override {
772 std::string attrValue;
773 if (attrType.has_value() && attrType.value() ==
"MlirIdentifier") {
774 attrValue =
"reinterpret_cast<MlirAttribute&>(" + attr.name.str() +
")";
776 attrValue = attr.name.str();
779 os <<
" if (!mlirAttributeIsNull(" << attrValue <<
")) {\n";
780 os <<
" attributes.push_back(mlirNamedAttributeGet(mlirIdentifierGet(ctx, "
781 <<
"mlirStringRefCreateFromCString(\"" << attr.name <<
"\")), " << attrValue <<
"));\n";
785 genAttributesSuffix(llvm::raw_ostream &os,
const mlir::tblgen::Operator & )
override {
786 os <<
" mlirOperationStateAddAttributes(&state, attributes.size(), attributes.data());\n";
788 void genRegionsPrefix(llvm::raw_ostream &os,
const mlir::tblgen::Operator &op)
override {
789 os <<
" llvm::SmallVector<MlirRegion, " << op.getNumRegions() <<
"> regions;\n";
791 void genRegion(llvm::raw_ostream &os,
const mlir::tblgen::NamedRegion ®ion)
override {
792 if (region.isVariadic()) {
793 os << llvm::formatv(
" for (unsigned i = 0; i < {0}Count; ++i)\n ", region.name);
795 os <<
" regions.push_back(mlirRegionCreate());\n";
797 void genRegionsSuffix(llvm::raw_ostream &os,
const mlir::tblgen::Operator & )
override {
798 os <<
" mlirOperationStateAddOwnedRegions(&state, regions.size(), regions.data());\n";
800 } paramStringGenerator;
801 return paramStringGenerator.gen(op);
805static bool emitOpCAPIImpl(
const llvm::RecordKeeper &records, raw_ostream &os) {
806 emitSourceFileHeader(
"Op C API Definitions", os, records);
809 generator.genPrologue();
811 for (
const auto *def : records.getAllDerivedDefinitions(
"Op")) {
812 const Operator op(def);
813 const Dialect &dialect = op.getDialect();
820 generator.setNamespaceAndClassName(dialect, op.getCppClassName());
824 std::string assignments = generateCAPIAssignments(op);
825 generator.genOpBuildImpl(op.getOperationName(), generateCAPIBuildParams(op), assignments);
830 generator.genIsAImpl();
834 for (
int i = 0, e = op.getNumOperands(); i < e; ++i) {
835 const auto &operand = op.getOperand(i);
836 generator.setOperandName(operand.name);
837 if (operand.isVariadic()) {
839 generator.genVariadicOperandGetterImpl(i);
842 if (operand.isVariadicOfVariadic()) {
843 generator.genVariadicOfVariadicOperandSetterImpl(
844 operand.constraint.getVariadicOfVariadicSegmentSizeAttr()
847 generator.genVariadicOperandSetterImpl();
852 generator.genOperandGetterImpl(i);
855 generator.genOperandSetterImpl(i);
861 for (
const auto &namedAttr : op.getAttributes()) {
862 generator.setAttributeName(namedAttr.name);
864 generator.genAttributeGetterImpl(namedAttr.name);
867 generator.genAttributeSetterImpl(namedAttr.name);
873 for (
int i = 0, e = op.getNumResults(); i < e; ++i) {
874 const auto &result = op.getResult(i);
875 generator.setResultName(result.name, i);
876 if (result.isVariadic()) {
877 generator.genVariadicResultGetterImpl(i);
879 generator.genResultGetterImpl(i);
886 for (
unsigned i = 0, e = op.getNumRegions(); i < e; ++i) {
887 const auto ®ion = op.getRegion(i);
888 generator.setRegionName(region.name, i);
889 if (region.isVariadic()) {
890 generator.genVariadicRegionGetterImpl(i);
892 generator.genRegionGetterImpl(i);
900 generator.genExtraMethod(method);
909 static mlir::GenRegistration genOpCAPIHeader(
910 "gen-op-capi-header",
"Generate operation C API header", &emitOpCAPIHeader
913 static mlir::GenRegistration genOpCAPIImpl(
914 "gen-op-capi-impl",
"Generate operation C API implementation", &emitOpCAPIImpl
llvm::cl::opt< bool > & getGenOpOperandGetters()
Return the GenOpOperandGetters option, registering it on first access.
std::optional< std::string > tryCppTypeToCapiType(StringRef cppType)
Convert C++ type to MLIR C API type.
llvm::cl::opt< std::string > & getFunctionPrefix()
Return the FunctionPrefix option, registering it on first access.
llvm::cl::opt< bool > & getGenOpRegionGetters()
Return the GenOpRegionGetters option, registering it on first access.
llvm::cl::opt< bool > & getGenOpResultGetters()
Return the GenOpResultGetters option, registering it on first access.
llvm::cl::opt< std::string > & getDialectName()
Return the DialectName option, registering it on first access.
llvm::cl::opt< bool > & getGenOpAttributeSetters()
Return the GenOpAttributeSetters option, registering it on first access.
llvm::cl::opt< bool > & getGenOpBuild()
Return the GenOpBuild option, registering it on first access.
llvm::cl::opt< bool > & getGenOpAttributeGetters()
Return the GenOpAttributeGetters option, registering it on first access.
llvm::cl::opt< bool > & getGenExtraClassMethods()
Return the GenExtraClassMethods option, registering it on first access.
llvm::cl::opt< bool > & getGenIsA()
Return the GenIsA option, registering it on first access.
llvm::cl::opt< bool > & getGenOpOperandSetters()
Return the GenOpOperandSetters option, registering it on first access.
llvm::SmallVector< ExtraMethod > getCAPIExposedOpMethods(const mlir::tblgen::Operator &op)
Return public operation methods explicitly requested by DeclareOpInterfaceMethods traits and declared...
std::string toPascalCase(mlir::StringRef str)
Convert names separated by underscore or colon to PascalCase.
void registerOpCAPIGenerators()
Register the operation C API generators before command-line parsing.
Helper struct to generate a string from operation operand, attribute, and result pieces.
mlir::StringRef className
mlir::StringRef dialectNamespace
std::string dialectNameCapitalized
Generator for common C implementation file elements.
Common between header and implementation generators for operations.
void setAttributeName(mlir::StringRef name)
void setResultName(mlir::StringRef name, int resultIndex)
void setOperandName(mlir::StringRef name)
std::string resultNameCapitalized
std::string attrNameCapitalized
std::string operandNameCapitalized
void setRegionName(mlir::StringRef name, unsigned regionIndex)
std::string regionNameCapitalized
Generator for operation C implementation files.
void genOperandGetterImpl(int index) const
void genRegionGetterImpl(unsigned index) const
void genAttributeGetterImpl(mlir::StringRef attrName) const
void genVariadicRegionGetterImpl(unsigned startIdx) const
void genVariadicResultGetterImpl(int startIdx) const
void genVariadicOfVariadicOperandSetterImpl(mlir::StringRef segSizeAttrName) const
void genOpBuildImpl(const std::string &operationName, const std::string ¶ms, const std::string &assignments) const
Generate operation "Build" function implementation.
void genResultGetterImpl(int index) const
~OpImplementationGenerator() override=default
void genOperandSetterImpl(int index) const
void genVariadicOperandGetterImpl(int index) const
void genPrologue() const override
void genAttributeSetterImpl(mlir::StringRef attrName) const
void genVariadicOperandSetterImpl() const