@@ -24,10 +24,6 @@ let trans_crate
24
24
in
25
25
26
26
(* Helpers for adding metadata. *)
27
- let (dbg_mdkind:int ) = Llvm. mdkind_id llctx " dbg" in
28
- let set_dbg_metadata (inst :Llvm.llvalue ) (md :Llvm.llvalue ) : unit =
29
- Llvm. set_metadata inst dbg_mdkind md
30
- in
31
27
let md_str (s :string ) : Llvm.llvalue = Llvm. mdstring llctx s in
32
28
let md_node (vals :Llvm.llvalue array ) : Llvm.llvalue =
33
29
Llvm. mdnode llctx vals
@@ -43,6 +39,73 @@ let trans_crate
43
39
const_i32 (llvm_debug_version lor (Dwarf. dw_tag_to_int tag))
44
40
in
45
41
42
+ (* See http://llvm.org/docs/SourceLevelDebugging.html. *)
43
+ let crate_compile_unit : Llvm.llvalue =
44
+ let name = Hashtbl. find sem_cx.Semant. ctxt_item_files crate.id in
45
+ md_node [| const_dw_tag Dwarf. DW_TAG_compile_unit ;
46
+ const_i32 0 ; (* Unused. *)
47
+ const_i32 2 ; (* DW_LANG_C. FIXME: Pick a Rust DW_LANG code. *)
48
+ md_str (Filename. basename name);
49
+ md_str (Filename. concat
50
+ (Sys. getcwd() ) (Filename. dirname name));
51
+ md_str (" Rustboot " ^ Version. version);
52
+ (* This is the main compile unit. There must be exactly one of
53
+ these in an LLVM module for it to emit debug info. *)
54
+ const_i1 1 ;
55
+ (* There are a couple more supported fields, which we ignore
56
+ here. *)
57
+ |]
58
+ in
59
+ let di_file (filepath :string ) =
60
+ md_node [| const_dw_tag Dwarf. DW_TAG_file_type ;
61
+ md_str (Filename. basename filepath);
62
+ md_str (Filename. concat
63
+ (Sys. getcwd() ) (Filename. dirname filepath));
64
+ crate_compile_unit
65
+ |]
66
+ in
67
+ let di_subprogram (scope :Llvm.llvalue ) (name :string ) (fullname :string )
68
+ (di_file :Llvm.llvalue ) (line :int ) (llfunction :Llvm.llvalue )
69
+ : Llvm.llvalue =
70
+ (* 'scope' is generally a compile unit or other subprogram. *)
71
+ md_node [| const_dw_tag Dwarf. DW_TAG_subprogram ;
72
+ const_i32 0 ; (* Unused. *)
73
+ scope;
74
+ md_str name;
75
+ md_str fullname; (* Display name *)
76
+ md_str fullname; (* Linkage name *)
77
+ di_file;
78
+ const_i32 line;
79
+ (* FIXME: Fill in the following fields. *)
80
+ md_node [||];
81
+ const_i1 1 ;
82
+ const_i1 1 ;
83
+ const_i32 0 ;
84
+ const_i32 0 ;
85
+ md_node [||];
86
+ const_i1 0 ;
87
+ const_i1 0 ;
88
+ llfunction (* The llvm::Function this reflects. *)
89
+ |]
90
+ in
91
+ let di_location (line :int ) (col :int ) (scope :Llvm.llvalue ) : Llvm.llvalue =
92
+ (* 'scope' is generally a subprogram or block. *)
93
+ md_node [| const_i32 line; const_i32 col; scope; const_i32 0 |]
94
+ in
95
+
96
+ (* Sets the 'llbuilder's current location (which it attaches to all
97
+ instructions) to the location of the start of the 'id' node within
98
+ 'scope', usually a subprogram or lexical block. *)
99
+ let set_debug_location
100
+ (llbuilder :Llvm.llbuilder ) (scope :Llvm.llvalue ) (id :node_id )
101
+ : unit =
102
+ match Session. get_span sess id with
103
+ None -> ()
104
+ | Some {lo =(_ , line , col )} ->
105
+ Llvm. set_current_debug_location llbuilder
106
+ (di_location line col scope)
107
+ in
108
+
46
109
(* Translation of our node_ids into LLVM identifiers, which are strings. *)
47
110
let next_anon_llid = ref 0 in
48
111
let num_llid num klass = Printf. sprintf " %s%d" klass num in
@@ -475,44 +538,31 @@ let trans_crate
475
538
in
476
539
477
540
let (llitems:(node_id, Llvm.llvalue) Hashtbl. t ) = Hashtbl. create 0 in
541
+ (* Maps a fn's or block's id to an LLVM metadata node (subprogram or
542
+ lexical block) representing it. *)
543
+ let (dbg_llscopes:(node_id, Llvm.llvalue) Hashtbl. t ) = Hashtbl. create 0 in
478
544
let declare_mod_item
479
545
(name :Ast.ident )
480
546
{ node = { Ast. decl_item = (item :Ast.mod_item' ) } ; id = id }
481
547
: unit =
482
548
let full_name = Semant. item_str sem_cx id in
483
- let line_num =
549
+ let (filename, line_num) =
484
550
match Session. get_span sess id with
485
- None -> 0
551
+ None -> ( " " , 0 )
486
552
| Some span ->
487
- let (_ , line, _) = span.lo in
488
- line
553
+ let (file , line, _) = span.lo in
554
+ (file, line)
489
555
in
490
556
match item with
491
557
Ast. MOD_ITEM_fn _ ->
492
558
let llty = trans_ty (ty_of_item id) in
493
559
let llfn = Llvm. declare_function (" _rust_" ^ name) llty llmod in
494
- let meta =
495
- md_node
496
- [|
497
- const_dw_tag Dwarf. DW_TAG_subprogram ;
498
- const_i32 0 ; (* unused *)
499
- const_i32 0 ; (* context metadata llvalue *)
500
- md_str name;
501
- md_str full_name;
502
- md_str full_name;
503
- const_i32 0 ; (* file metadata llvalue *)
504
- const_i32 line_num;
505
- const_i32 0 ; (* type descriptor metadata llvalue *)
506
- const_i1 1 ; (* flag: local to compile unit? *)
507
- const_i1 1 ; (* flag: defined in compile unit? *)
508
- |]
560
+ let meta = (di_subprogram crate_compile_unit name full_name
561
+ (di_file filename) line_num llfn)
509
562
in
510
563
Llvm. set_function_call_conv Llvm.CallConv. c llfn;
511
564
Hashtbl. add llitems id llfn;
512
-
513
- (* FIXME: Adding metadata does not work yet. . *)
514
- let _ = fun _ -> set_dbg_metadata llfn meta in
515
- ()
565
+ Hashtbl. add dbg_llscopes id meta
516
566
517
567
| _ -> () (* TODO *)
518
568
in
@@ -527,6 +577,7 @@ let trans_crate
527
577
let llfn = Hashtbl. find llitems fn_id in
528
578
let lloutptr = Llvm. param llfn 0 in
529
579
let lltask = Llvm. param llfn 1 in
580
+ let llsubprogram = Hashtbl. find dbg_llscopes fn_id in
530
581
531
582
(* LLVM requires that functions be grouped into basic blocks terminated by
532
583
* terminator instructions, while our AST is less strict. So we have to do
@@ -621,6 +672,12 @@ let trans_crate
621
672
(stmts :Ast.stmt list )
622
673
(terminate :(Llvm.llbuilder -> node_id -> unit) )
623
674
: unit =
675
+ let set_debug_loc (id :node_id ) =
676
+ (* Sets the llbuilder's current location (which it attaches to all
677
+ instructions) to the location of the start of the 'id' node. *)
678
+ set_debug_location llbuilder llsubprogram id
679
+ in
680
+
624
681
let trans_literal
625
682
(lit :Ast.lit )
626
683
: Llvm.llvalue =
@@ -645,6 +702,7 @@ let trans_crate
645
702
iflog (fun _ -> log sem_cx " trans_lval: %a" Ast. sprintf_lval lval);
646
703
match lval with
647
704
Ast. LVAL_base { id = base_id } ->
705
+ set_debug_loc base_id;
648
706
let id =
649
707
Hashtbl. find sem_cx.Semant. ctxt_lval_to_referent base_id
650
708
in
@@ -760,6 +818,8 @@ let trans_crate
760
818
in
761
819
let trans_tail () = trans_tail_with_builder llbuilder in
762
820
821
+ set_debug_loc head.id;
822
+
763
823
match head.node with
764
824
Ast. STMT_init_tup (dest , elems ) ->
765
825
let zero = const_i32 0 in
0 commit comments