xref: /llvm-project-15.0.7/mlir/test/CAPI/ir.c (revision b5e9f83e)
1 //===- ir.c - Simple test of C APIs ---------------------------------------===//
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 /* RUN: mlir-capi-ir-test 2>&1 | FileCheck %s
11  */
12 
13 #include "mlir-c/IR.h"
14 #include "mlir-c/AffineExpr.h"
15 #include "mlir-c/AffineMap.h"
16 #include "mlir-c/BuiltinAttributes.h"
17 #include "mlir-c/BuiltinTypes.h"
18 #include "mlir-c/Diagnostics.h"
19 #include "mlir-c/Dialect/Standard.h"
20 #include "mlir-c/IntegerSet.h"
21 #include "mlir-c/Registration.h"
22 #include "mlir-c/Support.h"
23 
24 #include <assert.h>
25 #include <inttypes.h>
26 #include <math.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 
31 void populateLoopBody(MlirContext ctx, MlirBlock loopBody,
32                       MlirLocation location, MlirBlock funcBody) {
33   MlirValue iv = mlirBlockGetArgument(loopBody, 0);
34   MlirValue funcArg0 = mlirBlockGetArgument(funcBody, 0);
35   MlirValue funcArg1 = mlirBlockGetArgument(funcBody, 1);
36   MlirType f32Type =
37       mlirTypeParseGet(ctx, mlirStringRefCreateFromCString("f32"));
38 
39   MlirOperationState loadLHSState = mlirOperationStateGet(
40       mlirStringRefCreateFromCString("memref.load"), location);
41   MlirValue loadLHSOperands[] = {funcArg0, iv};
42   mlirOperationStateAddOperands(&loadLHSState, 2, loadLHSOperands);
43   mlirOperationStateAddResults(&loadLHSState, 1, &f32Type);
44   MlirOperation loadLHS = mlirOperationCreate(&loadLHSState);
45   mlirBlockAppendOwnedOperation(loopBody, loadLHS);
46 
47   MlirOperationState loadRHSState = mlirOperationStateGet(
48       mlirStringRefCreateFromCString("memref.load"), location);
49   MlirValue loadRHSOperands[] = {funcArg1, iv};
50   mlirOperationStateAddOperands(&loadRHSState, 2, loadRHSOperands);
51   mlirOperationStateAddResults(&loadRHSState, 1, &f32Type);
52   MlirOperation loadRHS = mlirOperationCreate(&loadRHSState);
53   mlirBlockAppendOwnedOperation(loopBody, loadRHS);
54 
55   MlirOperationState addState = mlirOperationStateGet(
56       mlirStringRefCreateFromCString("arith.addf"), location);
57   MlirValue addOperands[] = {mlirOperationGetResult(loadLHS, 0),
58                              mlirOperationGetResult(loadRHS, 0)};
59   mlirOperationStateAddOperands(&addState, 2, addOperands);
60   mlirOperationStateAddResults(&addState, 1, &f32Type);
61   MlirOperation add = mlirOperationCreate(&addState);
62   mlirBlockAppendOwnedOperation(loopBody, add);
63 
64   MlirOperationState storeState = mlirOperationStateGet(
65       mlirStringRefCreateFromCString("memref.store"), location);
66   MlirValue storeOperands[] = {mlirOperationGetResult(add, 0), funcArg0, iv};
67   mlirOperationStateAddOperands(&storeState, 3, storeOperands);
68   MlirOperation store = mlirOperationCreate(&storeState);
69   mlirBlockAppendOwnedOperation(loopBody, store);
70 
71   MlirOperationState yieldState = mlirOperationStateGet(
72       mlirStringRefCreateFromCString("scf.yield"), location);
73   MlirOperation yield = mlirOperationCreate(&yieldState);
74   mlirBlockAppendOwnedOperation(loopBody, yield);
75 }
76 
77 MlirModule makeAndDumpAdd(MlirContext ctx, MlirLocation location) {
78   MlirModule moduleOp = mlirModuleCreateEmpty(location);
79   MlirBlock moduleBody = mlirModuleGetBody(moduleOp);
80 
81   MlirType memrefType =
82       mlirTypeParseGet(ctx, mlirStringRefCreateFromCString("memref<?xf32>"));
83   MlirType funcBodyArgTypes[] = {memrefType, memrefType};
84   MlirRegion funcBodyRegion = mlirRegionCreate();
85   MlirBlock funcBody = mlirBlockCreate(
86       sizeof(funcBodyArgTypes) / sizeof(MlirType), funcBodyArgTypes);
87   mlirRegionAppendOwnedBlock(funcBodyRegion, funcBody);
88 
89   MlirAttribute funcTypeAttr = mlirAttributeParseGet(
90       ctx,
91       mlirStringRefCreateFromCString("(memref<?xf32>, memref<?xf32>) -> ()"));
92   MlirAttribute funcNameAttr =
93       mlirAttributeParseGet(ctx, mlirStringRefCreateFromCString("\"add\""));
94   MlirNamedAttribute funcAttrs[] = {
95       mlirNamedAttributeGet(
96           mlirIdentifierGet(ctx, mlirStringRefCreateFromCString("type")),
97           funcTypeAttr),
98       mlirNamedAttributeGet(
99           mlirIdentifierGet(ctx, mlirStringRefCreateFromCString("sym_name")),
100           funcNameAttr)};
101   MlirOperationState funcState = mlirOperationStateGet(
102       mlirStringRefCreateFromCString("builtin.func"), location);
103   mlirOperationStateAddAttributes(&funcState, 2, funcAttrs);
104   mlirOperationStateAddOwnedRegions(&funcState, 1, &funcBodyRegion);
105   MlirOperation func = mlirOperationCreate(&funcState);
106   mlirBlockInsertOwnedOperation(moduleBody, 0, func);
107 
108   MlirType indexType =
109       mlirTypeParseGet(ctx, mlirStringRefCreateFromCString("index"));
110   MlirAttribute indexZeroLiteral =
111       mlirAttributeParseGet(ctx, mlirStringRefCreateFromCString("0 : index"));
112   MlirNamedAttribute indexZeroValueAttr = mlirNamedAttributeGet(
113       mlirIdentifierGet(ctx, mlirStringRefCreateFromCString("value")),
114       indexZeroLiteral);
115   MlirOperationState constZeroState = mlirOperationStateGet(
116       mlirStringRefCreateFromCString("arith.constant"), location);
117   mlirOperationStateAddResults(&constZeroState, 1, &indexType);
118   mlirOperationStateAddAttributes(&constZeroState, 1, &indexZeroValueAttr);
119   MlirOperation constZero = mlirOperationCreate(&constZeroState);
120   mlirBlockAppendOwnedOperation(funcBody, constZero);
121 
122   MlirValue funcArg0 = mlirBlockGetArgument(funcBody, 0);
123   MlirValue constZeroValue = mlirOperationGetResult(constZero, 0);
124   MlirValue dimOperands[] = {funcArg0, constZeroValue};
125   MlirOperationState dimState = mlirOperationStateGet(
126       mlirStringRefCreateFromCString("memref.dim"), location);
127   mlirOperationStateAddOperands(&dimState, 2, dimOperands);
128   mlirOperationStateAddResults(&dimState, 1, &indexType);
129   MlirOperation dim = mlirOperationCreate(&dimState);
130   mlirBlockAppendOwnedOperation(funcBody, dim);
131 
132   MlirRegion loopBodyRegion = mlirRegionCreate();
133   MlirBlock loopBody = mlirBlockCreate(0, NULL);
134   mlirBlockAddArgument(loopBody, indexType);
135   mlirRegionAppendOwnedBlock(loopBodyRegion, loopBody);
136 
137   MlirAttribute indexOneLiteral =
138       mlirAttributeParseGet(ctx, mlirStringRefCreateFromCString("1 : index"));
139   MlirNamedAttribute indexOneValueAttr = mlirNamedAttributeGet(
140       mlirIdentifierGet(ctx, mlirStringRefCreateFromCString("value")),
141       indexOneLiteral);
142   MlirOperationState constOneState = mlirOperationStateGet(
143       mlirStringRefCreateFromCString("arith.constant"), location);
144   mlirOperationStateAddResults(&constOneState, 1, &indexType);
145   mlirOperationStateAddAttributes(&constOneState, 1, &indexOneValueAttr);
146   MlirOperation constOne = mlirOperationCreate(&constOneState);
147   mlirBlockAppendOwnedOperation(funcBody, constOne);
148 
149   MlirValue dimValue = mlirOperationGetResult(dim, 0);
150   MlirValue constOneValue = mlirOperationGetResult(constOne, 0);
151   MlirValue loopOperands[] = {constZeroValue, dimValue, constOneValue};
152   MlirOperationState loopState = mlirOperationStateGet(
153       mlirStringRefCreateFromCString("scf.for"), location);
154   mlirOperationStateAddOperands(&loopState, 3, loopOperands);
155   mlirOperationStateAddOwnedRegions(&loopState, 1, &loopBodyRegion);
156   MlirOperation loop = mlirOperationCreate(&loopState);
157   mlirBlockAppendOwnedOperation(funcBody, loop);
158 
159   populateLoopBody(ctx, loopBody, location, funcBody);
160 
161   MlirOperationState retState = mlirOperationStateGet(
162       mlirStringRefCreateFromCString("std.return"), location);
163   MlirOperation ret = mlirOperationCreate(&retState);
164   mlirBlockAppendOwnedOperation(funcBody, ret);
165 
166   MlirOperation module = mlirModuleGetOperation(moduleOp);
167   mlirOperationDump(module);
168   // clang-format off
169   // CHECK: module {
170   // CHECK:   func @add(%[[ARG0:.*]]: memref<?xf32>, %[[ARG1:.*]]: memref<?xf32>) {
171   // CHECK:     %[[C0:.*]] = arith.constant 0 : index
172   // CHECK:     %[[DIM:.*]] = memref.dim %[[ARG0]], %[[C0]] : memref<?xf32>
173   // CHECK:     %[[C1:.*]] = arith.constant 1 : index
174   // CHECK:     scf.for %[[I:.*]] = %[[C0]] to %[[DIM]] step %[[C1]] {
175   // CHECK:       %[[LHS:.*]] = memref.load %[[ARG0]][%[[I]]] : memref<?xf32>
176   // CHECK:       %[[RHS:.*]] = memref.load %[[ARG1]][%[[I]]] : memref<?xf32>
177   // CHECK:       %[[SUM:.*]] = arith.addf %[[LHS]], %[[RHS]] : f32
178   // CHECK:       memref.store %[[SUM]], %[[ARG0]][%[[I]]] : memref<?xf32>
179   // CHECK:     }
180   // CHECK:     return
181   // CHECK:   }
182   // CHECK: }
183   // clang-format on
184 
185   return moduleOp;
186 }
187 
188 struct OpListNode {
189   MlirOperation op;
190   struct OpListNode *next;
191 };
192 typedef struct OpListNode OpListNode;
193 
194 struct ModuleStats {
195   unsigned numOperations;
196   unsigned numAttributes;
197   unsigned numBlocks;
198   unsigned numRegions;
199   unsigned numValues;
200   unsigned numBlockArguments;
201   unsigned numOpResults;
202 };
203 typedef struct ModuleStats ModuleStats;
204 
205 int collectStatsSingle(OpListNode *head, ModuleStats *stats) {
206   MlirOperation operation = head->op;
207   stats->numOperations += 1;
208   stats->numValues += mlirOperationGetNumResults(operation);
209   stats->numAttributes += mlirOperationGetNumAttributes(operation);
210 
211   unsigned numRegions = mlirOperationGetNumRegions(operation);
212 
213   stats->numRegions += numRegions;
214 
215   intptr_t numResults = mlirOperationGetNumResults(operation);
216   for (intptr_t i = 0; i < numResults; ++i) {
217     MlirValue result = mlirOperationGetResult(operation, i);
218     if (!mlirValueIsAOpResult(result))
219       return 1;
220     if (mlirValueIsABlockArgument(result))
221       return 2;
222     if (!mlirOperationEqual(operation, mlirOpResultGetOwner(result)))
223       return 3;
224     if (i != mlirOpResultGetResultNumber(result))
225       return 4;
226     ++stats->numOpResults;
227   }
228 
229   for (unsigned i = 0; i < numRegions; ++i) {
230     MlirRegion region = mlirOperationGetRegion(operation, i);
231     for (MlirBlock block = mlirRegionGetFirstBlock(region);
232          !mlirBlockIsNull(block); block = mlirBlockGetNextInRegion(block)) {
233       ++stats->numBlocks;
234       intptr_t numArgs = mlirBlockGetNumArguments(block);
235       stats->numValues += numArgs;
236       for (intptr_t j = 0; j < numArgs; ++j) {
237         MlirValue arg = mlirBlockGetArgument(block, j);
238         if (!mlirValueIsABlockArgument(arg))
239           return 5;
240         if (mlirValueIsAOpResult(arg))
241           return 6;
242         if (!mlirBlockEqual(block, mlirBlockArgumentGetOwner(arg)))
243           return 7;
244         if (j != mlirBlockArgumentGetArgNumber(arg))
245           return 8;
246         ++stats->numBlockArguments;
247       }
248 
249       for (MlirOperation child = mlirBlockGetFirstOperation(block);
250            !mlirOperationIsNull(child);
251            child = mlirOperationGetNextInBlock(child)) {
252         OpListNode *node = malloc(sizeof(OpListNode));
253         node->op = child;
254         node->next = head->next;
255         head->next = node;
256       }
257     }
258   }
259   return 0;
260 }
261 
262 int collectStats(MlirOperation operation) {
263   OpListNode *head = malloc(sizeof(OpListNode));
264   head->op = operation;
265   head->next = NULL;
266 
267   ModuleStats stats;
268   stats.numOperations = 0;
269   stats.numAttributes = 0;
270   stats.numBlocks = 0;
271   stats.numRegions = 0;
272   stats.numValues = 0;
273   stats.numBlockArguments = 0;
274   stats.numOpResults = 0;
275 
276   do {
277     int retval = collectStatsSingle(head, &stats);
278     if (retval)
279       return retval;
280     OpListNode *next = head->next;
281     free(head);
282     head = next;
283   } while (head);
284 
285   if (stats.numValues != stats.numBlockArguments + stats.numOpResults)
286     return 100;
287 
288   fprintf(stderr, "@stats\n");
289   fprintf(stderr, "Number of operations: %u\n", stats.numOperations);
290   fprintf(stderr, "Number of attributes: %u\n", stats.numAttributes);
291   fprintf(stderr, "Number of blocks: %u\n", stats.numBlocks);
292   fprintf(stderr, "Number of regions: %u\n", stats.numRegions);
293   fprintf(stderr, "Number of values: %u\n", stats.numValues);
294   fprintf(stderr, "Number of block arguments: %u\n", stats.numBlockArguments);
295   fprintf(stderr, "Number of op results: %u\n", stats.numOpResults);
296   // clang-format off
297   // CHECK-LABEL: @stats
298   // CHECK: Number of operations: 12
299   // CHECK: Number of attributes: 4
300   // CHECK: Number of blocks: 3
301   // CHECK: Number of regions: 3
302   // CHECK: Number of values: 9
303   // CHECK: Number of block arguments: 3
304   // CHECK: Number of op results: 6
305   // clang-format on
306   return 0;
307 }
308 
309 static void printToStderr(MlirStringRef str, void *userData) {
310   (void)userData;
311   fwrite(str.data, 1, str.length, stderr);
312 }
313 
314 static void printFirstOfEach(MlirContext ctx, MlirOperation operation) {
315   // Assuming we are given a module, go to the first operation of the first
316   // function.
317   MlirRegion region = mlirOperationGetRegion(operation, 0);
318   MlirBlock block = mlirRegionGetFirstBlock(region);
319   operation = mlirBlockGetFirstOperation(block);
320   region = mlirOperationGetRegion(operation, 0);
321   MlirOperation parentOperation = operation;
322   block = mlirRegionGetFirstBlock(region);
323   operation = mlirBlockGetFirstOperation(block);
324   assert(mlirModuleIsNull(mlirModuleFromOperation(operation)));
325 
326   // Verify that parent operation and block report correctly.
327   // CHECK: Parent operation eq: 1
328   fprintf(stderr, "Parent operation eq: %d\n",
329           mlirOperationEqual(mlirOperationGetParentOperation(operation),
330                              parentOperation));
331   // CHECK: Block eq: 1
332   fprintf(stderr, "Block eq: %d\n",
333           mlirBlockEqual(mlirOperationGetBlock(operation), block));
334   // CHECK: Block parent operation eq: 1
335   fprintf(
336       stderr, "Block parent operation eq: %d\n",
337       mlirOperationEqual(mlirBlockGetParentOperation(block), parentOperation));
338   // CHECK: Block parent region eq: 1
339   fprintf(stderr, "Block parent region eq: %d\n",
340           mlirRegionEqual(mlirBlockGetParentRegion(block), region));
341 
342   // In the module we created, the first operation of the first function is
343   // an "memref.dim", which has an attribute and a single result that we can
344   // use to test the printing mechanism.
345   mlirBlockPrint(block, printToStderr, NULL);
346   fprintf(stderr, "\n");
347   fprintf(stderr, "First operation: ");
348   mlirOperationPrint(operation, printToStderr, NULL);
349   fprintf(stderr, "\n");
350   // clang-format off
351   // CHECK:   %[[C0:.*]] = arith.constant 0 : index
352   // CHECK:   %[[DIM:.*]] = memref.dim %{{.*}}, %[[C0]] : memref<?xf32>
353   // CHECK:   %[[C1:.*]] = arith.constant 1 : index
354   // CHECK:   scf.for %[[I:.*]] = %[[C0]] to %[[DIM]] step %[[C1]] {
355   // CHECK:     %[[LHS:.*]] = memref.load %{{.*}}[%[[I]]] : memref<?xf32>
356   // CHECK:     %[[RHS:.*]] = memref.load %{{.*}}[%[[I]]] : memref<?xf32>
357   // CHECK:     %[[SUM:.*]] = arith.addf %[[LHS]], %[[RHS]] : f32
358   // CHECK:     memref.store %[[SUM]], %{{.*}}[%[[I]]] : memref<?xf32>
359   // CHECK:   }
360   // CHECK: return
361   // CHECK: First operation: {{.*}} = arith.constant 0 : index
362   // clang-format on
363 
364   // Get the operation name and print it.
365   MlirIdentifier ident = mlirOperationGetName(operation);
366   MlirStringRef identStr = mlirIdentifierStr(ident);
367   fprintf(stderr, "Operation name: '");
368   for (size_t i = 0; i < identStr.length; ++i)
369     fputc(identStr.data[i], stderr);
370   fprintf(stderr, "'\n");
371   // CHECK: Operation name: 'arith.constant'
372 
373   // Get the identifier again and verify equal.
374   MlirIdentifier identAgain = mlirIdentifierGet(ctx, identStr);
375   fprintf(stderr, "Identifier equal: %d\n",
376           mlirIdentifierEqual(ident, identAgain));
377   // CHECK: Identifier equal: 1
378 
379   // Get the block terminator and print it.
380   MlirOperation terminator = mlirBlockGetTerminator(block);
381   fprintf(stderr, "Terminator: ");
382   mlirOperationPrint(terminator, printToStderr, NULL);
383   fprintf(stderr, "\n");
384   // CHECK: Terminator: return
385 
386   // Get the attribute by index.
387   MlirNamedAttribute namedAttr0 = mlirOperationGetAttribute(operation, 0);
388   fprintf(stderr, "Get attr 0: ");
389   mlirAttributePrint(namedAttr0.attribute, printToStderr, NULL);
390   fprintf(stderr, "\n");
391   // CHECK: Get attr 0: 0 : index
392 
393   // Now re-get the attribute by name.
394   MlirAttribute attr0ByName = mlirOperationGetAttributeByName(
395       operation, mlirIdentifierStr(namedAttr0.name));
396   fprintf(stderr, "Get attr 0 by name: ");
397   mlirAttributePrint(attr0ByName, printToStderr, NULL);
398   fprintf(stderr, "\n");
399   // CHECK: Get attr 0 by name: 0 : index
400 
401   // Get a non-existing attribute and assert that it is null (sanity).
402   fprintf(stderr, "does_not_exist is null: %d\n",
403           mlirAttributeIsNull(mlirOperationGetAttributeByName(
404               operation, mlirStringRefCreateFromCString("does_not_exist"))));
405   // CHECK: does_not_exist is null: 1
406 
407   // Get result 0 and its type.
408   MlirValue value = mlirOperationGetResult(operation, 0);
409   fprintf(stderr, "Result 0: ");
410   mlirValuePrint(value, printToStderr, NULL);
411   fprintf(stderr, "\n");
412   fprintf(stderr, "Value is null: %d\n", mlirValueIsNull(value));
413   // CHECK: Result 0: {{.*}} = arith.constant 0 : index
414   // CHECK: Value is null: 0
415 
416   MlirType type = mlirValueGetType(value);
417   fprintf(stderr, "Result 0 type: ");
418   mlirTypePrint(type, printToStderr, NULL);
419   fprintf(stderr, "\n");
420   // CHECK: Result 0 type: index
421 
422   // Set a custom attribute.
423   mlirOperationSetAttributeByName(operation,
424                                   mlirStringRefCreateFromCString("custom_attr"),
425                                   mlirBoolAttrGet(ctx, 1));
426   fprintf(stderr, "Op with set attr: ");
427   mlirOperationPrint(operation, printToStderr, NULL);
428   fprintf(stderr, "\n");
429   // CHECK: Op with set attr: {{.*}} {custom_attr = true}
430 
431   // Remove the attribute.
432   fprintf(stderr, "Remove attr: %d\n",
433           mlirOperationRemoveAttributeByName(
434               operation, mlirStringRefCreateFromCString("custom_attr")));
435   fprintf(stderr, "Remove attr again: %d\n",
436           mlirOperationRemoveAttributeByName(
437               operation, mlirStringRefCreateFromCString("custom_attr")));
438   fprintf(stderr, "Removed attr is null: %d\n",
439           mlirAttributeIsNull(mlirOperationGetAttributeByName(
440               operation, mlirStringRefCreateFromCString("custom_attr"))));
441   // CHECK: Remove attr: 1
442   // CHECK: Remove attr again: 0
443   // CHECK: Removed attr is null: 1
444 
445   // Add a large attribute to verify printing flags.
446   int64_t eltsShape[] = {4};
447   int32_t eltsData[] = {1, 2, 3, 4};
448   mlirOperationSetAttributeByName(
449       operation, mlirStringRefCreateFromCString("elts"),
450       mlirDenseElementsAttrInt32Get(
451           mlirRankedTensorTypeGet(1, eltsShape, mlirIntegerTypeGet(ctx, 32),
452                                   mlirAttributeGetNull()),
453           4, eltsData));
454   MlirOpPrintingFlags flags = mlirOpPrintingFlagsCreate();
455   mlirOpPrintingFlagsElideLargeElementsAttrs(flags, 2);
456   mlirOpPrintingFlagsPrintGenericOpForm(flags);
457   mlirOpPrintingFlagsEnableDebugInfo(flags, /*prettyForm=*/0);
458   mlirOpPrintingFlagsUseLocalScope(flags);
459   fprintf(stderr, "Op print with all flags: ");
460   mlirOperationPrintWithFlags(operation, flags, printToStderr, NULL);
461   fprintf(stderr, "\n");
462   // clang-format off
463   // CHECK: Op print with all flags: %{{.*}} = "arith.constant"() {elts = opaque<"_", "0xDEADBEEF"> : tensor<4xi32>, value = 0 : index} : () -> index loc(unknown)
464   // clang-format on
465 
466   mlirOpPrintingFlagsDestroy(flags);
467 }
468 
469 static int constructAndTraverseIr(MlirContext ctx) {
470   MlirLocation location = mlirLocationUnknownGet(ctx);
471 
472   MlirModule moduleOp = makeAndDumpAdd(ctx, location);
473   MlirOperation module = mlirModuleGetOperation(moduleOp);
474   assert(!mlirModuleIsNull(mlirModuleFromOperation(module)));
475 
476   int errcode = collectStats(module);
477   if (errcode)
478     return errcode;
479 
480   printFirstOfEach(ctx, module);
481 
482   mlirModuleDestroy(moduleOp);
483   return 0;
484 }
485 
486 /// Creates an operation with a region containing multiple blocks with
487 /// operations and dumps it. The blocks and operations are inserted using
488 /// block/operation-relative API and their final order is checked.
489 static void buildWithInsertionsAndPrint(MlirContext ctx) {
490   MlirLocation loc = mlirLocationUnknownGet(ctx);
491   mlirContextSetAllowUnregisteredDialects(ctx, true);
492 
493   MlirRegion owningRegion = mlirRegionCreate();
494   MlirBlock nullBlock = mlirRegionGetFirstBlock(owningRegion);
495   MlirOperationState state = mlirOperationStateGet(
496       mlirStringRefCreateFromCString("insertion.order.test"), loc);
497   mlirOperationStateAddOwnedRegions(&state, 1, &owningRegion);
498   MlirOperation op = mlirOperationCreate(&state);
499   MlirRegion region = mlirOperationGetRegion(op, 0);
500 
501   // Use integer types of different bitwidth as block arguments in order to
502   // differentiate blocks.
503   MlirType i1 = mlirIntegerTypeGet(ctx, 1);
504   MlirType i2 = mlirIntegerTypeGet(ctx, 2);
505   MlirType i3 = mlirIntegerTypeGet(ctx, 3);
506   MlirType i4 = mlirIntegerTypeGet(ctx, 4);
507   MlirBlock block1 = mlirBlockCreate(1, &i1);
508   MlirBlock block2 = mlirBlockCreate(1, &i2);
509   MlirBlock block3 = mlirBlockCreate(1, &i3);
510   MlirBlock block4 = mlirBlockCreate(1, &i4);
511   // Insert blocks so as to obtain the 1-2-3-4 order,
512   mlirRegionInsertOwnedBlockBefore(region, nullBlock, block3);
513   mlirRegionInsertOwnedBlockBefore(region, block3, block2);
514   mlirRegionInsertOwnedBlockAfter(region, nullBlock, block1);
515   mlirRegionInsertOwnedBlockAfter(region, block3, block4);
516 
517   MlirOperationState op1State =
518       mlirOperationStateGet(mlirStringRefCreateFromCString("dummy.op1"), loc);
519   MlirOperationState op2State =
520       mlirOperationStateGet(mlirStringRefCreateFromCString("dummy.op2"), loc);
521   MlirOperationState op3State =
522       mlirOperationStateGet(mlirStringRefCreateFromCString("dummy.op3"), loc);
523   MlirOperationState op4State =
524       mlirOperationStateGet(mlirStringRefCreateFromCString("dummy.op4"), loc);
525   MlirOperationState op5State =
526       mlirOperationStateGet(mlirStringRefCreateFromCString("dummy.op5"), loc);
527   MlirOperationState op6State =
528       mlirOperationStateGet(mlirStringRefCreateFromCString("dummy.op6"), loc);
529   MlirOperationState op7State =
530       mlirOperationStateGet(mlirStringRefCreateFromCString("dummy.op7"), loc);
531   MlirOperation op1 = mlirOperationCreate(&op1State);
532   MlirOperation op2 = mlirOperationCreate(&op2State);
533   MlirOperation op3 = mlirOperationCreate(&op3State);
534   MlirOperation op4 = mlirOperationCreate(&op4State);
535   MlirOperation op5 = mlirOperationCreate(&op5State);
536   MlirOperation op6 = mlirOperationCreate(&op6State);
537   MlirOperation op7 = mlirOperationCreate(&op7State);
538 
539   // Insert operations in the first block so as to obtain the 1-2-3-4 order.
540   MlirOperation nullOperation = mlirBlockGetFirstOperation(block1);
541   assert(mlirOperationIsNull(nullOperation));
542   mlirBlockInsertOwnedOperationBefore(block1, nullOperation, op3);
543   mlirBlockInsertOwnedOperationBefore(block1, op3, op2);
544   mlirBlockInsertOwnedOperationAfter(block1, nullOperation, op1);
545   mlirBlockInsertOwnedOperationAfter(block1, op3, op4);
546 
547   // Append operations to the rest of blocks to make them non-empty and thus
548   // printable.
549   mlirBlockAppendOwnedOperation(block2, op5);
550   mlirBlockAppendOwnedOperation(block3, op6);
551   mlirBlockAppendOwnedOperation(block4, op7);
552 
553   mlirOperationDump(op);
554   mlirOperationDestroy(op);
555   mlirContextSetAllowUnregisteredDialects(ctx, false);
556   // clang-format off
557   // CHECK-LABEL:  "insertion.order.test"
558   // CHECK:      ^{{.*}}(%{{.*}}: i1
559   // CHECK:        "dummy.op1"
560   // CHECK-NEXT:   "dummy.op2"
561   // CHECK-NEXT:   "dummy.op3"
562   // CHECK-NEXT:   "dummy.op4"
563   // CHECK:      ^{{.*}}(%{{.*}}: i2
564   // CHECK:        "dummy.op5"
565   // CHECK:      ^{{.*}}(%{{.*}}: i3
566   // CHECK:        "dummy.op6"
567   // CHECK:      ^{{.*}}(%{{.*}}: i4
568   // CHECK:        "dummy.op7"
569   // clang-format on
570 }
571 
572 /// Creates operations with type inference and tests various failure modes.
573 static int createOperationWithTypeInference(MlirContext ctx) {
574   MlirLocation loc = mlirLocationUnknownGet(ctx);
575   MlirAttribute iAttr = mlirIntegerAttrGet(mlirIntegerTypeGet(ctx, 32), 4);
576 
577   // The shape.const_size op implements result type inference and is only used
578   // for that reason.
579   MlirOperationState state = mlirOperationStateGet(
580       mlirStringRefCreateFromCString("shape.const_size"), loc);
581   MlirNamedAttribute valueAttr = mlirNamedAttributeGet(
582       mlirIdentifierGet(ctx, mlirStringRefCreateFromCString("value")), iAttr);
583   mlirOperationStateAddAttributes(&state, 1, &valueAttr);
584   mlirOperationStateEnableResultTypeInference(&state);
585 
586   // Expect result type inference to succeed.
587   MlirOperation op = mlirOperationCreate(&state);
588   if (mlirOperationIsNull(op)) {
589     fprintf(stderr, "ERROR: Result type inference unexpectedly failed");
590     return 1;
591   }
592 
593   // CHECK: RESULT_TYPE_INFERENCE: !shape.size
594   fprintf(stderr, "RESULT_TYPE_INFERENCE: ");
595   mlirTypeDump(mlirValueGetType(mlirOperationGetResult(op, 0)));
596   fprintf(stderr, "\n");
597   mlirOperationDestroy(op);
598   return 0;
599 }
600 
601 /// Dumps instances of all builtin types to check that C API works correctly.
602 /// Additionally, performs simple identity checks that a builtin type
603 /// constructed with C API can be inspected and has the expected type. The
604 /// latter achieves full coverage of C API for builtin types. Returns 0 on
605 /// success and a non-zero error code on failure.
606 static int printBuiltinTypes(MlirContext ctx) {
607   // Integer types.
608   MlirType i32 = mlirIntegerTypeGet(ctx, 32);
609   MlirType si32 = mlirIntegerTypeSignedGet(ctx, 32);
610   MlirType ui32 = mlirIntegerTypeUnsignedGet(ctx, 32);
611   if (!mlirTypeIsAInteger(i32) || mlirTypeIsAF32(i32))
612     return 1;
613   if (!mlirTypeIsAInteger(si32) || !mlirIntegerTypeIsSigned(si32))
614     return 2;
615   if (!mlirTypeIsAInteger(ui32) || !mlirIntegerTypeIsUnsigned(ui32))
616     return 3;
617   if (mlirTypeEqual(i32, ui32) || mlirTypeEqual(i32, si32))
618     return 4;
619   if (mlirIntegerTypeGetWidth(i32) != mlirIntegerTypeGetWidth(si32))
620     return 5;
621   fprintf(stderr, "@types\n");
622   mlirTypeDump(i32);
623   fprintf(stderr, "\n");
624   mlirTypeDump(si32);
625   fprintf(stderr, "\n");
626   mlirTypeDump(ui32);
627   fprintf(stderr, "\n");
628   // CHECK-LABEL: @types
629   // CHECK: i32
630   // CHECK: si32
631   // CHECK: ui32
632 
633   // Index type.
634   MlirType index = mlirIndexTypeGet(ctx);
635   if (!mlirTypeIsAIndex(index))
636     return 6;
637   mlirTypeDump(index);
638   fprintf(stderr, "\n");
639   // CHECK: index
640 
641   // Floating-point types.
642   MlirType bf16 = mlirBF16TypeGet(ctx);
643   MlirType f16 = mlirF16TypeGet(ctx);
644   MlirType f32 = mlirF32TypeGet(ctx);
645   MlirType f64 = mlirF64TypeGet(ctx);
646   if (!mlirTypeIsABF16(bf16))
647     return 7;
648   if (!mlirTypeIsAF16(f16))
649     return 9;
650   if (!mlirTypeIsAF32(f32))
651     return 10;
652   if (!mlirTypeIsAF64(f64))
653     return 11;
654   mlirTypeDump(bf16);
655   fprintf(stderr, "\n");
656   mlirTypeDump(f16);
657   fprintf(stderr, "\n");
658   mlirTypeDump(f32);
659   fprintf(stderr, "\n");
660   mlirTypeDump(f64);
661   fprintf(stderr, "\n");
662   // CHECK: bf16
663   // CHECK: f16
664   // CHECK: f32
665   // CHECK: f64
666 
667   // None type.
668   MlirType none = mlirNoneTypeGet(ctx);
669   if (!mlirTypeIsANone(none))
670     return 12;
671   mlirTypeDump(none);
672   fprintf(stderr, "\n");
673   // CHECK: none
674 
675   // Complex type.
676   MlirType cplx = mlirComplexTypeGet(f32);
677   if (!mlirTypeIsAComplex(cplx) ||
678       !mlirTypeEqual(mlirComplexTypeGetElementType(cplx), f32))
679     return 13;
680   mlirTypeDump(cplx);
681   fprintf(stderr, "\n");
682   // CHECK: complex<f32>
683 
684   // Vector (and Shaped) type. ShapedType is a common base class for vectors,
685   // memrefs and tensors, one cannot create instances of this class so it is
686   // tested on an instance of vector type.
687   int64_t shape[] = {2, 3};
688   MlirType vector =
689       mlirVectorTypeGet(sizeof(shape) / sizeof(int64_t), shape, f32);
690   if (!mlirTypeIsAVector(vector) || !mlirTypeIsAShaped(vector))
691     return 14;
692   if (!mlirTypeEqual(mlirShapedTypeGetElementType(vector), f32) ||
693       !mlirShapedTypeHasRank(vector) || mlirShapedTypeGetRank(vector) != 2 ||
694       mlirShapedTypeGetDimSize(vector, 0) != 2 ||
695       mlirShapedTypeIsDynamicDim(vector, 0) ||
696       mlirShapedTypeGetDimSize(vector, 1) != 3 ||
697       !mlirShapedTypeHasStaticShape(vector))
698     return 15;
699   mlirTypeDump(vector);
700   fprintf(stderr, "\n");
701   // CHECK: vector<2x3xf32>
702 
703   // Ranked tensor type.
704   MlirType rankedTensor = mlirRankedTensorTypeGet(
705       sizeof(shape) / sizeof(int64_t), shape, f32, mlirAttributeGetNull());
706   if (!mlirTypeIsATensor(rankedTensor) ||
707       !mlirTypeIsARankedTensor(rankedTensor) ||
708       !mlirAttributeIsNull(mlirRankedTensorTypeGetEncoding(rankedTensor)))
709     return 16;
710   mlirTypeDump(rankedTensor);
711   fprintf(stderr, "\n");
712   // CHECK: tensor<2x3xf32>
713 
714   // Unranked tensor type.
715   MlirType unrankedTensor = mlirUnrankedTensorTypeGet(f32);
716   if (!mlirTypeIsATensor(unrankedTensor) ||
717       !mlirTypeIsAUnrankedTensor(unrankedTensor) ||
718       mlirShapedTypeHasRank(unrankedTensor))
719     return 17;
720   mlirTypeDump(unrankedTensor);
721   fprintf(stderr, "\n");
722   // CHECK: tensor<*xf32>
723 
724   // MemRef type.
725   MlirAttribute memSpace2 = mlirIntegerAttrGet(mlirIntegerTypeGet(ctx, 64), 2);
726   MlirType memRef = mlirMemRefTypeContiguousGet(
727       f32, sizeof(shape) / sizeof(int64_t), shape, memSpace2);
728   if (!mlirTypeIsAMemRef(memRef) ||
729       !mlirAttributeEqual(mlirMemRefTypeGetMemorySpace(memRef), memSpace2))
730     return 18;
731   mlirTypeDump(memRef);
732   fprintf(stderr, "\n");
733   // CHECK: memref<2x3xf32, 2>
734 
735   // Unranked MemRef type.
736   MlirAttribute memSpace4 = mlirIntegerAttrGet(mlirIntegerTypeGet(ctx, 64), 4);
737   MlirType unrankedMemRef = mlirUnrankedMemRefTypeGet(f32, memSpace4);
738   if (!mlirTypeIsAUnrankedMemRef(unrankedMemRef) ||
739       mlirTypeIsAMemRef(unrankedMemRef) ||
740       !mlirAttributeEqual(mlirUnrankedMemrefGetMemorySpace(unrankedMemRef),
741                           memSpace4))
742     return 19;
743   mlirTypeDump(unrankedMemRef);
744   fprintf(stderr, "\n");
745   // CHECK: memref<*xf32, 4>
746 
747   // Tuple type.
748   MlirType types[] = {unrankedMemRef, f32};
749   MlirType tuple = mlirTupleTypeGet(ctx, 2, types);
750   if (!mlirTypeIsATuple(tuple) || mlirTupleTypeGetNumTypes(tuple) != 2 ||
751       !mlirTypeEqual(mlirTupleTypeGetType(tuple, 0), unrankedMemRef) ||
752       !mlirTypeEqual(mlirTupleTypeGetType(tuple, 1), f32))
753     return 20;
754   mlirTypeDump(tuple);
755   fprintf(stderr, "\n");
756   // CHECK: tuple<memref<*xf32, 4>, f32>
757 
758   // Function type.
759   MlirType funcInputs[2] = {mlirIndexTypeGet(ctx), mlirIntegerTypeGet(ctx, 1)};
760   MlirType funcResults[3] = {mlirIntegerTypeGet(ctx, 16),
761                              mlirIntegerTypeGet(ctx, 32),
762                              mlirIntegerTypeGet(ctx, 64)};
763   MlirType funcType = mlirFunctionTypeGet(ctx, 2, funcInputs, 3, funcResults);
764   if (mlirFunctionTypeGetNumInputs(funcType) != 2)
765     return 21;
766   if (mlirFunctionTypeGetNumResults(funcType) != 3)
767     return 22;
768   if (!mlirTypeEqual(funcInputs[0], mlirFunctionTypeGetInput(funcType, 0)) ||
769       !mlirTypeEqual(funcInputs[1], mlirFunctionTypeGetInput(funcType, 1)))
770     return 23;
771   if (!mlirTypeEqual(funcResults[0], mlirFunctionTypeGetResult(funcType, 0)) ||
772       !mlirTypeEqual(funcResults[1], mlirFunctionTypeGetResult(funcType, 1)) ||
773       !mlirTypeEqual(funcResults[2], mlirFunctionTypeGetResult(funcType, 2)))
774     return 24;
775   mlirTypeDump(funcType);
776   fprintf(stderr, "\n");
777   // CHECK: (index, i1) -> (i16, i32, i64)
778 
779   return 0;
780 }
781 
782 void callbackSetFixedLengthString(const char *data, intptr_t len,
783                                   void *userData) {
784   strncpy(userData, data, len);
785 }
786 
787 bool stringIsEqual(const char *lhs, MlirStringRef rhs) {
788   if (strlen(lhs) != rhs.length) {
789     return false;
790   }
791   return !strncmp(lhs, rhs.data, rhs.length);
792 }
793 
794 int printBuiltinAttributes(MlirContext ctx) {
795   MlirAttribute floating =
796       mlirFloatAttrDoubleGet(ctx, mlirF64TypeGet(ctx), 2.0);
797   if (!mlirAttributeIsAFloat(floating) ||
798       fabs(mlirFloatAttrGetValueDouble(floating) - 2.0) > 1E-6)
799     return 1;
800   fprintf(stderr, "@attrs\n");
801   mlirAttributeDump(floating);
802   // CHECK-LABEL: @attrs
803   // CHECK: 2.000000e+00 : f64
804 
805   // Exercise mlirAttributeGetType() just for the first one.
806   MlirType floatingType = mlirAttributeGetType(floating);
807   mlirTypeDump(floatingType);
808   // CHECK: f64
809 
810   MlirAttribute integer = mlirIntegerAttrGet(mlirIntegerTypeGet(ctx, 32), 42);
811   if (!mlirAttributeIsAInteger(integer) ||
812       mlirIntegerAttrGetValueInt(integer) != 42)
813     return 2;
814   mlirAttributeDump(integer);
815   // CHECK: 42 : i32
816 
817   MlirAttribute boolean = mlirBoolAttrGet(ctx, 1);
818   if (!mlirAttributeIsABool(boolean) || !mlirBoolAttrGetValue(boolean))
819     return 3;
820   mlirAttributeDump(boolean);
821   // CHECK: true
822 
823   const char data[] = "abcdefghijklmnopqestuvwxyz";
824   MlirAttribute opaque =
825       mlirOpaqueAttrGet(ctx, mlirStringRefCreateFromCString("std"), 3, data,
826                         mlirNoneTypeGet(ctx));
827   if (!mlirAttributeIsAOpaque(opaque) ||
828       !stringIsEqual("std", mlirOpaqueAttrGetDialectNamespace(opaque)))
829     return 4;
830 
831   MlirStringRef opaqueData = mlirOpaqueAttrGetData(opaque);
832   if (opaqueData.length != 3 ||
833       strncmp(data, opaqueData.data, opaqueData.length))
834     return 5;
835   mlirAttributeDump(opaque);
836   // CHECK: #std.abc
837 
838   MlirAttribute string =
839       mlirStringAttrGet(ctx, mlirStringRefCreate(data + 3, 2));
840   if (!mlirAttributeIsAString(string))
841     return 6;
842 
843   MlirStringRef stringValue = mlirStringAttrGetValue(string);
844   if (stringValue.length != 2 ||
845       strncmp(data + 3, stringValue.data, stringValue.length))
846     return 7;
847   mlirAttributeDump(string);
848   // CHECK: "de"
849 
850   MlirAttribute flatSymbolRef =
851       mlirFlatSymbolRefAttrGet(ctx, mlirStringRefCreate(data + 5, 3));
852   if (!mlirAttributeIsAFlatSymbolRef(flatSymbolRef))
853     return 8;
854 
855   MlirStringRef flatSymbolRefValue =
856       mlirFlatSymbolRefAttrGetValue(flatSymbolRef);
857   if (flatSymbolRefValue.length != 3 ||
858       strncmp(data + 5, flatSymbolRefValue.data, flatSymbolRefValue.length))
859     return 9;
860   mlirAttributeDump(flatSymbolRef);
861   // CHECK: @fgh
862 
863   MlirAttribute symbols[] = {flatSymbolRef, flatSymbolRef};
864   MlirAttribute symbolRef =
865       mlirSymbolRefAttrGet(ctx, mlirStringRefCreate(data + 8, 2), 2, symbols);
866   if (!mlirAttributeIsASymbolRef(symbolRef) ||
867       mlirSymbolRefAttrGetNumNestedReferences(symbolRef) != 2 ||
868       !mlirAttributeEqual(mlirSymbolRefAttrGetNestedReference(symbolRef, 0),
869                           flatSymbolRef) ||
870       !mlirAttributeEqual(mlirSymbolRefAttrGetNestedReference(symbolRef, 1),
871                           flatSymbolRef))
872     return 10;
873 
874   MlirStringRef symbolRefLeaf = mlirSymbolRefAttrGetLeafReference(symbolRef);
875   MlirStringRef symbolRefRoot = mlirSymbolRefAttrGetRootReference(symbolRef);
876   if (symbolRefLeaf.length != 3 ||
877       strncmp(data + 5, symbolRefLeaf.data, symbolRefLeaf.length) ||
878       symbolRefRoot.length != 2 ||
879       strncmp(data + 8, symbolRefRoot.data, symbolRefRoot.length))
880     return 11;
881   mlirAttributeDump(symbolRef);
882   // CHECK: @ij::@fgh::@fgh
883 
884   MlirAttribute type = mlirTypeAttrGet(mlirF32TypeGet(ctx));
885   if (!mlirAttributeIsAType(type) ||
886       !mlirTypeEqual(mlirF32TypeGet(ctx), mlirTypeAttrGetValue(type)))
887     return 12;
888   mlirAttributeDump(type);
889   // CHECK: f32
890 
891   MlirAttribute unit = mlirUnitAttrGet(ctx);
892   if (!mlirAttributeIsAUnit(unit))
893     return 13;
894   mlirAttributeDump(unit);
895   // CHECK: unit
896 
897   int64_t shape[] = {1, 2};
898 
899   int bools[] = {0, 1};
900   uint8_t uints8[] = {0u, 1u};
901   int8_t ints8[] = {0, 1};
902   uint32_t uints32[] = {0u, 1u};
903   int32_t ints32[] = {0, 1};
904   uint64_t uints64[] = {0u, 1u};
905   int64_t ints64[] = {0, 1};
906   float floats[] = {0.0f, 1.0f};
907   double doubles[] = {0.0, 1.0};
908   MlirAttribute encoding = mlirAttributeGetNull();
909   MlirAttribute boolElements = mlirDenseElementsAttrBoolGet(
910       mlirRankedTensorTypeGet(2, shape, mlirIntegerTypeGet(ctx, 1), encoding),
911       2, bools);
912   MlirAttribute uint8Elements = mlirDenseElementsAttrUInt8Get(
913       mlirRankedTensorTypeGet(2, shape, mlirIntegerTypeUnsignedGet(ctx, 8),
914                               encoding),
915       2, uints8);
916   MlirAttribute int8Elements = mlirDenseElementsAttrInt8Get(
917       mlirRankedTensorTypeGet(2, shape, mlirIntegerTypeGet(ctx, 8), encoding),
918       2, ints8);
919   MlirAttribute uint32Elements = mlirDenseElementsAttrUInt32Get(
920       mlirRankedTensorTypeGet(2, shape, mlirIntegerTypeUnsignedGet(ctx, 32),
921                               encoding),
922       2, uints32);
923   MlirAttribute int32Elements = mlirDenseElementsAttrInt32Get(
924       mlirRankedTensorTypeGet(2, shape, mlirIntegerTypeGet(ctx, 32), encoding),
925       2, ints32);
926   MlirAttribute uint64Elements = mlirDenseElementsAttrUInt64Get(
927       mlirRankedTensorTypeGet(2, shape, mlirIntegerTypeUnsignedGet(ctx, 64),
928                               encoding),
929       2, uints64);
930   MlirAttribute int64Elements = mlirDenseElementsAttrInt64Get(
931       mlirRankedTensorTypeGet(2, shape, mlirIntegerTypeGet(ctx, 64), encoding),
932       2, ints64);
933   MlirAttribute floatElements = mlirDenseElementsAttrFloatGet(
934       mlirRankedTensorTypeGet(2, shape, mlirF32TypeGet(ctx), encoding), 2,
935       floats);
936   MlirAttribute doubleElements = mlirDenseElementsAttrDoubleGet(
937       mlirRankedTensorTypeGet(2, shape, mlirF64TypeGet(ctx), encoding), 2,
938       doubles);
939 
940   if (!mlirAttributeIsADenseElements(boolElements) ||
941       !mlirAttributeIsADenseElements(uint8Elements) ||
942       !mlirAttributeIsADenseElements(int8Elements) ||
943       !mlirAttributeIsADenseElements(uint32Elements) ||
944       !mlirAttributeIsADenseElements(int32Elements) ||
945       !mlirAttributeIsADenseElements(uint64Elements) ||
946       !mlirAttributeIsADenseElements(int64Elements) ||
947       !mlirAttributeIsADenseElements(floatElements) ||
948       !mlirAttributeIsADenseElements(doubleElements))
949     return 14;
950 
951   if (mlirDenseElementsAttrGetBoolValue(boolElements, 1) != 1 ||
952       mlirDenseElementsAttrGetUInt8Value(uint8Elements, 1) != 1 ||
953       mlirDenseElementsAttrGetInt8Value(int8Elements, 1) != 1 ||
954       mlirDenseElementsAttrGetUInt32Value(uint32Elements, 1) != 1 ||
955       mlirDenseElementsAttrGetInt32Value(int32Elements, 1) != 1 ||
956       mlirDenseElementsAttrGetUInt64Value(uint64Elements, 1) != 1 ||
957       mlirDenseElementsAttrGetInt64Value(int64Elements, 1) != 1 ||
958       fabsf(mlirDenseElementsAttrGetFloatValue(floatElements, 1) - 1.0f) >
959           1E-6f ||
960       fabs(mlirDenseElementsAttrGetDoubleValue(doubleElements, 1) - 1.0) > 1E-6)
961     return 15;
962 
963   mlirAttributeDump(boolElements);
964   mlirAttributeDump(uint8Elements);
965   mlirAttributeDump(int8Elements);
966   mlirAttributeDump(uint32Elements);
967   mlirAttributeDump(int32Elements);
968   mlirAttributeDump(uint64Elements);
969   mlirAttributeDump(int64Elements);
970   mlirAttributeDump(floatElements);
971   mlirAttributeDump(doubleElements);
972   // CHECK: dense<{{\[}}[false, true]]> : tensor<1x2xi1>
973   // CHECK: dense<{{\[}}[0, 1]]> : tensor<1x2xui8>
974   // CHECK: dense<{{\[}}[0, 1]]> : tensor<1x2xi8>
975   // CHECK: dense<{{\[}}[0, 1]]> : tensor<1x2xui32>
976   // CHECK: dense<{{\[}}[0, 1]]> : tensor<1x2xi32>
977   // CHECK: dense<{{\[}}[0, 1]]> : tensor<1x2xui64>
978   // CHECK: dense<{{\[}}[0, 1]]> : tensor<1x2xi64>
979   // CHECK: dense<{{\[}}[0.000000e+00, 1.000000e+00]]> : tensor<1x2xf32>
980   // CHECK: dense<{{\[}}[0.000000e+00, 1.000000e+00]]> : tensor<1x2xf64>
981 
982   MlirAttribute splatBool = mlirDenseElementsAttrBoolSplatGet(
983       mlirRankedTensorTypeGet(2, shape, mlirIntegerTypeGet(ctx, 1), encoding),
984       1);
985   MlirAttribute splatUInt8 = mlirDenseElementsAttrUInt8SplatGet(
986       mlirRankedTensorTypeGet(2, shape, mlirIntegerTypeUnsignedGet(ctx, 8),
987                               encoding),
988       1);
989   MlirAttribute splatInt8 = mlirDenseElementsAttrInt8SplatGet(
990       mlirRankedTensorTypeGet(2, shape, mlirIntegerTypeGet(ctx, 8), encoding),
991       1);
992   MlirAttribute splatUInt32 = mlirDenseElementsAttrUInt32SplatGet(
993       mlirRankedTensorTypeGet(2, shape, mlirIntegerTypeUnsignedGet(ctx, 32),
994                               encoding),
995       1);
996   MlirAttribute splatInt32 = mlirDenseElementsAttrInt32SplatGet(
997       mlirRankedTensorTypeGet(2, shape, mlirIntegerTypeGet(ctx, 32), encoding),
998       1);
999   MlirAttribute splatUInt64 = mlirDenseElementsAttrUInt64SplatGet(
1000       mlirRankedTensorTypeGet(2, shape, mlirIntegerTypeUnsignedGet(ctx, 64),
1001                               encoding),
1002       1);
1003   MlirAttribute splatInt64 = mlirDenseElementsAttrInt64SplatGet(
1004       mlirRankedTensorTypeGet(2, shape, mlirIntegerTypeGet(ctx, 64), encoding),
1005       1);
1006   MlirAttribute splatFloat = mlirDenseElementsAttrFloatSplatGet(
1007       mlirRankedTensorTypeGet(2, shape, mlirF32TypeGet(ctx), encoding), 1.0f);
1008   MlirAttribute splatDouble = mlirDenseElementsAttrDoubleSplatGet(
1009       mlirRankedTensorTypeGet(2, shape, mlirF64TypeGet(ctx), encoding), 1.0);
1010 
1011   if (!mlirAttributeIsADenseElements(splatBool) ||
1012       !mlirDenseElementsAttrIsSplat(splatBool) ||
1013       !mlirAttributeIsADenseElements(splatUInt8) ||
1014       !mlirDenseElementsAttrIsSplat(splatUInt8) ||
1015       !mlirAttributeIsADenseElements(splatInt8) ||
1016       !mlirDenseElementsAttrIsSplat(splatInt8) ||
1017       !mlirAttributeIsADenseElements(splatUInt32) ||
1018       !mlirDenseElementsAttrIsSplat(splatUInt32) ||
1019       !mlirAttributeIsADenseElements(splatInt32) ||
1020       !mlirDenseElementsAttrIsSplat(splatInt32) ||
1021       !mlirAttributeIsADenseElements(splatUInt64) ||
1022       !mlirDenseElementsAttrIsSplat(splatUInt64) ||
1023       !mlirAttributeIsADenseElements(splatInt64) ||
1024       !mlirDenseElementsAttrIsSplat(splatInt64) ||
1025       !mlirAttributeIsADenseElements(splatFloat) ||
1026       !mlirDenseElementsAttrIsSplat(splatFloat) ||
1027       !mlirAttributeIsADenseElements(splatDouble) ||
1028       !mlirDenseElementsAttrIsSplat(splatDouble))
1029     return 16;
1030 
1031   if (mlirDenseElementsAttrGetBoolSplatValue(splatBool) != 1 ||
1032       mlirDenseElementsAttrGetUInt8SplatValue(splatUInt8) != 1 ||
1033       mlirDenseElementsAttrGetInt8SplatValue(splatInt8) != 1 ||
1034       mlirDenseElementsAttrGetUInt32SplatValue(splatUInt32) != 1 ||
1035       mlirDenseElementsAttrGetInt32SplatValue(splatInt32) != 1 ||
1036       mlirDenseElementsAttrGetUInt64SplatValue(splatUInt64) != 1 ||
1037       mlirDenseElementsAttrGetInt64SplatValue(splatInt64) != 1 ||
1038       fabsf(mlirDenseElementsAttrGetFloatSplatValue(splatFloat) - 1.0f) >
1039           1E-6f ||
1040       fabs(mlirDenseElementsAttrGetDoubleSplatValue(splatDouble) - 1.0) > 1E-6)
1041     return 17;
1042 
1043   uint8_t *uint8RawData =
1044       (uint8_t *)mlirDenseElementsAttrGetRawData(uint8Elements);
1045   int8_t *int8RawData = (int8_t *)mlirDenseElementsAttrGetRawData(int8Elements);
1046   uint32_t *uint32RawData =
1047       (uint32_t *)mlirDenseElementsAttrGetRawData(uint32Elements);
1048   int32_t *int32RawData =
1049       (int32_t *)mlirDenseElementsAttrGetRawData(int32Elements);
1050   uint64_t *uint64RawData =
1051       (uint64_t *)mlirDenseElementsAttrGetRawData(uint64Elements);
1052   int64_t *int64RawData =
1053       (int64_t *)mlirDenseElementsAttrGetRawData(int64Elements);
1054   float *floatRawData = (float *)mlirDenseElementsAttrGetRawData(floatElements);
1055   double *doubleRawData =
1056       (double *)mlirDenseElementsAttrGetRawData(doubleElements);
1057   if (uint8RawData[0] != 0u || uint8RawData[1] != 1u || int8RawData[0] != 0 ||
1058       int8RawData[1] != 1 || uint32RawData[0] != 0u || uint32RawData[1] != 1u ||
1059       int32RawData[0] != 0 || int32RawData[1] != 1 || uint64RawData[0] != 0u ||
1060       uint64RawData[1] != 1u || int64RawData[0] != 0 || int64RawData[1] != 1 ||
1061       floatRawData[0] != 0.0f || floatRawData[1] != 1.0f ||
1062       doubleRawData[0] != 0.0 || doubleRawData[1] != 1.0)
1063     return 18;
1064 
1065   mlirAttributeDump(splatBool);
1066   mlirAttributeDump(splatUInt8);
1067   mlirAttributeDump(splatInt8);
1068   mlirAttributeDump(splatUInt32);
1069   mlirAttributeDump(splatInt32);
1070   mlirAttributeDump(splatUInt64);
1071   mlirAttributeDump(splatInt64);
1072   mlirAttributeDump(splatFloat);
1073   mlirAttributeDump(splatDouble);
1074   // CHECK: dense<true> : tensor<1x2xi1>
1075   // CHECK: dense<1> : tensor<1x2xui8>
1076   // CHECK: dense<1> : tensor<1x2xi8>
1077   // CHECK: dense<1> : tensor<1x2xui32>
1078   // CHECK: dense<1> : tensor<1x2xi32>
1079   // CHECK: dense<1> : tensor<1x2xui64>
1080   // CHECK: dense<1> : tensor<1x2xi64>
1081   // CHECK: dense<1.000000e+00> : tensor<1x2xf32>
1082   // CHECK: dense<1.000000e+00> : tensor<1x2xf64>
1083 
1084   mlirAttributeDump(mlirElementsAttrGetValue(floatElements, 2, uints64));
1085   mlirAttributeDump(mlirElementsAttrGetValue(doubleElements, 2, uints64));
1086   // CHECK: 1.000000e+00 : f32
1087   // CHECK: 1.000000e+00 : f64
1088 
1089   int64_t indices[] = {0, 1};
1090   int64_t one = 1;
1091   MlirAttribute indicesAttr = mlirDenseElementsAttrInt64Get(
1092       mlirRankedTensorTypeGet(2, shape, mlirIntegerTypeGet(ctx, 64), encoding),
1093       2, indices);
1094   MlirAttribute valuesAttr = mlirDenseElementsAttrFloatGet(
1095       mlirRankedTensorTypeGet(1, &one, mlirF32TypeGet(ctx), encoding), 1,
1096       floats);
1097   MlirAttribute sparseAttr = mlirSparseElementsAttribute(
1098       mlirRankedTensorTypeGet(2, shape, mlirF32TypeGet(ctx), encoding),
1099       indicesAttr, valuesAttr);
1100   mlirAttributeDump(sparseAttr);
1101   // CHECK: sparse<{{\[}}[0, 1]], 0.000000e+00> : tensor<1x2xf32>
1102 
1103   return 0;
1104 }
1105 
1106 int printAffineMap(MlirContext ctx) {
1107   MlirAffineMap emptyAffineMap = mlirAffineMapEmptyGet(ctx);
1108   MlirAffineMap affineMap = mlirAffineMapZeroResultGet(ctx, 3, 2);
1109   MlirAffineMap constAffineMap = mlirAffineMapConstantGet(ctx, 2);
1110   MlirAffineMap multiDimIdentityAffineMap =
1111       mlirAffineMapMultiDimIdentityGet(ctx, 3);
1112   MlirAffineMap minorIdentityAffineMap =
1113       mlirAffineMapMinorIdentityGet(ctx, 3, 2);
1114   unsigned permutation[] = {1, 2, 0};
1115   MlirAffineMap permutationAffineMap = mlirAffineMapPermutationGet(
1116       ctx, sizeof(permutation) / sizeof(unsigned), permutation);
1117 
1118   fprintf(stderr, "@affineMap\n");
1119   mlirAffineMapDump(emptyAffineMap);
1120   mlirAffineMapDump(affineMap);
1121   mlirAffineMapDump(constAffineMap);
1122   mlirAffineMapDump(multiDimIdentityAffineMap);
1123   mlirAffineMapDump(minorIdentityAffineMap);
1124   mlirAffineMapDump(permutationAffineMap);
1125   // CHECK-LABEL: @affineMap
1126   // CHECK: () -> ()
1127   // CHECK: (d0, d1, d2)[s0, s1] -> ()
1128   // CHECK: () -> (2)
1129   // CHECK: (d0, d1, d2) -> (d0, d1, d2)
1130   // CHECK: (d0, d1, d2) -> (d1, d2)
1131   // CHECK: (d0, d1, d2) -> (d1, d2, d0)
1132 
1133   if (!mlirAffineMapIsIdentity(emptyAffineMap) ||
1134       mlirAffineMapIsIdentity(affineMap) ||
1135       mlirAffineMapIsIdentity(constAffineMap) ||
1136       !mlirAffineMapIsIdentity(multiDimIdentityAffineMap) ||
1137       mlirAffineMapIsIdentity(minorIdentityAffineMap) ||
1138       mlirAffineMapIsIdentity(permutationAffineMap))
1139     return 1;
1140 
1141   if (!mlirAffineMapIsMinorIdentity(emptyAffineMap) ||
1142       mlirAffineMapIsMinorIdentity(affineMap) ||
1143       !mlirAffineMapIsMinorIdentity(multiDimIdentityAffineMap) ||
1144       !mlirAffineMapIsMinorIdentity(minorIdentityAffineMap) ||
1145       mlirAffineMapIsMinorIdentity(permutationAffineMap))
1146     return 2;
1147 
1148   if (!mlirAffineMapIsEmpty(emptyAffineMap) ||
1149       mlirAffineMapIsEmpty(affineMap) || mlirAffineMapIsEmpty(constAffineMap) ||
1150       mlirAffineMapIsEmpty(multiDimIdentityAffineMap) ||
1151       mlirAffineMapIsEmpty(minorIdentityAffineMap) ||
1152       mlirAffineMapIsEmpty(permutationAffineMap))
1153     return 3;
1154 
1155   if (mlirAffineMapIsSingleConstant(emptyAffineMap) ||
1156       mlirAffineMapIsSingleConstant(affineMap) ||
1157       !mlirAffineMapIsSingleConstant(constAffineMap) ||
1158       mlirAffineMapIsSingleConstant(multiDimIdentityAffineMap) ||
1159       mlirAffineMapIsSingleConstant(minorIdentityAffineMap) ||
1160       mlirAffineMapIsSingleConstant(permutationAffineMap))
1161     return 4;
1162 
1163   if (mlirAffineMapGetSingleConstantResult(constAffineMap) != 2)
1164     return 5;
1165 
1166   if (mlirAffineMapGetNumDims(emptyAffineMap) != 0 ||
1167       mlirAffineMapGetNumDims(affineMap) != 3 ||
1168       mlirAffineMapGetNumDims(constAffineMap) != 0 ||
1169       mlirAffineMapGetNumDims(multiDimIdentityAffineMap) != 3 ||
1170       mlirAffineMapGetNumDims(minorIdentityAffineMap) != 3 ||
1171       mlirAffineMapGetNumDims(permutationAffineMap) != 3)
1172     return 6;
1173 
1174   if (mlirAffineMapGetNumSymbols(emptyAffineMap) != 0 ||
1175       mlirAffineMapGetNumSymbols(affineMap) != 2 ||
1176       mlirAffineMapGetNumSymbols(constAffineMap) != 0 ||
1177       mlirAffineMapGetNumSymbols(multiDimIdentityAffineMap) != 0 ||
1178       mlirAffineMapGetNumSymbols(minorIdentityAffineMap) != 0 ||
1179       mlirAffineMapGetNumSymbols(permutationAffineMap) != 0)
1180     return 7;
1181 
1182   if (mlirAffineMapGetNumResults(emptyAffineMap) != 0 ||
1183       mlirAffineMapGetNumResults(affineMap) != 0 ||
1184       mlirAffineMapGetNumResults(constAffineMap) != 1 ||
1185       mlirAffineMapGetNumResults(multiDimIdentityAffineMap) != 3 ||
1186       mlirAffineMapGetNumResults(minorIdentityAffineMap) != 2 ||
1187       mlirAffineMapGetNumResults(permutationAffineMap) != 3)
1188     return 8;
1189 
1190   if (mlirAffineMapGetNumInputs(emptyAffineMap) != 0 ||
1191       mlirAffineMapGetNumInputs(affineMap) != 5 ||
1192       mlirAffineMapGetNumInputs(constAffineMap) != 0 ||
1193       mlirAffineMapGetNumInputs(multiDimIdentityAffineMap) != 3 ||
1194       mlirAffineMapGetNumInputs(minorIdentityAffineMap) != 3 ||
1195       mlirAffineMapGetNumInputs(permutationAffineMap) != 3)
1196     return 9;
1197 
1198   if (!mlirAffineMapIsProjectedPermutation(emptyAffineMap) ||
1199       !mlirAffineMapIsPermutation(emptyAffineMap) ||
1200       mlirAffineMapIsProjectedPermutation(affineMap) ||
1201       mlirAffineMapIsPermutation(affineMap) ||
1202       mlirAffineMapIsProjectedPermutation(constAffineMap) ||
1203       mlirAffineMapIsPermutation(constAffineMap) ||
1204       !mlirAffineMapIsProjectedPermutation(multiDimIdentityAffineMap) ||
1205       !mlirAffineMapIsPermutation(multiDimIdentityAffineMap) ||
1206       !mlirAffineMapIsProjectedPermutation(minorIdentityAffineMap) ||
1207       mlirAffineMapIsPermutation(minorIdentityAffineMap) ||
1208       !mlirAffineMapIsProjectedPermutation(permutationAffineMap) ||
1209       !mlirAffineMapIsPermutation(permutationAffineMap))
1210     return 10;
1211 
1212   intptr_t sub[] = {1};
1213 
1214   MlirAffineMap subMap = mlirAffineMapGetSubMap(
1215       multiDimIdentityAffineMap, sizeof(sub) / sizeof(intptr_t), sub);
1216   MlirAffineMap majorSubMap =
1217       mlirAffineMapGetMajorSubMap(multiDimIdentityAffineMap, 1);
1218   MlirAffineMap minorSubMap =
1219       mlirAffineMapGetMinorSubMap(multiDimIdentityAffineMap, 1);
1220 
1221   mlirAffineMapDump(subMap);
1222   mlirAffineMapDump(majorSubMap);
1223   mlirAffineMapDump(minorSubMap);
1224   // CHECK: (d0, d1, d2) -> (d1)
1225   // CHECK: (d0, d1, d2) -> (d0)
1226   // CHECK: (d0, d1, d2) -> (d2)
1227 
1228   return 0;
1229 }
1230 
1231 int printAffineExpr(MlirContext ctx) {
1232   MlirAffineExpr affineDimExpr = mlirAffineDimExprGet(ctx, 5);
1233   MlirAffineExpr affineSymbolExpr = mlirAffineSymbolExprGet(ctx, 5);
1234   MlirAffineExpr affineConstantExpr = mlirAffineConstantExprGet(ctx, 5);
1235   MlirAffineExpr affineAddExpr =
1236       mlirAffineAddExprGet(affineDimExpr, affineSymbolExpr);
1237   MlirAffineExpr affineMulExpr =
1238       mlirAffineMulExprGet(affineDimExpr, affineSymbolExpr);
1239   MlirAffineExpr affineModExpr =
1240       mlirAffineModExprGet(affineDimExpr, affineSymbolExpr);
1241   MlirAffineExpr affineFloorDivExpr =
1242       mlirAffineFloorDivExprGet(affineDimExpr, affineSymbolExpr);
1243   MlirAffineExpr affineCeilDivExpr =
1244       mlirAffineCeilDivExprGet(affineDimExpr, affineSymbolExpr);
1245 
1246   // Tests mlirAffineExprDump.
1247   fprintf(stderr, "@affineExpr\n");
1248   mlirAffineExprDump(affineDimExpr);
1249   mlirAffineExprDump(affineSymbolExpr);
1250   mlirAffineExprDump(affineConstantExpr);
1251   mlirAffineExprDump(affineAddExpr);
1252   mlirAffineExprDump(affineMulExpr);
1253   mlirAffineExprDump(affineModExpr);
1254   mlirAffineExprDump(affineFloorDivExpr);
1255   mlirAffineExprDump(affineCeilDivExpr);
1256   // CHECK-LABEL: @affineExpr
1257   // CHECK: d5
1258   // CHECK: s5
1259   // CHECK: 5
1260   // CHECK: d5 + s5
1261   // CHECK: d5 * s5
1262   // CHECK: d5 mod s5
1263   // CHECK: d5 floordiv s5
1264   // CHECK: d5 ceildiv s5
1265 
1266   // Tests methods of affine binary operation expression, takes add expression
1267   // as an example.
1268   mlirAffineExprDump(mlirAffineBinaryOpExprGetLHS(affineAddExpr));
1269   mlirAffineExprDump(mlirAffineBinaryOpExprGetRHS(affineAddExpr));
1270   // CHECK: d5
1271   // CHECK: s5
1272 
1273   // Tests methods of affine dimension expression.
1274   if (mlirAffineDimExprGetPosition(affineDimExpr) != 5)
1275     return 1;
1276 
1277   // Tests methods of affine symbol expression.
1278   if (mlirAffineSymbolExprGetPosition(affineSymbolExpr) != 5)
1279     return 2;
1280 
1281   // Tests methods of affine constant expression.
1282   if (mlirAffineConstantExprGetValue(affineConstantExpr) != 5)
1283     return 3;
1284 
1285   // Tests methods of affine expression.
1286   if (mlirAffineExprIsSymbolicOrConstant(affineDimExpr) ||
1287       !mlirAffineExprIsSymbolicOrConstant(affineSymbolExpr) ||
1288       !mlirAffineExprIsSymbolicOrConstant(affineConstantExpr) ||
1289       mlirAffineExprIsSymbolicOrConstant(affineAddExpr) ||
1290       mlirAffineExprIsSymbolicOrConstant(affineMulExpr) ||
1291       mlirAffineExprIsSymbolicOrConstant(affineModExpr) ||
1292       mlirAffineExprIsSymbolicOrConstant(affineFloorDivExpr) ||
1293       mlirAffineExprIsSymbolicOrConstant(affineCeilDivExpr))
1294     return 4;
1295 
1296   if (!mlirAffineExprIsPureAffine(affineDimExpr) ||
1297       !mlirAffineExprIsPureAffine(affineSymbolExpr) ||
1298       !mlirAffineExprIsPureAffine(affineConstantExpr) ||
1299       !mlirAffineExprIsPureAffine(affineAddExpr) ||
1300       mlirAffineExprIsPureAffine(affineMulExpr) ||
1301       mlirAffineExprIsPureAffine(affineModExpr) ||
1302       mlirAffineExprIsPureAffine(affineFloorDivExpr) ||
1303       mlirAffineExprIsPureAffine(affineCeilDivExpr))
1304     return 5;
1305 
1306   if (mlirAffineExprGetLargestKnownDivisor(affineDimExpr) != 1 ||
1307       mlirAffineExprGetLargestKnownDivisor(affineSymbolExpr) != 1 ||
1308       mlirAffineExprGetLargestKnownDivisor(affineConstantExpr) != 5 ||
1309       mlirAffineExprGetLargestKnownDivisor(affineAddExpr) != 1 ||
1310       mlirAffineExprGetLargestKnownDivisor(affineMulExpr) != 1 ||
1311       mlirAffineExprGetLargestKnownDivisor(affineModExpr) != 1 ||
1312       mlirAffineExprGetLargestKnownDivisor(affineFloorDivExpr) != 1 ||
1313       mlirAffineExprGetLargestKnownDivisor(affineCeilDivExpr) != 1)
1314     return 6;
1315 
1316   if (!mlirAffineExprIsMultipleOf(affineDimExpr, 1) ||
1317       !mlirAffineExprIsMultipleOf(affineSymbolExpr, 1) ||
1318       !mlirAffineExprIsMultipleOf(affineConstantExpr, 5) ||
1319       !mlirAffineExprIsMultipleOf(affineAddExpr, 1) ||
1320       !mlirAffineExprIsMultipleOf(affineMulExpr, 1) ||
1321       !mlirAffineExprIsMultipleOf(affineModExpr, 1) ||
1322       !mlirAffineExprIsMultipleOf(affineFloorDivExpr, 1) ||
1323       !mlirAffineExprIsMultipleOf(affineCeilDivExpr, 1))
1324     return 7;
1325 
1326   if (!mlirAffineExprIsFunctionOfDim(affineDimExpr, 5) ||
1327       mlirAffineExprIsFunctionOfDim(affineSymbolExpr, 5) ||
1328       mlirAffineExprIsFunctionOfDim(affineConstantExpr, 5) ||
1329       !mlirAffineExprIsFunctionOfDim(affineAddExpr, 5) ||
1330       !mlirAffineExprIsFunctionOfDim(affineMulExpr, 5) ||
1331       !mlirAffineExprIsFunctionOfDim(affineModExpr, 5) ||
1332       !mlirAffineExprIsFunctionOfDim(affineFloorDivExpr, 5) ||
1333       !mlirAffineExprIsFunctionOfDim(affineCeilDivExpr, 5))
1334     return 8;
1335 
1336   // Tests 'IsA' methods of affine binary operation expression.
1337   if (!mlirAffineExprIsAAdd(affineAddExpr))
1338     return 9;
1339 
1340   if (!mlirAffineExprIsAMul(affineMulExpr))
1341     return 10;
1342 
1343   if (!mlirAffineExprIsAMod(affineModExpr))
1344     return 11;
1345 
1346   if (!mlirAffineExprIsAFloorDiv(affineFloorDivExpr))
1347     return 12;
1348 
1349   if (!mlirAffineExprIsACeilDiv(affineCeilDivExpr))
1350     return 13;
1351 
1352   if (!mlirAffineExprIsABinary(affineAddExpr))
1353     return 14;
1354 
1355   // Test other 'IsA' method on affine expressions.
1356   if (!mlirAffineExprIsAConstant(affineConstantExpr))
1357     return 15;
1358 
1359   if (!mlirAffineExprIsADim(affineDimExpr))
1360     return 16;
1361 
1362   if (!mlirAffineExprIsASymbol(affineSymbolExpr))
1363     return 17;
1364 
1365   // Test equality and nullity.
1366   MlirAffineExpr otherDimExpr = mlirAffineDimExprGet(ctx, 5);
1367   if (!mlirAffineExprEqual(affineDimExpr, otherDimExpr))
1368     return 18;
1369 
1370   if (mlirAffineExprIsNull(affineDimExpr))
1371     return 19;
1372 
1373   return 0;
1374 }
1375 
1376 int affineMapFromExprs(MlirContext ctx) {
1377   MlirAffineExpr affineDimExpr = mlirAffineDimExprGet(ctx, 0);
1378   MlirAffineExpr affineSymbolExpr = mlirAffineSymbolExprGet(ctx, 1);
1379   MlirAffineExpr exprs[] = {affineDimExpr, affineSymbolExpr};
1380   MlirAffineMap map = mlirAffineMapGet(ctx, 3, 3, 2, exprs);
1381 
1382   // CHECK-LABEL: @affineMapFromExprs
1383   fprintf(stderr, "@affineMapFromExprs");
1384   // CHECK: (d0, d1, d2)[s0, s1, s2] -> (d0, s1)
1385   mlirAffineMapDump(map);
1386 
1387   if (mlirAffineMapGetNumResults(map) != 2)
1388     return 1;
1389 
1390   if (!mlirAffineExprEqual(mlirAffineMapGetResult(map, 0), affineDimExpr))
1391     return 2;
1392 
1393   if (!mlirAffineExprEqual(mlirAffineMapGetResult(map, 1), affineSymbolExpr))
1394     return 3;
1395 
1396   return 0;
1397 }
1398 
1399 int printIntegerSet(MlirContext ctx) {
1400   MlirIntegerSet emptySet = mlirIntegerSetEmptyGet(ctx, 2, 1);
1401 
1402   // CHECK-LABEL: @printIntegerSet
1403   fprintf(stderr, "@printIntegerSet");
1404 
1405   // CHECK: (d0, d1)[s0] : (1 == 0)
1406   mlirIntegerSetDump(emptySet);
1407 
1408   if (!mlirIntegerSetIsCanonicalEmpty(emptySet))
1409     return 1;
1410 
1411   MlirIntegerSet anotherEmptySet = mlirIntegerSetEmptyGet(ctx, 2, 1);
1412   if (!mlirIntegerSetEqual(emptySet, anotherEmptySet))
1413     return 2;
1414 
1415   // Construct a set constrained by:
1416   //   d0 - s0 == 0,
1417   //   d1 - 42 >= 0.
1418   MlirAffineExpr negOne = mlirAffineConstantExprGet(ctx, -1);
1419   MlirAffineExpr negFortyTwo = mlirAffineConstantExprGet(ctx, -42);
1420   MlirAffineExpr d0 = mlirAffineDimExprGet(ctx, 0);
1421   MlirAffineExpr d1 = mlirAffineDimExprGet(ctx, 1);
1422   MlirAffineExpr s0 = mlirAffineSymbolExprGet(ctx, 0);
1423   MlirAffineExpr negS0 = mlirAffineMulExprGet(negOne, s0);
1424   MlirAffineExpr d0minusS0 = mlirAffineAddExprGet(d0, negS0);
1425   MlirAffineExpr d1minus42 = mlirAffineAddExprGet(d1, negFortyTwo);
1426   MlirAffineExpr constraints[] = {d0minusS0, d1minus42};
1427   bool flags[] = {true, false};
1428 
1429   MlirIntegerSet set = mlirIntegerSetGet(ctx, 2, 1, 2, constraints, flags);
1430   // CHECK: (d0, d1)[s0] : (
1431   // CHECK-DAG: d0 - s0 == 0
1432   // CHECK-DAG: d1 - 42 >= 0
1433   mlirIntegerSetDump(set);
1434 
1435   // Transform d1 into s0.
1436   MlirAffineExpr s1 = mlirAffineSymbolExprGet(ctx, 1);
1437   MlirAffineExpr repl[] = {d0, s1};
1438   MlirIntegerSet replaced = mlirIntegerSetReplaceGet(set, repl, &s0, 1, 2);
1439   // CHECK: (d0)[s0, s1] : (
1440   // CHECK-DAG: d0 - s0 == 0
1441   // CHECK-DAG: s1 - 42 >= 0
1442   mlirIntegerSetDump(replaced);
1443 
1444   if (mlirIntegerSetGetNumDims(set) != 2)
1445     return 3;
1446   if (mlirIntegerSetGetNumDims(replaced) != 1)
1447     return 4;
1448 
1449   if (mlirIntegerSetGetNumSymbols(set) != 1)
1450     return 5;
1451   if (mlirIntegerSetGetNumSymbols(replaced) != 2)
1452     return 6;
1453 
1454   if (mlirIntegerSetGetNumInputs(set) != 3)
1455     return 7;
1456 
1457   if (mlirIntegerSetGetNumConstraints(set) != 2)
1458     return 8;
1459 
1460   if (mlirIntegerSetGetNumEqualities(set) != 1)
1461     return 9;
1462 
1463   if (mlirIntegerSetGetNumInequalities(set) != 1)
1464     return 10;
1465 
1466   MlirAffineExpr cstr1 = mlirIntegerSetGetConstraint(set, 0);
1467   MlirAffineExpr cstr2 = mlirIntegerSetGetConstraint(set, 1);
1468   bool isEq1 = mlirIntegerSetIsConstraintEq(set, 0);
1469   bool isEq2 = mlirIntegerSetIsConstraintEq(set, 1);
1470   if (!mlirAffineExprEqual(cstr1, isEq1 ? d0minusS0 : d1minus42))
1471     return 11;
1472   if (!mlirAffineExprEqual(cstr2, isEq2 ? d0minusS0 : d1minus42))
1473     return 12;
1474 
1475   return 0;
1476 }
1477 
1478 int registerOnlyStd() {
1479   MlirContext ctx = mlirContextCreate();
1480   // The built-in dialect is always loaded.
1481   if (mlirContextGetNumLoadedDialects(ctx) != 1)
1482     return 1;
1483 
1484   MlirDialectHandle stdHandle = mlirGetDialectHandle__std__();
1485 
1486   MlirDialect std = mlirContextGetOrLoadDialect(
1487       ctx, mlirDialectHandleGetNamespace(stdHandle));
1488   if (!mlirDialectIsNull(std))
1489     return 2;
1490 
1491   mlirDialectHandleRegisterDialect(stdHandle, ctx);
1492 
1493   std = mlirContextGetOrLoadDialect(ctx,
1494                                     mlirDialectHandleGetNamespace(stdHandle));
1495   if (mlirDialectIsNull(std))
1496     return 3;
1497 
1498   MlirDialect alsoStd = mlirDialectHandleLoadDialect(stdHandle, ctx);
1499   if (!mlirDialectEqual(std, alsoStd))
1500     return 4;
1501 
1502   MlirStringRef stdNs = mlirDialectGetNamespace(std);
1503   MlirStringRef alsoStdNs = mlirDialectHandleGetNamespace(stdHandle);
1504   if (stdNs.length != alsoStdNs.length ||
1505       strncmp(stdNs.data, alsoStdNs.data, stdNs.length))
1506     return 5;
1507 
1508   fprintf(stderr, "@registration\n");
1509   // CHECK-LABEL: @registration
1510 
1511   // CHECK: std.cond_br is_registered: 1
1512   fprintf(stderr, "std.cond_br is_registered: %d\n",
1513           mlirContextIsRegisteredOperation(
1514               ctx, mlirStringRefCreateFromCString("std.cond_br")));
1515 
1516   // CHECK: std.not_existing_op is_registered: 0
1517   fprintf(stderr, "std.not_existing_op is_registered: %d\n",
1518           mlirContextIsRegisteredOperation(
1519               ctx, mlirStringRefCreateFromCString("std.not_existing_op")));
1520 
1521   // CHECK: not_existing_dialect.not_existing_op is_registered: 0
1522   fprintf(stderr, "not_existing_dialect.not_existing_op is_registered: %d\n",
1523           mlirContextIsRegisteredOperation(
1524               ctx, mlirStringRefCreateFromCString(
1525                        "not_existing_dialect.not_existing_op")));
1526 
1527   mlirContextDestroy(ctx);
1528   return 0;
1529 }
1530 
1531 /// Tests backreference APIs
1532 static int testBackreferences() {
1533   fprintf(stderr, "@test_backreferences\n");
1534 
1535   MlirContext ctx = mlirContextCreate();
1536   mlirContextSetAllowUnregisteredDialects(ctx, true);
1537   MlirLocation loc = mlirLocationUnknownGet(ctx);
1538 
1539   MlirOperationState opState =
1540       mlirOperationStateGet(mlirStringRefCreateFromCString("invalid.op"), loc);
1541   MlirRegion region = mlirRegionCreate();
1542   MlirBlock block = mlirBlockCreate(0, NULL);
1543   mlirRegionAppendOwnedBlock(region, block);
1544   mlirOperationStateAddOwnedRegions(&opState, 1, &region);
1545   MlirOperation op = mlirOperationCreate(&opState);
1546   MlirIdentifier ident =
1547       mlirIdentifierGet(ctx, mlirStringRefCreateFromCString("identifier"));
1548 
1549   if (!mlirContextEqual(ctx, mlirOperationGetContext(op))) {
1550     fprintf(stderr, "ERROR: Getting context from operation failed\n");
1551     return 1;
1552   }
1553   if (!mlirOperationEqual(op, mlirBlockGetParentOperation(block))) {
1554     fprintf(stderr, "ERROR: Getting parent operation from block failed\n");
1555     return 2;
1556   }
1557   if (!mlirContextEqual(ctx, mlirIdentifierGetContext(ident))) {
1558     fprintf(stderr, "ERROR: Getting context from identifier failed\n");
1559     return 3;
1560   }
1561 
1562   mlirOperationDestroy(op);
1563   mlirContextDestroy(ctx);
1564 
1565   // CHECK-LABEL: @test_backreferences
1566   return 0;
1567 }
1568 
1569 /// Tests operand APIs.
1570 int testOperands() {
1571   fprintf(stderr, "@testOperands\n");
1572   // CHECK-LABEL: @testOperands
1573 
1574   MlirContext ctx = mlirContextCreate();
1575   mlirRegisterAllDialects(ctx);
1576   mlirContextGetOrLoadDialect(ctx, mlirStringRefCreateFromCString("test"));
1577   MlirLocation loc = mlirLocationUnknownGet(ctx);
1578   MlirType indexType = mlirIndexTypeGet(ctx);
1579 
1580   // Create some constants to use as operands.
1581   MlirAttribute indexZeroLiteral =
1582       mlirAttributeParseGet(ctx, mlirStringRefCreateFromCString("0 : index"));
1583   MlirNamedAttribute indexZeroValueAttr = mlirNamedAttributeGet(
1584       mlirIdentifierGet(ctx, mlirStringRefCreateFromCString("value")),
1585       indexZeroLiteral);
1586   MlirOperationState constZeroState = mlirOperationStateGet(
1587       mlirStringRefCreateFromCString("arith.constant"), loc);
1588   mlirOperationStateAddResults(&constZeroState, 1, &indexType);
1589   mlirOperationStateAddAttributes(&constZeroState, 1, &indexZeroValueAttr);
1590   MlirOperation constZero = mlirOperationCreate(&constZeroState);
1591   MlirValue constZeroValue = mlirOperationGetResult(constZero, 0);
1592 
1593   MlirAttribute indexOneLiteral =
1594       mlirAttributeParseGet(ctx, mlirStringRefCreateFromCString("1 : index"));
1595   MlirNamedAttribute indexOneValueAttr = mlirNamedAttributeGet(
1596       mlirIdentifierGet(ctx, mlirStringRefCreateFromCString("value")),
1597       indexOneLiteral);
1598   MlirOperationState constOneState = mlirOperationStateGet(
1599       mlirStringRefCreateFromCString("arith.constant"), loc);
1600   mlirOperationStateAddResults(&constOneState, 1, &indexType);
1601   mlirOperationStateAddAttributes(&constOneState, 1, &indexOneValueAttr);
1602   MlirOperation constOne = mlirOperationCreate(&constOneState);
1603   MlirValue constOneValue = mlirOperationGetResult(constOne, 0);
1604 
1605   // Create the operation under test.
1606   mlirContextSetAllowUnregisteredDialects(ctx, true);
1607   MlirOperationState opState =
1608       mlirOperationStateGet(mlirStringRefCreateFromCString("dummy.op"), loc);
1609   MlirValue initialOperands[] = {constZeroValue};
1610   mlirOperationStateAddOperands(&opState, 1, initialOperands);
1611   MlirOperation op = mlirOperationCreate(&opState);
1612 
1613   // Test operand APIs.
1614   intptr_t numOperands = mlirOperationGetNumOperands(op);
1615   fprintf(stderr, "Num Operands: %" PRIdPTR "\n", numOperands);
1616   // CHECK: Num Operands: 1
1617 
1618   MlirValue opOperand = mlirOperationGetOperand(op, 0);
1619   fprintf(stderr, "Original operand: ");
1620   mlirValuePrint(opOperand, printToStderr, NULL);
1621   // CHECK: Original operand: {{.+}} arith.constant 0 : index
1622 
1623   mlirOperationSetOperand(op, 0, constOneValue);
1624   opOperand = mlirOperationGetOperand(op, 0);
1625   fprintf(stderr, "Updated operand: ");
1626   mlirValuePrint(opOperand, printToStderr, NULL);
1627   // CHECK: Updated operand: {{.+}} arith.constant 1 : index
1628 
1629   mlirOperationDestroy(op);
1630   mlirOperationDestroy(constZero);
1631   mlirOperationDestroy(constOne);
1632   mlirContextDestroy(ctx);
1633 
1634   return 0;
1635 }
1636 
1637 /// Tests clone APIs.
1638 int testClone() {
1639   fprintf(stderr, "@testClone\n");
1640   // CHECK-LABEL: @testClone
1641 
1642   MlirContext ctx = mlirContextCreate();
1643   mlirRegisterAllDialects(ctx);
1644   mlirContextGetOrLoadDialect(ctx, mlirStringRefCreateFromCString("std"));
1645   MlirLocation loc = mlirLocationUnknownGet(ctx);
1646   MlirType indexType = mlirIndexTypeGet(ctx);
1647   MlirStringRef valueStringRef = mlirStringRefCreateFromCString("value");
1648 
1649   MlirAttribute indexZeroLiteral =
1650       mlirAttributeParseGet(ctx, mlirStringRefCreateFromCString("0 : index"));
1651   MlirNamedAttribute indexZeroValueAttr = mlirNamedAttributeGet(
1652       mlirIdentifierGet(ctx, valueStringRef), indexZeroLiteral);
1653   MlirOperationState constZeroState = mlirOperationStateGet(
1654       mlirStringRefCreateFromCString("arith.constant"), loc);
1655   mlirOperationStateAddResults(&constZeroState, 1, &indexType);
1656   mlirOperationStateAddAttributes(&constZeroState, 1, &indexZeroValueAttr);
1657   MlirOperation constZero = mlirOperationCreate(&constZeroState);
1658 
1659   MlirAttribute indexOneLiteral =
1660       mlirAttributeParseGet(ctx, mlirStringRefCreateFromCString("1 : index"));
1661   MlirOperation constOne = mlirOperationClone(constZero);
1662   mlirOperationSetAttributeByName(constOne, valueStringRef, indexOneLiteral);
1663 
1664   mlirOperationPrint(constZero, printToStderr, NULL);
1665   mlirOperationPrint(constOne, printToStderr, NULL);
1666   // CHECK: arith.constant 0 : index
1667   // CHECK: arith.constant 1 : index
1668 
1669   mlirOperationDestroy(constZero);
1670   mlirOperationDestroy(constOne);
1671   mlirContextDestroy(ctx);
1672   return 0;
1673 }
1674 
1675 // Wraps a diagnostic into additional text we can match against.
1676 MlirLogicalResult errorHandler(MlirDiagnostic diagnostic, void *userData) {
1677   fprintf(stderr, "processing diagnostic (userData: %" PRIdPTR ") <<\n",
1678           (intptr_t)userData);
1679   mlirDiagnosticPrint(diagnostic, printToStderr, NULL);
1680   fprintf(stderr, "\n");
1681   MlirLocation loc = mlirDiagnosticGetLocation(diagnostic);
1682   mlirLocationPrint(loc, printToStderr, NULL);
1683   assert(mlirDiagnosticGetNumNotes(diagnostic) == 0);
1684   fprintf(stderr, "\n>> end of diagnostic (userData: %" PRIdPTR ")\n",
1685           (intptr_t)userData);
1686   return mlirLogicalResultSuccess();
1687 }
1688 
1689 // Logs when the delete user data callback is called
1690 static void deleteUserData(void *userData) {
1691   fprintf(stderr, "deleting user data (userData: %" PRIdPTR ")\n",
1692           (intptr_t)userData);
1693 }
1694 
1695 void testDiagnostics() {
1696   MlirContext ctx = mlirContextCreate();
1697   MlirDiagnosticHandlerID id = mlirContextAttachDiagnosticHandler(
1698       ctx, errorHandler, (void *)42, deleteUserData);
1699   fprintf(stderr, "@test_diagnostics\n");
1700   MlirLocation unknownLoc = mlirLocationUnknownGet(ctx);
1701   mlirEmitError(unknownLoc, "test diagnostics");
1702   MlirLocation fileLineColLoc = mlirLocationFileLineColGet(
1703       ctx, mlirStringRefCreateFromCString("file.c"), 1, 2);
1704   mlirEmitError(fileLineColLoc, "test diagnostics");
1705   MlirLocation callSiteLoc = mlirLocationCallSiteGet(
1706       mlirLocationFileLineColGet(
1707           ctx, mlirStringRefCreateFromCString("other-file.c"), 2, 3),
1708       fileLineColLoc);
1709   mlirEmitError(callSiteLoc, "test diagnostics");
1710   MlirLocation null = {0};
1711   MlirLocation nameLoc =
1712       mlirLocationNameGet(ctx, mlirStringRefCreateFromCString("named"), null);
1713   mlirEmitError(nameLoc, "test diagnostics");
1714   MlirLocation locs[2] = {nameLoc, callSiteLoc};
1715   MlirAttribute nullAttr = {0};
1716   MlirLocation fusedLoc = mlirLocationFusedGet(ctx, 2, locs, nullAttr);
1717   mlirEmitError(fusedLoc, "test diagnostics");
1718   mlirContextDetachDiagnosticHandler(ctx, id);
1719   mlirEmitError(unknownLoc, "more test diagnostics");
1720   // CHECK-LABEL: @test_diagnostics
1721   // CHECK: processing diagnostic (userData: 42) <<
1722   // CHECK:   test diagnostics
1723   // CHECK:   loc(unknown)
1724   // CHECK: >> end of diagnostic (userData: 42)
1725   // CHECK: processing diagnostic (userData: 42) <<
1726   // CHECK:   test diagnostics
1727   // CHECK:   loc("file.c":1:2)
1728   // CHECK: >> end of diagnostic (userData: 42)
1729   // CHECK: processing diagnostic (userData: 42) <<
1730   // CHECK:   test diagnostics
1731   // CHECK:   loc(callsite("other-file.c":2:3 at "file.c":1:2))
1732   // CHECK: >> end of diagnostic (userData: 42)
1733   // CHECK: processing diagnostic (userData: 42) <<
1734   // CHECK:   test diagnostics
1735   // CHECK:   loc("named")
1736   // CHECK: >> end of diagnostic (userData: 42)
1737   // CHECK: processing diagnostic (userData: 42) <<
1738   // CHECK:   test diagnostics
1739   // CHECK:   loc(fused["named", callsite("other-file.c":2:3 at "file.c":1:2)])
1740   // CHECK: deleting user data (userData: 42)
1741   // CHECK-NOT: processing diagnostic
1742   // CHECK:     more test diagnostics
1743   mlirContextDestroy(ctx);
1744 }
1745 
1746 int testTypeID(MlirContext ctx) {
1747   fprintf(stderr, "@testTypeID\n");
1748 
1749   // Test getting and comparing type and attribute type ids.
1750   MlirType i32 = mlirIntegerTypeGet(ctx, 32);
1751   MlirTypeID i32ID = mlirTypeGetTypeID(i32);
1752   MlirType ui32 = mlirIntegerTypeUnsignedGet(ctx, 32);
1753   MlirTypeID ui32ID = mlirTypeGetTypeID(ui32);
1754   MlirType f32 = mlirF32TypeGet(ctx);
1755   MlirTypeID f32ID = mlirTypeGetTypeID(f32);
1756   MlirAttribute i32Attr = mlirIntegerAttrGet(i32, 1);
1757   MlirTypeID i32AttrID = mlirAttributeGetTypeID(i32Attr);
1758 
1759   if (mlirTypeIDIsNull(i32ID) || mlirTypeIDIsNull(ui32ID) ||
1760       mlirTypeIDIsNull(f32ID) || mlirTypeIDIsNull(i32AttrID)) {
1761     fprintf(stderr, "ERROR: Expected type ids to be present\n");
1762     return 1;
1763   }
1764 
1765   if (!mlirTypeIDEqual(i32ID, ui32ID) ||
1766       mlirTypeIDHashValue(i32ID) != mlirTypeIDHashValue(ui32ID)) {
1767     fprintf(
1768         stderr,
1769         "ERROR: Expected different integer types to have the same type id\n");
1770     return 2;
1771   }
1772 
1773   if (mlirTypeIDEqual(i32ID, f32ID) ||
1774       mlirTypeIDHashValue(i32ID) == mlirTypeIDHashValue(f32ID)) {
1775     fprintf(stderr,
1776             "ERROR: Expected integer type id to not equal float type id\n");
1777     return 3;
1778   }
1779 
1780   if (mlirTypeIDEqual(i32ID, i32AttrID) ||
1781       mlirTypeIDHashValue(i32ID) == mlirTypeIDHashValue(i32AttrID)) {
1782     fprintf(stderr, "ERROR: Expected integer type id to not equal integer "
1783                     "attribute type id\n");
1784     return 4;
1785   }
1786 
1787   MlirLocation loc = mlirLocationUnknownGet(ctx);
1788   MlirType indexType = mlirIndexTypeGet(ctx);
1789   MlirStringRef valueStringRef = mlirStringRefCreateFromCString("value");
1790 
1791   // Create a registered operation, which should have a type id.
1792   MlirAttribute indexZeroLiteral =
1793       mlirAttributeParseGet(ctx, mlirStringRefCreateFromCString("0 : index"));
1794   MlirNamedAttribute indexZeroValueAttr = mlirNamedAttributeGet(
1795       mlirIdentifierGet(ctx, valueStringRef), indexZeroLiteral);
1796   MlirOperationState constZeroState = mlirOperationStateGet(
1797       mlirStringRefCreateFromCString("arith.constant"), loc);
1798   mlirOperationStateAddResults(&constZeroState, 1, &indexType);
1799   mlirOperationStateAddAttributes(&constZeroState, 1, &indexZeroValueAttr);
1800   MlirOperation constZero = mlirOperationCreate(&constZeroState);
1801 
1802   if (!mlirOperationVerify(constZero)) {
1803     fprintf(stderr, "ERROR: Expected operation to verify correctly\n");
1804     return 5;
1805   }
1806 
1807   if (mlirOperationIsNull(constZero)) {
1808     fprintf(stderr, "ERROR: Expected registered operation to be present\n");
1809     return 6;
1810   }
1811 
1812   MlirTypeID registeredOpID = mlirOperationGetTypeID(constZero);
1813 
1814   if (mlirTypeIDIsNull(registeredOpID)) {
1815     fprintf(stderr,
1816             "ERROR: Expected registered operation type id to be present\n");
1817     return 7;
1818   }
1819 
1820   // Create an unregistered operation, which should not have a type id.
1821   mlirContextSetAllowUnregisteredDialects(ctx, true);
1822   MlirOperationState opState =
1823       mlirOperationStateGet(mlirStringRefCreateFromCString("dummy.op"), loc);
1824   MlirOperation unregisteredOp = mlirOperationCreate(&opState);
1825   if (mlirOperationIsNull(unregisteredOp)) {
1826     fprintf(stderr, "ERROR: Expected unregistered operation to be present\n");
1827     return 8;
1828   }
1829 
1830   MlirTypeID unregisteredOpID = mlirOperationGetTypeID(unregisteredOp);
1831 
1832   if (!mlirTypeIDIsNull(unregisteredOpID)) {
1833     fprintf(stderr,
1834             "ERROR: Expected unregistered operation type id to be null\n");
1835     return 9;
1836   }
1837 
1838   mlirOperationDestroy(constZero);
1839   mlirOperationDestroy(unregisteredOp);
1840 
1841   return 0;
1842 }
1843 
1844 int main() {
1845   MlirContext ctx = mlirContextCreate();
1846   mlirRegisterAllDialects(ctx);
1847   if (constructAndTraverseIr(ctx))
1848     return 1;
1849   buildWithInsertionsAndPrint(ctx);
1850   if (createOperationWithTypeInference(ctx))
1851     return 2;
1852 
1853   if (printBuiltinTypes(ctx))
1854     return 3;
1855   if (printBuiltinAttributes(ctx))
1856     return 4;
1857   if (printAffineMap(ctx))
1858     return 5;
1859   if (printAffineExpr(ctx))
1860     return 6;
1861   if (affineMapFromExprs(ctx))
1862     return 7;
1863   if (printIntegerSet(ctx))
1864     return 8;
1865   if (registerOnlyStd())
1866     return 9;
1867   if (testBackreferences())
1868     return 10;
1869   if (testOperands())
1870     return 11;
1871   if (testClone())
1872     return 12;
1873   if (testTypeID(ctx)) {
1874     return 13;
1875   }
1876 
1877   mlirContextDestroy(ctx);
1878 
1879   testDiagnostics();
1880   return 0;
1881 }
1882