xref: /llvm-project-15.0.7/mlir/test/CAPI/ir.c (revision f811cb82)
1 //===- ir.c - Simple test of C APIs ---------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM
4 // Exceptions.
5 // See https://llvm.org/LICENSE.txt for license information.
6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //
8 //===----------------------------------------------------------------------===//
9 
10 /* RUN: mlir-capi-ir-test 2>&1 | FileCheck %s
11  */
12 
13 #include "mlir-c/IR.h"
14 #include "mlir-c/AffineExpr.h"
15 #include "mlir-c/AffineMap.h"
16 #include "mlir-c/BuiltinAttributes.h"
17 #include "mlir-c/BuiltinTypes.h"
18 #include "mlir-c/Diagnostics.h"
19 #include "mlir-c/Dialect/Standard.h"
20 #include "mlir-c/IntegerSet.h"
21 #include "mlir-c/Registration.h"
22 #include "mlir-c/Support.h"
23 
24 #include <assert.h>
25 #include <inttypes.h>
26 #include <math.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 
31 void populateLoopBody(MlirContext ctx, MlirBlock loopBody,
32                       MlirLocation location, MlirBlock funcBody) {
33   MlirValue iv = mlirBlockGetArgument(loopBody, 0);
34   MlirValue funcArg0 = mlirBlockGetArgument(funcBody, 0);
35   MlirValue funcArg1 = mlirBlockGetArgument(funcBody, 1);
36   MlirType f32Type =
37       mlirTypeParseGet(ctx, mlirStringRefCreateFromCString("f32"));
38 
39   MlirOperationState loadLHSState = mlirOperationStateGet(
40       mlirStringRefCreateFromCString("memref.load"), location);
41   MlirValue loadLHSOperands[] = {funcArg0, iv};
42   mlirOperationStateAddOperands(&loadLHSState, 2, loadLHSOperands);
43   mlirOperationStateAddResults(&loadLHSState, 1, &f32Type);
44   MlirOperation loadLHS = mlirOperationCreate(&loadLHSState);
45   mlirBlockAppendOwnedOperation(loopBody, loadLHS);
46 
47   MlirOperationState loadRHSState = mlirOperationStateGet(
48       mlirStringRefCreateFromCString("memref.load"), location);
49   MlirValue loadRHSOperands[] = {funcArg1, iv};
50   mlirOperationStateAddOperands(&loadRHSState, 2, loadRHSOperands);
51   mlirOperationStateAddResults(&loadRHSState, 1, &f32Type);
52   MlirOperation loadRHS = mlirOperationCreate(&loadRHSState);
53   mlirBlockAppendOwnedOperation(loopBody, loadRHS);
54 
55   MlirOperationState addState = mlirOperationStateGet(
56       mlirStringRefCreateFromCString("arith.addf"), location);
57   MlirValue addOperands[] = {mlirOperationGetResult(loadLHS, 0),
58                              mlirOperationGetResult(loadRHS, 0)};
59   mlirOperationStateAddOperands(&addState, 2, addOperands);
60   mlirOperationStateAddResults(&addState, 1, &f32Type);
61   MlirOperation add = mlirOperationCreate(&addState);
62   mlirBlockAppendOwnedOperation(loopBody, add);
63 
64   MlirOperationState storeState = mlirOperationStateGet(
65       mlirStringRefCreateFromCString("memref.store"), location);
66   MlirValue storeOperands[] = {mlirOperationGetResult(add, 0), funcArg0, iv};
67   mlirOperationStateAddOperands(&storeState, 3, storeOperands);
68   MlirOperation store = mlirOperationCreate(&storeState);
69   mlirBlockAppendOwnedOperation(loopBody, store);
70 
71   MlirOperationState yieldState = mlirOperationStateGet(
72       mlirStringRefCreateFromCString("scf.yield"), location);
73   MlirOperation yield = mlirOperationCreate(&yieldState);
74   mlirBlockAppendOwnedOperation(loopBody, yield);
75 }
76 
77 MlirModule makeAndDumpAdd(MlirContext ctx, MlirLocation location) {
78   MlirModule moduleOp = mlirModuleCreateEmpty(location);
79   MlirBlock moduleBody = mlirModuleGetBody(moduleOp);
80 
81   MlirType memrefType =
82       mlirTypeParseGet(ctx, mlirStringRefCreateFromCString("memref<?xf32>"));
83   MlirType funcBodyArgTypes[] = {memrefType, memrefType};
84   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("std.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   if (!mlirAttributeIsAInteger(integer) ||
817       mlirIntegerAttrGetValueInt(integer) != 42)
818     return 2;
819   mlirAttributeDump(integer);
820   // CHECK: 42 : i32
821 
822   MlirAttribute boolean = mlirBoolAttrGet(ctx, 1);
823   if (!mlirAttributeIsABool(boolean) || !mlirBoolAttrGetValue(boolean))
824     return 3;
825   mlirAttributeDump(boolean);
826   // CHECK: true
827 
828   const char data[] = "abcdefghijklmnopqestuvwxyz";
829   MlirAttribute opaque =
830       mlirOpaqueAttrGet(ctx, mlirStringRefCreateFromCString("std"), 3, data,
831                         mlirNoneTypeGet(ctx));
832   if (!mlirAttributeIsAOpaque(opaque) ||
833       !stringIsEqual("std", mlirOpaqueAttrGetDialectNamespace(opaque)))
834     return 4;
835 
836   MlirStringRef opaqueData = mlirOpaqueAttrGetData(opaque);
837   if (opaqueData.length != 3 ||
838       strncmp(data, opaqueData.data, opaqueData.length))
839     return 5;
840   mlirAttributeDump(opaque);
841   // CHECK: #std.abc
842 
843   MlirAttribute string =
844       mlirStringAttrGet(ctx, mlirStringRefCreate(data + 3, 2));
845   if (!mlirAttributeIsAString(string))
846     return 6;
847 
848   MlirStringRef stringValue = mlirStringAttrGetValue(string);
849   if (stringValue.length != 2 ||
850       strncmp(data + 3, stringValue.data, stringValue.length))
851     return 7;
852   mlirAttributeDump(string);
853   // CHECK: "de"
854 
855   MlirAttribute flatSymbolRef =
856       mlirFlatSymbolRefAttrGet(ctx, mlirStringRefCreate(data + 5, 3));
857   if (!mlirAttributeIsAFlatSymbolRef(flatSymbolRef))
858     return 8;
859 
860   MlirStringRef flatSymbolRefValue =
861       mlirFlatSymbolRefAttrGetValue(flatSymbolRef);
862   if (flatSymbolRefValue.length != 3 ||
863       strncmp(data + 5, flatSymbolRefValue.data, flatSymbolRefValue.length))
864     return 9;
865   mlirAttributeDump(flatSymbolRef);
866   // CHECK: @fgh
867 
868   MlirAttribute symbols[] = {flatSymbolRef, flatSymbolRef};
869   MlirAttribute symbolRef =
870       mlirSymbolRefAttrGet(ctx, mlirStringRefCreate(data + 8, 2), 2, symbols);
871   if (!mlirAttributeIsASymbolRef(symbolRef) ||
872       mlirSymbolRefAttrGetNumNestedReferences(symbolRef) != 2 ||
873       !mlirAttributeEqual(mlirSymbolRefAttrGetNestedReference(symbolRef, 0),
874                           flatSymbolRef) ||
875       !mlirAttributeEqual(mlirSymbolRefAttrGetNestedReference(symbolRef, 1),
876                           flatSymbolRef))
877     return 10;
878 
879   MlirStringRef symbolRefLeaf = mlirSymbolRefAttrGetLeafReference(symbolRef);
880   MlirStringRef symbolRefRoot = mlirSymbolRefAttrGetRootReference(symbolRef);
881   if (symbolRefLeaf.length != 3 ||
882       strncmp(data + 5, symbolRefLeaf.data, symbolRefLeaf.length) ||
883       symbolRefRoot.length != 2 ||
884       strncmp(data + 8, symbolRefRoot.data, symbolRefRoot.length))
885     return 11;
886   mlirAttributeDump(symbolRef);
887   // CHECK: @ij::@fgh::@fgh
888 
889   MlirAttribute type = mlirTypeAttrGet(mlirF32TypeGet(ctx));
890   if (!mlirAttributeIsAType(type) ||
891       !mlirTypeEqual(mlirF32TypeGet(ctx), mlirTypeAttrGetValue(type)))
892     return 12;
893   mlirAttributeDump(type);
894   // CHECK: f32
895 
896   MlirAttribute unit = mlirUnitAttrGet(ctx);
897   if (!mlirAttributeIsAUnit(unit))
898     return 13;
899   mlirAttributeDump(unit);
900   // CHECK: unit
901 
902   int64_t shape[] = {1, 2};
903 
904   int bools[] = {0, 1};
905   uint8_t uints8[] = {0u, 1u};
906   int8_t ints8[] = {0, 1};
907   uint32_t uints32[] = {0u, 1u};
908   int32_t ints32[] = {0, 1};
909   uint64_t uints64[] = {0u, 1u};
910   int64_t ints64[] = {0, 1};
911   float floats[] = {0.0f, 1.0f};
912   double doubles[] = {0.0, 1.0};
913   MlirAttribute encoding = mlirAttributeGetNull();
914   MlirAttribute boolElements = mlirDenseElementsAttrBoolGet(
915       mlirRankedTensorTypeGet(2, shape, mlirIntegerTypeGet(ctx, 1), encoding),
916       2, bools);
917   MlirAttribute uint8Elements = mlirDenseElementsAttrUInt8Get(
918       mlirRankedTensorTypeGet(2, shape, mlirIntegerTypeUnsignedGet(ctx, 8),
919                               encoding),
920       2, uints8);
921   MlirAttribute int8Elements = mlirDenseElementsAttrInt8Get(
922       mlirRankedTensorTypeGet(2, shape, mlirIntegerTypeGet(ctx, 8), encoding),
923       2, ints8);
924   MlirAttribute uint32Elements = mlirDenseElementsAttrUInt32Get(
925       mlirRankedTensorTypeGet(2, shape, mlirIntegerTypeUnsignedGet(ctx, 32),
926                               encoding),
927       2, uints32);
928   MlirAttribute int32Elements = mlirDenseElementsAttrInt32Get(
929       mlirRankedTensorTypeGet(2, shape, mlirIntegerTypeGet(ctx, 32), encoding),
930       2, ints32);
931   MlirAttribute uint64Elements = mlirDenseElementsAttrUInt64Get(
932       mlirRankedTensorTypeGet(2, shape, mlirIntegerTypeUnsignedGet(ctx, 64),
933                               encoding),
934       2, uints64);
935   MlirAttribute int64Elements = mlirDenseElementsAttrInt64Get(
936       mlirRankedTensorTypeGet(2, shape, mlirIntegerTypeGet(ctx, 64), encoding),
937       2, ints64);
938   MlirAttribute floatElements = mlirDenseElementsAttrFloatGet(
939       mlirRankedTensorTypeGet(2, shape, mlirF32TypeGet(ctx), encoding), 2,
940       floats);
941   MlirAttribute doubleElements = mlirDenseElementsAttrDoubleGet(
942       mlirRankedTensorTypeGet(2, shape, mlirF64TypeGet(ctx), encoding), 2,
943       doubles);
944 
945   if (!mlirAttributeIsADenseElements(boolElements) ||
946       !mlirAttributeIsADenseElements(uint8Elements) ||
947       !mlirAttributeIsADenseElements(int8Elements) ||
948       !mlirAttributeIsADenseElements(uint32Elements) ||
949       !mlirAttributeIsADenseElements(int32Elements) ||
950       !mlirAttributeIsADenseElements(uint64Elements) ||
951       !mlirAttributeIsADenseElements(int64Elements) ||
952       !mlirAttributeIsADenseElements(floatElements) ||
953       !mlirAttributeIsADenseElements(doubleElements))
954     return 14;
955 
956   if (mlirDenseElementsAttrGetBoolValue(boolElements, 1) != 1 ||
957       mlirDenseElementsAttrGetUInt8Value(uint8Elements, 1) != 1 ||
958       mlirDenseElementsAttrGetInt8Value(int8Elements, 1) != 1 ||
959       mlirDenseElementsAttrGetUInt32Value(uint32Elements, 1) != 1 ||
960       mlirDenseElementsAttrGetInt32Value(int32Elements, 1) != 1 ||
961       mlirDenseElementsAttrGetUInt64Value(uint64Elements, 1) != 1 ||
962       mlirDenseElementsAttrGetInt64Value(int64Elements, 1) != 1 ||
963       fabsf(mlirDenseElementsAttrGetFloatValue(floatElements, 1) - 1.0f) >
964           1E-6f ||
965       fabs(mlirDenseElementsAttrGetDoubleValue(doubleElements, 1) - 1.0) > 1E-6)
966     return 15;
967 
968   mlirAttributeDump(boolElements);
969   mlirAttributeDump(uint8Elements);
970   mlirAttributeDump(int8Elements);
971   mlirAttributeDump(uint32Elements);
972   mlirAttributeDump(int32Elements);
973   mlirAttributeDump(uint64Elements);
974   mlirAttributeDump(int64Elements);
975   mlirAttributeDump(floatElements);
976   mlirAttributeDump(doubleElements);
977   // CHECK: dense<{{\[}}[false, true]]> : tensor<1x2xi1>
978   // CHECK: dense<{{\[}}[0, 1]]> : tensor<1x2xui8>
979   // CHECK: dense<{{\[}}[0, 1]]> : tensor<1x2xi8>
980   // CHECK: dense<{{\[}}[0, 1]]> : tensor<1x2xui32>
981   // CHECK: dense<{{\[}}[0, 1]]> : tensor<1x2xi32>
982   // CHECK: dense<{{\[}}[0, 1]]> : tensor<1x2xui64>
983   // CHECK: dense<{{\[}}[0, 1]]> : tensor<1x2xi64>
984   // CHECK: dense<{{\[}}[0.000000e+00, 1.000000e+00]]> : tensor<1x2xf32>
985   // CHECK: dense<{{\[}}[0.000000e+00, 1.000000e+00]]> : tensor<1x2xf64>
986 
987   MlirAttribute splatBool = mlirDenseElementsAttrBoolSplatGet(
988       mlirRankedTensorTypeGet(2, shape, mlirIntegerTypeGet(ctx, 1), encoding),
989       1);
990   MlirAttribute splatUInt8 = mlirDenseElementsAttrUInt8SplatGet(
991       mlirRankedTensorTypeGet(2, shape, mlirIntegerTypeUnsignedGet(ctx, 8),
992                               encoding),
993       1);
994   MlirAttribute splatInt8 = mlirDenseElementsAttrInt8SplatGet(
995       mlirRankedTensorTypeGet(2, shape, mlirIntegerTypeGet(ctx, 8), encoding),
996       1);
997   MlirAttribute splatUInt32 = mlirDenseElementsAttrUInt32SplatGet(
998       mlirRankedTensorTypeGet(2, shape, mlirIntegerTypeUnsignedGet(ctx, 32),
999                               encoding),
1000       1);
1001   MlirAttribute splatInt32 = mlirDenseElementsAttrInt32SplatGet(
1002       mlirRankedTensorTypeGet(2, shape, mlirIntegerTypeGet(ctx, 32), encoding),
1003       1);
1004   MlirAttribute splatUInt64 = mlirDenseElementsAttrUInt64SplatGet(
1005       mlirRankedTensorTypeGet(2, shape, mlirIntegerTypeUnsignedGet(ctx, 64),
1006                               encoding),
1007       1);
1008   MlirAttribute splatInt64 = mlirDenseElementsAttrInt64SplatGet(
1009       mlirRankedTensorTypeGet(2, shape, mlirIntegerTypeGet(ctx, 64), encoding),
1010       1);
1011   MlirAttribute splatFloat = mlirDenseElementsAttrFloatSplatGet(
1012       mlirRankedTensorTypeGet(2, shape, mlirF32TypeGet(ctx), encoding), 1.0f);
1013   MlirAttribute splatDouble = mlirDenseElementsAttrDoubleSplatGet(
1014       mlirRankedTensorTypeGet(2, shape, mlirF64TypeGet(ctx), encoding), 1.0);
1015 
1016   if (!mlirAttributeIsADenseElements(splatBool) ||
1017       !mlirDenseElementsAttrIsSplat(splatBool) ||
1018       !mlirAttributeIsADenseElements(splatUInt8) ||
1019       !mlirDenseElementsAttrIsSplat(splatUInt8) ||
1020       !mlirAttributeIsADenseElements(splatInt8) ||
1021       !mlirDenseElementsAttrIsSplat(splatInt8) ||
1022       !mlirAttributeIsADenseElements(splatUInt32) ||
1023       !mlirDenseElementsAttrIsSplat(splatUInt32) ||
1024       !mlirAttributeIsADenseElements(splatInt32) ||
1025       !mlirDenseElementsAttrIsSplat(splatInt32) ||
1026       !mlirAttributeIsADenseElements(splatUInt64) ||
1027       !mlirDenseElementsAttrIsSplat(splatUInt64) ||
1028       !mlirAttributeIsADenseElements(splatInt64) ||
1029       !mlirDenseElementsAttrIsSplat(splatInt64) ||
1030       !mlirAttributeIsADenseElements(splatFloat) ||
1031       !mlirDenseElementsAttrIsSplat(splatFloat) ||
1032       !mlirAttributeIsADenseElements(splatDouble) ||
1033       !mlirDenseElementsAttrIsSplat(splatDouble))
1034     return 16;
1035 
1036   if (mlirDenseElementsAttrGetBoolSplatValue(splatBool) != 1 ||
1037       mlirDenseElementsAttrGetUInt8SplatValue(splatUInt8) != 1 ||
1038       mlirDenseElementsAttrGetInt8SplatValue(splatInt8) != 1 ||
1039       mlirDenseElementsAttrGetUInt32SplatValue(splatUInt32) != 1 ||
1040       mlirDenseElementsAttrGetInt32SplatValue(splatInt32) != 1 ||
1041       mlirDenseElementsAttrGetUInt64SplatValue(splatUInt64) != 1 ||
1042       mlirDenseElementsAttrGetInt64SplatValue(splatInt64) != 1 ||
1043       fabsf(mlirDenseElementsAttrGetFloatSplatValue(splatFloat) - 1.0f) >
1044           1E-6f ||
1045       fabs(mlirDenseElementsAttrGetDoubleSplatValue(splatDouble) - 1.0) > 1E-6)
1046     return 17;
1047 
1048   uint8_t *uint8RawData =
1049       (uint8_t *)mlirDenseElementsAttrGetRawData(uint8Elements);
1050   int8_t *int8RawData = (int8_t *)mlirDenseElementsAttrGetRawData(int8Elements);
1051   uint32_t *uint32RawData =
1052       (uint32_t *)mlirDenseElementsAttrGetRawData(uint32Elements);
1053   int32_t *int32RawData =
1054       (int32_t *)mlirDenseElementsAttrGetRawData(int32Elements);
1055   uint64_t *uint64RawData =
1056       (uint64_t *)mlirDenseElementsAttrGetRawData(uint64Elements);
1057   int64_t *int64RawData =
1058       (int64_t *)mlirDenseElementsAttrGetRawData(int64Elements);
1059   float *floatRawData = (float *)mlirDenseElementsAttrGetRawData(floatElements);
1060   double *doubleRawData =
1061       (double *)mlirDenseElementsAttrGetRawData(doubleElements);
1062   if (uint8RawData[0] != 0u || uint8RawData[1] != 1u || int8RawData[0] != 0 ||
1063       int8RawData[1] != 1 || uint32RawData[0] != 0u || uint32RawData[1] != 1u ||
1064       int32RawData[0] != 0 || int32RawData[1] != 1 || uint64RawData[0] != 0u ||
1065       uint64RawData[1] != 1u || int64RawData[0] != 0 || int64RawData[1] != 1 ||
1066       floatRawData[0] != 0.0f || floatRawData[1] != 1.0f ||
1067       doubleRawData[0] != 0.0 || doubleRawData[1] != 1.0)
1068     return 18;
1069 
1070   mlirAttributeDump(splatBool);
1071   mlirAttributeDump(splatUInt8);
1072   mlirAttributeDump(splatInt8);
1073   mlirAttributeDump(splatUInt32);
1074   mlirAttributeDump(splatInt32);
1075   mlirAttributeDump(splatUInt64);
1076   mlirAttributeDump(splatInt64);
1077   mlirAttributeDump(splatFloat);
1078   mlirAttributeDump(splatDouble);
1079   // CHECK: dense<true> : tensor<1x2xi1>
1080   // CHECK: dense<1> : tensor<1x2xui8>
1081   // CHECK: dense<1> : tensor<1x2xi8>
1082   // CHECK: dense<1> : tensor<1x2xui32>
1083   // CHECK: dense<1> : tensor<1x2xi32>
1084   // CHECK: dense<1> : tensor<1x2xui64>
1085   // CHECK: dense<1> : tensor<1x2xi64>
1086   // CHECK: dense<1.000000e+00> : tensor<1x2xf32>
1087   // CHECK: dense<1.000000e+00> : tensor<1x2xf64>
1088 
1089   mlirAttributeDump(mlirElementsAttrGetValue(floatElements, 2, uints64));
1090   mlirAttributeDump(mlirElementsAttrGetValue(doubleElements, 2, uints64));
1091   // CHECK: 1.000000e+00 : f32
1092   // CHECK: 1.000000e+00 : f64
1093 
1094   int64_t indices[] = {0, 1};
1095   int64_t one = 1;
1096   MlirAttribute indicesAttr = mlirDenseElementsAttrInt64Get(
1097       mlirRankedTensorTypeGet(2, shape, mlirIntegerTypeGet(ctx, 64), encoding),
1098       2, indices);
1099   MlirAttribute valuesAttr = mlirDenseElementsAttrFloatGet(
1100       mlirRankedTensorTypeGet(1, &one, mlirF32TypeGet(ctx), encoding), 1,
1101       floats);
1102   MlirAttribute sparseAttr = mlirSparseElementsAttribute(
1103       mlirRankedTensorTypeGet(2, shape, mlirF32TypeGet(ctx), encoding),
1104       indicesAttr, valuesAttr);
1105   mlirAttributeDump(sparseAttr);
1106   // CHECK: sparse<{{\[}}[0, 1]], 0.000000e+00> : tensor<1x2xf32>
1107 
1108   return 0;
1109 }
1110 
1111 int printAffineMap(MlirContext ctx) {
1112   MlirAffineMap emptyAffineMap = mlirAffineMapEmptyGet(ctx);
1113   MlirAffineMap affineMap = mlirAffineMapZeroResultGet(ctx, 3, 2);
1114   MlirAffineMap constAffineMap = mlirAffineMapConstantGet(ctx, 2);
1115   MlirAffineMap multiDimIdentityAffineMap =
1116       mlirAffineMapMultiDimIdentityGet(ctx, 3);
1117   MlirAffineMap minorIdentityAffineMap =
1118       mlirAffineMapMinorIdentityGet(ctx, 3, 2);
1119   unsigned permutation[] = {1, 2, 0};
1120   MlirAffineMap permutationAffineMap = mlirAffineMapPermutationGet(
1121       ctx, sizeof(permutation) / sizeof(unsigned), permutation);
1122 
1123   fprintf(stderr, "@affineMap\n");
1124   mlirAffineMapDump(emptyAffineMap);
1125   mlirAffineMapDump(affineMap);
1126   mlirAffineMapDump(constAffineMap);
1127   mlirAffineMapDump(multiDimIdentityAffineMap);
1128   mlirAffineMapDump(minorIdentityAffineMap);
1129   mlirAffineMapDump(permutationAffineMap);
1130   // CHECK-LABEL: @affineMap
1131   // CHECK: () -> ()
1132   // CHECK: (d0, d1, d2)[s0, s1] -> ()
1133   // CHECK: () -> (2)
1134   // CHECK: (d0, d1, d2) -> (d0, d1, d2)
1135   // CHECK: (d0, d1, d2) -> (d1, d2)
1136   // CHECK: (d0, d1, d2) -> (d1, d2, d0)
1137 
1138   if (!mlirAffineMapIsIdentity(emptyAffineMap) ||
1139       mlirAffineMapIsIdentity(affineMap) ||
1140       mlirAffineMapIsIdentity(constAffineMap) ||
1141       !mlirAffineMapIsIdentity(multiDimIdentityAffineMap) ||
1142       mlirAffineMapIsIdentity(minorIdentityAffineMap) ||
1143       mlirAffineMapIsIdentity(permutationAffineMap))
1144     return 1;
1145 
1146   if (!mlirAffineMapIsMinorIdentity(emptyAffineMap) ||
1147       mlirAffineMapIsMinorIdentity(affineMap) ||
1148       !mlirAffineMapIsMinorIdentity(multiDimIdentityAffineMap) ||
1149       !mlirAffineMapIsMinorIdentity(minorIdentityAffineMap) ||
1150       mlirAffineMapIsMinorIdentity(permutationAffineMap))
1151     return 2;
1152 
1153   if (!mlirAffineMapIsEmpty(emptyAffineMap) ||
1154       mlirAffineMapIsEmpty(affineMap) || mlirAffineMapIsEmpty(constAffineMap) ||
1155       mlirAffineMapIsEmpty(multiDimIdentityAffineMap) ||
1156       mlirAffineMapIsEmpty(minorIdentityAffineMap) ||
1157       mlirAffineMapIsEmpty(permutationAffineMap))
1158     return 3;
1159 
1160   if (mlirAffineMapIsSingleConstant(emptyAffineMap) ||
1161       mlirAffineMapIsSingleConstant(affineMap) ||
1162       !mlirAffineMapIsSingleConstant(constAffineMap) ||
1163       mlirAffineMapIsSingleConstant(multiDimIdentityAffineMap) ||
1164       mlirAffineMapIsSingleConstant(minorIdentityAffineMap) ||
1165       mlirAffineMapIsSingleConstant(permutationAffineMap))
1166     return 4;
1167 
1168   if (mlirAffineMapGetSingleConstantResult(constAffineMap) != 2)
1169     return 5;
1170 
1171   if (mlirAffineMapGetNumDims(emptyAffineMap) != 0 ||
1172       mlirAffineMapGetNumDims(affineMap) != 3 ||
1173       mlirAffineMapGetNumDims(constAffineMap) != 0 ||
1174       mlirAffineMapGetNumDims(multiDimIdentityAffineMap) != 3 ||
1175       mlirAffineMapGetNumDims(minorIdentityAffineMap) != 3 ||
1176       mlirAffineMapGetNumDims(permutationAffineMap) != 3)
1177     return 6;
1178 
1179   if (mlirAffineMapGetNumSymbols(emptyAffineMap) != 0 ||
1180       mlirAffineMapGetNumSymbols(affineMap) != 2 ||
1181       mlirAffineMapGetNumSymbols(constAffineMap) != 0 ||
1182       mlirAffineMapGetNumSymbols(multiDimIdentityAffineMap) != 0 ||
1183       mlirAffineMapGetNumSymbols(minorIdentityAffineMap) != 0 ||
1184       mlirAffineMapGetNumSymbols(permutationAffineMap) != 0)
1185     return 7;
1186 
1187   if (mlirAffineMapGetNumResults(emptyAffineMap) != 0 ||
1188       mlirAffineMapGetNumResults(affineMap) != 0 ||
1189       mlirAffineMapGetNumResults(constAffineMap) != 1 ||
1190       mlirAffineMapGetNumResults(multiDimIdentityAffineMap) != 3 ||
1191       mlirAffineMapGetNumResults(minorIdentityAffineMap) != 2 ||
1192       mlirAffineMapGetNumResults(permutationAffineMap) != 3)
1193     return 8;
1194 
1195   if (mlirAffineMapGetNumInputs(emptyAffineMap) != 0 ||
1196       mlirAffineMapGetNumInputs(affineMap) != 5 ||
1197       mlirAffineMapGetNumInputs(constAffineMap) != 0 ||
1198       mlirAffineMapGetNumInputs(multiDimIdentityAffineMap) != 3 ||
1199       mlirAffineMapGetNumInputs(minorIdentityAffineMap) != 3 ||
1200       mlirAffineMapGetNumInputs(permutationAffineMap) != 3)
1201     return 9;
1202 
1203   if (!mlirAffineMapIsProjectedPermutation(emptyAffineMap) ||
1204       !mlirAffineMapIsPermutation(emptyAffineMap) ||
1205       mlirAffineMapIsProjectedPermutation(affineMap) ||
1206       mlirAffineMapIsPermutation(affineMap) ||
1207       mlirAffineMapIsProjectedPermutation(constAffineMap) ||
1208       mlirAffineMapIsPermutation(constAffineMap) ||
1209       !mlirAffineMapIsProjectedPermutation(multiDimIdentityAffineMap) ||
1210       !mlirAffineMapIsPermutation(multiDimIdentityAffineMap) ||
1211       !mlirAffineMapIsProjectedPermutation(minorIdentityAffineMap) ||
1212       mlirAffineMapIsPermutation(minorIdentityAffineMap) ||
1213       !mlirAffineMapIsProjectedPermutation(permutationAffineMap) ||
1214       !mlirAffineMapIsPermutation(permutationAffineMap))
1215     return 10;
1216 
1217   intptr_t sub[] = {1};
1218 
1219   MlirAffineMap subMap = mlirAffineMapGetSubMap(
1220       multiDimIdentityAffineMap, sizeof(sub) / sizeof(intptr_t), sub);
1221   MlirAffineMap majorSubMap =
1222       mlirAffineMapGetMajorSubMap(multiDimIdentityAffineMap, 1);
1223   MlirAffineMap minorSubMap =
1224       mlirAffineMapGetMinorSubMap(multiDimIdentityAffineMap, 1);
1225 
1226   mlirAffineMapDump(subMap);
1227   mlirAffineMapDump(majorSubMap);
1228   mlirAffineMapDump(minorSubMap);
1229   // CHECK: (d0, d1, d2) -> (d1)
1230   // CHECK: (d0, d1, d2) -> (d0)
1231   // CHECK: (d0, d1, d2) -> (d2)
1232 
1233   return 0;
1234 }
1235 
1236 int printAffineExpr(MlirContext ctx) {
1237   MlirAffineExpr affineDimExpr = mlirAffineDimExprGet(ctx, 5);
1238   MlirAffineExpr affineSymbolExpr = mlirAffineSymbolExprGet(ctx, 5);
1239   MlirAffineExpr affineConstantExpr = mlirAffineConstantExprGet(ctx, 5);
1240   MlirAffineExpr affineAddExpr =
1241       mlirAffineAddExprGet(affineDimExpr, affineSymbolExpr);
1242   MlirAffineExpr affineMulExpr =
1243       mlirAffineMulExprGet(affineDimExpr, affineSymbolExpr);
1244   MlirAffineExpr affineModExpr =
1245       mlirAffineModExprGet(affineDimExpr, affineSymbolExpr);
1246   MlirAffineExpr affineFloorDivExpr =
1247       mlirAffineFloorDivExprGet(affineDimExpr, affineSymbolExpr);
1248   MlirAffineExpr affineCeilDivExpr =
1249       mlirAffineCeilDivExprGet(affineDimExpr, affineSymbolExpr);
1250 
1251   // Tests mlirAffineExprDump.
1252   fprintf(stderr, "@affineExpr\n");
1253   mlirAffineExprDump(affineDimExpr);
1254   mlirAffineExprDump(affineSymbolExpr);
1255   mlirAffineExprDump(affineConstantExpr);
1256   mlirAffineExprDump(affineAddExpr);
1257   mlirAffineExprDump(affineMulExpr);
1258   mlirAffineExprDump(affineModExpr);
1259   mlirAffineExprDump(affineFloorDivExpr);
1260   mlirAffineExprDump(affineCeilDivExpr);
1261   // CHECK-LABEL: @affineExpr
1262   // CHECK: d5
1263   // CHECK: s5
1264   // CHECK: 5
1265   // CHECK: d5 + s5
1266   // CHECK: d5 * s5
1267   // CHECK: d5 mod s5
1268   // CHECK: d5 floordiv s5
1269   // CHECK: d5 ceildiv s5
1270 
1271   // Tests methods of affine binary operation expression, takes add expression
1272   // as an example.
1273   mlirAffineExprDump(mlirAffineBinaryOpExprGetLHS(affineAddExpr));
1274   mlirAffineExprDump(mlirAffineBinaryOpExprGetRHS(affineAddExpr));
1275   // CHECK: d5
1276   // CHECK: s5
1277 
1278   // Tests methods of affine dimension expression.
1279   if (mlirAffineDimExprGetPosition(affineDimExpr) != 5)
1280     return 1;
1281 
1282   // Tests methods of affine symbol expression.
1283   if (mlirAffineSymbolExprGetPosition(affineSymbolExpr) != 5)
1284     return 2;
1285 
1286   // Tests methods of affine constant expression.
1287   if (mlirAffineConstantExprGetValue(affineConstantExpr) != 5)
1288     return 3;
1289 
1290   // Tests methods of affine expression.
1291   if (mlirAffineExprIsSymbolicOrConstant(affineDimExpr) ||
1292       !mlirAffineExprIsSymbolicOrConstant(affineSymbolExpr) ||
1293       !mlirAffineExprIsSymbolicOrConstant(affineConstantExpr) ||
1294       mlirAffineExprIsSymbolicOrConstant(affineAddExpr) ||
1295       mlirAffineExprIsSymbolicOrConstant(affineMulExpr) ||
1296       mlirAffineExprIsSymbolicOrConstant(affineModExpr) ||
1297       mlirAffineExprIsSymbolicOrConstant(affineFloorDivExpr) ||
1298       mlirAffineExprIsSymbolicOrConstant(affineCeilDivExpr))
1299     return 4;
1300 
1301   if (!mlirAffineExprIsPureAffine(affineDimExpr) ||
1302       !mlirAffineExprIsPureAffine(affineSymbolExpr) ||
1303       !mlirAffineExprIsPureAffine(affineConstantExpr) ||
1304       !mlirAffineExprIsPureAffine(affineAddExpr) ||
1305       mlirAffineExprIsPureAffine(affineMulExpr) ||
1306       mlirAffineExprIsPureAffine(affineModExpr) ||
1307       mlirAffineExprIsPureAffine(affineFloorDivExpr) ||
1308       mlirAffineExprIsPureAffine(affineCeilDivExpr))
1309     return 5;
1310 
1311   if (mlirAffineExprGetLargestKnownDivisor(affineDimExpr) != 1 ||
1312       mlirAffineExprGetLargestKnownDivisor(affineSymbolExpr) != 1 ||
1313       mlirAffineExprGetLargestKnownDivisor(affineConstantExpr) != 5 ||
1314       mlirAffineExprGetLargestKnownDivisor(affineAddExpr) != 1 ||
1315       mlirAffineExprGetLargestKnownDivisor(affineMulExpr) != 1 ||
1316       mlirAffineExprGetLargestKnownDivisor(affineModExpr) != 1 ||
1317       mlirAffineExprGetLargestKnownDivisor(affineFloorDivExpr) != 1 ||
1318       mlirAffineExprGetLargestKnownDivisor(affineCeilDivExpr) != 1)
1319     return 6;
1320 
1321   if (!mlirAffineExprIsMultipleOf(affineDimExpr, 1) ||
1322       !mlirAffineExprIsMultipleOf(affineSymbolExpr, 1) ||
1323       !mlirAffineExprIsMultipleOf(affineConstantExpr, 5) ||
1324       !mlirAffineExprIsMultipleOf(affineAddExpr, 1) ||
1325       !mlirAffineExprIsMultipleOf(affineMulExpr, 1) ||
1326       !mlirAffineExprIsMultipleOf(affineModExpr, 1) ||
1327       !mlirAffineExprIsMultipleOf(affineFloorDivExpr, 1) ||
1328       !mlirAffineExprIsMultipleOf(affineCeilDivExpr, 1))
1329     return 7;
1330 
1331   if (!mlirAffineExprIsFunctionOfDim(affineDimExpr, 5) ||
1332       mlirAffineExprIsFunctionOfDim(affineSymbolExpr, 5) ||
1333       mlirAffineExprIsFunctionOfDim(affineConstantExpr, 5) ||
1334       !mlirAffineExprIsFunctionOfDim(affineAddExpr, 5) ||
1335       !mlirAffineExprIsFunctionOfDim(affineMulExpr, 5) ||
1336       !mlirAffineExprIsFunctionOfDim(affineModExpr, 5) ||
1337       !mlirAffineExprIsFunctionOfDim(affineFloorDivExpr, 5) ||
1338       !mlirAffineExprIsFunctionOfDim(affineCeilDivExpr, 5))
1339     return 8;
1340 
1341   // Tests 'IsA' methods of affine binary operation expression.
1342   if (!mlirAffineExprIsAAdd(affineAddExpr))
1343     return 9;
1344 
1345   if (!mlirAffineExprIsAMul(affineMulExpr))
1346     return 10;
1347 
1348   if (!mlirAffineExprIsAMod(affineModExpr))
1349     return 11;
1350 
1351   if (!mlirAffineExprIsAFloorDiv(affineFloorDivExpr))
1352     return 12;
1353 
1354   if (!mlirAffineExprIsACeilDiv(affineCeilDivExpr))
1355     return 13;
1356 
1357   if (!mlirAffineExprIsABinary(affineAddExpr))
1358     return 14;
1359 
1360   // Test other 'IsA' method on affine expressions.
1361   if (!mlirAffineExprIsAConstant(affineConstantExpr))
1362     return 15;
1363 
1364   if (!mlirAffineExprIsADim(affineDimExpr))
1365     return 16;
1366 
1367   if (!mlirAffineExprIsASymbol(affineSymbolExpr))
1368     return 17;
1369 
1370   // Test equality and nullity.
1371   MlirAffineExpr otherDimExpr = mlirAffineDimExprGet(ctx, 5);
1372   if (!mlirAffineExprEqual(affineDimExpr, otherDimExpr))
1373     return 18;
1374 
1375   if (mlirAffineExprIsNull(affineDimExpr))
1376     return 19;
1377 
1378   return 0;
1379 }
1380 
1381 int affineMapFromExprs(MlirContext ctx) {
1382   MlirAffineExpr affineDimExpr = mlirAffineDimExprGet(ctx, 0);
1383   MlirAffineExpr affineSymbolExpr = mlirAffineSymbolExprGet(ctx, 1);
1384   MlirAffineExpr exprs[] = {affineDimExpr, affineSymbolExpr};
1385   MlirAffineMap map = mlirAffineMapGet(ctx, 3, 3, 2, exprs);
1386 
1387   // CHECK-LABEL: @affineMapFromExprs
1388   fprintf(stderr, "@affineMapFromExprs");
1389   // CHECK: (d0, d1, d2)[s0, s1, s2] -> (d0, s1)
1390   mlirAffineMapDump(map);
1391 
1392   if (mlirAffineMapGetNumResults(map) != 2)
1393     return 1;
1394 
1395   if (!mlirAffineExprEqual(mlirAffineMapGetResult(map, 0), affineDimExpr))
1396     return 2;
1397 
1398   if (!mlirAffineExprEqual(mlirAffineMapGetResult(map, 1), affineSymbolExpr))
1399     return 3;
1400 
1401   MlirAffineExpr affineDim2Expr = mlirAffineDimExprGet(ctx, 1);
1402   MlirAffineExpr composed = mlirAffineExprCompose(affineDim2Expr, map);
1403   // CHECK: s1
1404   mlirAffineExprDump(composed);
1405   if (!mlirAffineExprEqual(composed, affineSymbolExpr))
1406     return 4;
1407 
1408   return 0;
1409 }
1410 
1411 int printIntegerSet(MlirContext ctx) {
1412   MlirIntegerSet emptySet = mlirIntegerSetEmptyGet(ctx, 2, 1);
1413 
1414   // CHECK-LABEL: @printIntegerSet
1415   fprintf(stderr, "@printIntegerSet");
1416 
1417   // CHECK: (d0, d1)[s0] : (1 == 0)
1418   mlirIntegerSetDump(emptySet);
1419 
1420   if (!mlirIntegerSetIsCanonicalEmpty(emptySet))
1421     return 1;
1422 
1423   MlirIntegerSet anotherEmptySet = mlirIntegerSetEmptyGet(ctx, 2, 1);
1424   if (!mlirIntegerSetEqual(emptySet, anotherEmptySet))
1425     return 2;
1426 
1427   // Construct a set constrained by:
1428   //   d0 - s0 == 0,
1429   //   d1 - 42 >= 0.
1430   MlirAffineExpr negOne = mlirAffineConstantExprGet(ctx, -1);
1431   MlirAffineExpr negFortyTwo = mlirAffineConstantExprGet(ctx, -42);
1432   MlirAffineExpr d0 = mlirAffineDimExprGet(ctx, 0);
1433   MlirAffineExpr d1 = mlirAffineDimExprGet(ctx, 1);
1434   MlirAffineExpr s0 = mlirAffineSymbolExprGet(ctx, 0);
1435   MlirAffineExpr negS0 = mlirAffineMulExprGet(negOne, s0);
1436   MlirAffineExpr d0minusS0 = mlirAffineAddExprGet(d0, negS0);
1437   MlirAffineExpr d1minus42 = mlirAffineAddExprGet(d1, negFortyTwo);
1438   MlirAffineExpr constraints[] = {d0minusS0, d1minus42};
1439   bool flags[] = {true, false};
1440 
1441   MlirIntegerSet set = mlirIntegerSetGet(ctx, 2, 1, 2, constraints, flags);
1442   // CHECK: (d0, d1)[s0] : (
1443   // CHECK-DAG: d0 - s0 == 0
1444   // CHECK-DAG: d1 - 42 >= 0
1445   mlirIntegerSetDump(set);
1446 
1447   // Transform d1 into s0.
1448   MlirAffineExpr s1 = mlirAffineSymbolExprGet(ctx, 1);
1449   MlirAffineExpr repl[] = {d0, s1};
1450   MlirIntegerSet replaced = mlirIntegerSetReplaceGet(set, repl, &s0, 1, 2);
1451   // CHECK: (d0)[s0, s1] : (
1452   // CHECK-DAG: d0 - s0 == 0
1453   // CHECK-DAG: s1 - 42 >= 0
1454   mlirIntegerSetDump(replaced);
1455 
1456   if (mlirIntegerSetGetNumDims(set) != 2)
1457     return 3;
1458   if (mlirIntegerSetGetNumDims(replaced) != 1)
1459     return 4;
1460 
1461   if (mlirIntegerSetGetNumSymbols(set) != 1)
1462     return 5;
1463   if (mlirIntegerSetGetNumSymbols(replaced) != 2)
1464     return 6;
1465 
1466   if (mlirIntegerSetGetNumInputs(set) != 3)
1467     return 7;
1468 
1469   if (mlirIntegerSetGetNumConstraints(set) != 2)
1470     return 8;
1471 
1472   if (mlirIntegerSetGetNumEqualities(set) != 1)
1473     return 9;
1474 
1475   if (mlirIntegerSetGetNumInequalities(set) != 1)
1476     return 10;
1477 
1478   MlirAffineExpr cstr1 = mlirIntegerSetGetConstraint(set, 0);
1479   MlirAffineExpr cstr2 = mlirIntegerSetGetConstraint(set, 1);
1480   bool isEq1 = mlirIntegerSetIsConstraintEq(set, 0);
1481   bool isEq2 = mlirIntegerSetIsConstraintEq(set, 1);
1482   if (!mlirAffineExprEqual(cstr1, isEq1 ? d0minusS0 : d1minus42))
1483     return 11;
1484   if (!mlirAffineExprEqual(cstr2, isEq2 ? d0minusS0 : d1minus42))
1485     return 12;
1486 
1487   return 0;
1488 }
1489 
1490 int registerOnlyStd() {
1491   MlirContext ctx = mlirContextCreate();
1492   // The built-in dialect is always loaded.
1493   if (mlirContextGetNumLoadedDialects(ctx) != 1)
1494     return 1;
1495 
1496   MlirDialectHandle stdHandle = mlirGetDialectHandle__std__();
1497 
1498   MlirDialect std = mlirContextGetOrLoadDialect(
1499       ctx, mlirDialectHandleGetNamespace(stdHandle));
1500   if (!mlirDialectIsNull(std))
1501     return 2;
1502 
1503   mlirDialectHandleRegisterDialect(stdHandle, ctx);
1504 
1505   std = mlirContextGetOrLoadDialect(ctx,
1506                                     mlirDialectHandleGetNamespace(stdHandle));
1507   if (mlirDialectIsNull(std))
1508     return 3;
1509 
1510   MlirDialect alsoStd = mlirDialectHandleLoadDialect(stdHandle, ctx);
1511   if (!mlirDialectEqual(std, alsoStd))
1512     return 4;
1513 
1514   MlirStringRef stdNs = mlirDialectGetNamespace(std);
1515   MlirStringRef alsoStdNs = mlirDialectHandleGetNamespace(stdHandle);
1516   if (stdNs.length != alsoStdNs.length ||
1517       strncmp(stdNs.data, alsoStdNs.data, stdNs.length))
1518     return 5;
1519 
1520   fprintf(stderr, "@registration\n");
1521   // CHECK-LABEL: @registration
1522 
1523   // CHECK: std.cond_br is_registered: 1
1524   fprintf(stderr, "std.cond_br is_registered: %d\n",
1525           mlirContextIsRegisteredOperation(
1526               ctx, mlirStringRefCreateFromCString("std.cond_br")));
1527 
1528   // CHECK: std.not_existing_op is_registered: 0
1529   fprintf(stderr, "std.not_existing_op is_registered: %d\n",
1530           mlirContextIsRegisteredOperation(
1531               ctx, mlirStringRefCreateFromCString("std.not_existing_op")));
1532 
1533   // CHECK: not_existing_dialect.not_existing_op is_registered: 0
1534   fprintf(stderr, "not_existing_dialect.not_existing_op is_registered: %d\n",
1535           mlirContextIsRegisteredOperation(
1536               ctx, mlirStringRefCreateFromCString(
1537                        "not_existing_dialect.not_existing_op")));
1538 
1539   mlirContextDestroy(ctx);
1540   return 0;
1541 }
1542 
1543 /// Tests backreference APIs
1544 static int testBackreferences() {
1545   fprintf(stderr, "@test_backreferences\n");
1546 
1547   MlirContext ctx = mlirContextCreate();
1548   mlirContextSetAllowUnregisteredDialects(ctx, true);
1549   MlirLocation loc = mlirLocationUnknownGet(ctx);
1550 
1551   MlirOperationState opState =
1552       mlirOperationStateGet(mlirStringRefCreateFromCString("invalid.op"), loc);
1553   MlirRegion region = mlirRegionCreate();
1554   MlirBlock block = mlirBlockCreate(0, NULL, NULL);
1555   mlirRegionAppendOwnedBlock(region, block);
1556   mlirOperationStateAddOwnedRegions(&opState, 1, &region);
1557   MlirOperation op = mlirOperationCreate(&opState);
1558   MlirIdentifier ident =
1559       mlirIdentifierGet(ctx, mlirStringRefCreateFromCString("identifier"));
1560 
1561   if (!mlirContextEqual(ctx, mlirOperationGetContext(op))) {
1562     fprintf(stderr, "ERROR: Getting context from operation failed\n");
1563     return 1;
1564   }
1565   if (!mlirOperationEqual(op, mlirBlockGetParentOperation(block))) {
1566     fprintf(stderr, "ERROR: Getting parent operation from block failed\n");
1567     return 2;
1568   }
1569   if (!mlirContextEqual(ctx, mlirIdentifierGetContext(ident))) {
1570     fprintf(stderr, "ERROR: Getting context from identifier failed\n");
1571     return 3;
1572   }
1573 
1574   mlirOperationDestroy(op);
1575   mlirContextDestroy(ctx);
1576 
1577   // CHECK-LABEL: @test_backreferences
1578   return 0;
1579 }
1580 
1581 /// Tests operand APIs.
1582 int testOperands() {
1583   fprintf(stderr, "@testOperands\n");
1584   // CHECK-LABEL: @testOperands
1585 
1586   MlirContext ctx = mlirContextCreate();
1587   mlirRegisterAllDialects(ctx);
1588   mlirContextGetOrLoadDialect(ctx, mlirStringRefCreateFromCString("test"));
1589   MlirLocation loc = mlirLocationUnknownGet(ctx);
1590   MlirType indexType = mlirIndexTypeGet(ctx);
1591 
1592   // Create some constants to use as operands.
1593   MlirAttribute indexZeroLiteral =
1594       mlirAttributeParseGet(ctx, mlirStringRefCreateFromCString("0 : index"));
1595   MlirNamedAttribute indexZeroValueAttr = mlirNamedAttributeGet(
1596       mlirIdentifierGet(ctx, mlirStringRefCreateFromCString("value")),
1597       indexZeroLiteral);
1598   MlirOperationState constZeroState = mlirOperationStateGet(
1599       mlirStringRefCreateFromCString("arith.constant"), loc);
1600   mlirOperationStateAddResults(&constZeroState, 1, &indexType);
1601   mlirOperationStateAddAttributes(&constZeroState, 1, &indexZeroValueAttr);
1602   MlirOperation constZero = mlirOperationCreate(&constZeroState);
1603   MlirValue constZeroValue = mlirOperationGetResult(constZero, 0);
1604 
1605   MlirAttribute indexOneLiteral =
1606       mlirAttributeParseGet(ctx, mlirStringRefCreateFromCString("1 : index"));
1607   MlirNamedAttribute indexOneValueAttr = mlirNamedAttributeGet(
1608       mlirIdentifierGet(ctx, mlirStringRefCreateFromCString("value")),
1609       indexOneLiteral);
1610   MlirOperationState constOneState = mlirOperationStateGet(
1611       mlirStringRefCreateFromCString("arith.constant"), loc);
1612   mlirOperationStateAddResults(&constOneState, 1, &indexType);
1613   mlirOperationStateAddAttributes(&constOneState, 1, &indexOneValueAttr);
1614   MlirOperation constOne = mlirOperationCreate(&constOneState);
1615   MlirValue constOneValue = mlirOperationGetResult(constOne, 0);
1616 
1617   // Create the operation under test.
1618   mlirContextSetAllowUnregisteredDialects(ctx, true);
1619   MlirOperationState opState =
1620       mlirOperationStateGet(mlirStringRefCreateFromCString("dummy.op"), loc);
1621   MlirValue initialOperands[] = {constZeroValue};
1622   mlirOperationStateAddOperands(&opState, 1, initialOperands);
1623   MlirOperation op = mlirOperationCreate(&opState);
1624 
1625   // Test operand APIs.
1626   intptr_t numOperands = mlirOperationGetNumOperands(op);
1627   fprintf(stderr, "Num Operands: %" PRIdPTR "\n", numOperands);
1628   // CHECK: Num Operands: 1
1629 
1630   MlirValue opOperand = mlirOperationGetOperand(op, 0);
1631   fprintf(stderr, "Original operand: ");
1632   mlirValuePrint(opOperand, printToStderr, NULL);
1633   // CHECK: Original operand: {{.+}} arith.constant 0 : index
1634 
1635   mlirOperationSetOperand(op, 0, constOneValue);
1636   opOperand = mlirOperationGetOperand(op, 0);
1637   fprintf(stderr, "Updated operand: ");
1638   mlirValuePrint(opOperand, printToStderr, NULL);
1639   // CHECK: Updated operand: {{.+}} arith.constant 1 : index
1640 
1641   mlirOperationDestroy(op);
1642   mlirOperationDestroy(constZero);
1643   mlirOperationDestroy(constOne);
1644   mlirContextDestroy(ctx);
1645 
1646   return 0;
1647 }
1648 
1649 /// Tests clone APIs.
1650 int testClone() {
1651   fprintf(stderr, "@testClone\n");
1652   // CHECK-LABEL: @testClone
1653 
1654   MlirContext ctx = mlirContextCreate();
1655   mlirRegisterAllDialects(ctx);
1656   mlirContextGetOrLoadDialect(ctx, mlirStringRefCreateFromCString("std"));
1657   MlirLocation loc = mlirLocationUnknownGet(ctx);
1658   MlirType indexType = mlirIndexTypeGet(ctx);
1659   MlirStringRef valueStringRef = mlirStringRefCreateFromCString("value");
1660 
1661   MlirAttribute indexZeroLiteral =
1662       mlirAttributeParseGet(ctx, mlirStringRefCreateFromCString("0 : index"));
1663   MlirNamedAttribute indexZeroValueAttr = mlirNamedAttributeGet(
1664       mlirIdentifierGet(ctx, valueStringRef), indexZeroLiteral);
1665   MlirOperationState constZeroState = mlirOperationStateGet(
1666       mlirStringRefCreateFromCString("arith.constant"), loc);
1667   mlirOperationStateAddResults(&constZeroState, 1, &indexType);
1668   mlirOperationStateAddAttributes(&constZeroState, 1, &indexZeroValueAttr);
1669   MlirOperation constZero = mlirOperationCreate(&constZeroState);
1670 
1671   MlirAttribute indexOneLiteral =
1672       mlirAttributeParseGet(ctx, mlirStringRefCreateFromCString("1 : index"));
1673   MlirOperation constOne = mlirOperationClone(constZero);
1674   mlirOperationSetAttributeByName(constOne, valueStringRef, indexOneLiteral);
1675 
1676   mlirOperationPrint(constZero, printToStderr, NULL);
1677   mlirOperationPrint(constOne, printToStderr, NULL);
1678   // CHECK: arith.constant 0 : index
1679   // CHECK: arith.constant 1 : index
1680 
1681   mlirOperationDestroy(constZero);
1682   mlirOperationDestroy(constOne);
1683   mlirContextDestroy(ctx);
1684   return 0;
1685 }
1686 
1687 // Wraps a diagnostic into additional text we can match against.
1688 MlirLogicalResult errorHandler(MlirDiagnostic diagnostic, void *userData) {
1689   fprintf(stderr, "processing diagnostic (userData: %" PRIdPTR ") <<\n",
1690           (intptr_t)userData);
1691   mlirDiagnosticPrint(diagnostic, printToStderr, NULL);
1692   fprintf(stderr, "\n");
1693   MlirLocation loc = mlirDiagnosticGetLocation(diagnostic);
1694   mlirLocationPrint(loc, printToStderr, NULL);
1695   assert(mlirDiagnosticGetNumNotes(diagnostic) == 0);
1696   fprintf(stderr, "\n>> end of diagnostic (userData: %" PRIdPTR ")\n",
1697           (intptr_t)userData);
1698   return mlirLogicalResultSuccess();
1699 }
1700 
1701 // Logs when the delete user data callback is called
1702 static void deleteUserData(void *userData) {
1703   fprintf(stderr, "deleting user data (userData: %" PRIdPTR ")\n",
1704           (intptr_t)userData);
1705 }
1706 
1707 int testTypeID(MlirContext ctx) {
1708   fprintf(stderr, "@testTypeID\n");
1709 
1710   // Test getting and comparing type and attribute type ids.
1711   MlirType i32 = mlirIntegerTypeGet(ctx, 32);
1712   MlirTypeID i32ID = mlirTypeGetTypeID(i32);
1713   MlirType ui32 = mlirIntegerTypeUnsignedGet(ctx, 32);
1714   MlirTypeID ui32ID = mlirTypeGetTypeID(ui32);
1715   MlirType f32 = mlirF32TypeGet(ctx);
1716   MlirTypeID f32ID = mlirTypeGetTypeID(f32);
1717   MlirAttribute i32Attr = mlirIntegerAttrGet(i32, 1);
1718   MlirTypeID i32AttrID = mlirAttributeGetTypeID(i32Attr);
1719 
1720   if (mlirTypeIDIsNull(i32ID) || mlirTypeIDIsNull(ui32ID) ||
1721       mlirTypeIDIsNull(f32ID) || mlirTypeIDIsNull(i32AttrID)) {
1722     fprintf(stderr, "ERROR: Expected type ids to be present\n");
1723     return 1;
1724   }
1725 
1726   if (!mlirTypeIDEqual(i32ID, ui32ID) ||
1727       mlirTypeIDHashValue(i32ID) != mlirTypeIDHashValue(ui32ID)) {
1728     fprintf(
1729         stderr,
1730         "ERROR: Expected different integer types to have the same type id\n");
1731     return 2;
1732   }
1733 
1734   if (mlirTypeIDEqual(i32ID, f32ID) ||
1735       mlirTypeIDHashValue(i32ID) == mlirTypeIDHashValue(f32ID)) {
1736     fprintf(stderr,
1737             "ERROR: Expected integer type id to not equal float type id\n");
1738     return 3;
1739   }
1740 
1741   if (mlirTypeIDEqual(i32ID, i32AttrID) ||
1742       mlirTypeIDHashValue(i32ID) == mlirTypeIDHashValue(i32AttrID)) {
1743     fprintf(stderr, "ERROR: Expected integer type id to not equal integer "
1744                     "attribute type id\n");
1745     return 4;
1746   }
1747 
1748   MlirLocation loc = mlirLocationUnknownGet(ctx);
1749   MlirType indexType = mlirIndexTypeGet(ctx);
1750   MlirStringRef valueStringRef = mlirStringRefCreateFromCString("value");
1751 
1752   // Create a registered operation, which should have a type id.
1753   MlirAttribute indexZeroLiteral =
1754       mlirAttributeParseGet(ctx, mlirStringRefCreateFromCString("0 : index"));
1755   MlirNamedAttribute indexZeroValueAttr = mlirNamedAttributeGet(
1756       mlirIdentifierGet(ctx, valueStringRef), indexZeroLiteral);
1757   MlirOperationState constZeroState = mlirOperationStateGet(
1758       mlirStringRefCreateFromCString("arith.constant"), loc);
1759   mlirOperationStateAddResults(&constZeroState, 1, &indexType);
1760   mlirOperationStateAddAttributes(&constZeroState, 1, &indexZeroValueAttr);
1761   MlirOperation constZero = mlirOperationCreate(&constZeroState);
1762 
1763   if (!mlirOperationVerify(constZero)) {
1764     fprintf(stderr, "ERROR: Expected operation to verify correctly\n");
1765     return 5;
1766   }
1767 
1768   if (mlirOperationIsNull(constZero)) {
1769     fprintf(stderr, "ERROR: Expected registered operation to be present\n");
1770     return 6;
1771   }
1772 
1773   MlirTypeID registeredOpID = mlirOperationGetTypeID(constZero);
1774 
1775   if (mlirTypeIDIsNull(registeredOpID)) {
1776     fprintf(stderr,
1777             "ERROR: Expected registered operation type id to be present\n");
1778     return 7;
1779   }
1780 
1781   // Create an unregistered operation, which should not have a type id.
1782   mlirContextSetAllowUnregisteredDialects(ctx, true);
1783   MlirOperationState opState =
1784       mlirOperationStateGet(mlirStringRefCreateFromCString("dummy.op"), loc);
1785   MlirOperation unregisteredOp = mlirOperationCreate(&opState);
1786   if (mlirOperationIsNull(unregisteredOp)) {
1787     fprintf(stderr, "ERROR: Expected unregistered operation to be present\n");
1788     return 8;
1789   }
1790 
1791   MlirTypeID unregisteredOpID = mlirOperationGetTypeID(unregisteredOp);
1792 
1793   if (!mlirTypeIDIsNull(unregisteredOpID)) {
1794     fprintf(stderr,
1795             "ERROR: Expected unregistered operation type id to be null\n");
1796     return 9;
1797   }
1798 
1799   mlirOperationDestroy(constZero);
1800   mlirOperationDestroy(unregisteredOp);
1801 
1802   return 0;
1803 }
1804 
1805 int testSymbolTable(MlirContext ctx) {
1806   fprintf(stderr, "@testSymbolTable\n");
1807 
1808   const char *moduleString = "func private @foo()"
1809                              "func private @bar()";
1810   const char *otherModuleString = "func private @qux()"
1811                                   "func private @foo()";
1812 
1813   MlirModule module =
1814       mlirModuleCreateParse(ctx, mlirStringRefCreateFromCString(moduleString));
1815   MlirModule otherModule = mlirModuleCreateParse(
1816       ctx, mlirStringRefCreateFromCString(otherModuleString));
1817 
1818   MlirSymbolTable symbolTable =
1819       mlirSymbolTableCreate(mlirModuleGetOperation(module));
1820 
1821   MlirOperation funcFoo =
1822       mlirSymbolTableLookup(symbolTable, mlirStringRefCreateFromCString("foo"));
1823   if (mlirOperationIsNull(funcFoo))
1824     return 1;
1825 
1826   MlirOperation funcBar =
1827       mlirSymbolTableLookup(symbolTable, mlirStringRefCreateFromCString("bar"));
1828   if (mlirOperationEqual(funcFoo, funcBar))
1829     return 2;
1830 
1831   MlirOperation missing =
1832       mlirSymbolTableLookup(symbolTable, mlirStringRefCreateFromCString("qux"));
1833   if (!mlirOperationIsNull(missing))
1834     return 3;
1835 
1836   MlirBlock moduleBody = mlirModuleGetBody(module);
1837   MlirBlock otherModuleBody = mlirModuleGetBody(otherModule);
1838   MlirOperation operation = mlirBlockGetFirstOperation(otherModuleBody);
1839   mlirOperationRemoveFromParent(operation);
1840   mlirBlockAppendOwnedOperation(moduleBody, operation);
1841 
1842   // At this moment, the operation is still missing from the symbol table.
1843   MlirOperation stillMissing =
1844       mlirSymbolTableLookup(symbolTable, mlirStringRefCreateFromCString("qux"));
1845   if (!mlirOperationIsNull(stillMissing))
1846     return 4;
1847 
1848   // After it is added to the symbol table, and not only the operation with
1849   // which the table is associated, it can be looked up.
1850   mlirSymbolTableInsert(symbolTable, operation);
1851   MlirOperation funcQux =
1852       mlirSymbolTableLookup(symbolTable, mlirStringRefCreateFromCString("qux"));
1853   if (!mlirOperationEqual(operation, funcQux))
1854     return 5;
1855 
1856   // Erasing from the symbol table also removes the operation.
1857   mlirSymbolTableErase(symbolTable, funcBar);
1858   MlirOperation nowMissing =
1859       mlirSymbolTableLookup(symbolTable, mlirStringRefCreateFromCString("bar"));
1860   if (!mlirOperationIsNull(nowMissing))
1861     return 6;
1862 
1863   // Adding a symbol with the same name to the table should rename.
1864   MlirOperation duplicateNameOp = mlirBlockGetFirstOperation(otherModuleBody);
1865   mlirOperationRemoveFromParent(duplicateNameOp);
1866   mlirBlockAppendOwnedOperation(moduleBody, duplicateNameOp);
1867   MlirAttribute newName = mlirSymbolTableInsert(symbolTable, duplicateNameOp);
1868   MlirStringRef newNameStr = mlirStringAttrGetValue(newName);
1869   if (mlirStringRefEqual(newNameStr, mlirStringRefCreateFromCString("foo")))
1870     return 7;
1871   MlirAttribute updatedName = mlirOperationGetAttributeByName(
1872       duplicateNameOp, mlirSymbolTableGetSymbolAttributeName());
1873   if (!mlirAttributeEqual(updatedName, newName))
1874     return 8;
1875 
1876   mlirOperationDump(mlirModuleGetOperation(module));
1877   mlirOperationDump(mlirModuleGetOperation(otherModule));
1878   // clang-format off
1879   // CHECK-LABEL: @testSymbolTable
1880   // CHECK: module
1881   // CHECK:   func private @foo
1882   // CHECK:   func private @qux
1883   // CHECK:   func private @foo{{.+}}
1884   // CHECK: module
1885   // CHECK-NOT: @qux
1886   // CHECK-NOT: @foo
1887   // clang-format on
1888 
1889   mlirSymbolTableDestroy(symbolTable);
1890   mlirModuleDestroy(module);
1891   mlirModuleDestroy(otherModule);
1892 
1893   return 0;
1894 }
1895 
1896 void testDiagnostics() {
1897   MlirContext ctx = mlirContextCreate();
1898   MlirDiagnosticHandlerID id = mlirContextAttachDiagnosticHandler(
1899       ctx, errorHandler, (void *)42, deleteUserData);
1900   fprintf(stderr, "@test_diagnostics\n");
1901   MlirLocation unknownLoc = mlirLocationUnknownGet(ctx);
1902   mlirEmitError(unknownLoc, "test diagnostics");
1903   MlirLocation fileLineColLoc = mlirLocationFileLineColGet(
1904       ctx, mlirStringRefCreateFromCString("file.c"), 1, 2);
1905   mlirEmitError(fileLineColLoc, "test diagnostics");
1906   MlirLocation callSiteLoc = mlirLocationCallSiteGet(
1907       mlirLocationFileLineColGet(
1908           ctx, mlirStringRefCreateFromCString("other-file.c"), 2, 3),
1909       fileLineColLoc);
1910   mlirEmitError(callSiteLoc, "test diagnostics");
1911   MlirLocation null = {0};
1912   MlirLocation nameLoc =
1913       mlirLocationNameGet(ctx, mlirStringRefCreateFromCString("named"), null);
1914   mlirEmitError(nameLoc, "test diagnostics");
1915   MlirLocation locs[2] = {nameLoc, callSiteLoc};
1916   MlirAttribute nullAttr = {0};
1917   MlirLocation fusedLoc = mlirLocationFusedGet(ctx, 2, locs, nullAttr);
1918   mlirEmitError(fusedLoc, "test diagnostics");
1919   mlirContextDetachDiagnosticHandler(ctx, id);
1920   mlirEmitError(unknownLoc, "more test diagnostics");
1921   // CHECK-LABEL: @test_diagnostics
1922   // CHECK: processing diagnostic (userData: 42) <<
1923   // CHECK:   test diagnostics
1924   // CHECK:   loc(unknown)
1925   // CHECK: >> end of diagnostic (userData: 42)
1926   // CHECK: processing diagnostic (userData: 42) <<
1927   // CHECK:   test diagnostics
1928   // CHECK:   loc("file.c":1:2)
1929   // CHECK: >> end of diagnostic (userData: 42)
1930   // CHECK: processing diagnostic (userData: 42) <<
1931   // CHECK:   test diagnostics
1932   // CHECK:   loc(callsite("other-file.c":2:3 at "file.c":1:2))
1933   // CHECK: >> end of diagnostic (userData: 42)
1934   // CHECK: processing diagnostic (userData: 42) <<
1935   // CHECK:   test diagnostics
1936   // CHECK:   loc("named")
1937   // CHECK: >> end of diagnostic (userData: 42)
1938   // CHECK: processing diagnostic (userData: 42) <<
1939   // CHECK:   test diagnostics
1940   // CHECK:   loc(fused["named", callsite("other-file.c":2:3 at "file.c":1:2)])
1941   // CHECK: deleting user data (userData: 42)
1942   // CHECK-NOT: processing diagnostic
1943   // CHECK:     more test diagnostics
1944   mlirContextDestroy(ctx);
1945 }
1946 
1947 int main() {
1948   MlirContext ctx = mlirContextCreate();
1949   mlirRegisterAllDialects(ctx);
1950   if (constructAndTraverseIr(ctx))
1951     return 1;
1952   buildWithInsertionsAndPrint(ctx);
1953   if (createOperationWithTypeInference(ctx))
1954     return 2;
1955 
1956   if (printBuiltinTypes(ctx))
1957     return 3;
1958   if (printBuiltinAttributes(ctx))
1959     return 4;
1960   if (printAffineMap(ctx))
1961     return 5;
1962   if (printAffineExpr(ctx))
1963     return 6;
1964   if (affineMapFromExprs(ctx))
1965     return 7;
1966   if (printIntegerSet(ctx))
1967     return 8;
1968   if (registerOnlyStd())
1969     return 9;
1970   if (testBackreferences())
1971     return 10;
1972   if (testOperands())
1973     return 11;
1974   if (testClone())
1975     return 12;
1976   if (testTypeID(ctx))
1977     return 13;
1978   if (testSymbolTable(ctx))
1979     return 14;
1980 
1981   mlirContextDestroy(ctx);
1982 
1983   testDiagnostics();
1984   return 0;
1985 }
1986