auto merge of #12714 : michaelwoerister/rust/limited-debuginfo, r=alexcrichton
This PR brings back limited debuginfo which allows for nice backtraces and breakpoints, but omits any info about variables and types. The `-g` and `--debuginfo` command line options have been extended to take an optional argument: `-g0` means no debug info. `-g1` means line-tables only. `-g2` means full debug info. Specifying `-g` without argument is equivalent to `-g2`. Fixes #12280
This commit is contained in:
commit
14c620719c
@ -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 {
|
||||
|
@ -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()]) {
|
||||
|
@ -11,7 +11,8 @@
|
||||
|
||||
use back::link;
|
||||
use back::{arm, x86, x86_64, mips};
|
||||
use driver::session::{Aggressive, CrateTypeExecutable};
|
||||
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,7 +868,18 @@ 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 = 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| {
|
||||
Path::new(s.as_slice())
|
||||
@ -1012,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>", "FILENAME"),
|
||||
optopt("", "opt-level",
|
||||
"Optimize with possible levels 0-3", "LEVEL"),
|
||||
optopt( "", "out-dir",
|
||||
"Write output to compiler-chosen filename
|
||||
in <dir>", "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>", "FILENAME"),
|
||||
optopt("", "opt-level", "Optimize with possible levels 0-3", "LEVEL"),
|
||||
optopt( "", "out-dir", "Write output to compiler-chosen filename in <dir>", "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 <filename> 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 <filename> 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"),
|
||||
]
|
||||
}
|
||||
|
||||
|
@ -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()),
|
||||
|
@ -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 :(.
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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| {
|
||||
|
@ -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) {
|
||||
|
@ -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.
|
||||
|
52
src/test/debug-info/limited-debuginfo.rs
Normal file
52
src/test/debug-info/limited-debuginfo.rs
Normal file
@ -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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 }
|
Loading…
x
Reference in New Issue
Block a user