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