]> git.lizzy.rs Git - rust.git/commitdiff
debuginfo: Support for function arguments. (WIP)
authorMichael Woerister <michaelwoerister@gmail>
Thu, 18 Jul 2013 10:04:33 +0000 (12:04 +0200)
committerMichael Woerister <michaelwoerister@gmail>
Thu, 25 Jul 2013 17:47:03 +0000 (19:47 +0200)
src/librustc/middle/trans/debuginfo.rs
src/test/debug-info/function-arguments.rs

index 574f7aad119cbc3923795dd6ff3294a60c81d59f..add52254b02be06bfd19a12a409a08e289635f78 100644 (file)
 
 /// A context object for maintaining all state needed by the debuginfo module.
 pub struct DebugContext {
-    crate_file: ~str,
-    llcontext: ContextRef,
-    builder: DIBuilderRef,
-    curr_loc: (uint, uint),
-    created_files: HashMap<~str, DIFile>,
-    created_functions: HashMap<ast::node_id, DISubprogram>,
-    created_blocks: HashMap<ast::node_id, DILexicalBlock>,
-    created_types: HashMap<uint, DIType>
+    priv crate_file: ~str,
+    priv llcontext: ContextRef,
+    priv builder: DIBuilderRef,
+    priv curr_loc: (uint, uint),
+    priv created_files: HashMap<~str, DIFile>,
+    priv created_functions: HashMap<ast::node_id, DISubprogram>,
+    priv created_blocks: HashMap<ast::node_id, DILexicalBlock>,
+    priv created_types: HashMap<uint, DIType>,
+    priv argument_index_counters: HashMap<ast::node_id, uint>,
 }
 
 impl DebugContext {
@@ -116,6 +117,7 @@ pub fn new(llmod: ModuleRef, crate: ~str) -> DebugContext {
             created_functions: HashMap::new(),
             created_blocks: HashMap::new(),
             created_types: HashMap::new(),
+            argument_index_counters: HashMap::new(),
         };
     }
 }
@@ -138,11 +140,14 @@ pub fn create_local_var_metadata(bcx: @mut Block, local: &ast::Local) {
     let def_map = cx.tcx.def_map;
     let pattern = local.node.pat;
 
-    let context = match bcx.parent {
+    let scope = match bcx.parent {
         None => create_function_metadata(bcx.fcx),
         Some(_) => lexical_block_metadata(bcx)
     };
 
+    let filename = span_start(cx, local.span).file.name;
+    let file_metadata = file_metadata(cx, filename);
+
     do pat_util::pat_bindings(def_map, pattern) |_, node_id, span, path_ref| {
 
         let ident = ast_util::path_to_ident(path_ref);
@@ -151,14 +156,13 @@ pub fn create_local_var_metadata(bcx: @mut Block, local: &ast::Local) {
         let loc = span_start(cx, span);
         let ty = node_id_type(bcx, node_id);
         let type_metadata = type_metadata(cx, ty, span);
-        let file_metadata = file_metadata(cx, loc.file.name);
 
         let var_metadata = do as_c_str(name) |name| {
             unsafe {
                 llvm::LLVMDIBuilderCreateLocalVariable(
                     DIB(cx),
                     DW_TAG_auto_variable,
-                    context,
+                    scope,
                     name,
                     file_metadata,
                     loc.line as c_uint,
@@ -172,9 +176,7 @@ pub fn create_local_var_metadata(bcx: @mut Block, local: &ast::Local) {
         let llptr = match bcx.fcx.lllocals.find_copy(&node_id) {
             Some(v) => v,
             None => {
-                bcx.tcx().sess.span_bug(
-                    local.span,
-                    fmt!("No entry in lllocals table for %?", local.node.id));
+                bcx.tcx().sess.span_bug(span, fmt!("No entry in lllocals table for %?", node_id));
             }
         };
 
@@ -194,64 +196,77 @@ pub fn create_local_var_metadata(bcx: @mut Block, local: &ast::Local) {
 /// Creates debug information for the given function argument.
 ///
 /// Adds the created metadata nodes directly to the crate's IR.
-/// The return value should be ignored if called from outside of the debuginfo module.
-pub fn create_argument_metadata(bcx: @mut Block, arg: &ast::arg, span: span) -> Option<DIVariable> {
-    debug!("create_argument_metadata");
-    if true {
-        // XXX create_argument_metadata disabled for now because "node_id_type(bcx, arg.id)" below
-        // blows up:
-        // "error: internal compiler error: node_id_to_type: no type for node `arg (id=10)`"
-        return None;
-    }
-
+pub fn create_argument_metadata(bcx: @mut Block, arg: &ast::arg, span: span) {
     let fcx = bcx.fcx;
     let cx = fcx.ccx;
 
-    let loc = span_start(cx, span);
-    if "<intrinsic>" == loc.file.name {
-        return None;
+    if fcx.span.is_none() {
+        return;
     }
 
-    let ty = node_id_type(bcx, arg.id);
-    let type_metadata = type_metadata(cx, ty, arg.ty.span);
-    let file_metadata = file_metadata(cx, loc.file.name);
-    let context = create_function_metadata(fcx);
-
-    match arg.pat.node {
-        ast::pat_ident(_, ref path, _) => {
-            // XXX: This is wrong; it should work for multiple bindings.
-            let ident = path.idents.last();
-            let name: &str = cx.sess.str_of(*ident);
-            let var_metadata = do name.as_c_str |name| {
-                unsafe {
-                    llvm::LLVMDIBuilderCreateLocalVariable(
-                        DIB(cx),
-                        DW_TAG_arg_variable as u32,
-                        context,
-                        name,
-                        file_metadata,
-                        loc.line as c_uint,
-                        type_metadata,
-                        false,
-                        0,
-                        0)
-                    // XXX need to pass in a real argument number
-                }
-            };
+    if "<intrinsic>" == span_start(cx, span).file.name {
+        return;
+    }
+
+    let def_map = cx.tcx.def_map;
+    let pattern = arg.pat;
+
+    let mut argument_index = match dbg_cx(cx).argument_index_counters.find_copy(&arg.id) {
+        Some(value) => value,
+        None => 0
+    };
+
+    let filename = span_start(cx, span).file.name;
+    let file_metadata = file_metadata(cx, filename);
+    let scope = create_function_metadata(fcx);
+
+    do pat_util::pat_bindings(def_map, pattern) |_, node_id, span, path_ref| {
+
+        let ty = node_id_type(bcx, node_id);
+        let type_metadata = type_metadata(cx, ty, codemap::dummy_sp());
+        let loc = span_start(cx, span);
+        let ident = ast_util::path_to_ident(path_ref);
+        let name: &str = cx.sess.str_of(ident);
+        debug!("create_argument_metadata: %s", name);
 
-            let llptr = fcx.llargs.get_copy(&arg.id);
-            set_debug_location(cx, lexical_block_metadata(bcx), loc.line, loc.col.to_uint());
+        let arg_metadata = do as_c_str(name) |name| {
             unsafe {
-                let instr = llvm::LLVMDIBuilderInsertDeclareAtEnd(
-                        DIB(cx), llptr, var_metadata, bcx.llbb);
-                llvm::LLVMSetInstDebugLocation(trans::build::B(bcx).llbuilder, instr);
+                llvm::LLVMDIBuilderCreateLocalVariable(
+                    DIB(cx),
+                    DW_TAG_arg_variable,
+                    scope,
+                    name,
+                    file_metadata,
+                    loc.line as c_uint,
+                    type_metadata,
+                    false,
+                    0,
+                    argument_index as c_uint)
             }
-            return Some(var_metadata);
-        }
-        _ => {
-            return None;
+        };
+
+        argument_index += 1;
+
+        let llptr = match bcx.fcx.llargs.find_copy(&node_id) {
+            Some(v) => v,
+            None => {
+                bcx.tcx().sess.span_bug(span, fmt!("No entry in llargs table for %?", node_id));
+            }
+        };
+
+        set_debug_location(cx, lexical_block_metadata(bcx), loc.line, loc.col.to_uint());
+        unsafe {
+            let instr = llvm::LLVMDIBuilderInsertDeclareAtEnd(
+                DIB(cx),
+                llptr,
+                arg_metadata,
+                bcx.llbb);
+
+            llvm::LLVMSetInstDebugLocation(trans::build::B(bcx), instr);
         }
     }
+
+    dbg_cx(cx).argument_index_counters.insert(arg.id, argument_index);
 }
 
 /// Sets the current debug location at the beginning of the span
@@ -272,7 +287,6 @@ pub fn update_source_pos(bcx: @mut Block, span: span) {
 /// The return value should be ignored if called from outside of the debuginfo module.
 pub fn create_function_metadata(fcx: &FunctionContext) -> DISubprogram {
     let cx = fcx.ccx;
-    let span = fcx.span.get();
 
     let fnitem = cx.tcx.items.get_copy(&fcx.id);
     let (ident, ret_ty, id) = match fnitem {
@@ -318,7 +332,7 @@ pub fn create_function_metadata(fcx: &FunctionContext) -> DISubprogram {
             _) => {
             (ident, ty, id)
         }
-        _ => fcx.ccx.sess.bug("create_function_metadata: unexpected sort of node")
+        _ => fcx.ccx.sess.bug(fmt!("create_function_metadata: unexpected sort of node: %?", fnitem))
     };
 
     match dbg_cx(cx).created_functions.find(&id) {
@@ -326,6 +340,11 @@ pub fn create_function_metadata(fcx: &FunctionContext) -> DISubprogram {
         None => ()
     }
 
+    let span = match fcx.span {
+        Some(value) => value,
+        None => codemap::dummy_sp()
+    };
+
     debug!("create_function_metadata: %s, %s",
            cx.sess.str_of(ident),
            cx.sess.codemap.span_to_str(span));
index 225dfedfec721357361b0ac9f04e6a34d5f773a7..5a410ef6462caf40fd9a80c3b9859f89f4b8083c 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// xfail-test
-
 // compile-flags:-Z extra-debug-info
 // debugger:break zzz
 // debugger:run
@@ -34,7 +32,7 @@ fn main() {
     nested(2000, 3000);
 
     fn nested(a: i32, b: i64) -> (i32, i64) {
-        zzz()
+        zzz();
         (a, b)
     }
 }