Commit Graph

70 Commits

Author SHA1 Message Date
kweisamx c84b53ca9b [mlir] Add Python binding for MLIR Dict Attribute
Reviewed By: mehdi_amini

Differential Revision: https://reviews.llvm.org/D93004
2020-12-13 04:30:35 +00:00
Mehdi Amini aadcb26ee1 Store a MlirIdentifier instead of a MlirStringRef in MlirNameAttribute
This mirror the C++ API for NamedAttribute, and has the advantage or
internalizing earlier in the Context and not requiring the caller to
keep the StringRef alive beyong this call.

Differential Revision: https://reviews.llvm.org/D93133
2020-12-11 22:38:48 +00:00
Mehdi Amini 285c0aa262 Add MLIR Python binding for Array Attribute
Differential Revision: https://reviews.llvm.org/D92948
2020-12-10 20:51:34 +00:00
Mehdi Amini ac6ada4d3e Fix MLIR Python bindings build after changes to the C API to use StringRef (NFC) 2020-12-09 03:27:37 +00:00
Mehdi Amini e56f398dd3 Add Python binding for MLIR Type Attribute
Differential Revision: https://reviews.llvm.org/D92711
2020-12-07 23:06:58 +00:00
Mehdi Amini e15ae454b4 Customize exception thrown from mlir.Operation.create() python bindings
The default exception handling isn't very user friendly and does not
point accurately to the issue. Instead we can indicate which of the
operands isn't valid and provide contextual information in the error
message.

Differential Revision: https://reviews.llvm.org/D92710
2020-12-07 23:06:58 +00:00
River Riddle c7cae0e4fa [mlir][Attributes][NFC] Move all builtin Attribute classes to BuiltinAttributes.h
This mirrors the file structure of Types.

Differential Revision: https://reviews.llvm.org/D92499
2020-12-03 18:02:11 -08:00
River Riddle 09f7a55fad [mlir][Types][NFC] Move all of the builtin Type classes to BuiltinTypes.h
This is part of a larger refactoring the better congregates the builtin structures under the BuiltinDialect. This also removes the problematic "standard" naming that clashes with the "standard" dialect, which is not defined within IR/. A temporary forward is placed in StandardTypes.h to allow time for downstream users to replaced references.

Differential Revision: https://reviews.llvm.org/D92435
2020-12-03 18:02:10 -08:00
Mehdi Amini 1c2159494d Use the generic form when printing from the python bindings and the verifier fails
This reduces the chances of segfault. While it is a good practice to ensure
robust custom printers, it is unfortunately common to have them crash on
invalid input.

Reviewed By: stellaraccident

Differential Revision: https://reviews.llvm.org/D92536
2020-12-03 18:45:00 +00:00
Stella Laurenzo 62195b7548 [mlir][CAPI] Convert the rest of the API int -> bool.
* Follows on https://reviews.llvm.org/D92193
* I had a mid-air collision with some additional occurrences and then noticed that there were a lot more. Think I got them all.

Differential Revision: https://reviews.llvm.org/D92292
2020-11-29 20:36:42 -08:00
Stella Laurenzo ba0fe76b7e [mlir][Python] Add an Operation.result property.
* If ODS redefines this, it is fine, but I have found this accessor to be universally useful in the old npcomp bindings and I'm closing gaps that will let me switch.

Differential Revision: https://reviews.llvm.org/D92287
2020-11-29 18:09:07 -08:00
Stella Laurenzo bd2083c2fa [mlir][Python] Python API cleanups and additions found during code audit.
* Add capsule get/create for Attribute and Type, which already had capsule interop defined.
* Add capsule interop and get/create for Location.
* Add Location __eq__.
* Use get() and implicit cast to go from PyAttribute, PyType, PyLocation to MlirAttribute, MlirType, MlirLocation (bundled with this change because I didn't want to continue the pattern one more time).

Differential Revision: https://reviews.llvm.org/D92283
2020-11-29 18:09:07 -08:00
zhanghb97 5f0c1e3806 [mlir][Python] Sync Python bindings with C API MlirStringRef modification.
MLIR C API use the `MlirStringRef` instead of `const char *` for the string type now. This patch sync the Python bindings with the C API modification.

Differential Revision: https://reviews.llvm.org/D92007
2020-11-24 19:33:48 +00:00
Alex Zinenko ee6255d207 [mlir] move lib/Bindings/Python/Attributes.td to include/mlir/Bindings/Python
This file is intended to be included by other files, including
out-of-tree dialects, and makes more sense in `include` than in `lib`.

Depends On D91652

Reviewed By: mehdi_amini

Differential Revision: https://reviews.llvm.org/D91961
2020-11-24 09:19:01 +01:00
Alex Zinenko 029e199dbf [mlir] Make attributes mutable in Python bindings
Attributes represent additional data about an operation and are intended to be
modifiable during the lifetime of the operation. In the dialect-specific Python
bindings, attributes are exposed as properties on the operation class. Allow
for assigning values to these properties. Also support creating new and
deleting existing attributes through the generic "attributes" property of an
operation. Any validity checking must be performed by the op verifier after the
mutation, similarly to C++. Operations are not invalidated in the process: no
dangling pointers can be created as all attributes are owned by the context and
will remain live even if they are not used in any operation.

Introduce a Python Test dialect by analogy with the Test dialect and to avoid
polluting the latter with Python-specific constructs. Use this dialect to
implement a test for the attribute access and mutation API.

Reviewed By: stellaraccident, mehdi_amini

Differential Revision: https://reviews.llvm.org/D91652
2020-11-24 09:16:25 +01:00
zhanghb97 77133b29b9 [mlir] Get array from the dense elements attribute with buffer protocol.
- Add `mlirElementsAttrGetType` C API.
- Add `def_buffer` binding to PyDenseElementsAttribute.
- Implement the protocol to access the buffer.

Differential Revision: https://reviews.llvm.org/D91021
2020-11-18 15:50:59 +08:00
Stella Laurenzo 989b194429 [mlir][Python] Make DenseElementsAttr loading be int size agnostic.
* I had missed the note about "Standard size" in the docs. On Windows, the 'l' types are 32bit.
* This fixes the only failing MLIR-Python test on Windows.

Differential Revision: https://reviews.llvm.org/D91283
2020-11-17 21:50:44 -08:00
Alex Zinenko f3dab16dc7 [mlir] Add a _get_default_loc_context utility to Python bindings
This utility function is helpful for dialect-specific builders that need
to access the context through location, and the location itself may be
either provided as an argument or expected to be recovered from the
implicit location stack.

Reviewed By: stellaraccident

Differential Revision: https://reviews.llvm.org/D91623
2020-11-17 17:55:47 +01:00
Alex Zinenko c5a6712f8c [mlir] Add basic support for attributes in ODS-generated Python bindings
In ODS, attributes of an operation can be provided as a part of the "arguments"
field, together with operands. Such attributes are accepted by the op builder
and have accessors generated.

Implement similar functionality for ODS-generated op-specific Python bindings:
the `__init__` method now accepts arguments together with operands, in the same
order as in the ODS `arguments` field; the instance properties are introduced
to OpView classes to access the attributes.

This initial implementation accepts and returns instances of the corresponding
attribute class, and not the underlying values since the mapping scheme of the
value types between C++, C and Python is not yet clear. Default-valued
attributes are not supported as that would require Python to be able to parse
C++ literals.

Since attributes in ODS are tightely related to the actual C++ type system,
provide a separate Tablegen file with the mapping between ODS storage type for
attributes (typically, the underlying C++ attribute class), and the
corresponding class name. So far, this might look unnecessary since all names
match exactly, but this is not necessarily the cases for non-standard,
out-of-tree attributes, which may also be placed in non-default namespaces or
Python modules. This also allows out-of-tree users to generate Python bindings
without having to modify the bindings generator itself. Storage type was
preferred over the Tablegen "def" of the attribute class because ODS
essentially encodes attribute _constraints_ rather than classes, e.g. there may
be many Tablegen "def"s in the ODS that correspond to the same attribute type
with additional constraints

The presence of the explicit mapping requires the change in the .td file
structure: instead of just calling the bindings generator directly on the main
ODS file of the dialect, it becomes necessary to create a new file that
includes the main ODS file of the dialect and provides the mapping for
attribute types. Arguably, this approach offers better separability of the
Python bindings in the build system as the main dialect no longer needs to know
that it is being processed by the bindings generator.

Reviewed By: stellaraccident

Differential Revision: https://reviews.llvm.org/D91542
2020-11-17 11:47:37 +01:00
Stella Laurenzo 4726a402a3 [mlir][Python] Fix 'unreferenced local variable' warning on MSVC.
Differential Revision: https://reviews.llvm.org/D91282
2020-11-12 13:34:57 -08:00
Stella Laurenzo 5fef6ce0cc [mlir][Python] Allow PassManager to interop with the capsule APIs.
* Used in npcomp to cast Python objects via the C-API.

Differential Revision: https://reviews.llvm.org/D91232
2020-11-11 10:37:21 -08:00
Stella Laurenzo 99b1c42fd3 [mlir][Python] Add Windows DLL loader to get python extensions working there.
Differential Revision: https://reviews.llvm.org/D90958
2020-11-11 09:54:47 -08:00
Mehdi Amini 6cb1c0cae0 Add Python binding to run a PassManager on a MLIR Module
Reviewed By: ftynse, stellaraccident

Differential Revision: https://reviews.llvm.org/D90823
2020-11-10 20:06:23 +00:00
Mehdi Amini dc43f78565 Add basic Python bindings for the PassManager and bind libTransforms
This only exposes the ability to round-trip a textual pipeline at the
moment.
To exercise it, we also bind the libTransforms in a new Python extension. This
does not include any interesting bindings, but it includes all the
mechanism to add separate native extensions and load them dynamically.
As such passes in libTransforms are only registered after `import
mlir.transforms`.
To support this global registration, the TableGen backend is also
extended to bind to the C API the group registration for passes.

Reviewed By: stellaraccident

Differential Revision: https://reviews.llvm.org/D90819
2020-11-10 19:55:21 +00:00
Alex Zinenko fd407e1f1e [mlir] ODS-backed python binding generator for custom op classes
Introduce an ODS/Tablegen backend producing Op wrappers for Python bindings
based on the ODS operation definition. Usage:

  mlir-tblgen -gen-python-op-bindings -Iinclude <path/to/Ops.td> \
              -bind-dialect=<dialect-name>

Reviewed By: mehdi_amini

Differential Revision: https://reviews.llvm.org/D90960
2020-11-10 10:58:29 +01:00
Alex Zinenko 6c7e6b2c9a [mlir] Support slicing for operands in results in Python bindings
Slicing, that is element access with `[being🔚step]` structure, is
a common Python idiom for sequence-like containers. It is also necessary
to support custom accessor for operations with variadic operands and
results (an operation an return a slice of its operands that correspond
to the given variadic group).

Add generic utility to support slicing in Python bindings and use it
for operation operands and results.

Depends On D90923

Reviewed By: stellaraccident, mehdi_amini

Differential Revision: https://reviews.llvm.org/D90936
2020-11-10 10:46:21 +01:00
Alex Zinenko 4669ea3bd8 [mlir] Add initial Python bindings for DenseInt/FPElementsAttr
Enumerating elements in these classes is necessary to enable custom
operand accessors for variadic operands.

Depends On D90919

Reviewed By: stellaraccident

Differential Revision: https://reviews.llvm.org/D90923
2020-11-09 15:23:54 +01:00
Alex Zinenko c3a6e7c9b7 [mlir] Expose operation attributes to Python bindings
Operations in a MLIR have a dictionary of attributes attached. Expose
those to Python bindings through a pseudo-container that can be indexed
either by attribute name, producing a PyAttribute, or by a contiguous
index for enumeration purposes, producing a PyNamedAttribute.

Depends On D90917

Reviewed By: stellaraccident

Differential Revision: https://reviews.llvm.org/D90919
2020-11-09 14:59:56 +01:00
Stella Laurenzo 08c1a0dda4 [mlir][CAPI] Proposal: Always building a libMLIRPublicAPI.so (re-apply).
Re-applies the reverted https://reviews.llvm.org/D90824 now that the link issue on BFD has been resolved.

This reverts commit bb9b5d3971.

Differential Revision: https://reviews.llvm.org/D91044
2020-11-08 16:57:51 -08:00
Alex Zinenko b9c353fabb [mlir] Use PyValue instead of PyOpResult in Python operand container
The PyOpOperands container was erroneously constructing objects for
individual operands as PyOpResult. Operands in fact are just values,
which may or may not be results of another operation. The code would
eventually crash if the operand was a block argument. Add a test that
exercises the behavior that previously led to crashes.

Reviewed By: stellaraccident

Differential Revision: https://reviews.llvm.org/D90917
2020-11-06 19:02:35 +01:00
Alex Zinenko bb9b5d3971 Revert "[mlir][CAPI] Proposal: Always building a libMLIRPublicAPI.so."
This reverts commit 80fe2f61fa.

Broke linkage with GNU ld. See original review thread for more details.
2020-11-06 18:59:58 +01:00
Stella Laurenzo 80fe2f61fa [mlir][CAPI] Proposal: Always building a libMLIRPublicAPI.so.
We were discussing on discord regarding the need for extension-based systems like Python to dynamically link against MLIR (or else you can only have one extension that depends on it). Currently, when I set that up, I piggy-backed off of the flag that enables build libLLVM.so and libMLIR.so and depended on libMLIR.so from the python extension if shared library building was enabled. However, this is less than ideal.

In the current setup, libMLIR.so exports both all symbols from the C++ API and the C-API. The former is a kitchen sink and the latter is curated. We should be splitting them and for things that are properly factored to depend on the C-API, they should have the option to *only* depend on the C-API, and we should build that shared library no matter what. Its presence isn't just an optimization: it is a key part of the system.

To do this right, I needed to:

* Introduce visibility macros into mlir-c/Support.h. These should work on both *nix and windows as-is.
* Create a new libMLIRPublicAPI.so with just the mlir-c object files.
* Compile the C-API with -fvisibility=hidden.
* Conditionally depend on the libMLIR.so from libMLIRPublicAPI.so if building libMLIR.so (otherwise, also links against the static libs and will produce a mondo libMLIRPublicAPI.so).
* Disable re-exporting of static library symbols that come in as transitive deps.

This gives us a dynamic linked C-API layer that is minimal and should work as-is on all platforms. Since we don't support libMLIR.so building on Windows yet (and it is not very DLL friendly), this will fall back to a mondo build of libMLIRPublicAPI.so, which has its uses (it is also the most size conscious way to go if you happen to know exactly what you need).

Sizes (release/stripped, Ubuntu 20.04):

Shared library build:
	libMLIRPublicAPI.so: 121Kb
	_mlir.cpython-38-x86_64-linux-gnu.so: 1.4Mb
	mlir-capi-ir-test: 135Kb
	libMLIR.so: 21Mb

Static build:
	libMLIRPublicAPI.so: 5.5Mb (since this is a "static" build, this includes the MLIR implementation as non-exported code).
	_mlir.cpython-38-x86_64-linux-gnu.so: 1.4Mb
	mlir-capi-ir-test: 44Kb

Things like npcomp and circt which bring their own dialects/transforms/etc would still need the shared library build and code that links against libMLIR.so (since it is all C++ interop stuff), but hopefully things that only depend on the public C-API can just have the one narrow dep.

I spot checked everything with nm, and it looks good in terms of what is exporting/importing from each layer.

I'm not in a hurry to land this, but if it is controversial, I'll probably split off the Support.h and API visibility macro changes, since we should set that pattern regardless.

Reviewed By: mehdi_amini, benvanik

Differential Revision: https://reviews.llvm.org/D90824
2020-11-06 09:00:56 -08:00
Mehdi Amini 72dcd902e7 Add a custom MLIRBindingsPythonExtension cmake target to group all Python bindings (NFC)
This target will depend on each individual extension and represent "all"
Python bindings in the repo. User projects can get a finer grain control by
depending directly on some individual targets as needed.
2020-11-05 20:06:08 +00:00
Mehdi Amini 7f977086eb Fix MLIR Python bindings build (remove inexistant source from CMake list, NFC) 2020-11-05 20:06:07 +00:00
Mehdi Amini 24b3b2cd74 Refactor MLIR python extension CMake boilerplate in a reusable function (NFC)
Differential Revision: https://reviews.llvm.org/D90816
2020-11-05 19:57:12 +00:00
Mehdi Amini a1229c9518 Always link the MLIR python bindings native extension to libMLIR.so
The Python bindings now require -DLLVM_BUILD_LLVM_DYLIB=ON to build.
This change is needed to be able to build multiple Python native
extension without having each of them embedding a copy of MLIR, which
would make them incompatible with each other. Instead they should all
link to the same copy of MLIR.

Differential Revision: https://reviews.llvm.org/D90813
2020-11-05 19:57:11 +00:00
Mehdi Amini 5b29d26b21 Refactor PyPrintAccumulatorm, PyFileAccumulator, and PySinglePartStringAccumulator from IRModules.cpp to PybindUtils.h
These are reusable utilities across bindings.

Differential Revision: https://reviews.llvm.org/D90737
2020-11-04 18:46:36 +00:00
Stella Laurenzo 8260db752c [mlir][Python] Return and accept OpView for all functions.
* All functions that return an Operation now return an OpView.
* All functions that accept an Operation now accept an _OperationBase, which both Operation and OpView extend and can resolve to the backing Operation.
* Moves user-facing instance methods from Operation -> _OperationBase so that both can have the same API.
* Concretely, this means that if there are custom op classes defined (i.e. in Python), any iteration or creation will return the appropriate instance (i.e. if you get/create an std.addf, you will get an instance of the mlir.dialects.std.AddFOp class, getting full access to any custom API it exposes).
* Refactors all __eq__ methods after realizing the proper way to do this for _OperationBase.

Differential Revision: https://reviews.llvm.org/D90584
2020-11-03 22:48:34 -08:00
Stella Laurenzo af66cd173f [mlir][Python] Context managers for Context, InsertionPoint, Location.
* Finishes support for Context, InsertionPoint and Location to be carried by the thread using context managers.
* Introduces type casters and utilities so that DefaultPyMlirContext and DefaultPyLocation in method signatures does the right thing (allows explicit or gets from the thread context).
* Extend the rules for the thread context stack to handle nesting, appropriately inheriting and clearing depending on whether the context is the same.
* Refactors all method signatures to follow the new convention on trailing parameters for defaulting parameters (loc, ip, context). When the objects are carried in the thread context, this allows most explicit uses of these values to be elided.
* Removes the style guide section on putting accessors to construct global objects on the PyMlirContext: this style fails to make good use of the new facility since it is often the only thing remaining needing an MlirContext.
* Moves Module parse/creation from mlir.ir.Context to static methods on mlir.ir.Module.
* Moves Context.create_operation to a static Operation.create method.
* Moves Type parsing from mlir.ir.Context to static methods on mlir.ir.Type.
* Moves Attribute parsing from mlir.ir.Context to static methods on mlir.ir.Attribute.
* Move Location factory methods from mlir.ir.Context to static methods on mlir.ir.Location.
* Refactors the std dialect fake "ODS" generated code to take advantage of the new scheme.

Differential Revision: https://reviews.llvm.org/D90547
2020-11-01 19:00:39 -08:00
Stella Laurenzo c645ea5e29 Add InsertionPoint and context managers to the Python API.
* Removes index based insertion. All insertion now happens through the insertion point.
* Introduces thread local context managers for implicit creation relative to an insertion point.
* Introduces (but does not yet use) binding the Context to the thread local context stack. Intent is to refactor all methods to take context optionally and have them use the default if available.
* Adds C APIs for mlirOperationGetParentOperation(), mlirOperationGetBlock() and mlirBlockGetTerminator().
* Removes an assert in PyOperation creation that was incorrectly constraining. There is already a TODO to rework the keepAlive field that it was guarding and without the assert, it is no worse than the current state.

Differential Revision: https://reviews.llvm.org/D90368
2020-10-29 17:50:13 -07:00
Kazuaki Ishizaki 41b09f4eff [mlir] NFC: fix trivial typos
fix typos in comments and documents

Reviewed By: jpienaar

Differential Revision: https://reviews.llvm.org/D90089
2020-10-29 04:05:22 +09:00
Mehdi Amini 72023442c1 Add a `mlirModuleGetBody()` accessor to the C API and bind it in Python
Getting the body of a Module is a common need which justifies a
dedicated accessor instead of forcing users to go through the
region->blocks->front unwrapping manually.

Differential Revision: https://reviews.llvm.org/D90287
2020-10-28 17:53:52 +00:00
Stella Laurenzo 013b9322de [mlir][Python] Custom python op view wrappers for building and traversing.
* Still rough edges that need more sugar but the bones are there. Notes left in the test case for things that can be improved.
* Does not actually yield custom OpViews yet for traversing. Will rework that in a followup.

Differential Revision: https://reviews.llvm.org/D89932
2020-10-27 12:23:34 -07:00
Stella Laurenzo 74a58ec9c2 [mlir][CAPI][Python] Plumb OpPrintingFlags to C and Python APIs.
* Adds a new MlirOpPrintingFlags type and supporting accessors.
* Adds a new mlirOperationPrintWithFlags function.
* Adds a full featured python Operation.print method with all options and the ability to print directly to files/stdout in text or binary.
* Adds an Operation.get_asm which delegates to print and returns a str or bytes.
* Reworks Operation.__str__ to be based on get_asm.

Differential Revision: https://reviews.llvm.org/D89848
2020-10-21 12:14:06 -07:00
Alex Zinenko f6f27115e6 [mlir] Fix copy-pasted docstrings in Python bindings
Docstrings for `__str__` method in many classes was recycling the constant
string defined for `Type`, without being types themselves. Use proper
docstrings instead. Since they are succint, use string literals instead of
top-level constants to avoid further mistakes.

Differential Revision: https://reviews.llvm.org/D89780
2020-10-21 09:49:23 +02:00
Alex Zinenko 31782cd219 [mlir] Use the correct base class for Attributes in Python bindings
The pybind class typedef for concrete attribute classes was erroneously
deriving all of them from PyAttribute instead of the provided base class. This
has not been triggering any error because only one level of the hierarchy is
currently exposed.

Differential Revision: https://reviews.llvm.org/D89779
2020-10-21 09:49:23 +02:00
Alex Zinenko 580915d6a2 [mlir] Expose Value hierarchy to Python bindings
Values are ubiquitous in the IR, in particular block argument and operation
results are Values. Define Python classes for BlockArgument, OpResult and their
common ancestor Value. Define pseudo-container classes for lists of block
arguments and operation results, and use these containers to access the
corresponding values in blocks and operations.

Differential Revision: https://reviews.llvm.org/D89778
2020-10-21 09:49:22 +02:00
Stella Laurenzo 0e6beb2996 [mlir][Python] Add python binding to create DenseElementsAttribute.
* Interops with Python buffers/numpy arrays to create.
* Also cleans up 'get' factory methods on some types to be consistent.
* Adds mlirAttributeGetType() to C-API to facilitate error handling and other uses.
* Punts on a lot of features of the ElementsAttribute hierarchy for now.
* Does not yet support bool or string attributes.

Reviewed By: ftynse

Differential Revision: https://reviews.llvm.org/D89363
2020-10-19 22:29:35 -07:00
Stella Laurenzo ad958f648e [mlir][Python] Add missing capsule->module and Context.create_module.
* Extends Context/Operation interning to cover Module as well.
* Implements Module.context, Attribute.context, Type.context, and Location.context back-references (facilitated testing and also on the TODO list).
* Adds method to create an empty Module.
* Discovered missing in npcomp.

Differential Revision: https://reviews.llvm.org/D89294
2020-10-13 13:10:33 -07:00
Stella Laurenzo 75ae846de6 [mlir] Make Python bindings installable.
* Links against libMLIR.so if the project is built for DYLIBs.
* Puts things in the right place in build and install time python/ trees so that RPaths line up.
* Adds install actions to install both the extension and sources.
* Copies py source files to the build directory to match (consistent layout between build/install time and one place to point a PYTHONPATH for tests and interactive use).
* Finally, "import mlir" from an installed LLVM just works.

Differential Revision: https://reviews.llvm.org/D89167
2020-10-12 15:17:03 -07:00