xref: /llvm-project-15.0.7/mlir/test/CAPI/ir.c (revision cd4abc52)
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: 13
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)), 4,
442           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 =
691       mlirRankedTensorTypeGet(sizeof(shape) / sizeof(int64_t), shape, f32);
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 boolElements = mlirDenseElementsAttrBoolGet(
893       mlirRankedTensorTypeGet(2, shape, mlirIntegerTypeGet(ctx, 1)), 2, bools);
894   MlirAttribute uint32Elements = mlirDenseElementsAttrUInt32Get(
895       mlirRankedTensorTypeGet(2, shape, mlirIntegerTypeUnsignedGet(ctx, 32)), 2,
896       uints32);
897   MlirAttribute int32Elements = mlirDenseElementsAttrInt32Get(
898       mlirRankedTensorTypeGet(2, shape, mlirIntegerTypeGet(ctx, 32)), 2,
899       ints32);
900   MlirAttribute uint64Elements = mlirDenseElementsAttrUInt64Get(
901       mlirRankedTensorTypeGet(2, shape, mlirIntegerTypeUnsignedGet(ctx, 64)), 2,
902       uints64);
903   MlirAttribute int64Elements = mlirDenseElementsAttrInt64Get(
904       mlirRankedTensorTypeGet(2, shape, mlirIntegerTypeGet(ctx, 64)), 2,
905       ints64);
906   MlirAttribute floatElements = mlirDenseElementsAttrFloatGet(
907       mlirRankedTensorTypeGet(2, shape, mlirF32TypeGet(ctx)), 2, floats);
908   MlirAttribute doubleElements = mlirDenseElementsAttrDoubleGet(
909       mlirRankedTensorTypeGet(2, shape, mlirF64TypeGet(ctx)), 2, doubles);
910 
911   if (!mlirAttributeIsADenseElements(boolElements) ||
912       !mlirAttributeIsADenseElements(uint32Elements) ||
913       !mlirAttributeIsADenseElements(int32Elements) ||
914       !mlirAttributeIsADenseElements(uint64Elements) ||
915       !mlirAttributeIsADenseElements(int64Elements) ||
916       !mlirAttributeIsADenseElements(floatElements) ||
917       !mlirAttributeIsADenseElements(doubleElements))
918     return 14;
919 
920   if (mlirDenseElementsAttrGetBoolValue(boolElements, 1) != 1 ||
921       mlirDenseElementsAttrGetUInt32Value(uint32Elements, 1) != 1 ||
922       mlirDenseElementsAttrGetInt32Value(int32Elements, 1) != 1 ||
923       mlirDenseElementsAttrGetUInt64Value(uint64Elements, 1) != 1 ||
924       mlirDenseElementsAttrGetInt64Value(int64Elements, 1) != 1 ||
925       fabsf(mlirDenseElementsAttrGetFloatValue(floatElements, 1) - 1.0f) >
926           1E-6f ||
927       fabs(mlirDenseElementsAttrGetDoubleValue(doubleElements, 1) - 1.0) > 1E-6)
928     return 15;
929 
930   mlirAttributeDump(boolElements);
931   mlirAttributeDump(uint32Elements);
932   mlirAttributeDump(int32Elements);
933   mlirAttributeDump(uint64Elements);
934   mlirAttributeDump(int64Elements);
935   mlirAttributeDump(floatElements);
936   mlirAttributeDump(doubleElements);
937   // CHECK: dense<{{\[}}[false, true]]> : tensor<1x2xi1>
938   // CHECK: dense<{{\[}}[0, 1]]> : tensor<1x2xui32>
939   // CHECK: dense<{{\[}}[0, 1]]> : tensor<1x2xi32>
940   // CHECK: dense<{{\[}}[0, 1]]> : tensor<1x2xui64>
941   // CHECK: dense<{{\[}}[0, 1]]> : tensor<1x2xi64>
942   // CHECK: dense<{{\[}}[0.000000e+00, 1.000000e+00]]> : tensor<1x2xf32>
943   // CHECK: dense<{{\[}}[0.000000e+00, 1.000000e+00]]> : tensor<1x2xf64>
944 
945   MlirAttribute splatBool = mlirDenseElementsAttrBoolSplatGet(
946       mlirRankedTensorTypeGet(2, shape, mlirIntegerTypeGet(ctx, 1)), 1);
947   MlirAttribute splatUInt32 = mlirDenseElementsAttrUInt32SplatGet(
948       mlirRankedTensorTypeGet(2, shape, mlirIntegerTypeGet(ctx, 32)), 1);
949   MlirAttribute splatInt32 = mlirDenseElementsAttrInt32SplatGet(
950       mlirRankedTensorTypeGet(2, shape, mlirIntegerTypeGet(ctx, 32)), 1);
951   MlirAttribute splatUInt64 = mlirDenseElementsAttrUInt64SplatGet(
952       mlirRankedTensorTypeGet(2, shape, mlirIntegerTypeGet(ctx, 64)), 1);
953   MlirAttribute splatInt64 = mlirDenseElementsAttrInt64SplatGet(
954       mlirRankedTensorTypeGet(2, shape, mlirIntegerTypeGet(ctx, 64)), 1);
955   MlirAttribute splatFloat = mlirDenseElementsAttrFloatSplatGet(
956       mlirRankedTensorTypeGet(2, shape, mlirF32TypeGet(ctx)), 1.0f);
957   MlirAttribute splatDouble = mlirDenseElementsAttrDoubleSplatGet(
958       mlirRankedTensorTypeGet(2, shape, mlirF64TypeGet(ctx)), 1.0);
959 
960   if (!mlirAttributeIsADenseElements(splatBool) ||
961       !mlirDenseElementsAttrIsSplat(splatBool) ||
962       !mlirAttributeIsADenseElements(splatUInt32) ||
963       !mlirDenseElementsAttrIsSplat(splatUInt32) ||
964       !mlirAttributeIsADenseElements(splatInt32) ||
965       !mlirDenseElementsAttrIsSplat(splatInt32) ||
966       !mlirAttributeIsADenseElements(splatUInt64) ||
967       !mlirDenseElementsAttrIsSplat(splatUInt64) ||
968       !mlirAttributeIsADenseElements(splatInt64) ||
969       !mlirDenseElementsAttrIsSplat(splatInt64) ||
970       !mlirAttributeIsADenseElements(splatFloat) ||
971       !mlirDenseElementsAttrIsSplat(splatFloat) ||
972       !mlirAttributeIsADenseElements(splatDouble) ||
973       !mlirDenseElementsAttrIsSplat(splatDouble))
974     return 16;
975 
976   if (mlirDenseElementsAttrGetBoolSplatValue(splatBool) != 1 ||
977       mlirDenseElementsAttrGetUInt32SplatValue(splatUInt32) != 1 ||
978       mlirDenseElementsAttrGetInt32SplatValue(splatInt32) != 1 ||
979       mlirDenseElementsAttrGetUInt64SplatValue(splatUInt64) != 1 ||
980       mlirDenseElementsAttrGetInt64SplatValue(splatInt64) != 1 ||
981       fabsf(mlirDenseElementsAttrGetFloatSplatValue(splatFloat) - 1.0f) >
982           1E-6f ||
983       fabs(mlirDenseElementsAttrGetDoubleSplatValue(splatDouble) - 1.0) > 1E-6)
984     return 17;
985 
986   uint32_t *uint32RawData =
987       (uint32_t *)mlirDenseElementsAttrGetRawData(uint32Elements);
988   int32_t *int32RawData =
989       (int32_t *)mlirDenseElementsAttrGetRawData(int32Elements);
990   uint64_t *uint64RawData =
991       (uint64_t *)mlirDenseElementsAttrGetRawData(uint64Elements);
992   int64_t *int64RawData =
993       (int64_t *)mlirDenseElementsAttrGetRawData(int64Elements);
994   float *floatRawData = (float *)mlirDenseElementsAttrGetRawData(floatElements);
995   double *doubleRawData =
996       (double *)mlirDenseElementsAttrGetRawData(doubleElements);
997   if (uint32RawData[0] != 0u || uint32RawData[1] != 1u ||
998       int32RawData[0] != 0 || int32RawData[1] != 1 || uint64RawData[0] != 0u ||
999       uint64RawData[1] != 1u || int64RawData[0] != 0 || int64RawData[1] != 1 ||
1000       floatRawData[0] != 0.0f || floatRawData[1] != 1.0f ||
1001       doubleRawData[0] != 0.0 || doubleRawData[1] != 1.0)
1002     return 18;
1003 
1004   mlirAttributeDump(splatBool);
1005   mlirAttributeDump(splatUInt32);
1006   mlirAttributeDump(splatInt32);
1007   mlirAttributeDump(splatUInt64);
1008   mlirAttributeDump(splatInt64);
1009   mlirAttributeDump(splatFloat);
1010   mlirAttributeDump(splatDouble);
1011   // CHECK: dense<true> : tensor<1x2xi1>
1012   // CHECK: dense<1> : tensor<1x2xi32>
1013   // CHECK: dense<1> : tensor<1x2xi32>
1014   // CHECK: dense<1> : tensor<1x2xi64>
1015   // CHECK: dense<1> : tensor<1x2xi64>
1016   // CHECK: dense<1.000000e+00> : tensor<1x2xf32>
1017   // CHECK: dense<1.000000e+00> : tensor<1x2xf64>
1018 
1019   mlirAttributeDump(mlirElementsAttrGetValue(floatElements, 2, uints64));
1020   mlirAttributeDump(mlirElementsAttrGetValue(doubleElements, 2, uints64));
1021   // CHECK: 1.000000e+00 : f32
1022   // CHECK: 1.000000e+00 : f64
1023 
1024   int64_t indices[] = {4, 7};
1025   int64_t two = 2;
1026   MlirAttribute indicesAttr = mlirDenseElementsAttrInt64Get(
1027       mlirRankedTensorTypeGet(1, &two, mlirIntegerTypeGet(ctx, 64)), 2,
1028       indices);
1029   MlirAttribute valuesAttr = mlirDenseElementsAttrFloatGet(
1030       mlirRankedTensorTypeGet(1, &two, mlirF32TypeGet(ctx)), 2, floats);
1031   MlirAttribute sparseAttr = mlirSparseElementsAttribute(
1032       mlirRankedTensorTypeGet(2, shape, mlirF32TypeGet(ctx)), indicesAttr,
1033       valuesAttr);
1034   mlirAttributeDump(sparseAttr);
1035   // CHECK: sparse<[4, 7], [0.000000e+00, 1.000000e+00]> : tensor<1x2xf32>
1036 
1037   return 0;
1038 }
1039 
1040 int printAffineMap(MlirContext ctx) {
1041   MlirAffineMap emptyAffineMap = mlirAffineMapEmptyGet(ctx);
1042   MlirAffineMap affineMap = mlirAffineMapZeroResultGet(ctx, 3, 2);
1043   MlirAffineMap constAffineMap = mlirAffineMapConstantGet(ctx, 2);
1044   MlirAffineMap multiDimIdentityAffineMap =
1045       mlirAffineMapMultiDimIdentityGet(ctx, 3);
1046   MlirAffineMap minorIdentityAffineMap =
1047       mlirAffineMapMinorIdentityGet(ctx, 3, 2);
1048   unsigned permutation[] = {1, 2, 0};
1049   MlirAffineMap permutationAffineMap = mlirAffineMapPermutationGet(
1050       ctx, sizeof(permutation) / sizeof(unsigned), permutation);
1051 
1052   fprintf(stderr, "@affineMap\n");
1053   mlirAffineMapDump(emptyAffineMap);
1054   mlirAffineMapDump(affineMap);
1055   mlirAffineMapDump(constAffineMap);
1056   mlirAffineMapDump(multiDimIdentityAffineMap);
1057   mlirAffineMapDump(minorIdentityAffineMap);
1058   mlirAffineMapDump(permutationAffineMap);
1059   // CHECK-LABEL: @affineMap
1060   // CHECK: () -> ()
1061   // CHECK: (d0, d1, d2)[s0, s1] -> ()
1062   // CHECK: () -> (2)
1063   // CHECK: (d0, d1, d2) -> (d0, d1, d2)
1064   // CHECK: (d0, d1, d2) -> (d1, d2)
1065   // CHECK: (d0, d1, d2) -> (d1, d2, d0)
1066 
1067   if (!mlirAffineMapIsIdentity(emptyAffineMap) ||
1068       mlirAffineMapIsIdentity(affineMap) ||
1069       mlirAffineMapIsIdentity(constAffineMap) ||
1070       !mlirAffineMapIsIdentity(multiDimIdentityAffineMap) ||
1071       mlirAffineMapIsIdentity(minorIdentityAffineMap) ||
1072       mlirAffineMapIsIdentity(permutationAffineMap))
1073     return 1;
1074 
1075   if (!mlirAffineMapIsMinorIdentity(emptyAffineMap) ||
1076       mlirAffineMapIsMinorIdentity(affineMap) ||
1077       !mlirAffineMapIsMinorIdentity(multiDimIdentityAffineMap) ||
1078       !mlirAffineMapIsMinorIdentity(minorIdentityAffineMap) ||
1079       mlirAffineMapIsMinorIdentity(permutationAffineMap))
1080     return 2;
1081 
1082   if (!mlirAffineMapIsEmpty(emptyAffineMap) ||
1083       mlirAffineMapIsEmpty(affineMap) || mlirAffineMapIsEmpty(constAffineMap) ||
1084       mlirAffineMapIsEmpty(multiDimIdentityAffineMap) ||
1085       mlirAffineMapIsEmpty(minorIdentityAffineMap) ||
1086       mlirAffineMapIsEmpty(permutationAffineMap))
1087     return 3;
1088 
1089   if (mlirAffineMapIsSingleConstant(emptyAffineMap) ||
1090       mlirAffineMapIsSingleConstant(affineMap) ||
1091       !mlirAffineMapIsSingleConstant(constAffineMap) ||
1092       mlirAffineMapIsSingleConstant(multiDimIdentityAffineMap) ||
1093       mlirAffineMapIsSingleConstant(minorIdentityAffineMap) ||
1094       mlirAffineMapIsSingleConstant(permutationAffineMap))
1095     return 4;
1096 
1097   if (mlirAffineMapGetSingleConstantResult(constAffineMap) != 2)
1098     return 5;
1099 
1100   if (mlirAffineMapGetNumDims(emptyAffineMap) != 0 ||
1101       mlirAffineMapGetNumDims(affineMap) != 3 ||
1102       mlirAffineMapGetNumDims(constAffineMap) != 0 ||
1103       mlirAffineMapGetNumDims(multiDimIdentityAffineMap) != 3 ||
1104       mlirAffineMapGetNumDims(minorIdentityAffineMap) != 3 ||
1105       mlirAffineMapGetNumDims(permutationAffineMap) != 3)
1106     return 6;
1107 
1108   if (mlirAffineMapGetNumSymbols(emptyAffineMap) != 0 ||
1109       mlirAffineMapGetNumSymbols(affineMap) != 2 ||
1110       mlirAffineMapGetNumSymbols(constAffineMap) != 0 ||
1111       mlirAffineMapGetNumSymbols(multiDimIdentityAffineMap) != 0 ||
1112       mlirAffineMapGetNumSymbols(minorIdentityAffineMap) != 0 ||
1113       mlirAffineMapGetNumSymbols(permutationAffineMap) != 0)
1114     return 7;
1115 
1116   if (mlirAffineMapGetNumResults(emptyAffineMap) != 0 ||
1117       mlirAffineMapGetNumResults(affineMap) != 0 ||
1118       mlirAffineMapGetNumResults(constAffineMap) != 1 ||
1119       mlirAffineMapGetNumResults(multiDimIdentityAffineMap) != 3 ||
1120       mlirAffineMapGetNumResults(minorIdentityAffineMap) != 2 ||
1121       mlirAffineMapGetNumResults(permutationAffineMap) != 3)
1122     return 8;
1123 
1124   if (mlirAffineMapGetNumInputs(emptyAffineMap) != 0 ||
1125       mlirAffineMapGetNumInputs(affineMap) != 5 ||
1126       mlirAffineMapGetNumInputs(constAffineMap) != 0 ||
1127       mlirAffineMapGetNumInputs(multiDimIdentityAffineMap) != 3 ||
1128       mlirAffineMapGetNumInputs(minorIdentityAffineMap) != 3 ||
1129       mlirAffineMapGetNumInputs(permutationAffineMap) != 3)
1130     return 9;
1131 
1132   if (!mlirAffineMapIsProjectedPermutation(emptyAffineMap) ||
1133       !mlirAffineMapIsPermutation(emptyAffineMap) ||
1134       mlirAffineMapIsProjectedPermutation(affineMap) ||
1135       mlirAffineMapIsPermutation(affineMap) ||
1136       mlirAffineMapIsProjectedPermutation(constAffineMap) ||
1137       mlirAffineMapIsPermutation(constAffineMap) ||
1138       !mlirAffineMapIsProjectedPermutation(multiDimIdentityAffineMap) ||
1139       !mlirAffineMapIsPermutation(multiDimIdentityAffineMap) ||
1140       !mlirAffineMapIsProjectedPermutation(minorIdentityAffineMap) ||
1141       mlirAffineMapIsPermutation(minorIdentityAffineMap) ||
1142       !mlirAffineMapIsProjectedPermutation(permutationAffineMap) ||
1143       !mlirAffineMapIsPermutation(permutationAffineMap))
1144     return 10;
1145 
1146   intptr_t sub[] = {1};
1147 
1148   MlirAffineMap subMap = mlirAffineMapGetSubMap(
1149       multiDimIdentityAffineMap, sizeof(sub) / sizeof(intptr_t), sub);
1150   MlirAffineMap majorSubMap =
1151       mlirAffineMapGetMajorSubMap(multiDimIdentityAffineMap, 1);
1152   MlirAffineMap minorSubMap =
1153       mlirAffineMapGetMinorSubMap(multiDimIdentityAffineMap, 1);
1154 
1155   mlirAffineMapDump(subMap);
1156   mlirAffineMapDump(majorSubMap);
1157   mlirAffineMapDump(minorSubMap);
1158   // CHECK: (d0, d1, d2) -> (d1)
1159   // CHECK: (d0, d1, d2) -> (d0)
1160   // CHECK: (d0, d1, d2) -> (d2)
1161 
1162   return 0;
1163 }
1164 
1165 int printAffineExpr(MlirContext ctx) {
1166   MlirAffineExpr affineDimExpr = mlirAffineDimExprGet(ctx, 5);
1167   MlirAffineExpr affineSymbolExpr = mlirAffineSymbolExprGet(ctx, 5);
1168   MlirAffineExpr affineConstantExpr = mlirAffineConstantExprGet(ctx, 5);
1169   MlirAffineExpr affineAddExpr =
1170       mlirAffineAddExprGet(affineDimExpr, affineSymbolExpr);
1171   MlirAffineExpr affineMulExpr =
1172       mlirAffineMulExprGet(affineDimExpr, affineSymbolExpr);
1173   MlirAffineExpr affineModExpr =
1174       mlirAffineModExprGet(affineDimExpr, affineSymbolExpr);
1175   MlirAffineExpr affineFloorDivExpr =
1176       mlirAffineFloorDivExprGet(affineDimExpr, affineSymbolExpr);
1177   MlirAffineExpr affineCeilDivExpr =
1178       mlirAffineCeilDivExprGet(affineDimExpr, affineSymbolExpr);
1179 
1180   // Tests mlirAffineExprDump.
1181   fprintf(stderr, "@affineExpr\n");
1182   mlirAffineExprDump(affineDimExpr);
1183   mlirAffineExprDump(affineSymbolExpr);
1184   mlirAffineExprDump(affineConstantExpr);
1185   mlirAffineExprDump(affineAddExpr);
1186   mlirAffineExprDump(affineMulExpr);
1187   mlirAffineExprDump(affineModExpr);
1188   mlirAffineExprDump(affineFloorDivExpr);
1189   mlirAffineExprDump(affineCeilDivExpr);
1190   // CHECK-LABEL: @affineExpr
1191   // CHECK: d5
1192   // CHECK: s5
1193   // CHECK: 5
1194   // CHECK: d5 + s5
1195   // CHECK: d5 * s5
1196   // CHECK: d5 mod s5
1197   // CHECK: d5 floordiv s5
1198   // CHECK: d5 ceildiv s5
1199 
1200   // Tests methods of affine binary operation expression, takes add expression
1201   // as an example.
1202   mlirAffineExprDump(mlirAffineBinaryOpExprGetLHS(affineAddExpr));
1203   mlirAffineExprDump(mlirAffineBinaryOpExprGetRHS(affineAddExpr));
1204   // CHECK: d5
1205   // CHECK: s5
1206 
1207   // Tests methods of affine dimension expression.
1208   if (mlirAffineDimExprGetPosition(affineDimExpr) != 5)
1209     return 1;
1210 
1211   // Tests methods of affine symbol expression.
1212   if (mlirAffineSymbolExprGetPosition(affineSymbolExpr) != 5)
1213     return 2;
1214 
1215   // Tests methods of affine constant expression.
1216   if (mlirAffineConstantExprGetValue(affineConstantExpr) != 5)
1217     return 3;
1218 
1219   // Tests methods of affine expression.
1220   if (mlirAffineExprIsSymbolicOrConstant(affineDimExpr) ||
1221       !mlirAffineExprIsSymbolicOrConstant(affineSymbolExpr) ||
1222       !mlirAffineExprIsSymbolicOrConstant(affineConstantExpr) ||
1223       mlirAffineExprIsSymbolicOrConstant(affineAddExpr) ||
1224       mlirAffineExprIsSymbolicOrConstant(affineMulExpr) ||
1225       mlirAffineExprIsSymbolicOrConstant(affineModExpr) ||
1226       mlirAffineExprIsSymbolicOrConstant(affineFloorDivExpr) ||
1227       mlirAffineExprIsSymbolicOrConstant(affineCeilDivExpr))
1228     return 4;
1229 
1230   if (!mlirAffineExprIsPureAffine(affineDimExpr) ||
1231       !mlirAffineExprIsPureAffine(affineSymbolExpr) ||
1232       !mlirAffineExprIsPureAffine(affineConstantExpr) ||
1233       !mlirAffineExprIsPureAffine(affineAddExpr) ||
1234       mlirAffineExprIsPureAffine(affineMulExpr) ||
1235       mlirAffineExprIsPureAffine(affineModExpr) ||
1236       mlirAffineExprIsPureAffine(affineFloorDivExpr) ||
1237       mlirAffineExprIsPureAffine(affineCeilDivExpr))
1238     return 5;
1239 
1240   if (mlirAffineExprGetLargestKnownDivisor(affineDimExpr) != 1 ||
1241       mlirAffineExprGetLargestKnownDivisor(affineSymbolExpr) != 1 ||
1242       mlirAffineExprGetLargestKnownDivisor(affineConstantExpr) != 5 ||
1243       mlirAffineExprGetLargestKnownDivisor(affineAddExpr) != 1 ||
1244       mlirAffineExprGetLargestKnownDivisor(affineMulExpr) != 1 ||
1245       mlirAffineExprGetLargestKnownDivisor(affineModExpr) != 1 ||
1246       mlirAffineExprGetLargestKnownDivisor(affineFloorDivExpr) != 1 ||
1247       mlirAffineExprGetLargestKnownDivisor(affineCeilDivExpr) != 1)
1248     return 6;
1249 
1250   if (!mlirAffineExprIsMultipleOf(affineDimExpr, 1) ||
1251       !mlirAffineExprIsMultipleOf(affineSymbolExpr, 1) ||
1252       !mlirAffineExprIsMultipleOf(affineConstantExpr, 5) ||
1253       !mlirAffineExprIsMultipleOf(affineAddExpr, 1) ||
1254       !mlirAffineExprIsMultipleOf(affineMulExpr, 1) ||
1255       !mlirAffineExprIsMultipleOf(affineModExpr, 1) ||
1256       !mlirAffineExprIsMultipleOf(affineFloorDivExpr, 1) ||
1257       !mlirAffineExprIsMultipleOf(affineCeilDivExpr, 1))
1258     return 7;
1259 
1260   if (!mlirAffineExprIsFunctionOfDim(affineDimExpr, 5) ||
1261       mlirAffineExprIsFunctionOfDim(affineSymbolExpr, 5) ||
1262       mlirAffineExprIsFunctionOfDim(affineConstantExpr, 5) ||
1263       !mlirAffineExprIsFunctionOfDim(affineAddExpr, 5) ||
1264       !mlirAffineExprIsFunctionOfDim(affineMulExpr, 5) ||
1265       !mlirAffineExprIsFunctionOfDim(affineModExpr, 5) ||
1266       !mlirAffineExprIsFunctionOfDim(affineFloorDivExpr, 5) ||
1267       !mlirAffineExprIsFunctionOfDim(affineCeilDivExpr, 5))
1268     return 8;
1269 
1270   // Tests 'IsA' methods of affine binary operation expression.
1271   if (!mlirAffineExprIsAAdd(affineAddExpr))
1272     return 9;
1273 
1274   if (!mlirAffineExprIsAMul(affineMulExpr))
1275     return 10;
1276 
1277   if (!mlirAffineExprIsAMod(affineModExpr))
1278     return 11;
1279 
1280   if (!mlirAffineExprIsAFloorDiv(affineFloorDivExpr))
1281     return 12;
1282 
1283   if (!mlirAffineExprIsACeilDiv(affineCeilDivExpr))
1284     return 13;
1285 
1286   if (!mlirAffineExprIsABinary(affineAddExpr))
1287     return 14;
1288 
1289   // Test other 'IsA' method on affine expressions.
1290   if (!mlirAffineExprIsAConstant(affineConstantExpr))
1291     return 15;
1292 
1293   if (!mlirAffineExprIsADim(affineDimExpr))
1294     return 16;
1295 
1296   if (!mlirAffineExprIsASymbol(affineSymbolExpr))
1297     return 17;
1298 
1299   // Test equality and nullity.
1300   MlirAffineExpr otherDimExpr = mlirAffineDimExprGet(ctx, 5);
1301   if (!mlirAffineExprEqual(affineDimExpr, otherDimExpr))
1302     return 18;
1303 
1304   if (mlirAffineExprIsNull(affineDimExpr))
1305     return 19;
1306 
1307   return 0;
1308 }
1309 
1310 int affineMapFromExprs(MlirContext ctx) {
1311   MlirAffineExpr affineDimExpr = mlirAffineDimExprGet(ctx, 0);
1312   MlirAffineExpr affineSymbolExpr = mlirAffineSymbolExprGet(ctx, 1);
1313   MlirAffineExpr exprs[] = {affineDimExpr, affineSymbolExpr};
1314   MlirAffineMap map = mlirAffineMapGet(ctx, 3, 3, 2, exprs);
1315 
1316   // CHECK-LABEL: @affineMapFromExprs
1317   fprintf(stderr, "@affineMapFromExprs");
1318   // CHECK: (d0, d1, d2)[s0, s1, s2] -> (d0, s1)
1319   mlirAffineMapDump(map);
1320 
1321   if (mlirAffineMapGetNumResults(map) != 2)
1322     return 1;
1323 
1324   if (!mlirAffineExprEqual(mlirAffineMapGetResult(map, 0), affineDimExpr))
1325     return 2;
1326 
1327   if (!mlirAffineExprEqual(mlirAffineMapGetResult(map, 1), affineSymbolExpr))
1328     return 3;
1329 
1330   return 0;
1331 }
1332 
1333 int printIntegerSet(MlirContext ctx) {
1334   MlirIntegerSet emptySet = mlirIntegerSetEmptyGet(ctx, 2, 1);
1335 
1336   // CHECK-LABEL: @printIntegerSet
1337   fprintf(stderr, "@printIntegerSet");
1338 
1339   // CHECK: (d0, d1)[s0] : (1 == 0)
1340   mlirIntegerSetDump(emptySet);
1341 
1342   if (!mlirIntegerSetIsCanonicalEmpty(emptySet))
1343     return 1;
1344 
1345   MlirIntegerSet anotherEmptySet = mlirIntegerSetEmptyGet(ctx, 2, 1);
1346   if (!mlirIntegerSetEqual(emptySet, anotherEmptySet))
1347     return 2;
1348 
1349   // Construct a set constrained by:
1350   //   d0 - s0 == 0,
1351   //   d1 - 42 >= 0.
1352   MlirAffineExpr negOne = mlirAffineConstantExprGet(ctx, -1);
1353   MlirAffineExpr negFortyTwo = mlirAffineConstantExprGet(ctx, -42);
1354   MlirAffineExpr d0 = mlirAffineDimExprGet(ctx, 0);
1355   MlirAffineExpr d1 = mlirAffineDimExprGet(ctx, 1);
1356   MlirAffineExpr s0 = mlirAffineSymbolExprGet(ctx, 0);
1357   MlirAffineExpr negS0 = mlirAffineMulExprGet(negOne, s0);
1358   MlirAffineExpr d0minusS0 = mlirAffineAddExprGet(d0, negS0);
1359   MlirAffineExpr d1minus42 = mlirAffineAddExprGet(d1, negFortyTwo);
1360   MlirAffineExpr constraints[] = {d0minusS0, d1minus42};
1361   bool flags[] = {true, false};
1362 
1363   MlirIntegerSet set = mlirIntegerSetGet(ctx, 2, 1, 2, constraints, flags);
1364   // CHECK: (d0, d1)[s0] : (
1365   // CHECK-DAG: d0 - s0 == 0
1366   // CHECK-DAG: d1 - 42 >= 0
1367   mlirIntegerSetDump(set);
1368 
1369   // Transform d1 into s0.
1370   MlirAffineExpr s1 = mlirAffineSymbolExprGet(ctx, 1);
1371   MlirAffineExpr repl[] = {d0, s1};
1372   MlirIntegerSet replaced = mlirIntegerSetReplaceGet(set, repl, &s0, 1, 2);
1373   // CHECK: (d0)[s0, s1] : (
1374   // CHECK-DAG: d0 - s0 == 0
1375   // CHECK-DAG: s1 - 42 >= 0
1376   mlirIntegerSetDump(replaced);
1377 
1378   if (mlirIntegerSetGetNumDims(set) != 2)
1379     return 3;
1380   if (mlirIntegerSetGetNumDims(replaced) != 1)
1381     return 4;
1382 
1383   if (mlirIntegerSetGetNumSymbols(set) != 1)
1384     return 5;
1385   if (mlirIntegerSetGetNumSymbols(replaced) != 2)
1386     return 6;
1387 
1388   if (mlirIntegerSetGetNumInputs(set) != 3)
1389     return 7;
1390 
1391   if (mlirIntegerSetGetNumConstraints(set) != 2)
1392     return 8;
1393 
1394   if (mlirIntegerSetGetNumEqualities(set) != 1)
1395     return 9;
1396 
1397   if (mlirIntegerSetGetNumInequalities(set) != 1)
1398     return 10;
1399 
1400   MlirAffineExpr cstr1 = mlirIntegerSetGetConstraint(set, 0);
1401   MlirAffineExpr cstr2 = mlirIntegerSetGetConstraint(set, 1);
1402   bool isEq1 = mlirIntegerSetIsConstraintEq(set, 0);
1403   bool isEq2 = mlirIntegerSetIsConstraintEq(set, 1);
1404   if (!mlirAffineExprEqual(cstr1, isEq1 ? d0minusS0 : d1minus42))
1405     return 11;
1406   if (!mlirAffineExprEqual(cstr2, isEq2 ? d0minusS0 : d1minus42))
1407     return 12;
1408 
1409   return 0;
1410 }
1411 
1412 int registerOnlyStd() {
1413   MlirContext ctx = mlirContextCreate();
1414   // The built-in dialect is always loaded.
1415   if (mlirContextGetNumLoadedDialects(ctx) != 1)
1416     return 1;
1417 
1418   MlirDialectHandle stdHandle = mlirGetDialectHandle__std__();
1419 
1420   MlirDialect std = mlirContextGetOrLoadDialect(
1421       ctx, mlirDialectHandleGetNamespace(stdHandle));
1422   if (!mlirDialectIsNull(std))
1423     return 2;
1424 
1425   mlirDialectHandleRegisterDialect(stdHandle, ctx);
1426 
1427   std = mlirContextGetOrLoadDialect(ctx,
1428                                     mlirDialectHandleGetNamespace(stdHandle));
1429   if (mlirDialectIsNull(std))
1430     return 3;
1431 
1432   MlirDialect alsoStd = mlirDialectHandleLoadDialect(stdHandle, ctx);
1433   if (!mlirDialectEqual(std, alsoStd))
1434     return 4;
1435 
1436   MlirStringRef stdNs = mlirDialectGetNamespace(std);
1437   MlirStringRef alsoStdNs = mlirDialectHandleGetNamespace(stdHandle);
1438   if (stdNs.length != alsoStdNs.length ||
1439       strncmp(stdNs.data, alsoStdNs.data, stdNs.length))
1440     return 5;
1441 
1442   fprintf(stderr, "@registration\n");
1443   // CHECK-LABEL: @registration
1444 
1445   return 0;
1446 }
1447 
1448 /// Tests backreference APIs
1449 static int testBackreferences() {
1450   fprintf(stderr, "@test_backreferences\n");
1451 
1452   MlirContext ctx = mlirContextCreate();
1453   mlirContextSetAllowUnregisteredDialects(ctx, true);
1454   MlirLocation loc = mlirLocationUnknownGet(ctx);
1455 
1456   MlirOperationState opState =
1457       mlirOperationStateGet(mlirStringRefCreateFromCString("invalid.op"), loc);
1458   MlirRegion region = mlirRegionCreate();
1459   MlirBlock block = mlirBlockCreate(0, NULL);
1460   mlirRegionAppendOwnedBlock(region, block);
1461   mlirOperationStateAddOwnedRegions(&opState, 1, &region);
1462   MlirOperation op = mlirOperationCreate(&opState);
1463   MlirIdentifier ident =
1464       mlirIdentifierGet(ctx, mlirStringRefCreateFromCString("identifier"));
1465 
1466   if (!mlirContextEqual(ctx, mlirOperationGetContext(op))) {
1467     fprintf(stderr, "ERROR: Getting context from operation failed\n");
1468     return 1;
1469   }
1470   if (!mlirOperationEqual(op, mlirBlockGetParentOperation(block))) {
1471     fprintf(stderr, "ERROR: Getting parent operation from block failed\n");
1472     return 2;
1473   }
1474   if (!mlirContextEqual(ctx, mlirIdentifierGetContext(ident))) {
1475     fprintf(stderr, "ERROR: Getting context from identifier failed\n");
1476     return 3;
1477   }
1478 
1479   mlirOperationDestroy(op);
1480   mlirContextDestroy(ctx);
1481 
1482   // CHECK-LABEL: @test_backreferences
1483   return 0;
1484 }
1485 
1486 // Wraps a diagnostic into additional text we can match against.
1487 MlirLogicalResult errorHandler(MlirDiagnostic diagnostic, void *userData) {
1488   fprintf(stderr, "processing diagnostic (userData: %ld) <<\n", (long)userData);
1489   mlirDiagnosticPrint(diagnostic, printToStderr, NULL);
1490   fprintf(stderr, "\n");
1491   MlirLocation loc = mlirDiagnosticGetLocation(diagnostic);
1492   mlirLocationPrint(loc, printToStderr, NULL);
1493   assert(mlirDiagnosticGetNumNotes(diagnostic) == 0);
1494   fprintf(stderr, "\n>> end of diagnostic (userData: %ld)\n", (long)userData);
1495   return mlirLogicalResultSuccess();
1496 }
1497 
1498 // Logs when the delete user data callback is called
1499 static void deleteUserData(void *userData) {
1500   fprintf(stderr, "deleting user data (userData: %ld)\n", (long)userData);
1501 }
1502 
1503 void testDiagnostics() {
1504   MlirContext ctx = mlirContextCreate();
1505   MlirDiagnosticHandlerID id = mlirContextAttachDiagnosticHandler(
1506       ctx, errorHandler, (void *)42, deleteUserData);
1507   fprintf(stderr, "@test_diagnostics\n");
1508   MlirLocation unknownLoc = mlirLocationUnknownGet(ctx);
1509   mlirEmitError(unknownLoc, "test diagnostics");
1510   MlirLocation fileLineColLoc = mlirLocationFileLineColGet(
1511       ctx, mlirStringRefCreateFromCString("file.c"), 1, 2);
1512   mlirEmitError(fileLineColLoc, "test diagnostics");
1513   MlirLocation callSiteLoc = mlirLocationCallSiteGet(
1514       mlirLocationFileLineColGet(
1515           ctx, mlirStringRefCreateFromCString("other-file.c"), 2, 3),
1516       fileLineColLoc);
1517   mlirEmitError(callSiteLoc, "test diagnostics");
1518   mlirContextDetachDiagnosticHandler(ctx, id);
1519   mlirEmitError(unknownLoc, "more test diagnostics");
1520   // CHECK-LABEL: @test_diagnostics
1521   // CHECK: processing diagnostic (userData: 42) <<
1522   // CHECK:   test diagnostics
1523   // CHECK:   loc(unknown)
1524   // CHECK: >> end of diagnostic (userData: 42)
1525   // CHECK: processing diagnostic (userData: 42) <<
1526   // CHECK:   test diagnostics
1527   // CHECK:   loc("file.c":1:2)
1528   // CHECK: >> end of diagnostic (userData: 42)
1529   // CHECK: processing diagnostic (userData: 42) <<
1530   // CHECK:   test diagnostics
1531   // CHECK:   loc(callsite("other-file.c":2:3 at "file.c":1:2))
1532   // CHECK: >> end of diagnostic (userData: 42)
1533   // CHECK: deleting user data (userData: 42)
1534   // CHECK-NOT: processing diagnostic
1535   // CHECK:     more test diagnostics
1536 }
1537 
1538 int main() {
1539   MlirContext ctx = mlirContextCreate();
1540   mlirRegisterAllDialects(ctx);
1541   if (constructAndTraverseIr(ctx))
1542     return 1;
1543   buildWithInsertionsAndPrint(ctx);
1544   if (createOperationWithTypeInference(ctx))
1545     return 2;
1546 
1547   if (printBuiltinTypes(ctx))
1548     return 3;
1549   if (printBuiltinAttributes(ctx))
1550     return 4;
1551   if (printAffineMap(ctx))
1552     return 5;
1553   if (printAffineExpr(ctx))
1554     return 6;
1555   if (affineMapFromExprs(ctx))
1556     return 7;
1557   if (printIntegerSet(ctx))
1558     return 8;
1559   if (registerOnlyStd())
1560     return 9;
1561   if (testBackreferences())
1562     return 10;
1563 
1564   mlirContextDestroy(ctx);
1565 
1566   testDiagnostics();
1567   return 0;
1568 }
1569