xref: /llvm-project/llvm/test/Bindings/OCaml/debuginfo.ml (revision 2a2fd488b6bc1f3df7a8c103f53fec8bf849da4a)
1(* RUN: rm -rf %t && mkdir -p %t && cp %s %t/debuginfo.ml && cp %S/Utils/Testsuite.ml %t/Testsuite.ml
2 * RUN: %ocamlc -g -w +A -package llvm.all_backends -package llvm.target -package llvm.analysis -package llvm.debuginfo -I %t/ -linkpkg %t/Testsuite.ml %t/debuginfo.ml -o %t/executable
3 * RUN: %t/executable | FileCheck %s
4 * RUN: %ocamlopt -g -w +A -package llvm.all_backends -package llvm.target -package llvm.analysis -package llvm.debuginfo -I %t/ -linkpkg %t/Testsuite.ml %t/debuginfo.ml -o %t/executable
5 * RUN: %t/executable | FileCheck %s
6 * XFAIL: vg_leak
7 *)
8
9open Testsuite
10
11let context = Llvm.global_context ()
12
13let filename = "di_test_file"
14
15let directory = "di_test_dir"
16
17let module_name = "di_test_module"
18
19let null_metadata = Llvm_debuginfo.llmetadata_null ()
20
21let string_of_metadata md =
22  Llvm.string_of_llvalue (Llvm.metadata_as_value context md)
23
24let stdout_metadata md = Printf.printf "%s\n" (string_of_metadata md)
25
26let prepare_target llmod =
27  Llvm_all_backends.initialize ();
28  let triple = Llvm_target.Target.default_triple () in
29  let lltarget = Llvm_target.Target.by_triple triple in
30  let llmachine = Llvm_target.TargetMachine.create ~triple lltarget in
31  let lldly =
32    Llvm_target.DataLayout.as_string
33      (Llvm_target.TargetMachine.data_layout llmachine)
34  in
35  let _ = Llvm.set_target_triple triple llmod in
36  let _ = Llvm.set_data_layout lldly llmod in
37  ()
38
39let new_module () =
40  let m = Llvm.create_module context module_name in
41  let () = prepare_target m in
42  let () = Llvm_debuginfo.set_is_new_dbg_info_format m true in
43  insist (Llvm_debuginfo.is_new_dbg_info_format m);
44  m
45
46let test_get_module () =
47  group "module_level_tests";
48  let m = new_module () in
49  let cur_ver = Llvm_debuginfo.debug_metadata_version () in
50  insist (cur_ver > 0);
51  let m_ver = Llvm_debuginfo.get_module_debug_metadata_version m in
52  (* We haven't added any debug info to the module *)
53  insist (m_ver = 0);
54  let dibuilder = Llvm_debuginfo.dibuilder m in
55  let di_version_key = "Debug Info Version" in
56  let ver =
57    Llvm.value_as_metadata @@ Llvm.const_int (Llvm.i32_type context) cur_ver
58  in
59  let () =
60    Llvm.add_module_flag m Llvm.ModuleFlagBehavior.Warning di_version_key ver
61  in
62  let file_di =
63    Llvm_debuginfo.dibuild_create_file dibuilder ~filename ~directory
64  in
65  stdout_metadata file_di;
66  (* CHECK: [[FILE_PTR:<0x[0-9a-f]*>]] = !DIFile(filename: "di_test_file", directory: "di_test_dir")
67  *)
68  insist
69    ( Llvm_debuginfo.di_file_get_filename ~file:file_di = filename
70    && Llvm_debuginfo.di_file_get_directory ~file:file_di = directory );
71  insist
72    ( Llvm_debuginfo.get_metadata_kind file_di
73    = Llvm_debuginfo.MetadataKind.DIFileMetadataKind );
74  let cu_di =
75    Llvm_debuginfo.dibuild_create_compile_unit dibuilder
76      Llvm_debuginfo.DWARFSourceLanguageKind.C89 ~file_ref:file_di
77      ~producer:"TestGen" ~is_optimized:false ~flags:"" ~runtime_ver:0
78      ~split_name:"" Llvm_debuginfo.DWARFEmissionKind.LineTablesOnly ~dwoid:0
79      ~di_inlining:false ~di_profiling:false ~sys_root:"" ~sdk:""
80  in
81  stdout_metadata cu_di;
82  (* CHECK: [[CMPUNIT_PTR:<0x[0-9a-f]*>]] = distinct !DICompileUnit(language: DW_LANG_C89, file: [[FILE_PTR]], producer: "TestGen", isOptimized: false, runtimeVersion: 0, emissionKind: LineTablesOnly, splitDebugInlining: false)
83  *)
84  insist
85    ( Llvm_debuginfo.get_metadata_kind cu_di
86    = Llvm_debuginfo.MetadataKind.DICompileUnitMetadataKind );
87  let m_di =
88    Llvm_debuginfo.dibuild_create_module dibuilder ~parent_ref:cu_di
89      ~name:module_name ~config_macros:"" ~include_path:"" ~sys_root:""
90  in
91  insist
92    ( Llvm_debuginfo.get_metadata_kind m_di
93    = Llvm_debuginfo.MetadataKind.DIModuleMetadataKind );
94  insist (Llvm_debuginfo.get_module_debug_metadata_version m = cur_ver);
95  stdout_metadata m_di;
96  (* CHECK: [[MODULE_PTR:<0x[0-9a-f]*>]] = !DIModule(scope: null, name: "di_test_module")
97  *)
98  (m, dibuilder, file_di, m_di)
99
100let flags_zero = Llvm_debuginfo.diflags_get Llvm_debuginfo.DIFlag.Zero
101
102let int_ty_di bits dibuilder =
103  Llvm_debuginfo.dibuild_create_basic_type dibuilder ~name:"int"
104    ~size_in_bits:bits ~encoding:0x05
105    (* llvm::dwarf::DW_ATE_signed *) flags_zero
106
107let test_get_function m dibuilder file_di m_di =
108  group "function_level_tests";
109
110  (* Create a function of type "void foo (int)". *)
111  let int_ty_di = int_ty_di 32 dibuilder in
112  stdout_metadata int_ty_di;
113  (* CHECK: [[INT32_PTR:<0x[0-9a-f]*>]] = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
114  *)
115  let param_types = [| null_metadata; int_ty_di |] in
116  let fty_di =
117    Llvm_debuginfo.dibuild_create_subroutine_type dibuilder ~file:file_di
118      ~param_types flags_zero
119  in
120  insist
121    ( Llvm_debuginfo.get_metadata_kind fty_di
122    = Llvm_debuginfo.MetadataKind.DISubroutineTypeMetadataKind );
123  (* To be able to print and verify the type array of the subroutine type,
124   * since we have no way to access it from fty_di, we build it again. *)
125  let fty_di_args =
126    Llvm_debuginfo.dibuild_get_or_create_type_array dibuilder ~data:param_types
127  in
128  stdout_metadata fty_di_args;
129  (* CHECK: [[FARGS_PTR:<0x[0-9a-f]*>]] = !{null, [[INT32_PTR]]}
130  *)
131  stdout_metadata fty_di;
132  (* CHECK: [[SBRTNTY_PTR:<0x[0-9a-f]*>]] = !DISubroutineType(types: [[FARGS_PTR]])
133  *)
134  (* Let's create the LLVM-IR function now. *)
135  let name = "tfun" in
136  let fty =
137    Llvm.function_type (Llvm.void_type context) [| Llvm.i32_type context |]
138  in
139  let f = Llvm.define_function name fty m in
140  let f_di =
141    Llvm_debuginfo.dibuild_create_function dibuilder ~scope:m_di ~name
142      ~linkage_name:name ~file:file_di ~line_no:10 ~ty:fty_di
143      ~is_local_to_unit:false ~is_definition:true ~scope_line:10
144      ~flags:flags_zero ~is_optimized:false
145  in
146  stdout_metadata f_di;
147  (* CHECK: [[SBPRG_PTR:<0x[0-9a-f]*>]] = distinct !DISubprogram(name: "tfun", linkageName: "tfun", scope: [[MODULE_PTR]], file: [[FILE_PTR]], line: 10, type: [[SBRTNTY_PTR]], scopeLine: 10, spFlags: DISPFlagDefinition, unit: [[CMPUNIT_PTR]])
148  *)
149  Llvm_debuginfo.set_subprogram f f_di;
150  ( match Llvm_debuginfo.get_subprogram f with
151  | Some f_di' -> insist (f_di = f_di')
152  | None -> insist false );
153  insist
154    ( Llvm_debuginfo.get_metadata_kind f_di
155    = Llvm_debuginfo.MetadataKind.DISubprogramMetadataKind );
156  insist (Llvm_debuginfo.di_subprogram_get_line f_di = 10);
157  (fty, f, f_di)
158
159let test_bbinstr fty f f_di file_di dibuilder =
160  group "basic_block and instructions tests";
161  (* Create this pattern:
162   *   if (arg0 != 0) {
163   *      foo(arg0);
164   *   }
165   *   return;
166   *)
167  let arg0 = (Llvm.params f).(0) in
168  let builder = Llvm.builder_at_end context (Llvm.entry_block f) in
169  let zero = Llvm.const_int (Llvm.i32_type context) 0 in
170  let cmpi = Llvm.build_icmp Llvm.Icmp.Ne zero arg0 "cmpi" builder in
171  let truebb = Llvm.append_block context "truebb" f in
172  let falsebb = Llvm.append_block context "falsebb" f in
173  let _ = Llvm.build_cond_br cmpi truebb falsebb builder in
174  let foodecl = Llvm.declare_function "foo" fty (Llvm.global_parent f) in
175  let _ =
176    Llvm.position_at_end truebb builder;
177    let scope =
178      Llvm_debuginfo.dibuild_create_lexical_block dibuilder ~scope:f_di
179        ~file:file_di ~line:9 ~column:4
180    in
181    let file_of_f_di = Llvm_debuginfo.di_scope_get_file ~scope:f_di in
182    let file_of_scope = Llvm_debuginfo.di_scope_get_file ~scope in
183    insist
184      ( match (file_of_f_di, file_of_scope) with
185      | Some file_of_f_di', Some file_of_scope' ->
186          file_of_f_di' = file_di && file_of_scope' = file_di
187      | _ -> false );
188    let foocall = Llvm.build_call fty foodecl [| arg0 |] "" builder in
189    let foocall_loc =
190      Llvm_debuginfo.dibuild_create_debug_location context ~line:10 ~column:12
191        ~scope
192    in
193    Llvm_debuginfo.instr_set_debug_loc foocall (Some foocall_loc);
194    insist
195      ( match Llvm_debuginfo.instr_get_debug_loc foocall with
196      | Some foocall_loc' -> foocall_loc' = foocall_loc
197      | None -> false );
198    stdout_metadata scope;
199    (* CHECK: [[BLOCK_PTR:<0x[0-9a-f]*>]] = distinct !DILexicalBlock(scope: [[SBPRG_PTR]], file: [[FILE_PTR]], line: 9, column: 4)
200     *)
201    stdout_metadata foocall_loc;
202    (* CHECK: !DILocation(line: 10, column: 12, scope: [[BLOCK_PTR]])
203     *)
204    insist
205      ( Llvm_debuginfo.di_location_get_scope ~location:foocall_loc = scope
206      && Llvm_debuginfo.di_location_get_line ~location:foocall_loc = 10
207      && Llvm_debuginfo.di_location_get_column ~location:foocall_loc = 12 );
208    insist
209      ( Llvm_debuginfo.get_metadata_kind foocall_loc
210        = Llvm_debuginfo.MetadataKind.DILocationMetadataKind
211      && Llvm_debuginfo.get_metadata_kind scope
212         = Llvm_debuginfo.MetadataKind.DILexicalBlockMetadataKind );
213    Llvm.build_br falsebb builder
214  in
215  let _ =
216    Llvm.position_at_end falsebb builder;
217    Llvm.build_ret_void builder
218  in
219  (* Printf.printf "%s\n" (Llvm.string_of_llmodule (Llvm.global_parent f)); *)
220  ()
221
222let test_global_variable_expression dibuilder f_di m_di =
223  group "global variable expression tests";
224  let cexpr_di =
225    Llvm_debuginfo.dibuild_create_constant_value_expression dibuilder 0
226  in
227  stdout_metadata cexpr_di;
228  (* CHECK: [[DICEXPR:!DIExpression\(DW_OP_constu, 0, DW_OP_stack_value\)]]
229   *)
230  insist
231    ( Llvm_debuginfo.get_metadata_kind cexpr_di
232    = Llvm_debuginfo.MetadataKind.DIExpressionMetadataKind );
233  let ty = int_ty_di 64 dibuilder in
234  stdout_metadata ty;
235  (* CHECK: [[INT64TY_PTR:<0x[0-9a-f]*>]] = !DIBasicType(name: "int", size: 64, encoding: DW_ATE_signed)
236   *)
237  let gvexpr_di =
238    Llvm_debuginfo.dibuild_create_global_variable_expression dibuilder
239      ~scope:m_di ~name:"my_global" ~linkage:"" ~file:f_di ~line:5 ~ty
240      ~is_local_to_unit:true ~expr:cexpr_di ~decl:null_metadata ~align_in_bits:0
241  in
242  insist
243    ( Llvm_debuginfo.get_metadata_kind gvexpr_di
244    = Llvm_debuginfo.MetadataKind.DIGlobalVariableExpressionMetadataKind );
245  ( match
246      Llvm_debuginfo.di_global_variable_expression_get_variable gvexpr_di
247    with
248  | Some gvexpr_var_di ->
249      insist
250        ( Llvm_debuginfo.get_metadata_kind gvexpr_var_di
251        = Llvm_debuginfo.MetadataKind.DIGlobalVariableMetadataKind );
252      stdout_metadata gvexpr_var_di
253      (* CHECK: [[GV_PTR:<0x[0-9a-f]*>]] = distinct !DIGlobalVariable(name: "my_global", scope: [[MODULE_PTR]], file: [[FILE_PTR]], line: 5, type: [[INT64TY_PTR]], isLocal: true, isDefinition: true)
254       *)
255  | None -> insist false );
256  stdout_metadata gvexpr_di;
257  (* CHECK: [[GVEXP_PTR:<0x[0-9a-f]*>]] = !DIGlobalVariableExpression(var: [[GV_PTR]], expr: [[DICEXPR]])
258   *)
259  ()
260
261let test_variables f dibuilder file_di fun_di =
262  let entry_term = Option.get @@ (Llvm.block_terminator (Llvm.entry_block f)) in
263  group "Local and parameter variable tests";
264  let ty = int_ty_di 64 dibuilder in
265  stdout_metadata ty;
266  (* CHECK: [[INT64TY_PTR:<0x[0-9a-f]*>]] = !DIBasicType(name: "int", size: 64, encoding: DW_ATE_signed)
267  *)
268  let auto_var =
269    Llvm_debuginfo.dibuild_create_auto_variable dibuilder ~scope:fun_di
270      ~name:"my_local" ~file:file_di ~line:10 ~ty
271      ~always_preserve:false flags_zero ~align_in_bits:0
272  in
273  stdout_metadata auto_var;
274  (* CHECK: [[LOCAL_VAR_PTR:<0x[0-9a-f]*>]] = !DILocalVariable(name: "my_local", scope: <{{0x[0-9a-f]*}}>, file: <{{0x[0-9a-f]*}}>, line: 10, type: [[INT64TY_PTR]])
275  *)
276  let builder = Llvm.builder_before context entry_term in
277  let all = Llvm.build_alloca (Llvm.i64_type context)  "my_alloca" builder in
278  let scope =
279    Llvm_debuginfo.dibuild_create_lexical_block dibuilder ~scope:fun_di
280      ~file:file_di ~line:9 ~column:4
281  in
282  let location =
283    Llvm_debuginfo.dibuild_create_debug_location
284    context ~line:10 ~column:12 ~scope
285  in
286  let vdi = Llvm_debuginfo.dibuild_insert_declare_before dibuilder ~storage:all
287    ~var_info:auto_var ~expr:(Llvm_debuginfo.dibuild_expression dibuilder [||])
288    ~location ~instr:entry_term
289  in
290  let () = Printf.printf "%s\n" (Llvm.string_of_lldbgrecord vdi) in
291  (* CHECK: dbg_declare(ptr %my_alloca, ![[#]], !DIExpression(), ![[#]])
292  *)
293  let arg0 = (Llvm.params f).(0) in
294  let arg_var = Llvm_debuginfo.dibuild_create_parameter_variable dibuilder ~scope:fun_di
295    ~name:"my_arg" ~argno:1 ~file:file_di ~line:10 ~ty
296    ~always_preserve:false flags_zero
297  in
298  let argdi = Llvm_debuginfo.dibuild_insert_declare_before dibuilder ~storage:arg0
299    ~var_info:arg_var ~expr:(Llvm_debuginfo.dibuild_expression dibuilder [||])
300    ~location ~instr:entry_term
301  in
302  let () = Printf.printf "%s\n" (Llvm.string_of_lldbgrecord argdi) in
303  (* CHECK: dbg_declare(i32 %0, ![[#]], !DIExpression(), ![[#]])
304  *)
305  ()
306
307let test_types dibuilder file_di m_di =
308  group "type tests";
309  let namespace_di =
310    Llvm_debuginfo.dibuild_create_namespace dibuilder ~parent_ref:m_di
311      ~name:"NameSpace1" ~export_symbols:false
312  in
313  stdout_metadata namespace_di;
314  (* CHECK: [[NAMESPACE_PTR:<0x[0-9a-f]*>]] = !DINamespace(name: "NameSpace1", scope: [[MODULE_PTR]])
315   *)
316  let int64_ty_di = int_ty_di 64 dibuilder in
317  let structty_args = [| int64_ty_di; int64_ty_di; int64_ty_di |] in
318  let struct_ty_di =
319    Llvm_debuginfo.dibuild_create_struct_type dibuilder ~scope:namespace_di
320      ~name:"StructType1" ~file:file_di ~line_number:20 ~size_in_bits:192
321      ~align_in_bits:0 flags_zero ~derived_from:null_metadata
322      ~elements:structty_args Llvm_debuginfo.DWARFSourceLanguageKind.C89
323      ~vtable_holder:null_metadata ~unique_id:"StructType1"
324  in
325  (* Since there's no way to fetch the element types which is now
326   * a type array, we build that again for checking. *)
327  let structty_di_eltypes =
328    Llvm_debuginfo.dibuild_get_or_create_type_array dibuilder
329      ~data:structty_args
330  in
331  stdout_metadata structty_di_eltypes;
332  (* CHECK: [[STRUCTELT_PTR:<0x[0-9a-f]*>]] = !{[[INT64TY_PTR]], [[INT64TY_PTR]], [[INT64TY_PTR]]}
333   *)
334  stdout_metadata struct_ty_di;
335  (* CHECK: [[STRUCT_PTR:<0x[0-9a-f]*>]] = !DICompositeType(tag: DW_TAG_structure_type, name: "StructType1", scope: [[NAMESPACE_PTR]], file: [[FILE_PTR]], line: 20, size: 192, elements: [[STRUCTELT_PTR]], identifier: "StructType1")
336   *)
337  insist
338    ( Llvm_debuginfo.get_metadata_kind struct_ty_di
339    = Llvm_debuginfo.MetadataKind.DICompositeTypeMetadataKind );
340  let structptr_di =
341    Llvm_debuginfo.dibuild_create_pointer_type dibuilder
342      ~pointee_ty:struct_ty_di ~size_in_bits:192 ~align_in_bits:0
343      ~address_space:0 ~name:""
344  in
345  stdout_metadata structptr_di;
346  (* CHECK: [[STRUCTPTR_PTR:<0x[0-9a-f]*>]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: [[STRUCT_PTR]], size: 192, dwarfAddressSpace: 0)
347   *)
348  insist
349    ( Llvm_debuginfo.get_metadata_kind structptr_di
350    = Llvm_debuginfo.MetadataKind.DIDerivedTypeMetadataKind );
351  let enumerator1 =
352    Llvm_debuginfo.dibuild_create_enumerator dibuilder ~name:"Test_A" ~value:0
353      ~is_unsigned:true
354  in
355  stdout_metadata enumerator1;
356  (* CHECK: [[ENUMERATOR1_PTR:<0x[0-9a-f]*>]] = !DIEnumerator(name: "Test_A", value: 0, isUnsigned: true)
357   *)
358  let enumerator2 =
359    Llvm_debuginfo.dibuild_create_enumerator dibuilder ~name:"Test_B" ~value:1
360      ~is_unsigned:true
361  in
362  stdout_metadata enumerator2;
363  (* CHECK: [[ENUMERATOR2_PTR:<0x[0-9a-f]*>]] = !DIEnumerator(name: "Test_B", value: 1, isUnsigned: true)
364   *)
365  let enumerator3 =
366    Llvm_debuginfo.dibuild_create_enumerator dibuilder ~name:"Test_C" ~value:2
367      ~is_unsigned:true
368  in
369  insist
370    ( Llvm_debuginfo.get_metadata_kind enumerator1
371      = Llvm_debuginfo.MetadataKind.DIEnumeratorMetadataKind
372    && Llvm_debuginfo.get_metadata_kind enumerator2
373       = Llvm_debuginfo.MetadataKind.DIEnumeratorMetadataKind
374    && Llvm_debuginfo.get_metadata_kind enumerator3
375       = Llvm_debuginfo.MetadataKind.DIEnumeratorMetadataKind );
376  stdout_metadata enumerator3;
377  (* CHECK: [[ENUMERATOR3_PTR:<0x[0-9a-f]*>]] = !DIEnumerator(name: "Test_C", value: 2, isUnsigned: true)
378   *)
379  let elements = [| enumerator1; enumerator2; enumerator3 |] in
380  let enumeration_ty_di =
381    Llvm_debuginfo.dibuild_create_enumeration_type dibuilder ~scope:namespace_di
382      ~name:"EnumTest" ~file:file_di ~line_number:1 ~size_in_bits:64
383      ~align_in_bits:0 ~elements ~class_ty:int64_ty_di
384  in
385  let elements_arr =
386    Llvm_debuginfo.dibuild_get_or_create_array dibuilder ~data:elements
387  in
388  stdout_metadata elements_arr;
389  (* CHECK: [[ELEMENTS_PTR:<0x[0-9a-f]*>]] = !{[[ENUMERATOR1_PTR]], [[ENUMERATOR2_PTR]], [[ENUMERATOR3_PTR]]}
390   *)
391  stdout_metadata enumeration_ty_di;
392  (* CHECK: [[ENUMERATION_PTR:<0x[0-9a-f]*>]] = !DICompositeType(tag: DW_TAG_enumeration_type, name: "EnumTest", scope: [[NAMESPACE_PTR]], file: [[FILE_PTR]], line: 1, baseType: [[INT64TY_PTR]], size: 64, elements: [[ELEMENTS_PTR]])
393   *)
394  insist
395    ( Llvm_debuginfo.get_metadata_kind enumeration_ty_di
396    = Llvm_debuginfo.MetadataKind.DICompositeTypeMetadataKind );
397  let int32_ty_di = int_ty_di 32 dibuilder in
398  let class_mem1 =
399    Llvm_debuginfo.dibuild_create_member_type dibuilder ~scope:namespace_di
400      ~name:"Field1" ~file:file_di ~line_number:3 ~size_in_bits:32
401      ~align_in_bits:0 ~offset_in_bits:0 flags_zero ~ty:int32_ty_di
402  in
403  stdout_metadata class_mem1;
404  (* CHECK: [[MEMB1_PTR:<0x[0-9a-f]*>]] = !DIDerivedType(tag: DW_TAG_member, name: "Field1", scope: [[NAMESPACE_PTR]], file: [[FILE_PTR]], line: 3, baseType: [[INT32_PTR]], size: 32)
405   *)
406  insist (Llvm_debuginfo.di_type_get_name class_mem1 = "Field1");
407  insist (Llvm_debuginfo.di_type_get_line class_mem1 = 3);
408  let class_mem2 =
409    Llvm_debuginfo.dibuild_create_member_type dibuilder ~scope:namespace_di
410      ~name:"Field2" ~file:file_di ~line_number:4 ~size_in_bits:64
411      ~align_in_bits:8 ~offset_in_bits:32 flags_zero ~ty:int64_ty_di
412  in
413  stdout_metadata class_mem2;
414  (* CHECK: [[MEMB2_PTR:<0x[0-9a-f]*>]] = !DIDerivedType(tag: DW_TAG_member, name: "Field2", scope: [[NAMESPACE_PTR]], file: [[FILE_PTR]], line: 4, baseType: [[INT64TY_PTR]], size: 64, align: 8, offset: 32)
415   *)
416  insist (Llvm_debuginfo.di_type_get_offset_in_bits class_mem2 = 32);
417  insist (Llvm_debuginfo.di_type_get_size_in_bits class_mem2 = 64);
418  insist (Llvm_debuginfo.di_type_get_align_in_bits class_mem2 = 8);
419  let class_elements = [| class_mem1; class_mem2 |] in
420  insist
421    ( Llvm_debuginfo.get_metadata_kind class_mem1
422      = Llvm_debuginfo.MetadataKind.DIDerivedTypeMetadataKind
423    && Llvm_debuginfo.get_metadata_kind class_mem2
424       = Llvm_debuginfo.MetadataKind.DIDerivedTypeMetadataKind );
425  stdout_metadata
426    (Llvm_debuginfo.dibuild_get_or_create_type_array dibuilder
427       ~data:class_elements);
428  (* CHECK: [[CLASSMEM_PTRS:<0x[0-9a-f]*>]] = !{[[MEMB1_PTR]], [[MEMB2_PTR]]}
429   *)
430  let classty_di =
431    Llvm_debuginfo.dibuild_create_class_type dibuilder ~scope:namespace_di
432      ~name:"MyClass" ~file:file_di ~line_number:1 ~size_in_bits:96
433      ~align_in_bits:0 ~offset_in_bits:0 flags_zero ~derived_from:null_metadata
434      ~elements:class_elements ~vtable_holder:null_metadata
435      ~template_params_node:null_metadata ~unique_identifier:"MyClass"
436  in
437  stdout_metadata classty_di;
438  (* [[CLASS_PTR:<0x[0-9a-f]*>]] = !DICompositeType(tag: DW_TAG_structure_type, name: "MyClass", scope: [[NAMESPACE_PTR]], file: [[FILE_PTR]], line: 1, size: 96, elements: [[CLASSMEM_PTRS]], identifier: "MyClass")
439   *)
440  insist
441    ( Llvm_debuginfo.get_metadata_kind classty_di
442    = Llvm_debuginfo.MetadataKind.DICompositeTypeMetadataKind );
443  ()
444
445let () =
446  let m, dibuilder, file_di, m_di = test_get_module () in
447  let fty, f, fun_di = test_get_function m dibuilder file_di m_di in
448  let () = test_bbinstr fty f fun_di file_di dibuilder in
449  let () = test_global_variable_expression dibuilder file_di m_di in
450  let () = test_variables f dibuilder file_di fun_di in
451  let () = test_types dibuilder file_di m_di in
452  Llvm_debuginfo.dibuild_finalize dibuilder;
453  ( match Llvm_analysis.verify_module m with
454  | Some err ->
455      prerr_endline ("Verification of module failed: " ^ err);
456      exit_status := 1
457  | None -> () );
458  exit !exit_status
459