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