Skip to content

Commit 14c9207

Browse files
committed
[mlir] support interfaces in Python bindings
Introduce the initial support for operation interfaces in C API and Python bindings. Interfaces are a key component of MLIR's extensibility and should be available in bindings to make use of full potential of MLIR. This initial implementation exposes InferTypeOpInterface all the way to the Python bindings since it can be later used to simplify the operation construction methods by inferring their return types instead of requiring the user to do so. The general infrastructure for binding interfaces is defined and InferTypeOpInterface can be used as an example for binding other interfaces. Reviewed By: gysit Differential Revision: https://reviews.llvm.org/D111656
1 parent 1f49b71 commit 14c9207

File tree

25 files changed

+778
-41
lines changed

25 files changed

+778
-41
lines changed

mlir/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ add_subdirectory(include/mlir)
123123
add_subdirectory(lib)
124124
# C API needs all dialects for registration, but should be built before tests.
125125
add_subdirectory(lib/CAPI)
126+
126127
if (MLIR_INCLUDE_TESTS)
127128
add_definitions(-DMLIR_INCLUDE_TESTS)
128129
add_custom_target(MLIRUnitTests)

mlir/docs/Bindings/Python.md

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -536,6 +536,68 @@ except ValueError:
536536
concrete = OpResult(value)
537537
```
538538

539+
#### Interfaces
540+
541+
MLIR interfaces are a mechanism to interact with the IR without needing to know
542+
specific types of operations but only some of their aspects. Operation
543+
interfaces are available as Python classes with the same name as their C++
544+
counterparts. Objects of these classes can be constructed from either:
545+
546+
- an object of the `Operation` class or of any `OpView` subclass; in this
547+
case, all interface methods are available;
548+
- a subclass of `OpView` and a context; in this case, only the *static*
549+
interface methods are available as there is no associated operation.
550+
551+
In both cases, construction of the interface raises a `ValueError` if the
552+
operation class does not implement the interface in the given context (or, for
553+
operations, in the context that the operation is defined in). Similarly to
554+
attributes and types, the MLIR context may be set up by a surrounding context
555+
manager.
556+
557+
```python
558+
from mlir.ir import Context, InferTypeOpInterface
559+
560+
with Context():
561+
op = <...>
562+
563+
# Attempt to cast the operation into an interface.
564+
try:
565+
iface = InferTypeOpInterface(op)
566+
except ValueError:
567+
print("Operation does not implement InferTypeOpInterface.")
568+
raise
569+
570+
# All methods are available on interface objects constructed from an Operation
571+
# or an OpView.
572+
iface.someInstanceMethod()
573+
574+
# An interface object can also be constructed given an OpView subclass. It
575+
# also needs a context in which the interface will be looked up. The context
576+
# can be provided explicitly or set up by the surrounding context manager.
577+
try:
578+
iface = InferTypeOpInterface(some_dialect.SomeOp)
579+
except ValueError:
580+
print("SomeOp does not implement InferTypeOpInterface.")
581+
raise
582+
583+
# Calling an instance method on an interface object constructed from a class
584+
# will raise TypeError.
585+
try:
586+
iface.someInstanceMethod()
587+
except TypeError:
588+
pass
589+
590+
# One can still call static interface methods though.
591+
iface.inferOpReturnTypes(<...>)
592+
```
593+
594+
If an interface object was constructed from an `Operation` or an `OpView`, they
595+
are available as `.operation` and `.opview` properties of the interface object,
596+
respectively.
597+
598+
Only a subset of operation interfaces are currently provided in Python bindings.
599+
Attribute and type interfaces are not yet available in Python bindings.
600+
539601
### Creating IR Objects
540602

541603
Python bindings also support IR creation and manipulation.

mlir/docs/CAPI.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,3 +194,23 @@ counterparts. `wrap` converts a C++ class into a C structure and `unwrap` does
194194
the inverse conversion. Once the C++ object is available, the API implementation
195195
should rely on `isa` to implement `mlirXIsAY` and is expected to use `cast`
196196
inside other API calls.
197+
198+
### Extensions for Interfaces
199+
200+
Interfaces can follow the example of IR interfaces and should be placed in the
201+
appropriate library (e.g., common interfaces in `mlir-c/Interfaces` and
202+
dialect-specific interfaces in their dialect library). Similarly to other type
203+
hierarchies, interfaces are not expected to have objects of their own type and
204+
instead operate on top-level objects: `MlirAttribute`, `MlirOperation` and
205+
`MlirType`. Static interface methods are expected to take as leading argument a
206+
canonical identifier of the class, `MlirStringRef` with the name for operations
207+
and `MlirTypeID` for attributes and types, followed by `MlirContext` in which
208+
the interfaces are registered.
209+
210+
Individual interfaces are expected provide a `mlir<InterfaceName>TypeID()`
211+
function that can be used to check whether an object or a class implements this
212+
interface using `mlir<Attribute/Operation/Type>ImplementsInterface` or
213+
`mlir<Attribute/Operation?Type>ImplementsInterfaceStatic` functions,
214+
respectively. Rationale: C++ `isa` only works when an object exists, static
215+
methods are usually dispatched to using templates; lookup by `TypeID` in
216+
`MLIRContext` works even without an object.

mlir/include/mlir-c/Interfaces.h

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
//===-- mlir-c/Interfaces.h - C API to Core MLIR IR interfaces ----*- C -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM
4+
// Exceptions.
5+
// See https://llvm.org/LICENSE.txt for license information.
6+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
//
8+
//===----------------------------------------------------------------------===//
9+
//
10+
// This header declares the C interface to MLIR interface classes. It is
11+
// intended to contain interfaces defined in lib/Interfaces.
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
#ifndef MLIR_C_DIALECT_H
16+
#define MLIR_C_DIALECT_H
17+
18+
#include "mlir-c/IR.h"
19+
#include "mlir-c/Support.h"
20+
21+
#ifdef __cplusplus
22+
extern "C" {
23+
#endif
24+
25+
/// Returns `true` if the given operation implements an interface identified by
26+
/// its TypeID.
27+
MLIR_CAPI_EXPORTED bool
28+
mlirOperationImplementsInterface(MlirOperation operation,
29+
MlirTypeID interfaceTypeID);
30+
31+
/// Returns `true` if the operation identified by its canonical string name
32+
/// implements the interface identified by its TypeID in the given context.
33+
/// Note that interfaces may be attached to operations in some contexts and not
34+
/// others.
35+
MLIR_CAPI_EXPORTED bool
36+
mlirOperationImplementsInterfaceStatic(MlirStringRef operationName,
37+
MlirContext context,
38+
MlirTypeID interfaceTypeID);
39+
40+
//===----------------------------------------------------------------------===//
41+
// InferTypeOpInterface.
42+
//===----------------------------------------------------------------------===//
43+
44+
/// Returns the interface TypeID of the InferTypeOpInterface.
45+
MLIR_CAPI_EXPORTED MlirTypeID mlirInferTypeOpInterfaceTypeID();
46+
47+
/// These callbacks are used to return multiple types from functions while
48+
/// transferring ownerhsip to the caller. The first argument is the number of
49+
/// consecutive elements pointed to by the second argument. The third argument
50+
/// is an opaque pointer forwarded to the callback by the caller.
51+
typedef void (*MlirTypesCallback)(intptr_t, MlirType *, void *);
52+
53+
/// Infers the return types of the operation identified by its canonical given
54+
/// the arguments that will be supplied to its generic builder. Calls `callback`
55+
/// with the types of inferred arguments, potentially several times, on success.
56+
/// Returns failure otherwise.
57+
MLIR_CAPI_EXPORTED MlirLogicalResult mlirInferTypeOpInterfaceInferReturnTypes(
58+
MlirStringRef opName, MlirContext context, MlirLocation location,
59+
intptr_t nOperands, MlirValue *operands, MlirAttribute attributes,
60+
intptr_t nRegions, MlirRegion *regions, MlirTypesCallback callback,
61+
void *userData);
62+
63+
#ifdef __cplusplus
64+
}
65+
#endif
66+
67+
#endif // MLIR_C_DIALECT_H
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//===- Interfaces.h - C API Utils for MLIR interfaces -----------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This file contains declarations of implementation details of the C API for
10+
// MLIR interface classes. This file should not be included from C++ code other
11+
// than C API implementation nor from C code.
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
#ifndef MLIR_CAPI_INTERFACES_H
16+
#define MLIR_CAPI_INTERFACES_H
17+
18+
#endif // MLIR_CAPI_INTERFACES_H

0 commit comments

Comments
 (0)