(* RUN: rm -rf %t && mkdir -p %t && cp %s %t/debuginfo.ml && cp %S/Utils/Testsuite.ml %t/Testsuite.ml
* 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
* RUN: %t/executable | FileCheck %s
* 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
* RUN: %t/executable | FileCheck %s
* XFAIL: vg_leak
*)
let context = global_context (
let filename = "di_test_file"
let directory = "di_test_dir"
let module_name = "di_test_module"
let null_metadata = llmetadata_null (
string_of_llvalue
printf "%s\n"
initialize (;
let triple = default_triple ( in
let lltarget = by_triple triple in
let llmachine = create ~triple lltarget in
let lldly =
as_string
in
let _ = set_target_triple triple llmod in
let _ = set_data_layout lldly llmod in
(
let m = create_module context module_name in
let ( = prepare_target m in
m
group "module_level_tests";
let m = new_module ( in
let cur_ver = debug_metadata_version ( in
insist ;
let m_ver = get_module_debug_metadata_version m in
(* We haven't added any debug info to the module *)
insist ;
let dibuilder = dibuilder m in
let di_version_key = "Debug Info Version" in
let ver =
value_as_metadata @@ const_int cur_ver
in
let ( =
add_module_flag m Warning di_version_key ver
in
let file_di =
dibuild_create_file dibuilder ~filename ~directory
in
stdout_metadata file_di;
(* CHECK: [[FILE_PTR:<0x[0-9a-f]*>]] = !DIFile(filename: "di_test_file", directory: "di_test_dir")
*)
insist
;
insist
;
let cu_di =
dibuild_create_compile_unit dibuilder
C89 ~file_ref:file_di
~producer:"TestGen" ~is_optimized:false ~flags:"" ~runtime_ver:0
~split_name:"" LineTablesOnly ~dwoid:0
~di_inlining:false ~di_profiling:false ~sys_root:"" ~sdk:""
in
stdout_metadata cu_di;
(* 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)
*)
insist
;
let m_di =
dibuild_create_module dibuilder ~parent_ref:cu_di
~name:module_name ~config_macros:"" ~include_path:"" ~sys_root:""
in
insist
;
insist ;
stdout_metadata m_di;
(* CHECK: [[MODULE_PTR:<0x[0-9a-f]*>]] = !DIModule(scope: null, name: "di_test_module")
*)
let flags_zero = diflags_get Zero
dibuild_create_basic_type dibuilder ~name:"int"
~size_in_bits:bits ~encoding:0x05
(* llvm::dwarf::DW_ATE_signed *) flags_zero
group "function_level_tests";
(* Create a function of type "void foo (int)". *)
let int_ty_di = int_ty_di 32 dibuilder in
stdout_metadata int_ty_di;
(* CHECK: [[INT32_PTR:<0x[0-9a-f]*>]] = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
*)
let param_types = in
let fty_di =
dibuild_create_subroutine_type dibuilder ~file:file_di
~param_types flags_zero
in
insist
;
(* To be able to print and verify the type array of the subroutine type,
* since we have no way to access it from fty_di, we build it again. *)
let fty_di_args =
dibuild_get_or_create_type_array dibuilder ~data:param_types
in
stdout_metadata fty_di_args;
(* CHECK: [[FARGS_PTR:<0x[0-9a-f]*>]] = !{null, [[INT32_PTR]]}
*)
stdout_metadata fty_di;
(* CHECK: [[SBRTNTY_PTR:<0x[0-9a-f]*>]] = !DISubroutineType(types: [[FARGS_PTR]])
*)
(* Let's create the LLVM-IR function now. *)
let name = "tfun" in
let fty =
function_type
in
let f = define_function name fty m in
let f_di =
dibuild_create_function dibuilder ~scope:m_di ~name
~linkage_name:name ~file:file_di ~line_no:10 ~ty:fty_di
~is_local_to_unit:false ~is_definition:true ~scope_line:10
~flags:flags_zero ~is_optimized:false
in
stdout_metadata f_di;
(* 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]], retainedNodes: {{<0x[0-9a-f]*>}})
*)
set_subprogram f f_di;
;
insist
;
insist ;
group "basic_block and instructions tests";
(* Create this pattern:
* if (arg0 != 0) {
* foo(arg0);
* }
* return;
*)
let arg0 = . in
let builder = builder_at_end context in
let zero = const_int 0 in
let cmpi = build_icmp Ne zero arg0 "cmpi" builder in
let truebb = append_block context "truebb" f in
let falsebb = append_block context "falsebb" f in
let _ = build_cond_br cmpi truebb falsebb builder in
let foodecl = declare_function "foo" fty in
let _ =
position_at_end truebb builder;
let scope =
dibuild_create_lexical_block dibuilder ~scope:f_di
~file:file_di ~line:9 ~column:4
in
let file_of_f_di = di_scope_get_file ~scope:f_di in
let file_of_scope = di_scope_get_file ~scope in
insist
;
let foocall = build_call2 fty foodecl "" builder in
let foocall_loc =
dibuild_create_debug_location context ~line:10 ~column:12
~scope
in
instr_set_debug_loc foocall ;
insist
;
stdout_metadata scope;
(* CHECK: [[BLOCK_PTR:<0x[0-9a-f]*>]] = distinct !DILexicalBlock(scope: [[SBPRG_PTR]], file: [[FILE_PTR]], line: 9, column: 4)
*)
stdout_metadata foocall_loc;
(* CHECK: !DILocation(line: 10, column: 12, scope: [[BLOCK_PTR]])
*)
insist
;
insist
;
build_br falsebb builder
in
let _ =
position_at_end falsebb builder;
build_ret_void builder
in
(* Printf.printf "%s\n" (Llvm.string_of_llmodule (Llvm.global_parent f)); *)
(
group "global variable expression tests";
let cexpr_di =
dibuild_create_constant_value_expression dibuilder 0
in
stdout_metadata cexpr_di;
(* CHECK: [[DICEXPR:!DIExpression\(DW_OP_constu, 0, DW_OP_stack_value\)]]
*)
insist
;
let ty = int_ty_di 64 dibuilder in
stdout_metadata ty;
(* CHECK: [[INT64TY_PTR:<0x[0-9a-f]*>]] = !DIBasicType(name: "int", size: 64, encoding: DW_ATE_signed)
*)
let gvexpr_di =
dibuild_create_global_variable_expression dibuilder
~scope:m_di ~name:"my_global" ~linkage:"" ~file:f_di ~line:5 ~ty
~is_local_to_unit:true ~expr:cexpr_di ~decl:null_metadata ~align_in_bits:0
in
insist
;
;
stdout_metadata gvexpr_di;
(* CHECK: [[GVEXP_PTR:<0x[0-9a-f]*>]] = !DIGlobalVariableExpression(var: [[GV_PTR]], expr: [[DICEXPR]])
*)
(
let entry_term = get @@ in
group "Local and parameter variable tests";
let ty = int_ty_di 64 dibuilder in
stdout_metadata ty;
(* CHECK: [[INT64TY_PTR:<0x[0-9a-f]*>]] = !DIBasicType(name: "int", size: 64, encoding: DW_ATE_signed)
*)
let auto_var =
dibuild_create_auto_variable dibuilder ~scope:fun_di
~name:"my_local" ~file:file_di ~line:10 ~ty
~always_preserve:false flags_zero ~align_in_bits:0
in
stdout_metadata auto_var;
(* 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]])
*)
let builder = builder_before context entry_term in
let all = build_alloca "my_alloca" builder in
let scope =
dibuild_create_lexical_block dibuilder ~scope:fun_di
~file:file_di ~line:9 ~column:4
in
let location =
dibuild_create_debug_location
context ~line:10 ~column:12 ~scope
in
let vdi = dibuild_insert_declare_before dibuilder ~storage:all
~var_info:auto_var ~expr:
~location ~instr:entry_term
in
let ( = printf "%s\n" in
(* CHECK: call void @llvm.dbg.declare(metadata ptr %my_alloca, metadata {{![0-9]+}}, metadata !DIExpression()), !dbg {{\![0-9]+}}
*)
let arg0 = . in
let arg_var = dibuild_create_parameter_variable dibuilder ~scope:fun_di
~name:"my_arg" ~argno:0 ~file:file_di ~line:10 ~ty
~always_preserve:false flags_zero
in
let argdi = dibuild_insert_declare_before dibuilder ~storage:arg0
~var_info:arg_var ~expr:
~location ~instr:entry_term
in
let ( = printf "%s\n" in
(* CHECK: call void @llvm.dbg.declare(metadata i32 %0, metadata {{![0-9]+}}, metadata !DIExpression()), !dbg {{\![0-9]+}}
*)
(
group "type tests";
let namespace_di =
dibuild_create_namespace dibuilder ~parent_ref:m_di
~name:"NameSpace1" ~export_symbols:false
in
stdout_metadata namespace_di;
(* CHECK: [[NAMESPACE_PTR:<0x[0-9a-f]*>]] = !DINamespace(name: "NameSpace1", scope: [[MODULE_PTR]])
*)
let int64_ty_di = int_ty_di 64 dibuilder in
let structty_args = in
let struct_ty_di =
dibuild_create_struct_type dibuilder ~scope:namespace_di
~name:"StructType1" ~file:file_di ~line_number:20 ~size_in_bits:192
~align_in_bits:0 flags_zero ~derived_from:null_metadata
~elements:structty_args C89
~vtable_holder:null_metadata ~unique_id:"StructType1"
in
(* Since there's no way to fetch the element types which is now
* a type array, we build that again for checking. *)
let structty_di_eltypes =
dibuild_get_or_create_type_array dibuilder
~data:structty_args
in
stdout_metadata structty_di_eltypes;
(* CHECK: [[STRUCTELT_PTR:<0x[0-9a-f]*>]] = !{[[INT64TY_PTR]], [[INT64TY_PTR]], [[INT64TY_PTR]]}
*)
stdout_metadata struct_ty_di;
(* 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")
*)
insist
;
let structptr_di =
dibuild_create_pointer_type dibuilder
~pointee_ty:struct_ty_di ~size_in_bits:192 ~align_in_bits:0
~address_space:0 ~name:""
in
stdout_metadata structptr_di;
(* CHECK: [[STRUCTPTR_PTR:<0x[0-9a-f]*>]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: [[STRUCT_PTR]], size: 192, dwarfAddressSpace: 0)
*)
insist
;
let enumerator1 =
dibuild_create_enumerator dibuilder ~name:"Test_A" ~value:0
~is_unsigned:true
in
stdout_metadata enumerator1;
(* CHECK: [[ENUMERATOR1_PTR:<0x[0-9a-f]*>]] = !DIEnumerator(name: "Test_A", value: 0, isUnsigned: true)
*)
let enumerator2 =
dibuild_create_enumerator dibuilder ~name:"Test_B" ~value:1
~is_unsigned:true
in
stdout_metadata enumerator2;
(* CHECK: [[ENUMERATOR2_PTR:<0x[0-9a-f]*>]] = !DIEnumerator(name: "Test_B", value: 1, isUnsigned: true)
*)
let enumerator3 =
dibuild_create_enumerator dibuilder ~name:"Test_C" ~value:2
~is_unsigned:true
in
insist
;
stdout_metadata enumerator3;
(* CHECK: [[ENUMERATOR3_PTR:<0x[0-9a-f]*>]] = !DIEnumerator(name: "Test_C", value: 2, isUnsigned: true)
*)
let elements = in
let enumeration_ty_di =
dibuild_create_enumeration_type dibuilder ~scope:namespace_di
~name:"EnumTest" ~file:file_di ~line_number:1 ~size_in_bits:64
~align_in_bits:0 ~elements ~class_ty:int64_ty_di
in
let elements_arr =
dibuild_get_or_create_array dibuilder ~data:elements
in
stdout_metadata elements_arr;
(* CHECK: [[ELEMENTS_PTR:<0x[0-9a-f]*>]] = !{[[ENUMERATOR1_PTR]], [[ENUMERATOR2_PTR]], [[ENUMERATOR3_PTR]]}
*)
stdout_metadata enumeration_ty_di;
(* 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]])
*)
insist
;
let int32_ty_di = int_ty_di 32 dibuilder in
let class_mem1 =
dibuild_create_member_type dibuilder ~scope:namespace_di
~name:"Field1" ~file:file_di ~line_number:3 ~size_in_bits:32
~align_in_bits:0 ~offset_in_bits:0 flags_zero ~ty:int32_ty_di
in
stdout_metadata class_mem1;
(* 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)
*)
insist ;
insist ;
let class_mem2 =
dibuild_create_member_type dibuilder ~scope:namespace_di
~name:"Field2" ~file:file_di ~line_number:4 ~size_in_bits:64
~align_in_bits:8 ~offset_in_bits:32 flags_zero ~ty:int64_ty_di
in
stdout_metadata class_mem2;
(* 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)
*)
insist ;
insist ;
insist ;
let class_elements = in
insist
;
stdout_metadata
;
(* CHECK: [[CLASSMEM_PTRS:<0x[0-9a-f]*>]] = !{[[MEMB1_PTR]], [[MEMB2_PTR]]}
*)
let classty_di =
dibuild_create_class_type dibuilder ~scope:namespace_di
~name:"MyClass" ~file:file_di ~line_number:1 ~size_in_bits:96
~align_in_bits:0 ~offset_in_bits:0 flags_zero ~derived_from:null_metadata
~elements:class_elements ~vtable_holder:null_metadata
~template_params_node:null_metadata ~unique_identifier:"MyClass"
in
stdout_metadata classty_di;
(* [[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")
*)
insist
;
(
let ( =
let m, dibuilder, file_di, m_di = test_get_module ( in
let fty, f, fun_di = test_get_function m dibuilder file_di m_di in
let ( = test_bbinstr fty f fun_di file_di dibuilder in
let ( = test_global_variable_expression dibuilder file_di m_di in
let ( = test_variables f dibuilder file_di fun_di in
let ( = test_types dibuilder file_di m_di in
dibuild_finalize dibuilder;
;
exit !exit_status