blob: 52152960f4156c6dac27eb84cd9d7072edc130f9 [file] [log] [blame]
/*===-- mlir-c/IR.h - C API to Core MLIR IR classes ---------------*- C -*-===*\
|* *|
|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *|
|* Exceptions. *|
|* See https://llvm.org/LICENSE.txt for license information. *|
|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *|
|* *|
|*===----------------------------------------------------------------------===*|
|* *|
|* This header declares the C interface to MLIR core IR classes. *|
|* *|
|* Many exotic languages can interoperate with C code but have a harder time *|
|* with C++ due to name mangling. So in addition to C, this interface enables *|
|* tools written in such languages. *|
|* *|
\*===----------------------------------------------------------------------===*/
#ifndef MLIR_C_IR_H
#define MLIR_C_IR_H
#include <stdint.h>
#include "mlir-c/Support.h"
#ifdef __cplusplus
extern "C" {
#endif
/*============================================================================*/
/** Opaque type declarations.
*
* Types are exposed to C bindings as structs containing opaque pointers. They
* are not supposed to be inspected from C. This allows the underlying
* representation to change without affecting the API users. The use of structs
* instead of typedefs enables some type safety as structs are not implicitly
* convertible to each other.
*
* Instances of these types may or may not own the underlying object (most often
* only point to an IR fragment without owning it). The ownership semantics is
* defined by how an instance of the type was obtained.
*/
/*============================================================================*/
#define DEFINE_C_API_STRUCT(name, storage) \
struct name { \
storage *ptr; \
}; \
typedef struct name name
DEFINE_C_API_STRUCT(MlirContext, void);
DEFINE_C_API_STRUCT(MlirDialect, void);
DEFINE_C_API_STRUCT(MlirOperation, void);
DEFINE_C_API_STRUCT(MlirOpPrintingFlags, void);
DEFINE_C_API_STRUCT(MlirBlock, void);
DEFINE_C_API_STRUCT(MlirRegion, void);
DEFINE_C_API_STRUCT(MlirValue, const void);
DEFINE_C_API_STRUCT(MlirAttribute, const void);
DEFINE_C_API_STRUCT(MlirType, const void);
DEFINE_C_API_STRUCT(MlirLocation, const void);
DEFINE_C_API_STRUCT(MlirModule, const void);
/** Named MLIR attribute.
*
* A named attribute is essentially a (name, attribute) pair where the name is
* a string.
*/
struct MlirNamedAttribute {
const char *name;
MlirAttribute attribute;
};
typedef struct MlirNamedAttribute MlirNamedAttribute;
/** A callback for returning string references.
*
* This function is called back by the functions that need to return a reference
* to the portion of the string with the following arguments:
* - a pointer to the beginning of a string;
* - the length of the string (the pointer may point to a larger buffer, not
* necessarily null-terminated);
* - a pointer to user data forwarded from the printing call.
*/
typedef void (*MlirStringCallback)(const char *, intptr_t, void *);
/*============================================================================*/
/* Context API. */
/*============================================================================*/
/** Creates an MLIR context and transfers its ownership to the caller. */
MlirContext mlirContextCreate();
/** Checks if two contexts are equal. */
int mlirContextEqual(MlirContext ctx1, MlirContext ctx2);
/** Checks whether a context is null. */
static inline int mlirContextIsNull(MlirContext context) {
return !context.ptr;
}
/** Takes an MLIR context owned by the caller and destroys it. */
void mlirContextDestroy(MlirContext context);
/** Sets whether unregistered dialects are allowed in this context. */
void mlirContextSetAllowUnregisteredDialects(MlirContext context, int allow);
/** Returns whether the context allows unregistered dialects. */
int mlirContextGetAllowUnregisteredDialects(MlirContext context);
/** Returns the number of dialects registered with the given context. A
* registered dialect will be loaded if needed by the parser. */
intptr_t mlirContextGetNumRegisteredDialects(MlirContext context);
/** Returns the number of dialects loaded by the context.
*/
intptr_t mlirContextGetNumLoadedDialects(MlirContext context);
/** Gets the dialect instance owned by the given context using the dialect
* namespace to identify it, loads (i.e., constructs the instance of) the
* dialect if necessary. If the dialect is not registered with the context,
* returns null. Use mlirContextLoad<Name>Dialect to load an unregistered
* dialect. */
MlirDialect mlirContextGetOrLoadDialect(MlirContext context,
MlirStringRef name);
/*============================================================================*/
/* Dialect API. */
/*============================================================================*/
/** Returns the context that owns the dialect. */
MlirContext mlirDialectGetContext(MlirDialect dialect);
/** Checks if the dialect is null. */
static inline int mlirDialectIsNull(MlirDialect dialect) {
return !dialect.ptr;
}
/** Checks if two dialects that belong to the same context are equal. Dialects
* from different contexts will not compare equal. */
int mlirDialectEqual(MlirDialect dialect1, MlirDialect dialect2);
/** Returns the namespace of the given dialect. */
MlirStringRef mlirDialectGetNamespace(MlirDialect dialect);
/*============================================================================*/
/* Location API. */
/*============================================================================*/
/** Creates an File/Line/Column location owned by the given context. */
MlirLocation mlirLocationFileLineColGet(MlirContext context,
const char *filename, unsigned line,
unsigned col);
/** Creates a location with unknown position owned by the given context. */
MlirLocation mlirLocationUnknownGet(MlirContext context);
/** Gets the context that a location was created with. */
MlirContext mlirLocationGetContext(MlirLocation location);
/** Prints a location by sending chunks of the string representation and
* forwarding `userData to `callback`. Note that the callback may be called
* several times with consecutive chunks of the string. */
void mlirLocationPrint(MlirLocation location, MlirStringCallback callback,
void *userData);
/*============================================================================*/
/* Module API. */
/*============================================================================*/
/** Creates a new, empty module and transfers ownership to the caller. */
MlirModule mlirModuleCreateEmpty(MlirLocation location);
/** Parses a module from the string and transfers ownership to the caller. */
MlirModule mlirModuleCreateParse(MlirContext context, const char *module);
/** Gets the context that a module was created with. */
MlirContext mlirModuleGetContext(MlirModule module);
/** Gets the body of the module, i.e. the only block it contains. */
MlirBlock mlirModuleGetBody(MlirModule module);
/** Checks whether a module is null. */
static inline int mlirModuleIsNull(MlirModule module) { return !module.ptr; }
/** Takes a module owned by the caller and deletes it. */
void mlirModuleDestroy(MlirModule module);
/** Views the module as a generic operation. */
MlirOperation mlirModuleGetOperation(MlirModule module);
/*============================================================================*/
/* Operation state. */
/*============================================================================*/
/** An auxiliary class for constructing operations.
*
* This class contains all the information necessary to construct the operation.
* It owns the MlirRegions it has pointers to and does not own anything else.
* By default, the state can be constructed from a name and location, the latter
* being also used to access the context, and has no other components. These
* components can be added progressively until the operation is constructed.
* Users are not expected to rely on the internals of this class and should use
* mlirOperationState* functions instead.
*/
struct MlirOperationState {
const char *name;
MlirLocation location;
intptr_t nResults;
MlirType *results;
intptr_t nOperands;
MlirValue *operands;
intptr_t nRegions;
MlirRegion *regions;
intptr_t nSuccessors;
MlirBlock *successors;
intptr_t nAttributes;
MlirNamedAttribute *attributes;
};
typedef struct MlirOperationState MlirOperationState;
/** Constructs an operation state from a name and a location. */
MlirOperationState mlirOperationStateGet(const char *name, MlirLocation loc);
/** Adds a list of components to the operation state. */
void mlirOperationStateAddResults(MlirOperationState *state, intptr_t n,
MlirType *results);
void mlirOperationStateAddOperands(MlirOperationState *state, intptr_t n,
MlirValue *operands);
void mlirOperationStateAddOwnedRegions(MlirOperationState *state, intptr_t n,
MlirRegion *regions);
void mlirOperationStateAddSuccessors(MlirOperationState *state, intptr_t n,
MlirBlock *successors);
void mlirOperationStateAddAttributes(MlirOperationState *state, intptr_t n,
MlirNamedAttribute *attributes);
/*============================================================================*/
/* Op Printing flags API. */
/* While many of these are simple settings that could be represented in a */
/* struct, they are wrapped in a heap allocated object and accessed via */
/* functions to maximize the possibility of compatibility over time. */
/*============================================================================*/
/** Creates new printing flags with defaults, intended for customization.
* Must be freed with a call to mlirOpPrintingFlagsDestroy(). */
MlirOpPrintingFlags mlirOpPrintingFlagsCreate();
/** Destroys printing flags created with mlirOpPrintingFlagsCreate. */
void mlirOpPrintingFlagsDestroy(MlirOpPrintingFlags flags);
/** Enables the elision of large elements attributes by printing a lexically
* valid but otherwise meaningless form instead of the element data. The
* `largeElementLimit` is used to configure what is considered to be a "large"
* ElementsAttr by providing an upper limit to the number of elements. */
void mlirOpPrintingFlagsElideLargeElementsAttrs(MlirOpPrintingFlags flags,
intptr_t largeElementLimit);
/** Enable printing of debug information. If 'prettyForm' is set to true,
* debug information is printed in a more readable 'pretty' form. Note: The
* IR generated with 'prettyForm' is not parsable. */
void mlirOpPrintingFlagsEnableDebugInfo(MlirOpPrintingFlags flags,
int prettyForm);
/** Always print operations in the generic form. */
void mlirOpPrintingFlagsPrintGenericOpForm(MlirOpPrintingFlags flags);
/** Use local scope when printing the operation. This allows for using the
* printer in a more localized and thread-safe setting, but may not
* necessarily be identical to what the IR will look like when dumping
* the full module. */
void mlirOpPrintingFlagsUseLocalScope(MlirOpPrintingFlags flags);
/*============================================================================*/
/* Operation API. */
/*============================================================================*/
/** Creates an operation and transfers ownership to the caller. */
MlirOperation mlirOperationCreate(const MlirOperationState *state);
/** Takes an operation owned by the caller and destroys it. */
void mlirOperationDestroy(MlirOperation op);
/** Checks whether the underlying operation is null. */
static inline int mlirOperationIsNull(MlirOperation op) { return !op.ptr; }
/** Checks whether two operation handles point to the same operation. This does
* not perform deep comparison. */
int mlirOperationEqual(MlirOperation op, MlirOperation other);
/** Gets the block that owns this operation, returning null if the operation is
* not owned. */
MlirBlock mlirOperationGetBlock(MlirOperation op);
/** Gets the operation that owns this operation, returning null if the operation
* is not owned. */
MlirOperation mlirOperationGetParentOperation(MlirOperation op);
/** Returns the number of regions attached to the given operation. */
intptr_t mlirOperationGetNumRegions(MlirOperation op);
/** Returns `pos`-th region attached to the operation. */
MlirRegion mlirOperationGetRegion(MlirOperation op, intptr_t pos);
/** Returns an operation immediately following the given operation it its
* enclosing block. */
MlirOperation mlirOperationGetNextInBlock(MlirOperation op);
/** Returns the number of operands of the operation. */
intptr_t mlirOperationGetNumOperands(MlirOperation op);
/** Returns `pos`-th operand of the operation. */
MlirValue mlirOperationGetOperand(MlirOperation op, intptr_t pos);
/** Returns the number of results of the operation. */
intptr_t mlirOperationGetNumResults(MlirOperation op);
/** Returns `pos`-th result of the operation. */
MlirValue mlirOperationGetResult(MlirOperation op, intptr_t pos);
/** Returns the number of successor blocks of the operation. */
intptr_t mlirOperationGetNumSuccessors(MlirOperation op);
/** Returns `pos`-th successor of the operation. */
MlirBlock mlirOperationGetSuccessor(MlirOperation op, intptr_t pos);
/** Returns the number of attributes attached to the operation. */
intptr_t mlirOperationGetNumAttributes(MlirOperation op);
/** Return `pos`-th attribute of the operation. */
MlirNamedAttribute mlirOperationGetAttribute(MlirOperation op, intptr_t pos);
/** Returns an attribute attached to the operation given its name. */
MlirAttribute mlirOperationGetAttributeByName(MlirOperation op,
const char *name);
/** Sets an attribute by name, replacing the existing if it exists or
* adding a new one otherwise. */
void mlirOperationSetAttributeByName(MlirOperation op, const char *name,
MlirAttribute attr);
/** Removes an attribute by name. Returns 0 if the attribute was not found
* and !0 if removed. */
int mlirOperationRemoveAttributeByName(MlirOperation op, const char *name);
/** Prints an operation by sending chunks of the string representation and
* forwarding `userData to `callback`. Note that the callback may be called
* several times with consecutive chunks of the string. */
void mlirOperationPrint(MlirOperation op, MlirStringCallback callback,
void *userData);
/** Same as mlirOperationPrint but accepts flags controlling the printing
* behavior. */
void mlirOperationPrintWithFlags(MlirOperation op, MlirOpPrintingFlags flags,
MlirStringCallback callback, void *userData);
/** Prints an operation to stderr. */
void mlirOperationDump(MlirOperation op);
/*============================================================================*/
/* Region API. */
/*============================================================================*/
/** Creates a new empty region and transfers ownership to the caller. */
MlirRegion mlirRegionCreate();
/** Takes a region owned by the caller and destroys it. */
void mlirRegionDestroy(MlirRegion region);
/** Checks whether a region is null. */
static inline int mlirRegionIsNull(MlirRegion region) { return !region.ptr; }
/** Gets the first block in the region. */
MlirBlock mlirRegionGetFirstBlock(MlirRegion region);
/** Takes a block owned by the caller and appends it to the given region. */
void mlirRegionAppendOwnedBlock(MlirRegion region, MlirBlock block);
/** Takes a block owned by the caller and inserts it at `pos` to the given
* region. This is an expensive operation that linearly scans the region, prefer
* insertAfter/Before instead. */
void mlirRegionInsertOwnedBlock(MlirRegion region, intptr_t pos,
MlirBlock block);
/** Takes a block owned by the caller and inserts it after the (non-owned)
* reference block in the given region. The reference block must belong to the
* region. If the reference block is null, prepends the block to the region. */
void mlirRegionInsertOwnedBlockAfter(MlirRegion region, MlirBlock reference,
MlirBlock block);
/** Takes a block owned by the caller and inserts it before the (non-owned)
* reference block in the given region. The reference block must belong to the
* region. If the reference block is null, appends the block to the region. */
void mlirRegionInsertOwnedBlockBefore(MlirRegion region, MlirBlock reference,
MlirBlock block);
/*============================================================================*/
/* Block API. */
/*============================================================================*/
/** Creates a new empty block with the given argument types and transfers
* ownership to the caller. */
MlirBlock mlirBlockCreate(intptr_t nArgs, MlirType *args);
/** Takes a block owned by the caller and destroys it. */
void mlirBlockDestroy(MlirBlock block);
/** Checks whether a block is null. */
static inline int mlirBlockIsNull(MlirBlock block) { return !block.ptr; }
/** Checks whether two blocks handles point to the same block. This does not
* perform deep comparison. */
int mlirBlockEqual(MlirBlock block, MlirBlock other);
/** Returns the block immediately following the given block in its parent
* region. */
MlirBlock mlirBlockGetNextInRegion(MlirBlock block);
/** Returns the first operation in the block. */
MlirOperation mlirBlockGetFirstOperation(MlirBlock block);
/** Returns the terminator operation in the block or null if no terminator. */
MlirOperation mlirBlockGetTerminator(MlirBlock block);
/** Takes an operation owned by the caller and appends it to the block. */
void mlirBlockAppendOwnedOperation(MlirBlock block, MlirOperation operation);
/** Takes an operation owned by the caller and inserts it as `pos` to the block.
This is an expensive operation that scans the block linearly, prefer
insertBefore/After instead. */
void mlirBlockInsertOwnedOperation(MlirBlock block, intptr_t pos,
MlirOperation operation);
/** Takes an operation owned by the caller and inserts it after the (non-owned)
* reference operation in the given block. If the reference is null, prepends
* the operation. Otherwise, the reference must belong to the block. */
void mlirBlockInsertOwnedOperationAfter(MlirBlock block,
MlirOperation reference,
MlirOperation operation);
/** Takes an operation owned by the caller and inserts it before the (non-owned)
* reference operation in the given block. If the reference is null, appends the
* operation. Otherwise, the reference must belong to the block. */
void mlirBlockInsertOwnedOperationBefore(MlirBlock block,
MlirOperation reference,
MlirOperation operation);
/** Returns the number of arguments of the block. */
intptr_t mlirBlockGetNumArguments(MlirBlock block);
/** Returns `pos`-th argument of the block. */
MlirValue mlirBlockGetArgument(MlirBlock block, intptr_t pos);
/** Prints a block by sending chunks of the string representation and
* forwarding `userData to `callback`. Note that the callback may be called
* several times with consecutive chunks of the string. */
void mlirBlockPrint(MlirBlock block, MlirStringCallback callback,
void *userData);
/*============================================================================*/
/* Value API. */
/*============================================================================*/
/** Returns whether the value is null. */
static inline int mlirValueIsNull(MlirValue value) { return !value.ptr; }
/** Returns 1 if the value is a block argument, 0 otherwise. */
int mlirValueIsABlockArgument(MlirValue value);
/** Returns 1 if the value is an operation result, 0 otherwise. */
int mlirValueIsAOpResult(MlirValue value);
/** Returns the block in which this value is defined as an argument. Asserts if
* the value is not a block argument. */
MlirBlock mlirBlockArgumentGetOwner(MlirValue value);
/** Returns the position of the value in the argument list of its block. */
intptr_t mlirBlockArgumentGetArgNumber(MlirValue value);
/** Sets the type of the block argument to the given type. */
void mlirBlockArgumentSetType(MlirValue value, MlirType type);
/** Returns an operation that produced this value as its result. Asserts if the
* value is not an op result. */
MlirOperation mlirOpResultGetOwner(MlirValue value);
/** Returns the position of the value in the list of results of the operation
* that produced it. */
intptr_t mlirOpResultGetResultNumber(MlirValue value);
/** Returns the type of the value. */
MlirType mlirValueGetType(MlirValue value);
/** Prints the value to the standard error stream. */
void mlirValueDump(MlirValue value);
/** Prints a value by sending chunks of the string representation and
* forwarding `userData to `callback`. Note that the callback may be called
* several times with consecutive chunks of the string. */
void mlirValuePrint(MlirValue value, MlirStringCallback callback,
void *userData);
/*============================================================================*/
/* Type API. */
/*============================================================================*/
/** Parses a type. The type is owned by the context. */
MlirType mlirTypeParseGet(MlirContext context, const char *type);
/** Gets the context that a type was created with. */
MlirContext mlirTypeGetContext(MlirType type);
/** Checks whether a type is null. */
static inline int mlirTypeIsNull(MlirType type) { return !type.ptr; }
/** Checks if two types are equal. */
int mlirTypeEqual(MlirType t1, MlirType t2);
/** Prints a location by sending chunks of the string representation and
* forwarding `userData to `callback`. Note that the callback may be called
* several times with consecutive chunks of the string. */
void mlirTypePrint(MlirType type, MlirStringCallback callback, void *userData);
/** Prints the type to the standard error stream. */
void mlirTypeDump(MlirType type);
/*============================================================================*/
/* Attribute API. */
/*============================================================================*/
/** Parses an attribute. The attribute is owned by the context. */
MlirAttribute mlirAttributeParseGet(MlirContext context, const char *attr);
/** Gets the context that an attribute was created with. */
MlirContext mlirAttributeGetContext(MlirAttribute attribute);
/** Gets the type of this attribute. */
MlirType mlirAttributeGetType(MlirAttribute attribute);
/** Checks whether an attribute is null. */
static inline int mlirAttributeIsNull(MlirAttribute attr) { return !attr.ptr; }
/** Checks if two attributes are equal. */
int mlirAttributeEqual(MlirAttribute a1, MlirAttribute a2);
/** Prints an attribute by sending chunks of the string representation and
* forwarding `userData to `callback`. Note that the callback may be called
* several times with consecutive chunks of the string. */
void mlirAttributePrint(MlirAttribute attr, MlirStringCallback callback,
void *userData);
/** Prints the attribute to the standard error stream. */
void mlirAttributeDump(MlirAttribute attr);
/** Associates an attribute with the name. Takes ownership of neither. */
MlirNamedAttribute mlirNamedAttributeGet(const char *name, MlirAttribute attr);
#ifdef __cplusplus
}
#endif
#endif // MLIR_C_IR_H