diff options
Diffstat (limited to 'src/boot')
| -rw-r--r-- | src/boot/llvm/lltrans.ml | 114 |
1 files changed, 87 insertions, 27 deletions
diff --git a/src/boot/llvm/lltrans.ml b/src/boot/llvm/lltrans.ml index 0b780e5e..e104391d 100644 --- a/src/boot/llvm/lltrans.ml +++ b/src/boot/llvm/lltrans.ml @@ -24,10 +24,6 @@ let trans_crate in (* Helpers for adding metadata. *) - let (dbg_mdkind:int) = Llvm.mdkind_id llctx "dbg" in - let set_dbg_metadata (inst:Llvm.llvalue) (md:Llvm.llvalue) : unit = - Llvm.set_metadata inst dbg_mdkind md - in let md_str (s:string) : Llvm.llvalue = Llvm.mdstring llctx s in let md_node (vals:Llvm.llvalue array) : Llvm.llvalue = Llvm.mdnode llctx vals @@ -43,6 +39,73 @@ let trans_crate const_i32 (llvm_debug_version lor (Dwarf.dw_tag_to_int tag)) in + (* See http://llvm.org/docs/SourceLevelDebugging.html. *) + let crate_compile_unit : Llvm.llvalue = + let name = Hashtbl.find sem_cx.Semant.ctxt_item_files crate.id in + md_node [| const_dw_tag Dwarf.DW_TAG_compile_unit; + const_i32 0; (* Unused. *) + const_i32 2; (* DW_LANG_C. FIXME: Pick a Rust DW_LANG code. *) + md_str (Filename.basename name); + md_str (Filename.concat + (Sys.getcwd()) (Filename.dirname name)); + md_str ("Rustboot " ^ Version.version); + (* This is the main compile unit. There must be exactly one of + these in an LLVM module for it to emit debug info. *) + const_i1 1; + (* There are a couple more supported fields, which we ignore + here. *) + |] + in + let di_file (filepath:string) = + md_node [| const_dw_tag Dwarf.DW_TAG_file_type; + md_str (Filename.basename filepath); + md_str (Filename.concat + (Sys.getcwd()) (Filename.dirname filepath)); + crate_compile_unit + |] + in + let di_subprogram (scope:Llvm.llvalue) (name:string) (fullname:string) + (di_file:Llvm.llvalue) (line:int) (llfunction:Llvm.llvalue) + : Llvm.llvalue = + (* 'scope' is generally a compile unit or other subprogram. *) + md_node [| const_dw_tag Dwarf.DW_TAG_subprogram; + const_i32 0; (* Unused. *) + scope; + md_str name; + md_str fullname; (* Display name *) + md_str fullname; (* Linkage name *) + di_file; + const_i32 line; + (* FIXME: Fill in the following fields. *) + md_node [||]; + const_i1 1; + const_i1 1; + const_i32 0; + const_i32 0; + md_node [||]; + const_i1 0; + const_i1 0; + llfunction (* The llvm::Function this reflects. *) + |] + in + let di_location (line:int) (col:int) (scope:Llvm.llvalue) : Llvm.llvalue = + (* 'scope' is generally a subprogram or block. *) + md_node [| const_i32 line; const_i32 col; scope; const_i32 0 |] + in + + (* Sets the 'llbuilder's current location (which it attaches to all + instructions) to the location of the start of the 'id' node within + 'scope', usually a subprogram or lexical block. *) + let set_debug_location + (llbuilder:Llvm.llbuilder) (scope:Llvm.llvalue) (id:node_id) + : unit = + match Session.get_span sess id with + None -> () + | Some {lo=(_, line, col)} -> + Llvm.set_current_debug_location llbuilder + (di_location line col scope) + in + (* Translation of our node_ids into LLVM identifiers, which are strings. *) let next_anon_llid = ref 0 in let num_llid num klass = Printf.sprintf "%s%d" klass num in @@ -475,44 +538,31 @@ let trans_crate in let (llitems:(node_id, Llvm.llvalue) Hashtbl.t) = Hashtbl.create 0 in + (* Maps a fn's or block's id to an LLVM metadata node (subprogram or + lexical block) representing it. *) + let (dbg_llscopes:(node_id, Llvm.llvalue) Hashtbl.t) = Hashtbl.create 0 in let declare_mod_item (name:Ast.ident) { node = { Ast.decl_item = (item:Ast.mod_item') }; id = id } : unit = let full_name = Semant.item_str sem_cx id in - let line_num = + let (filename, line_num) = match Session.get_span sess id with - None -> 0 + None -> ("", 0) | Some span -> - let (_, line, _) = span.lo in - line + let (file, line, _) = span.lo in + (file, line) in match item with Ast.MOD_ITEM_fn _ -> let llty = trans_ty (ty_of_item id) in let llfn = Llvm.declare_function ("_rust_" ^ name) llty llmod in - let meta = - md_node - [| - const_dw_tag Dwarf.DW_TAG_subprogram; - const_i32 0; (* unused *) - const_i32 0; (* context metadata llvalue *) - md_str name; - md_str full_name; - md_str full_name; - const_i32 0; (* file metadata llvalue *) - const_i32 line_num; - const_i32 0; (* type descriptor metadata llvalue *) - const_i1 1; (* flag: local to compile unit? *) - const_i1 1; (* flag: defined in compile unit? *) - |] + let meta = (di_subprogram crate_compile_unit name full_name + (di_file filename) line_num llfn) in Llvm.set_function_call_conv Llvm.CallConv.c llfn; Hashtbl.add llitems id llfn; - - (* FIXME: Adding metadata does not work yet. . *) - let _ = fun _ -> set_dbg_metadata llfn meta in - () + Hashtbl.add dbg_llscopes id meta | _ -> () (* TODO *) in @@ -527,6 +577,7 @@ let trans_crate let llfn = Hashtbl.find llitems fn_id in let lloutptr = Llvm.param llfn 0 in let lltask = Llvm.param llfn 1 in + let llsubprogram = Hashtbl.find dbg_llscopes fn_id in (* LLVM requires that functions be grouped into basic blocks terminated by * terminator instructions, while our AST is less strict. So we have to do @@ -621,6 +672,12 @@ let trans_crate (stmts:Ast.stmt list) (terminate:(Llvm.llbuilder -> node_id -> unit)) : unit = + let set_debug_loc (id:node_id) = + (* Sets the llbuilder's current location (which it attaches to all + instructions) to the location of the start of the 'id' node. *) + set_debug_location llbuilder llsubprogram id + in + let trans_literal (lit:Ast.lit) : Llvm.llvalue = @@ -645,6 +702,7 @@ let trans_crate iflog (fun _ -> log sem_cx "trans_lval: %a" Ast.sprintf_lval lval); match lval with Ast.LVAL_base { id = base_id } -> + set_debug_loc base_id; let id = Hashtbl.find sem_cx.Semant.ctxt_lval_to_referent base_id in @@ -760,6 +818,8 @@ let trans_crate in let trans_tail () = trans_tail_with_builder llbuilder in + set_debug_loc head.id; + match head.node with Ast.STMT_init_tup (dest, elems) -> let zero = const_i32 0 in |