IR.h 19.9 KB
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449
/*===-- 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(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. */
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. */
int mlirDialectIsNull(MlirDialect dialect);

/** 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);

/** Checks whether a module is null. */
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);

/*============================================================================*/
/* 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. */
int mlirOperationIsNull(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);

/** 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);

/** 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. */
int mlirRegionIsNull(MlirRegion region);

/** 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. */
int mlirBlockIsNull(MlirBlock block);

/** 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);

/** 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 the type of the value. */
MlirType mlirValueGetType(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. */
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);

/** Checks whether an attribute is null. */
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