xref: /llvm-project/mlir/test/CAPI/llvm.c (revision 2918e779a9545a66c0031b03b3af5bf4d8517cec)
1 //===- llvm.c - Test of llvm 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-llvm-test 2>&1 | FileCheck %s
11 
12 #include "mlir-c/Dialect/LLVM.h"
13 #include "mlir-c/BuiltinAttributes.h"
14 #include "mlir-c/BuiltinTypes.h"
15 #include "mlir-c/IR.h"
16 #include "mlir-c/Support.h"
17 #include "llvm-c/Core.h"
18 #include "llvm-c/DebugInfo.h"
19 
20 #include <assert.h>
21 #include <inttypes.h>
22 #include <math.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 
27 // CHECK-LABEL: testTypeCreation()
28 static void testTypeCreation(MlirContext ctx) {
29   fprintf(stderr, "testTypeCreation()\n");
30   MlirType i8 = mlirIntegerTypeGet(ctx, 8);
31   MlirType i32 = mlirIntegerTypeGet(ctx, 32);
32   MlirType i64 = mlirIntegerTypeGet(ctx, 64);
33 
34   const char *ptr_text = "!llvm.ptr";
35   MlirType ptr = mlirLLVMPointerTypeGet(ctx, 0);
36   MlirType ptr_ref =
37       mlirTypeParseGet(ctx, mlirStringRefCreateFromCString(ptr_text));
38   // CHECK: !llvm.ptr: 1
39   fprintf(stderr, "%s: %d\n", ptr_text, mlirTypeEqual(ptr, ptr_ref));
40 
41   const char *ptr_addr_text = "!llvm.ptr<42>";
42   MlirType ptr_addr = mlirLLVMPointerTypeGet(ctx, 42);
43   MlirType ptr_addr_ref =
44       mlirTypeParseGet(ctx, mlirStringRefCreateFromCString(ptr_addr_text));
45   // CHECK: !llvm.ptr<42>: 1
46   fprintf(stderr, "%s: %d\n", ptr_addr_text,
47           mlirTypeEqual(ptr_addr, ptr_addr_ref));
48 
49   const char *voidt_text = "!llvm.void";
50   MlirType voidt = mlirLLVMVoidTypeGet(ctx);
51   MlirType voidt_ref =
52       mlirTypeParseGet(ctx, mlirStringRefCreateFromCString(voidt_text));
53   // CHECK: !llvm.void: 1
54   fprintf(stderr, "%s: %d\n", voidt_text, mlirTypeEqual(voidt, voidt_ref));
55 
56   const char *i32_4_text = "!llvm.array<4 x i32>";
57   MlirType i32_4 = mlirLLVMArrayTypeGet(i32, 4);
58   MlirType i32_4_ref =
59       mlirTypeParseGet(ctx, mlirStringRefCreateFromCString(i32_4_text));
60   // CHECK: !llvm.array<4 x i32>: 1
61   fprintf(stderr, "%s: %d\n", i32_4_text, mlirTypeEqual(i32_4, i32_4_ref));
62 
63   const char *i8_i32_i64_text = "!llvm.func<i8 (i32, i64)>";
64   const MlirType i32_i64_arr[] = {i32, i64};
65   MlirType i8_i32_i64 = mlirLLVMFunctionTypeGet(i8, 2, i32_i64_arr, false);
66   MlirType i8_i32_i64_ref =
67       mlirTypeParseGet(ctx, mlirStringRefCreateFromCString(i8_i32_i64_text));
68   // CHECK: !llvm.func<i8 (i32, i64)>: 1
69   fprintf(stderr, "%s: %d\n", i8_i32_i64_text,
70           mlirTypeEqual(i8_i32_i64, i8_i32_i64_ref));
71 
72   const char *i32_i64_s_text = "!llvm.struct<(i32, i64)>";
73   MlirType i32_i64_s = mlirLLVMStructTypeLiteralGet(ctx, 2, i32_i64_arr, false);
74   MlirType i32_i64_s_ref =
75       mlirTypeParseGet(ctx, mlirStringRefCreateFromCString(i32_i64_s_text));
76   // CHECK: !llvm.struct<(i32, i64)>: 1
77   fprintf(stderr, "%s: %d\n", i32_i64_s_text,
78           mlirTypeEqual(i32_i64_s, i32_i64_s_ref));
79 }
80 
81 // CHECK-LABEL: testStructTypeCreation
82 static int testStructTypeCreation(MlirContext ctx) {
83   fprintf(stderr, "testStructTypeCreation\n");
84 
85   // CHECK: !llvm.struct<()>
86   mlirTypeDump(mlirLLVMStructTypeLiteralGet(ctx, /*nFieldTypes=*/0,
87                                             /*fieldTypes=*/NULL,
88                                             /*isPacked=*/false));
89 
90   MlirType i8 = mlirIntegerTypeGet(ctx, 8);
91   MlirType i32 = mlirIntegerTypeGet(ctx, 32);
92   MlirType i64 = mlirIntegerTypeGet(ctx, 64);
93   MlirType i8_i32_i64[] = {i8, i32, i64};
94   // CHECK: !llvm.struct<(i8, i32, i64)>
95   mlirTypeDump(
96       mlirLLVMStructTypeLiteralGet(ctx, sizeof(i8_i32_i64) / sizeof(MlirType),
97                                    i8_i32_i64, /*isPacked=*/false));
98   // CHECK: !llvm.struct<(i32)>
99   mlirTypeDump(mlirLLVMStructTypeLiteralGet(ctx, 1, &i32, /*isPacked=*/false));
100   MlirType i32_i32[] = {i32, i32};
101   // CHECK: !llvm.struct<packed (i32, i32)>
102   mlirTypeDump(mlirLLVMStructTypeLiteralGet(
103       ctx, sizeof(i32_i32) / sizeof(MlirType), i32_i32, /*isPacked=*/true));
104 
105   MlirType literal =
106       mlirLLVMStructTypeLiteralGet(ctx, sizeof(i8_i32_i64) / sizeof(MlirType),
107                                    i8_i32_i64, /*isPacked=*/false);
108   // CHECK: num elements: 3
109   // CHECK: i8
110   // CHECK: i32
111   // CHECK: i64
112   fprintf(stderr, "num elements: %" PRIdPTR "\n",
113           mlirLLVMStructTypeGetNumElementTypes(literal));
114   for (intptr_t i = 0; i < 3; ++i) {
115     mlirTypeDump(mlirLLVMStructTypeGetElementType(literal, i));
116   }
117 
118   if (!mlirTypeEqual(
119           mlirLLVMStructTypeLiteralGet(ctx, 1, &i32, /*isPacked=*/false),
120           mlirLLVMStructTypeLiteralGet(ctx, 1, &i32, /*isPacked=*/false))) {
121     return 1;
122   }
123   if (mlirTypeEqual(
124           mlirLLVMStructTypeLiteralGet(ctx, 1, &i32, /*isPacked=*/false),
125           mlirLLVMStructTypeLiteralGet(ctx, 1, &i64, /*isPacked=*/false))) {
126     return 2;
127   }
128 
129   // CHECK: !llvm.struct<"foo", opaque>
130   // CHECK: !llvm.struct<"bar", opaque>
131   mlirTypeDump(mlirLLVMStructTypeIdentifiedGet(
132       ctx, mlirStringRefCreateFromCString("foo")));
133   mlirTypeDump(mlirLLVMStructTypeIdentifiedGet(
134       ctx, mlirStringRefCreateFromCString("bar")));
135 
136   if (!mlirTypeEqual(mlirLLVMStructTypeIdentifiedGet(
137                          ctx, mlirStringRefCreateFromCString("foo")),
138                      mlirLLVMStructTypeIdentifiedGet(
139                          ctx, mlirStringRefCreateFromCString("foo")))) {
140     return 3;
141   }
142   if (mlirTypeEqual(mlirLLVMStructTypeIdentifiedGet(
143                         ctx, mlirStringRefCreateFromCString("foo")),
144                     mlirLLVMStructTypeIdentifiedGet(
145                         ctx, mlirStringRefCreateFromCString("bar")))) {
146     return 4;
147   }
148 
149   MlirType fooStruct = mlirLLVMStructTypeIdentifiedGet(
150       ctx, mlirStringRefCreateFromCString("foo"));
151   MlirStringRef name = mlirLLVMStructTypeGetIdentifier(fooStruct);
152   if (memcmp(name.data, "foo", name.length))
153     return 5;
154   if (!mlirLLVMStructTypeIsOpaque(fooStruct))
155     return 6;
156 
157   MlirType i32_i64[] = {i32, i64};
158   MlirLogicalResult result =
159       mlirLLVMStructTypeSetBody(fooStruct, sizeof(i32_i64) / sizeof(MlirType),
160                                 i32_i64, /*isPacked=*/false);
161   if (!mlirLogicalResultIsSuccess(result))
162     return 7;
163 
164   // CHECK: !llvm.struct<"foo", (i32, i64)>
165   mlirTypeDump(fooStruct);
166   if (mlirLLVMStructTypeIsOpaque(fooStruct))
167     return 8;
168   if (mlirLLVMStructTypeIsPacked(fooStruct))
169     return 9;
170   if (!mlirTypeEqual(mlirLLVMStructTypeIdentifiedGet(
171                          ctx, mlirStringRefCreateFromCString("foo")),
172                      fooStruct)) {
173     return 10;
174   }
175 
176   MlirType barStruct = mlirLLVMStructTypeIdentifiedGet(
177       ctx, mlirStringRefCreateFromCString("bar"));
178   result = mlirLLVMStructTypeSetBody(barStruct, 1, &i32, /*isPacked=*/true);
179   if (!mlirLogicalResultIsSuccess(result))
180     return 11;
181 
182   // CHECK: !llvm.struct<"bar", packed (i32)>
183   mlirTypeDump(barStruct);
184   if (!mlirLLVMStructTypeIsPacked(barStruct))
185     return 12;
186 
187   // Same body, should succeed.
188   result =
189       mlirLLVMStructTypeSetBody(fooStruct, sizeof(i32_i64) / sizeof(MlirType),
190                                 i32_i64, /*isPacked=*/false);
191   if (!mlirLogicalResultIsSuccess(result))
192     return 13;
193 
194   // Different body, should fail.
195   result = mlirLLVMStructTypeSetBody(fooStruct, 1, &i32, /*isPacked=*/false);
196   if (mlirLogicalResultIsSuccess(result))
197     return 14;
198 
199   // Packed flag differs, should fail.
200   result = mlirLLVMStructTypeSetBody(barStruct, 1, &i32, /*isPacked=*/false);
201   if (mlirLogicalResultIsSuccess(result))
202     return 15;
203 
204   // Should have a different name.
205   // CHECK: !llvm.struct<"foo{{[^"]+}}
206   mlirTypeDump(mlirLLVMStructTypeIdentifiedNewGet(
207       ctx, mlirStringRefCreateFromCString("foo"), /*nFieldTypes=*/0,
208       /*fieldTypes=*/NULL, /*isPacked=*/false));
209 
210   // Two freshly created "new" types must differ.
211   if (mlirTypeEqual(
212           mlirLLVMStructTypeIdentifiedNewGet(
213               ctx, mlirStringRefCreateFromCString("foo"), /*nFieldTypes=*/0,
214               /*fieldTypes=*/NULL, /*isPacked=*/false),
215           mlirLLVMStructTypeIdentifiedNewGet(
216               ctx, mlirStringRefCreateFromCString("foo"), /*nFieldTypes=*/0,
217               /*fieldTypes=*/NULL, /*isPacked=*/false))) {
218     return 16;
219   }
220 
221   MlirType opaque = mlirLLVMStructTypeOpaqueGet(
222       ctx, mlirStringRefCreateFromCString("opaque"));
223   // CHECK: !llvm.struct<"opaque", opaque>
224   mlirTypeDump(opaque);
225   if (!mlirLLVMStructTypeIsOpaque(opaque))
226     return 17;
227 
228   return 0;
229 }
230 
231 // CHECK-LABEL: testLLVMAttributes
232 static void testLLVMAttributes(MlirContext ctx) {
233   fprintf(stderr, "testLLVMAttributes\n");
234 
235   // CHECK: #llvm.linkage<internal>
236   mlirAttributeDump(mlirLLVMLinkageAttrGet(ctx, MlirLLVMLinkageInternal));
237   // CHECK: #llvm.cconv<ccc>
238   mlirAttributeDump(mlirLLVMCConvAttrGet(ctx, MlirLLVMCConvC));
239   // CHECK: #llvm<comdat any>
240   mlirAttributeDump(mlirLLVMComdatAttrGet(ctx, MlirLLVMComdatAny));
241 }
242 
243 // CHECK-LABEL: testDebugInfoAttributes
244 static void testDebugInfoAttributes(MlirContext ctx) {
245   fprintf(stderr, "testDebugInfoAttributes\n");
246 
247   MlirAttribute foo =
248       mlirStringAttrGet(ctx, mlirStringRefCreateFromCString("foo"));
249   MlirAttribute bar =
250       mlirStringAttrGet(ctx, mlirStringRefCreateFromCString("bar"));
251 
252   MlirAttribute none = mlirUnitAttrGet(ctx);
253   MlirAttribute id = mlirDisctinctAttrCreate(none);
254   MlirAttribute recId0 = mlirDisctinctAttrCreate(none);
255   MlirAttribute recId1 = mlirDisctinctAttrCreate(none);
256 
257   // CHECK: #llvm.di_null_type
258   mlirAttributeDump(mlirLLVMDINullTypeAttrGet(ctx));
259 
260   // CHECK: #llvm.di_basic_type<name = "foo", sizeInBits =
261   // CHECK-SAME: 64, encoding = DW_ATE_signed>
262   MlirAttribute di_type =
263       mlirLLVMDIBasicTypeAttrGet(ctx, 0, foo, 64, MlirLLVMTypeEncodingSigned);
264   mlirAttributeDump(di_type);
265 
266   MlirAttribute file = mlirLLVMDIFileAttrGet(ctx, foo, bar);
267 
268   // CHECK: #llvm.di_file<"foo" in "bar">
269   mlirAttributeDump(file);
270 
271   MlirAttribute compile_unit = mlirLLVMDICompileUnitAttrGet(
272       ctx, id, LLVMDWARFSourceLanguageC99, file, foo, false,
273       MlirLLVMDIEmissionKindFull, MlirLLVMDINameTableKindDefault);
274 
275   // CHECK: #llvm.di_compile_unit<{{.*}}>
276   mlirAttributeDump(compile_unit);
277 
278   MlirAttribute di_module = mlirLLVMDIModuleAttrGet(
279       ctx, file, compile_unit, foo,
280       mlirStringAttrGet(ctx, mlirStringRefCreateFromCString("")), bar, foo, 1,
281       0);
282   // CHECK: #llvm.di_module<{{.*}}>
283   mlirAttributeDump(di_module);
284 
285   // CHECK: #llvm.di_compile_unit<{{.*}}>
286   mlirAttributeDump(mlirLLVMDIModuleAttrGetScope(di_module));
287 
288   // CHECK: 1 : i32
289   mlirAttributeDump(mlirLLVMDIFlagsAttrGet(ctx, 0x1));
290 
291   // CHECK: #llvm.di_lexical_block<{{.*}}>
292   mlirAttributeDump(
293       mlirLLVMDILexicalBlockAttrGet(ctx, compile_unit, file, 1, 2));
294 
295   // CHECK: #llvm.di_lexical_block_file<{{.*}}>
296   mlirAttributeDump(
297       mlirLLVMDILexicalBlockFileAttrGet(ctx, compile_unit, file, 3));
298 
299   // CHECK: #llvm.di_local_variable<{{.*}}>
300   MlirAttribute local_var = mlirLLVMDILocalVariableAttrGet(
301       ctx, compile_unit, foo, file, 1, 0, 8, di_type, 0);
302   mlirAttributeDump(local_var);
303   // CHECK: #llvm.di_derived_type<{{.*}}>
304   // CHECK-NOT: dwarfAddressSpace
305   mlirAttributeDump(mlirLLVMDIDerivedTypeAttrGet(
306       ctx, 0, bar, di_type, 64, 8, 0, MLIR_CAPI_DWARF_ADDRESS_SPACE_NULL,
307       di_type));
308 
309   // CHECK: #llvm.di_derived_type<{{.*}} dwarfAddressSpace = 3{{.*}}>
310   mlirAttributeDump(
311       mlirLLVMDIDerivedTypeAttrGet(ctx, 0, bar, di_type, 64, 8, 0, 3, di_type));
312 
313   MlirAttribute subroutine_type =
314       mlirLLVMDISubroutineTypeAttrGet(ctx, 0x0, 1, &di_type);
315 
316   // CHECK: #llvm.di_subroutine_type<{{.*}}>
317   mlirAttributeDump(subroutine_type);
318 
319   MlirAttribute di_subprogram_self_rec =
320       mlirLLVMDISubprogramAttrGetRecSelf(recId0);
321   MlirAttribute di_imported_entity = mlirLLVMDIImportedEntityAttrGet(
322       ctx, 0, di_subprogram_self_rec, di_module, file, 1, foo, 1, &local_var);
323 
324   mlirAttributeDump(di_imported_entity);
325   // CHECK: #llvm.di_imported_entity<{{.*}}>
326 
327   MlirAttribute di_annotation = mlirLLVMDIAnnotationAttrGet(
328       ctx, mlirStringAttrGet(ctx, mlirStringRefCreateFromCString("foo")),
329       mlirStringAttrGet(ctx, mlirStringRefCreateFromCString("bar")));
330 
331   mlirAttributeDump(di_annotation);
332   // CHECK: #llvm.di_annotation<{{.*}}>
333 
334   MlirAttribute di_subprogram = mlirLLVMDISubprogramAttrGet(
335       ctx, recId0, false, id, compile_unit, compile_unit, foo, bar, file, 1, 2,
336       0, subroutine_type, 1, &di_imported_entity, 1, &di_annotation);
337   // CHECK: #llvm.di_subprogram<{{.*}}>
338   mlirAttributeDump(di_subprogram);
339 
340   // CHECK: #llvm.di_compile_unit<{{.*}}>
341   mlirAttributeDump(mlirLLVMDISubprogramAttrGetScope(di_subprogram));
342 
343   // CHECK: #llvm.di_file<{{.*}}>
344   mlirAttributeDump(mlirLLVMDISubprogramAttrGetFile(di_subprogram));
345 
346   // CHECK: #llvm.di_subroutine_type<{{.*}}>
347   mlirAttributeDump(mlirLLVMDISubprogramAttrGetType(di_subprogram));
348 
349   MlirAttribute expression_elem =
350       mlirLLVMDIExpressionElemAttrGet(ctx, 1, 1, &(uint64_t){1});
351 
352   // CHECK: #llvm<di_expression_elem(1)>
353   mlirAttributeDump(expression_elem);
354 
355   MlirAttribute expression =
356       mlirLLVMDIExpressionAttrGet(ctx, 1, &expression_elem);
357   // CHECK: #llvm.di_expression<[(1)]>
358   mlirAttributeDump(expression);
359 
360   MlirAttribute string_type =
361       mlirLLVMDIStringTypeAttrGet(ctx, 0x0, foo, 16, 0, local_var, expression,
362                                   expression, MlirLLVMTypeEncodingSigned);
363   // CHECK: #llvm.di_string_type<{{.*}}>
364   mlirAttributeDump(string_type);
365 
366   // CHECK: #llvm.di_composite_type<recId = {{.*}}, isRecSelf = true>
367   mlirAttributeDump(mlirLLVMDICompositeTypeAttrGetRecSelf(recId1));
368 
369   // CHECK: #llvm.di_composite_type<{{.*}}>
370   mlirAttributeDump(mlirLLVMDICompositeTypeAttrGet(
371       ctx, recId1, false, 0, foo, file, 1, compile_unit, di_type, 0, 64, 8, 1,
372       &di_type, expression, expression, expression, expression));
373 }
374 
375 int main(void) {
376   MlirContext ctx = mlirContextCreate();
377   mlirDialectHandleRegisterDialect(mlirGetDialectHandle__llvm__(), ctx);
378   mlirContextGetOrLoadDialect(ctx, mlirStringRefCreateFromCString("llvm"));
379   testTypeCreation(ctx);
380   int result = testStructTypeCreation(ctx);
381   testLLVMAttributes(ctx);
382   testDebugInfoAttributes(ctx);
383   mlirContextDestroy(ctx);
384   if (result)
385     fprintf(stderr, "FAILED: code %d", result);
386   return result;
387 }
388