# Melior [![GitHub Action](https://img.shields.io/github/actions/workflow/status/raviqqe/melior/test.yaml?branch=main&style=flat-square)](https://github.com/raviqqe/melior/actions?query=workflow%3Atest) [![Crate](https://img.shields.io/crates/v/melior.svg?style=flat-square)](https://crates.io/crates/melior) [![License](https://img.shields.io/github/license/raviqqe/melior.svg?style=flat-square)](https://github.com/raviqqe/melior/blob/main/LICENSE) Melior is the MLIR bindings for Rust. It aims to provide a simple, safe, and complete API for MLIR with a reasonably sane ownership model represented by the type system in Rust. This crate is a wrapper of [the MLIR C API](https://mlir.llvm.org/docs/CAPI/). ## Examples ### Building a function to add integers ```rust use melior::{ Context, dialect::{arith, DialectRegistry, func}, ir::{*, attribute::{StringAttribute, TypeAttribute}, r#type::FunctionType}, utility::register_all_dialects, }; let registry = DialectRegistry::new(); register_all_dialects(®istry); let context = Context::new(); context.append_dialect_registry(®istry); context.load_all_available_dialects(); let location = Location::unknown(&context); let module = Module::new(location); let index_type = Type::index(&context); module.body().append_operation(func::func( &context, StringAttribute::new(&context, "add"), TypeAttribute::new(FunctionType::new(&context, &[index_type, index_type], &[index_type]).into()), { let block = Block::new(&[(index_type, location), (index_type, location)]); let sum = block.append_operation(arith::addi( block.argument(0).unwrap().into(), block.argument(1).unwrap().into(), location )); block.append_operation(func::r#return( &[sum.result(0).unwrap().into()], location)); let region = Region::new(); region.append_block(block); region }, &[], location, )); assert!(module.as_operation().verify()); ``` ## Install ```sh cargo add melior ``` ### Dependencies [LLVM/MLIR 17](https://llvm.org/) needs to be installed on your system. On Linux and macOS, you can install it via [Homebrew](https://brew.sh). ```sh brew install llvm@17 ``` ## Documentation On [GitHub Pages](https://raviqqe.github.io/melior/melior/). ## Contribution Contribution is welcome! But, Melior is still in the alpha stage as well as the MLIR C API. Note that the API is unstable and can have breaking changes in the future. ### Technical notes - We always use `&T` for MLIR objects instead of `&mut T` to mitigate the intricacy of representing a loose ownership model of the MLIR C API in Rust. - Only UTF-8 is supported as string encoding. - Most string conversion between Rust and C is cached internally. ### Naming conventions - `Mlir` objects are named `` if they have no destructor. Otherwise, they are named `` for owned objects and `Ref` for borrowed references. - `mlirCreate` functions are renamed as `::new`. - `mlirGet` functions are renamed as follows: - If the resulting objects refer to `&self`, they are named `::as_`. - Otherwise, they are named just `::` and may have arguments, such as position indices. ### Safety Although Melior aims to be completely type safe, some part of the current API is not. - Access to operations, types, or attributes that belong to dialects not loaded in contexts can lead to runtime errors or segmentation faults in the worst case. - Fix plan: Load all dialects by default on creation of contexts, and provide unsafe constructors of contexts for advanced users. - IR object references returned from functions that move ownership of arguments might get invalidated later. - This is because we need to borrow `&self` rather than `&mut self` to return such references. - e.g. `Region::append_block()` - Fix plan: Use dynamic check, such as `RefCell`, for the objects. ## References - The raw C binding generation depends on [femtomc/mlir-sys](https://github.com/femtomc/mlir-sys). - The overall design is inspired by [TheDan64/inkwell](https://github.com/TheDan64/inkwell). ## License [Apache 2.0](https://github.com/raviqqe/melior/blob/main/LICENSE)