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