From 1938e87393929ab33928210d55bff4bc2d73f6c2 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Wed, 5 Mar 2014 09:51:47 +0100 Subject: [PATCH 1/3] debuginfo: Re-introduce the notion of line-table-only debuginfo. --- src/librustc/back/link.rs | 8 ++++---- src/librustc/driver/driver.rs | 8 ++++++-- src/librustc/driver/session.rs | 11 +++++++++-- src/librustc/middle/trans/_match.rs | 5 +++-- src/librustc/middle/trans/base.rs | 6 +++--- src/librustc/middle/trans/closure.rs | 3 ++- src/librustc/middle/trans/context.rs | 5 +++-- src/librustc/middle/trans/controlflow.rs | 3 ++- src/librustc/middle/trans/debuginfo.rs | 13 +++++++------ 9 files changed, 39 insertions(+), 23 deletions(-) diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs index 3a1c646144b..09e5b99fc23 100644 --- a/src/librustc/back/link.rs +++ b/src/librustc/back/link.rs @@ -12,7 +12,7 @@ use back::archive::{Archive, METADATA_FILENAME}; use back::rpath; use back::svh::Svh; use driver::driver::{CrateTranslation, OutputFilenames}; -use driver::session::Session; +use driver::session::{NoDebugInfo, Session}; use driver::session; use lib::llvm::llvm; use lib::llvm::ModuleRef; @@ -92,7 +92,7 @@ pub mod write { use back::link::{OutputTypeExe, OutputTypeLlvmAssembly}; use back::link::{OutputTypeObject}; use driver::driver::{CrateTranslation, OutputFilenames}; - use driver::session::Session; + use driver::session::{NoDebugInfo, Session}; use driver::session; use lib::llvm::llvm; use lib::llvm::{ModuleRef, TargetMachineRef, PassManagerRef}; @@ -148,7 +148,7 @@ pub mod write { // FIXME: #11906: Omitting frame pointers breaks retrieving the value of a parameter. // FIXME: #11954: mac64 unwinding may not work with fp elim - let no_fp_elim = sess.opts.debuginfo || + let no_fp_elim = (sess.opts.debuginfo != NoDebugInfo) || (sess.targ_cfg.os == abi::OsMacos && sess.targ_cfg.arch == abi::X86_64); @@ -1052,7 +1052,7 @@ fn link_natively(sess: Session, dylib: bool, obj_filename: &Path, // On OSX, debuggers need this utility to get run to do some munging of // the symbols - if sess.targ_cfg.os == abi::OsMacos && sess.opts.debuginfo { + if sess.targ_cfg.os == abi::OsMacos && (sess.opts.debuginfo != NoDebugInfo) { // FIXME (#9639): This needs to handle non-utf8 paths match Process::status("dsymutil", [out_filename.as_str().unwrap().to_owned()]) { diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index 88526dd15a9..a4fe2478f6d 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -11,7 +11,7 @@ use back::link; use back::{arm, x86, x86_64, mips}; -use driver::session::{Aggressive, CrateTypeExecutable}; +use driver::session::{Aggressive, CrateTypeExecutable, FullDebugInfo, NoDebugInfo}; use driver::session::{Session, Session_, No, Less, Default}; use driver::session; use front; @@ -865,7 +865,11 @@ pub fn build_session_options(matches: &getopts::Matches) } else { No } }; let gc = debugging_opts & session::GC != 0; - let debuginfo = matches.opt_present("g") || matches.opt_present("debuginfo"); + let debuginfo = if matches.opt_present("g") || matches.opt_present("debuginfo") { + FullDebugInfo + } else { + NoDebugInfo + }; let addl_lib_search_paths = matches.opt_strs("L").map(|s| { Path::new(s.as_slice()) diff --git a/src/librustc/driver/session.rs b/src/librustc/driver/session.rs index d404360bf14..10d910636fc 100644 --- a/src/librustc/driver/session.rs +++ b/src/librustc/driver/session.rs @@ -114,6 +114,13 @@ pub enum OptLevel { Aggressive // -O3 } +#[deriving(Clone, Eq)] +pub enum DebugInfoLevel { + NoDebugInfo, + LimitedDebugInfo, + FullDebugInfo, +} + #[deriving(Clone)] pub struct Options { // The crate config requested for the session, which may be combined @@ -122,7 +129,7 @@ pub struct Options { gc: bool, optimize: OptLevel, - debuginfo: bool, + debuginfo: DebugInfoLevel, lint_opts: ~[(lint::Lint, lint::level)], output_types: ~[back::link::OutputType], // This was mutable for rustpkg, which updates search paths based on the @@ -314,7 +321,7 @@ pub fn basic_options() -> @Options { crate_types: ~[], gc: false, optimize: No, - debuginfo: false, + debuginfo: NoDebugInfo, lint_opts: ~[], output_types: ~[], addl_lib_search_paths: @RefCell::new(HashSet::new()), diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs index 6247577c1a3..13104cfa40a 100644 --- a/src/librustc/middle/trans/_match.rs +++ b/src/librustc/middle/trans/_match.rs @@ -195,6 +195,7 @@ #[allow(non_camel_case_types)]; use back::abi; +use driver::session::FullDebugInfo; use lib::llvm::{llvm, ValueRef, BasicBlockRef}; use middle::const_eval; use middle::borrowck::root_map_key; @@ -1393,7 +1394,7 @@ fn insert_lllocals<'a>(bcx: &'a Block<'a>, llmap.get().insert(binding_info.id, datum); } - if bcx.sess().opts.debuginfo { + if bcx.sess().opts.debuginfo == FullDebugInfo { debuginfo::create_match_binding_metadata(bcx, ident, binding_info.id, @@ -2052,7 +2053,7 @@ pub fn store_arg<'a>(mut bcx: &'a Block<'a>, // like `x: T` let arg_ty = node_id_type(bcx, pat.id); if type_of::arg_is_indirect(bcx.ccx(), arg_ty) - && !bcx.ccx().sess.opts.debuginfo { + && bcx.ccx().sess.opts.debuginfo != FullDebugInfo { // Don't copy an indirect argument to an alloca, the caller // already put it in a temporary alloca and gave it up, unless // we emit extra-debug-info, which requires local allocas :(. diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index f838bcf9c5e..b9d5eb851b9 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -28,7 +28,7 @@ use back::link::{mangle_exported_name}; use back::{link, abi}; use driver::session; -use driver::session::Session; +use driver::session::{Session, NoDebugInfo, FullDebugInfo}; use driver::driver::OutputFilenames; use driver::driver::{CrateAnalysis, CrateTranslation}; use lib::llvm::{ModuleRef, ValueRef, BasicBlockRef}; @@ -1367,7 +1367,7 @@ fn copy_args_to_allocas<'a>(fcx: &FunctionContext<'a>, bcx = _match::store_arg(bcx, args[i].pat, arg_datum, arg_scope_id); - if fcx.ccx.sess.opts.debuginfo { + if fcx.ccx.sess.opts.debuginfo == FullDebugInfo { debuginfo::create_argument_metadata(bcx, &args[i]); } } @@ -2678,7 +2678,7 @@ pub fn trans_crate(sess: session::Session, } glue::emit_tydescs(ccx); - if ccx.sess.opts.debuginfo { + if ccx.sess.opts.debuginfo != NoDebugInfo { debuginfo::finalize(ccx); } diff --git a/src/librustc/middle/trans/closure.rs b/src/librustc/middle/trans/closure.rs index 2be53b92db1..aabe19deefc 100644 --- a/src/librustc/middle/trans/closure.rs +++ b/src/librustc/middle/trans/closure.rs @@ -11,6 +11,7 @@ use back::abi; use back::link::mangle_internal_name_by_path_and_seq; +use driver::session::FullDebugInfo; use lib::llvm::ValueRef; use middle::moves; use middle::trans::base::*; @@ -299,7 +300,7 @@ fn load_environment<'a>(bcx: &'a Block<'a>, cdata_ty: ty::t, // Store the pointer to closure data in an alloca for debug info because that's what the // llvm.dbg.declare intrinsic expects - let env_pointer_alloca = if bcx.ccx().sess.opts.debuginfo { + let env_pointer_alloca = if bcx.ccx().sess.opts.debuginfo == FullDebugInfo { let alloc = alloc_ty(bcx, ty::mk_mut_ptr(bcx.tcx(), cdata_ty), "__debuginfo_env_ptr"); Store(bcx, llcdata, alloc); Some(alloc) diff --git a/src/librustc/middle/trans/context.rs b/src/librustc/middle/trans/context.rs index b90fc4f6bbf..5011ee8be6e 100644 --- a/src/librustc/middle/trans/context.rs +++ b/src/librustc/middle/trans/context.rs @@ -10,6 +10,7 @@ use driver::session; +use driver::session::NoDebugInfo; use lib::llvm::{ContextRef, ModuleRef, ValueRef}; use lib::llvm::{llvm, TargetData, TypeNames}; use lib::llvm::mk_target_data; @@ -151,7 +152,7 @@ impl CrateContext { let tn = TypeNames::new(); let mut intrinsics = base::declare_intrinsics(llmod); - if sess.opts.debuginfo { + if sess.opts.debuginfo != NoDebugInfo { base::declare_dbg_intrinsics(llmod, &mut intrinsics); } let int_type = Type::int(targ_cfg.arch); @@ -165,7 +166,7 @@ impl CrateContext { tn.associate_type("str_slice", &str_slice_ty); let (crate_map_name, crate_map) = decl_crate_map(sess, link_meta.clone(), llmod); - let dbg_cx = if sess.opts.debuginfo { + let dbg_cx = if sess.opts.debuginfo != NoDebugInfo { Some(debuginfo::CrateDebugContext::new(llmod)) } else { None diff --git a/src/librustc/middle/trans/controlflow.rs b/src/librustc/middle/trans/controlflow.rs index 2aab8926223..215f36a776d 100644 --- a/src/librustc/middle/trans/controlflow.rs +++ b/src/librustc/middle/trans/controlflow.rs @@ -9,6 +9,7 @@ // except according to those terms. use lib::llvm::*; +use driver::session::FullDebugInfo; use middle::lang_items::{FailFnLangItem, FailBoundsCheckFnLangItem}; use middle::trans::base::*; use middle::trans::build::*; @@ -54,7 +55,7 @@ pub fn trans_stmt<'a>(cx: &'a Block<'a>, match d.node { ast::DeclLocal(ref local) => { bcx = init_local(bcx, *local); - if cx.sess().opts.debuginfo { + if cx.sess().opts.debuginfo == FullDebugInfo { debuginfo::create_local_var_metadata(bcx, *local); } } diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index fef559698ab..e88319e6d67 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -126,6 +126,7 @@ is still disabled, so there is no need to do anything special with source locati use driver::session; +use driver::session::{FullDebugInfo, LimitedDebugInfo, NoDebugInfo}; use lib::llvm::llvm; use lib::llvm::{ModuleRef, ContextRef, ValueRef}; use lib::llvm::debuginfo::*; @@ -530,7 +531,7 @@ pub fn create_function_debug_context(cx: &CrateContext, fn_ast_id: ast::NodeId, param_substs: Option<@param_substs>, llfn: ValueRef) -> FunctionDebugContext { - if !cx.sess.opts.debuginfo { + if cx.sess.opts.debuginfo == NoDebugInfo { return DebugInfoDisabled; } @@ -706,7 +707,7 @@ pub fn create_function_debug_context(cx: &CrateContext, fn_decl: &ast::FnDecl, param_substs: Option<@param_substs>, error_span: Span) -> DIArray { - if !cx.sess.opts.debuginfo { + if cx.sess.opts.debuginfo == LimitedDebugInfo { return create_DIArray(DIB(cx), []); } @@ -783,8 +784,8 @@ pub fn create_function_debug_context(cx: &CrateContext, name_to_append_suffix_to.push_str(","); } - // Only create type information if debuginfo is enabled - if cx.sess.opts.debuginfo { + // Only create type information if full debuginfo is enabled + if cx.sess.opts.debuginfo == FullDebugInfo { let actual_self_type_metadata = type_metadata(cx, actual_self_type, codemap::DUMMY_SP); @@ -827,8 +828,8 @@ pub fn create_function_debug_context(cx: &CrateContext, name_to_append_suffix_to.push_str(","); } - // Again, only create type information if debuginfo is enabled - if cx.sess.opts.debuginfo { + // Again, only create type information if full debuginfo is enabled + if cx.sess.opts.debuginfo == FullDebugInfo { let actual_type_metadata = type_metadata(cx, actual_type, codemap::DUMMY_SP); let param_metadata = token::get_ident(ident).get() .with_c_str(|name| { From e15fd400baa37ac22be9c2e2d9664b7cf3df2dbf Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Wed, 5 Mar 2014 14:32:30 +0100 Subject: [PATCH 2/3] debuginfo: Expose limited debuginfo in command line options --- src/libgetopts/lib.rs | 19 ++++ src/librustc/driver/driver.rs | 100 +++++++++--------- src/test/debug-info/issue7712.rs | 2 +- .../lexical-scope-in-parameterless-closure.rs | 2 +- 4 files changed, 69 insertions(+), 54 deletions(-) diff --git a/src/libgetopts/lib.rs b/src/libgetopts/lib.rs index c9b8ed36391..b1b8351b040 100644 --- a/src/libgetopts/lib.rs +++ b/src/libgetopts/lib.rs @@ -455,6 +455,25 @@ pub fn optmulti(short_name: &str, long_name: &str, desc: &str, hint: &str) -> Op } } +/// Create a generic option group, stating all parameters explicitly +pub fn opt(short_name: &str, + long_name: &str, + desc: &str, + hint: &str, + hasarg: HasArg, + occur: Occur) -> OptGroup { + let len = short_name.len(); + assert!(len == 1 || len == 0); + OptGroup { + short_name: short_name.to_owned(), + long_name: long_name.to_owned(), + hint: hint.to_owned(), + desc: desc.to_owned(), + hasarg: hasarg, + occur: occur + } +} + impl Fail_ { /// Convert a `Fail_` enum into an error string. pub fn to_err_msg(self) -> ~str { diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index a4fe2478f6d..c4f3bb21059 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -11,7 +11,8 @@ use back::link; use back::{arm, x86, x86_64, mips}; -use driver::session::{Aggressive, CrateTypeExecutable, FullDebugInfo, NoDebugInfo}; +use driver::session::{Aggressive, CrateTypeExecutable, FullDebugInfo, LimitedDebugInfo, + NoDebugInfo}; use driver::session::{Session, Session_, No, Less, Default}; use driver::session; use front; @@ -38,7 +39,9 @@ use std::vec; use std::vec_ng::Vec; use std::vec_ng; use collections::{HashMap, HashSet}; -use getopts::{optopt, optmulti, optflag, optflagopt}; +use getopts::{optopt, optmulti, optflag, optflagopt, opt}; +use MaybeHasArg = getopts::Maybe; +use OccurOptional = getopts::Optional; use getopts; use syntax::ast; use syntax::abi; @@ -865,10 +868,17 @@ pub fn build_session_options(matches: &getopts::Matches) } else { No } }; let gc = debugging_opts & session::GC != 0; - let debuginfo = if matches.opt_present("g") || matches.opt_present("debuginfo") { - FullDebugInfo - } else { - NoDebugInfo + + let debuginfo = match matches.opt_default("debuginfo", "2") { + Some(level) => { + match level { + ~"0" => NoDebugInfo, + ~"1" => LimitedDebugInfo, + ~"2" => FullDebugInfo, + _ => early_error("debug info level needs to be between 0-2") + } + } + None => NoDebugInfo }; let addl_lib_search_paths = matches.opt_strs("L").map(|s| { @@ -1016,61 +1026,47 @@ pub fn optgroups() -> ~[getopts::OptGroup] { optflag("h", "help", "Display this message"), optmulti("", "cfg", "Configure the compilation environment", "SPEC"), optmulti("L", "", "Add a directory to the library search path", "PATH"), - optmulti("", "crate-type", "Comma separated list of types of crates for the \ - compiler to emit", + optmulti("", "crate-type", "Comma separated list of types of crates for the compiler to emit", "[bin|lib|rlib|dylib|staticlib]"), - optmulti("", "emit", "Comma separated list of types of output for the compiler - to emit", + optmulti("", "emit", "Comma separated list of types of output for the compiler to emit", "[asm|bc|ir|obj|link]"), optflag("", "crate-id", "Output the crate id and exit"), optflag("", "crate-name", "Output the crate name and exit"), optflag("", "crate-file-name", "Output the file(s) that would be written if compilation \ continued and exit"), optflag("", "ls", "List the symbols defined by a library crate"), - optflag("g", "debuginfo", "Emit DWARF debug info to the objects created"), - optflag("", "no-trans", - "Run all passes except translation; no output"), - optflag("", "no-analysis", - "Parse and expand the output, but run no analysis or produce \ - output"), - optflag("O", "", "Equivalent to --opt-level=2"), - optopt("o", "", "Write output to ", "FILENAME"), - optopt("", "opt-level", - "Optimize with possible levels 0-3", "LEVEL"), - optopt( "", "out-dir", - "Write output to compiler-chosen filename - in ", "DIR"), - optflag("", "parse-only", - "Parse only; do not compile, assemble, or link"), + opt("g", "debuginfo", "Emit DWARF debug info to the objects created: + 0 = no debug info, + 1 = line-tables only (for stacktraces), + 2 = full debug info with variable, argument and type information", + "LEVEL", MaybeHasArg, OccurOptional), + optflag("", "no-trans", "Run all passes except translation; no output"), + optflag("", "no-analysis", "Parse and expand the output, but run no analysis or produce output"), + optflag("O", "", "Equivalent to --opt-level=2"), + optopt("o", "", "Write output to ", "FILENAME"), + optopt("", "opt-level", "Optimize with possible levels 0-3", "LEVEL"), + optopt( "", "out-dir", "Write output to compiler-chosen filename in ", "DIR"), + optflag("", "parse-only", "Parse only; do not compile, assemble, or link"), optflagopt("", "pretty", - "Pretty-print the input instead of compiling; - valid types are: normal (un-annotated source), - expanded (crates expanded), - typed (crates expanded, with type annotations), - or identified (fully parenthesized, - AST nodes and blocks with IDs)", "TYPE"), - optflagopt("", "dep-info", - "Output dependency info to after compiling", "FILENAME"), - optopt("", "sysroot", - "Override the system root", "PATH"), + "Pretty-print the input instead of compiling; + valid types are: normal (un-annotated source), + expanded (crates expanded), + typed (crates expanded, with type annotations), + or identified (fully parenthesized, + AST nodes and blocks with IDs)", "TYPE"), + optflagopt("", "dep-info", "Output dependency info to after compiling", "FILENAME"), + optopt("", "sysroot", "Override the system root", "PATH"), optflag("", "test", "Build a test harness"), - optopt("", "target", - "Target triple cpu-manufacturer-kernel[-os] - to compile for (see chapter 3.4 of http://www.sourceware.org/autobook/ - for details)", "TRIPLE"), - optmulti("W", "warn", - "Set lint warnings", "OPT"), - optmulti("A", "allow", - "Set lint allowed", "OPT"), - optmulti("D", "deny", - "Set lint denied", "OPT"), - optmulti("F", "forbid", - "Set lint forbidden", "OPT"), - optmulti("C", "codegen", - "Set a codegen option", "OPT[=VALUE]"), - optmulti("Z", "", "Set internal debugging options", "FLAG"), - optflag( "v", "version", - "Print version info and exit"), + optopt("", "target", "Target triple cpu-manufacturer-kernel[-os] + to compile for (see chapter 3.4 of http://www.sourceware.org/autobook/ + for details)", "TRIPLE"), + optmulti("W", "warn", "Set lint warnings", "OPT"), + optmulti("A", "allow", "Set lint allowed", "OPT"), + optmulti("D", "deny", "Set lint denied", "OPT"), + optmulti("F", "forbid", "Set lint forbidden", "OPT"), + optmulti("C", "codegen", "Set a codegen option", "OPT[=VALUE]"), + optmulti("Z", "", "Set internal debugging options", "FLAG"), + optflag( "v", "version", "Print version info and exit"), ] } diff --git a/src/test/debug-info/issue7712.rs b/src/test/debug-info/issue7712.rs index f91112416e3..af9b84085e3 100644 --- a/src/test/debug-info/issue7712.rs +++ b/src/test/debug-info/issue7712.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags:-g +// compile-flags:-g1 pub trait TraitWithDefaultMethod { fn method(self) { diff --git a/src/test/debug-info/lexical-scope-in-parameterless-closure.rs b/src/test/debug-info/lexical-scope-in-parameterless-closure.rs index f0cb670a23c..ec2c80034d2 100644 --- a/src/test/debug-info/lexical-scope-in-parameterless-closure.rs +++ b/src/test/debug-info/lexical-scope-in-parameterless-closure.rs @@ -10,7 +10,7 @@ // ignore-android: FIXME(#10381) -// compile-flags:-g +// compile-flags:-g1 // debugger:run // Nothing to do here really, just make sure it compiles. See issue #8513. From a5b4d94e3daa0fc2ea59785cb6480e421c4bd8e6 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Wed, 5 Mar 2014 16:11:54 +0100 Subject: [PATCH 3/3] debuginfo: Add test case for limited debuginfo --- src/test/debug-info/limited-debuginfo.rs | 52 ++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 src/test/debug-info/limited-debuginfo.rs diff --git a/src/test/debug-info/limited-debuginfo.rs b/src/test/debug-info/limited-debuginfo.rs new file mode 100644 index 00000000000..ccf1506a565 --- /dev/null +++ b/src/test/debug-info/limited-debuginfo.rs @@ -0,0 +1,52 @@ +// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-android: FIXME(#10381) + +// compile-flags:-g1 + +// Make sure functions have proper names +// debugger:info functions +// check:static void limited-debuginfo::main(); +// check:static void limited-debuginfo::some_function(); +// check:static void limited-debuginfo::some_other_function(); +// check:static void limited-debuginfo::zzz(); + +// debugger:rbreak zzz +// debugger:run + +// Make sure there is no information about locals +// debugger:finish +// debugger:info locals +// check:No locals. +// debugger:continue + + +#[allow(unused_variable)]; + +struct Struct { + a: i64, + b: i32 +} + +fn main() { + some_function(101, 202); +} + + +fn zzz() {()} + +fn some_function(a: int, b: int) { + let some_variable = Struct { a: 11, b: 22 }; + let some_other_variable = 23; + zzz(); +} + +fn some_other_function(a: int, b: int) -> bool { true } \ No newline at end of file