mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 23:04:33 +00:00
debuginfo: Implemented proper handling of lexical scopes and variable shadowing.
This commit is contained in:
parent
4601ea65f8
commit
33e7d95e9c
@ -214,6 +214,7 @@ use middle::trans::expr;
|
|||||||
use middle::trans::glue;
|
use middle::trans::glue;
|
||||||
use middle::trans::tvec;
|
use middle::trans::tvec;
|
||||||
use middle::trans::type_of;
|
use middle::trans::type_of;
|
||||||
|
use middle::trans::debuginfo;
|
||||||
use middle::ty;
|
use middle::ty;
|
||||||
use util::common::indenter;
|
use util::common::indenter;
|
||||||
use util::ppaux::{Repr, vec_map_to_str};
|
use util::ppaux::{Repr, vec_map_to_str};
|
||||||
@ -385,6 +386,7 @@ struct BindingInfo {
|
|||||||
llmatch: ValueRef,
|
llmatch: ValueRef,
|
||||||
trmode: TransBindingMode,
|
trmode: TransBindingMode,
|
||||||
id: ast::NodeId,
|
id: ast::NodeId,
|
||||||
|
span: span,
|
||||||
ty: ty::t,
|
ty: ty::t,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1305,7 +1307,7 @@ fn insert_lllocals(bcx: @mut Block,
|
|||||||
BindArgument => bcx.fcx.llargs
|
BindArgument => bcx.fcx.llargs
|
||||||
};
|
};
|
||||||
|
|
||||||
for (_, &binding_info) in bindings_map.iter() {
|
for (&ident, &binding_info) in bindings_map.iter() {
|
||||||
let llval = match binding_info.trmode {
|
let llval = match binding_info.trmode {
|
||||||
// By value bindings: use the stack slot that we
|
// By value bindings: use the stack slot that we
|
||||||
// copied/moved the value into
|
// copied/moved the value into
|
||||||
@ -1325,6 +1327,14 @@ fn insert_lllocals(bcx: @mut Block,
|
|||||||
|
|
||||||
debug!("binding %? to %s", binding_info.id, bcx.val_to_str(llval));
|
debug!("binding %? to %s", binding_info.id, bcx.val_to_str(llval));
|
||||||
llmap.insert(binding_info.id, llval);
|
llmap.insert(binding_info.id, llval);
|
||||||
|
|
||||||
|
if bcx.sess().opts.extra_debuginfo {
|
||||||
|
debuginfo::create_match_binding_metadata(bcx,
|
||||||
|
ident,
|
||||||
|
binding_info.id,
|
||||||
|
binding_info.ty,
|
||||||
|
binding_info.span);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return bcx;
|
return bcx;
|
||||||
}
|
}
|
||||||
@ -1771,7 +1781,7 @@ fn create_bindings_map(bcx: @mut Block, pat: @ast::pat) -> BindingsMap {
|
|||||||
let ccx = bcx.ccx();
|
let ccx = bcx.ccx();
|
||||||
let tcx = bcx.tcx();
|
let tcx = bcx.tcx();
|
||||||
let mut bindings_map = HashMap::new();
|
let mut bindings_map = HashMap::new();
|
||||||
do pat_bindings(tcx.def_map, pat) |bm, p_id, _s, path| {
|
do pat_bindings(tcx.def_map, pat) |bm, p_id, span, path| {
|
||||||
let ident = path_to_ident(path);
|
let ident = path_to_ident(path);
|
||||||
let variable_ty = node_id_type(bcx, p_id);
|
let variable_ty = node_id_type(bcx, p_id);
|
||||||
let llvariable_ty = type_of::type_of(ccx, variable_ty);
|
let llvariable_ty = type_of::type_of(ccx, variable_ty);
|
||||||
@ -1793,8 +1803,11 @@ fn create_bindings_map(bcx: @mut Block, pat: @ast::pat) -> BindingsMap {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
bindings_map.insert(ident, BindingInfo {
|
bindings_map.insert(ident, BindingInfo {
|
||||||
llmatch: llmatch, trmode: trmode,
|
llmatch: llmatch,
|
||||||
id: p_id, ty: variable_ty
|
trmode: trmode,
|
||||||
|
id: p_id,
|
||||||
|
span: span,
|
||||||
|
ty: variable_ty
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return bindings_map;
|
return bindings_map;
|
||||||
|
@ -1103,7 +1103,6 @@ pub fn trans_stmt(cx: @mut Block, s: &ast::stmt) -> @mut Block {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut bcx = cx;
|
let mut bcx = cx;
|
||||||
debuginfo::update_source_pos(cx, s.span);
|
|
||||||
|
|
||||||
match s.node {
|
match s.node {
|
||||||
ast::stmt_expr(e, _) | ast::stmt_semi(e, _) => {
|
ast::stmt_expr(e, _) | ast::stmt_semi(e, _) => {
|
||||||
@ -1634,7 +1633,8 @@ pub fn new_fn_ctxt_w_id(ccx: @mut CrateContext,
|
|||||||
param_substs: param_substs,
|
param_substs: param_substs,
|
||||||
span: sp,
|
span: sp,
|
||||||
path: path,
|
path: path,
|
||||||
ccx: ccx
|
ccx: ccx,
|
||||||
|
debug_context: None,
|
||||||
};
|
};
|
||||||
fcx.llenv = unsafe {
|
fcx.llenv = unsafe {
|
||||||
llvm::LLVMGetParam(llfndecl, fcx.env_arg_pos() as c_uint)
|
llvm::LLVMGetParam(llfndecl, fcx.env_arg_pos() as c_uint)
|
||||||
@ -1933,7 +1933,7 @@ pub fn trans_fn(ccx: @mut CrateContext,
|
|||||||
attrs,
|
attrs,
|
||||||
output_type,
|
output_type,
|
||||||
|fcx| {
|
|fcx| {
|
||||||
if ccx.sess.opts.extra_debuginfo
|
if ccx.sess.opts.debuginfo
|
||||||
&& fcx_has_nonzero_span(fcx) {
|
&& fcx_has_nonzero_span(fcx) {
|
||||||
debuginfo::create_function_metadata(fcx);
|
debuginfo::create_function_metadata(fcx);
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@ use middle::trans::build;
|
|||||||
use middle::trans::datum;
|
use middle::trans::datum;
|
||||||
use middle::trans::glue;
|
use middle::trans::glue;
|
||||||
use middle::trans::write_guard;
|
use middle::trans::write_guard;
|
||||||
|
use middle::trans::debuginfo;
|
||||||
use middle::ty::substs;
|
use middle::ty::substs;
|
||||||
use middle::ty;
|
use middle::ty;
|
||||||
use middle::typeck;
|
use middle::typeck;
|
||||||
@ -226,7 +227,12 @@ pub struct FunctionContext {
|
|||||||
path: path,
|
path: path,
|
||||||
|
|
||||||
// This function's enclosing crate context.
|
// This function's enclosing crate context.
|
||||||
ccx: @mut CrateContext
|
ccx: @mut CrateContext,
|
||||||
|
|
||||||
|
// Used and maintained by the debuginfo module.
|
||||||
|
// @jdm: Not sure if the Option-wrapper is a good idea. It allows to save some space in
|
||||||
|
// non-debug builds, but generates quite a bit of noise at usage sites. What's your opinion?
|
||||||
|
debug_context: Option<~debuginfo::FunctionDebugContext>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FunctionContext {
|
impl FunctionContext {
|
||||||
|
@ -19,7 +19,6 @@ use middle::trans::base::*;
|
|||||||
use middle::trans::build::*;
|
use middle::trans::build::*;
|
||||||
use middle::trans::callee;
|
use middle::trans::callee;
|
||||||
use middle::trans::common::*;
|
use middle::trans::common::*;
|
||||||
use middle::trans::debuginfo;
|
|
||||||
use middle::trans::expr;
|
use middle::trans::expr;
|
||||||
use middle::trans::type_of::*;
|
use middle::trans::type_of::*;
|
||||||
use middle::ty;
|
use middle::ty;
|
||||||
@ -38,12 +37,10 @@ pub fn trans_block(bcx: @mut Block, b: &ast::Block, dest: expr::Dest) -> @mut Bl
|
|||||||
let _icx = push_ctxt("trans_block");
|
let _icx = push_ctxt("trans_block");
|
||||||
let mut bcx = bcx;
|
let mut bcx = bcx;
|
||||||
for s in b.stmts.iter() {
|
for s in b.stmts.iter() {
|
||||||
debuginfo::update_source_pos(bcx, b.span);
|
|
||||||
bcx = trans_stmt(bcx, *s);
|
bcx = trans_stmt(bcx, *s);
|
||||||
}
|
}
|
||||||
match b.expr {
|
match b.expr {
|
||||||
Some(e) => {
|
Some(e) => {
|
||||||
debuginfo::update_source_pos(bcx, e.span);
|
|
||||||
bcx = expr::trans_into(bcx, e, dest);
|
bcx = expr::trans_into(bcx, e, dest);
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
|
@ -99,9 +99,7 @@ pub struct DebugContext {
|
|||||||
priv created_files: HashMap<~str, DIFile>,
|
priv created_files: HashMap<~str, DIFile>,
|
||||||
priv created_functions: HashMap<ast::NodeId, DISubprogram>,
|
priv created_functions: HashMap<ast::NodeId, DISubprogram>,
|
||||||
priv created_blocks: HashMap<ast::NodeId, DILexicalBlock>,
|
priv created_blocks: HashMap<ast::NodeId, DILexicalBlock>,
|
||||||
priv created_types: HashMap<uint, DIType>,
|
priv created_types: HashMap<uint, DIType>
|
||||||
priv last_function_context_id: ast::NodeId,
|
|
||||||
priv argument_counter: uint,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DebugContext {
|
impl DebugContext {
|
||||||
@ -118,8 +116,21 @@ impl DebugContext {
|
|||||||
created_files: HashMap::new(),
|
created_files: HashMap::new(),
|
||||||
created_functions: HashMap::new(),
|
created_functions: HashMap::new(),
|
||||||
created_blocks: HashMap::new(),
|
created_blocks: HashMap::new(),
|
||||||
created_types: HashMap::new(),
|
created_types: HashMap::new()
|
||||||
last_function_context_id: -1, // magic value :(
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub struct FunctionDebugContext {
|
||||||
|
priv scope_map: HashMap<ast::NodeId, DIScope>,
|
||||||
|
priv argument_counter: uint,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FunctionDebugContext {
|
||||||
|
priv fn new() -> FunctionDebugContext {
|
||||||
|
return FunctionDebugContext {
|
||||||
|
scope_map: HashMap::new(),
|
||||||
argument_counter: 1,
|
argument_counter: 1,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -141,61 +152,24 @@ pub fn finalize(cx: @mut CrateContext) {
|
|||||||
pub fn create_local_var_metadata(bcx: @mut Block, local: &ast::Local) {
|
pub fn create_local_var_metadata(bcx: @mut Block, local: &ast::Local) {
|
||||||
let cx = bcx.ccx();
|
let cx = bcx.ccx();
|
||||||
let def_map = cx.tcx.def_map;
|
let def_map = cx.tcx.def_map;
|
||||||
let pattern = local.pat;
|
|
||||||
|
|
||||||
let scope = match bcx.parent {
|
do pat_util::pat_bindings(def_map, local.pat) |_, node_id, span, path_ref| {
|
||||||
None => create_function_metadata(bcx.fcx),
|
|
||||||
Some(_) => lexical_block_metadata(bcx)
|
|
||||||
};
|
|
||||||
|
|
||||||
let filename = span_start(cx, local.span).file.name;
|
let var_ident = ast_util::path_to_ident(path_ref);
|
||||||
let file_metadata = file_metadata(cx, filename);
|
let var_type = node_id_type(bcx, node_id);
|
||||||
|
|
||||||
do pat_util::pat_bindings(def_map, pattern) |_, node_id, span, path_ref| {
|
declare_local(bcx, var_ident, node_id, var_type, span);
|
||||||
|
|
||||||
let ident = ast_util::path_to_ident(path_ref);
|
|
||||||
let name: &str = cx.sess.str_of(ident);
|
|
||||||
debug!("create_local_var_metadata: %s", name);
|
|
||||||
let loc = span_start(cx, span);
|
|
||||||
let ty = node_id_type(bcx, node_id);
|
|
||||||
let type_metadata = type_metadata(cx, ty, span);
|
|
||||||
|
|
||||||
let var_metadata = do name.to_c_str().with_ref |name| {
|
|
||||||
unsafe {
|
|
||||||
llvm::LLVMDIBuilderCreateLocalVariable(
|
|
||||||
DIB(cx),
|
|
||||||
DW_TAG_auto_variable,
|
|
||||||
scope,
|
|
||||||
name,
|
|
||||||
file_metadata,
|
|
||||||
loc.line as c_uint,
|
|
||||||
type_metadata,
|
|
||||||
false,
|
|
||||||
0,
|
|
||||||
0)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let llptr = match bcx.fcx.lllocals.find_copy(&node_id) {
|
|
||||||
Some(v) => v,
|
|
||||||
None => {
|
|
||||||
bcx.tcx().sess.span_bug(span, fmt!("No entry in lllocals 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,
|
|
||||||
var_metadata,
|
|
||||||
bcx.llbb);
|
|
||||||
|
|
||||||
llvm::LLVMSetInstDebugLocation(trans::build::B(bcx).llbuilder, instr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn create_match_binding_metadata(bcx: @mut Block,
|
||||||
|
variable_ident: ast::ident,
|
||||||
|
node_id: ast::NodeId,
|
||||||
|
variable_type: ty::t,
|
||||||
|
span: span) {
|
||||||
|
declare_local(bcx, variable_ident, node_id, variable_type, span);
|
||||||
|
}
|
||||||
|
|
||||||
/// Creates debug information for the given function argument.
|
/// Creates debug information for the given function argument.
|
||||||
///
|
///
|
||||||
/// Adds the created metadata nodes directly to the crate's IR.
|
/// Adds the created metadata nodes directly to the crate's IR.
|
||||||
@ -213,20 +187,6 @@ pub fn create_argument_metadata(bcx: @mut Block,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Limited the scope within which `debug_context` is live,
|
|
||||||
// otherwise => borrowing errors
|
|
||||||
{
|
|
||||||
let debug_context = dbg_cx(cx);
|
|
||||||
|
|
||||||
// If this is a new function, reset the counter. llvm::DIBuilder
|
|
||||||
// wants arguments to be indexed starting from 1.
|
|
||||||
if fcx.id != debug_context.last_function_context_id {
|
|
||||||
debug_context.argument_counter = 1;
|
|
||||||
}
|
|
||||||
// Keep track of the function we are in
|
|
||||||
debug_context.last_function_context_id = fcx.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
let def_map = cx.tcx.def_map;
|
let def_map = cx.tcx.def_map;
|
||||||
let file_metadata = file_metadata(cx, filename);
|
let file_metadata = file_metadata(cx, filename);
|
||||||
let scope = create_function_metadata(fcx);
|
let scope = create_function_metadata(fcx);
|
||||||
@ -241,9 +201,9 @@ pub fn create_argument_metadata(bcx: @mut Block,
|
|||||||
debug!("create_argument_metadata: %s", name);
|
debug!("create_argument_metadata: %s", name);
|
||||||
|
|
||||||
let argument_index = {
|
let argument_index = {
|
||||||
let debug_context = dbg_cx(cx);
|
let counter = &mut fcx.debug_context.get_mut_ref().argument_counter;
|
||||||
let argument_index = debug_context.argument_counter;
|
let argument_index = *counter;
|
||||||
debug_context.argument_counter += 1;
|
*counter += 1;
|
||||||
argument_index as c_uint
|
argument_index as c_uint
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -270,7 +230,7 @@ pub fn create_argument_metadata(bcx: @mut Block,
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
set_debug_location(cx, lexical_block_metadata(bcx), loc.line, loc.col.to_uint());
|
set_debug_location(cx, scope, loc.line, loc.col.to_uint());
|
||||||
unsafe {
|
unsafe {
|
||||||
let instr = llvm::LLVMDIBuilderInsertDeclareAtEnd(
|
let instr = llvm::LLVMDIBuilderInsertDeclareAtEnd(
|
||||||
DIB(cx),
|
DIB(cx),
|
||||||
@ -286,20 +246,28 @@ pub fn create_argument_metadata(bcx: @mut Block,
|
|||||||
/// Sets the current debug location at the beginning of the span
|
/// Sets the current debug location at the beginning of the span
|
||||||
///
|
///
|
||||||
/// Maps to a call to llvm::LLVMSetCurrentDebugLocation(...)
|
/// Maps to a call to llvm::LLVMSetCurrentDebugLocation(...)
|
||||||
pub fn update_source_pos(bcx: @mut Block, span: span) {
|
pub fn update_source_pos(fcx: &FunctionContext,
|
||||||
if !bcx.sess().opts.debuginfo || (*span.lo == 0 && *span.hi == 0) {
|
node_id: ast::NodeId,
|
||||||
|
span: span) {
|
||||||
|
let cx: &mut CrateContext = fcx.ccx;
|
||||||
|
|
||||||
|
if !cx.sess.opts.debuginfo || (*span.lo == 0 && *span.hi == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
debug!("update_source_pos: %s", bcx.sess().codemap.span_to_str(span));
|
|
||||||
let loc = span_start(bcx.ccx(), span);
|
debug!("update_source_pos: %s", cx.sess.codemap.span_to_str(span));
|
||||||
set_debug_location(bcx.ccx(), lexical_block_metadata(bcx), loc.line, loc.col.to_uint())
|
|
||||||
|
let loc = span_start(cx, span);
|
||||||
|
let scope = scope_metadata(fcx, node_id, span);
|
||||||
|
|
||||||
|
set_debug_location(cx, scope, loc.line, loc.col.to_uint());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates debug information for the given function.
|
/// Creates debug information for the given function.
|
||||||
///
|
///
|
||||||
/// Adds the created metadata nodes directly to the crate's IR.
|
/// 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.
|
/// The return value should be ignored if called from outside of the debuginfo module.
|
||||||
pub fn create_function_metadata(fcx: &FunctionContext) -> DISubprogram {
|
pub fn create_function_metadata(fcx: &mut FunctionContext) -> DISubprogram {
|
||||||
let cx = fcx.ccx;
|
let cx = fcx.ccx;
|
||||||
|
|
||||||
let fnitem = cx.tcx.items.get_copy(&fcx.id);
|
let fnitem = cx.tcx.items.get_copy(&fcx.id);
|
||||||
@ -349,8 +317,8 @@ pub fn create_function_metadata(fcx: &FunctionContext) -> DISubprogram {
|
|||||||
_ => fcx.ccx.sess.bug(fmt!("create_function_metadata: unexpected sort of node: %?", fnitem))
|
_ => fcx.ccx.sess.bug(fmt!("create_function_metadata: unexpected sort of node: %?", fnitem))
|
||||||
};
|
};
|
||||||
|
|
||||||
match dbg_cx(cx).created_functions.find(&id) {
|
match dbg_cx(cx).created_functions.find_copy(&id) {
|
||||||
Some(fn_metadata) => return *fn_metadata,
|
Some(fn_metadata) => return fn_metadata,
|
||||||
None => ()
|
None => ()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -405,6 +373,25 @@ pub fn create_function_metadata(fcx: &FunctionContext) -> DISubprogram {
|
|||||||
}
|
}
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
assert!(fcx.debug_context.is_none());
|
||||||
|
|
||||||
|
let mut fn_debug_context = ~FunctionDebugContext::new();
|
||||||
|
let entry_block_id = fcx.entry_bcx.get_ref().node_info.get_ref().id;
|
||||||
|
let entry_block = cx.tcx.items.get(&entry_block_id);
|
||||||
|
|
||||||
|
match *entry_block {
|
||||||
|
ast_map::node_block(ref block) => {
|
||||||
|
let scope_map = &mut fn_debug_context.scope_map;
|
||||||
|
populate_scope_map(cx, block, fn_metadata, scope_map);
|
||||||
|
}
|
||||||
|
_ => cx.sess.span_bug(span,
|
||||||
|
fmt!("debuginfo::create_function_metadata() - \
|
||||||
|
FunctionContext::entry_bcx::node_info points to wrong type of ast_map entry. \
|
||||||
|
Expected: ast_map::node_block, actual: %?", *entry_block))
|
||||||
|
}
|
||||||
|
|
||||||
|
fcx.debug_context = Some(fn_debug_context);
|
||||||
|
|
||||||
dbg_cx(cx).created_functions.insert(id, fn_metadata);
|
dbg_cx(cx).created_functions.insert(id, fn_metadata);
|
||||||
return fn_metadata;
|
return fn_metadata;
|
||||||
}
|
}
|
||||||
@ -445,6 +432,56 @@ fn compile_unit_metadata(cx: @mut CrateContext) {
|
|||||||
}}}}};
|
}}}}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn declare_local(bcx: @mut Block,
|
||||||
|
variable_ident: ast::ident,
|
||||||
|
node_id: ast::NodeId,
|
||||||
|
variable_type: ty::t,
|
||||||
|
span: span) {
|
||||||
|
let cx: &mut CrateContext = bcx.ccx();
|
||||||
|
|
||||||
|
let filename = span_start(cx, span).file.name;
|
||||||
|
let file_metadata = file_metadata(cx, filename);
|
||||||
|
|
||||||
|
let name: &str = cx.sess.str_of(variable_ident);
|
||||||
|
let loc = span_start(cx, span);
|
||||||
|
let type_metadata = type_metadata(cx, variable_type, span);
|
||||||
|
let scope = scope_metadata(bcx.fcx, node_id, span);
|
||||||
|
|
||||||
|
let var_metadata = do name.as_c_str |name| {
|
||||||
|
unsafe {
|
||||||
|
llvm::LLVMDIBuilderCreateLocalVariable(
|
||||||
|
DIB(cx),
|
||||||
|
DW_TAG_auto_variable,
|
||||||
|
scope,
|
||||||
|
name,
|
||||||
|
file_metadata,
|
||||||
|
loc.line as c_uint,
|
||||||
|
type_metadata,
|
||||||
|
false,
|
||||||
|
0,
|
||||||
|
0)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let llptr = match bcx.fcx.lllocals.find_copy(&node_id) {
|
||||||
|
Some(v) => v,
|
||||||
|
None => {
|
||||||
|
bcx.tcx().sess.span_bug(span, fmt!("No entry in lllocals table for %?", node_id));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
set_debug_location(cx, scope, loc.line, loc.col.to_uint());
|
||||||
|
unsafe {
|
||||||
|
let instr = llvm::LLVMDIBuilderInsertDeclareAtEnd(
|
||||||
|
DIB(cx),
|
||||||
|
llptr,
|
||||||
|
var_metadata,
|
||||||
|
bcx.llbb);
|
||||||
|
|
||||||
|
llvm::LLVMSetInstDebugLocation(trans::build::B(bcx).llbuilder, instr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn file_metadata(cx: &mut CrateContext, full_path: &str) -> DIFile {
|
fn file_metadata(cx: &mut CrateContext, full_path: &str) -> DIFile {
|
||||||
match dbg_cx(cx).created_files.find_equiv(&full_path) {
|
match dbg_cx(cx).created_files.find_equiv(&full_path) {
|
||||||
Some(file_metadata) => return *file_metadata,
|
Some(file_metadata) => return *file_metadata,
|
||||||
@ -473,50 +510,26 @@ fn file_metadata(cx: &mut CrateContext, full_path: &str) -> DIFile {
|
|||||||
return file_metadata;
|
return file_metadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get or create the lexical block metadata node for the given LLVM basic block.
|
/// Finds the scope metadata node for the given AST node.
|
||||||
fn lexical_block_metadata(bcx: @mut Block) -> DILexicalBlock {
|
fn scope_metadata(fcx: &FunctionContext,
|
||||||
let cx = bcx.ccx();
|
node_id: ast::NodeId,
|
||||||
let mut bcx = bcx;
|
span: span) -> DIScope {
|
||||||
|
if fcx.debug_context.is_none() {
|
||||||
|
fcx.ccx.sess.span_bug(span, "debuginfo: FunctionDebugContext should be initialized \
|
||||||
|
but is not!");
|
||||||
|
}
|
||||||
|
|
||||||
// Search up the tree of basic blocks until we find one that knows the containing lexical block.
|
let scope_map = &fcx.debug_context.get_ref().scope_map;
|
||||||
while bcx.node_info.is_none() {
|
|
||||||
match bcx.parent {
|
match scope_map.find_copy(&node_id) {
|
||||||
Some(b) => bcx = b,
|
Some(scope_metadata) => scope_metadata,
|
||||||
None => cx.sess.bug("debuginfo: Could not find lexical block for LLVM basic block.")
|
None => {
|
||||||
|
let node = fcx.ccx.tcx.items.get_copy(&node_id);
|
||||||
|
|
||||||
|
fcx.ccx.sess.span_bug(span,
|
||||||
|
fmt!("debuginfo: Could not find scope info for node %?", node));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let span = bcx.node_info.unwrap().span;
|
|
||||||
let id = bcx.node_info.unwrap().id;
|
|
||||||
|
|
||||||
// Check whether we already have a cache entry for this node id
|
|
||||||
match dbg_cx(cx).created_blocks.find(&id) {
|
|
||||||
Some(block) => return *block,
|
|
||||||
None => ()
|
|
||||||
}
|
|
||||||
|
|
||||||
debug!("lexical_block_metadata: %s", bcx.sess().codemap.span_to_str(span));
|
|
||||||
|
|
||||||
let parent = match bcx.parent {
|
|
||||||
None => create_function_metadata(bcx.fcx),
|
|
||||||
Some(b) => lexical_block_metadata(b)
|
|
||||||
};
|
|
||||||
|
|
||||||
let loc = span_start(cx, span);
|
|
||||||
let file_metadata = file_metadata(cx, loc.file.name);
|
|
||||||
|
|
||||||
let lexical_block_metadata = unsafe {
|
|
||||||
llvm::LLVMDIBuilderCreateLexicalBlock(
|
|
||||||
DIB(cx),
|
|
||||||
parent,
|
|
||||||
file_metadata,
|
|
||||||
loc.line as c_uint,
|
|
||||||
loc.col.to_uint() as c_uint)
|
|
||||||
};
|
|
||||||
|
|
||||||
dbg_cx(cx).created_blocks.insert(id, lexical_block_metadata);
|
|
||||||
|
|
||||||
return lexical_block_metadata;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn basic_type_metadata(cx: &mut CrateContext, t: ty::t) -> DIType {
|
fn basic_type_metadata(cx: &mut CrateContext, t: ty::t) -> DIType {
|
||||||
@ -1206,7 +1219,7 @@ fn type_metadata(cx: &mut CrateContext,
|
|||||||
return type_metadata;
|
return type_metadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_debug_location(cx: @mut CrateContext, scope: DIScope, line: uint, col: uint) {
|
fn set_debug_location(cx: &mut CrateContext, scope: DIScope, line: uint, col: uint) {
|
||||||
if dbg_cx(cx).curr_loc == (line, col) {
|
if dbg_cx(cx).curr_loc == (line, col) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1224,7 +1237,6 @@ fn set_debug_location(cx: @mut CrateContext, scope: DIScope, line: uint, col: ui
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//=-------------------------------------------------------------------------------------------------
|
//=-------------------------------------------------------------------------------------------------
|
||||||
// Utility Functions
|
// Utility Functions
|
||||||
//=-------------------------------------------------------------------------------------------------
|
//=-------------------------------------------------------------------------------------------------
|
||||||
@ -1256,3 +1268,436 @@ fn dbg_cx<'a>(cx: &'a mut CrateContext) -> &'a mut DebugContext {
|
|||||||
fn DIB(cx: &CrateContext) -> DIBuilderRef {
|
fn DIB(cx: &CrateContext) -> DIBuilderRef {
|
||||||
cx.dbg_cx.get_ref().builder
|
cx.dbg_cx.get_ref().builder
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// This procedure builds the *scope map* for a given function, which maps any given ast::NodeId in
|
||||||
|
// the function's AST to the correct DIScope metadata instance.
|
||||||
|
//
|
||||||
|
// This builder procedure walks the AST in execution order and keeps track of what belongs to which
|
||||||
|
// scope, creating DIScope DIEs along the way, and introducing *artificial* lexical scope
|
||||||
|
// descriptors where necessary. These artificial scopes allow GDB to correctly handle name
|
||||||
|
// shadowing.
|
||||||
|
fn populate_scope_map(cx: &mut CrateContext,
|
||||||
|
fn_entry_block: &ast::Block,
|
||||||
|
fn_metadata: DISubprogram,
|
||||||
|
scope_map: &mut HashMap<ast::NodeId, DIScope>) {
|
||||||
|
|
||||||
|
struct ScopeStackEntry {
|
||||||
|
scope_metadata: DIScope,
|
||||||
|
ident: Option<ast::ident>
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut scope_stack = ~[ScopeStackEntry { scope_metadata: fn_metadata, ident: None }];
|
||||||
|
|
||||||
|
walk_block(cx, fn_entry_block, &mut scope_stack, scope_map);
|
||||||
|
|
||||||
|
// local helper functions for walking the AST.
|
||||||
|
|
||||||
|
fn with_new_scope(cx: &mut CrateContext,
|
||||||
|
scope_span: span,
|
||||||
|
scope_stack: &mut ~[ScopeStackEntry],
|
||||||
|
scope_map: &mut HashMap<ast::NodeId, DIScope>,
|
||||||
|
inner_walk: &fn(&mut CrateContext,
|
||||||
|
&mut ~[ScopeStackEntry],
|
||||||
|
&mut HashMap<ast::NodeId, DIScope>)) {
|
||||||
|
|
||||||
|
// Create a new lexical scope and push it onto the stack
|
||||||
|
let loc = cx.sess.codemap.lookup_char_pos(scope_span.lo);
|
||||||
|
let file_metadata = file_metadata(cx, loc.file.name);
|
||||||
|
let parent_scope = scope_stack.last().scope_metadata;
|
||||||
|
|
||||||
|
let scope_metadata = unsafe {
|
||||||
|
llvm::LLVMDIBuilderCreateLexicalBlock(
|
||||||
|
DIB(cx),
|
||||||
|
parent_scope,
|
||||||
|
file_metadata,
|
||||||
|
loc.line as c_uint,
|
||||||
|
loc.col.to_uint() as c_uint)
|
||||||
|
};
|
||||||
|
|
||||||
|
scope_stack.push(ScopeStackEntry { scope_metadata: scope_metadata, ident: None });
|
||||||
|
|
||||||
|
inner_walk(cx, scope_stack, scope_map);
|
||||||
|
|
||||||
|
// pop artificial scopes
|
||||||
|
while scope_stack.last().ident.is_some() {
|
||||||
|
scope_stack.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
if scope_stack.last().scope_metadata != scope_metadata {
|
||||||
|
cx.sess.span_bug(scope_span, "debuginfo: Inconsistency in scope management.");
|
||||||
|
}
|
||||||
|
|
||||||
|
scope_stack.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn walk_block(cx: &mut CrateContext,
|
||||||
|
block: &ast::Block,
|
||||||
|
scope_stack: &mut ~[ScopeStackEntry],
|
||||||
|
scope_map: &mut HashMap<ast::NodeId, DIScope>) {
|
||||||
|
|
||||||
|
scope_map.insert(block.id, scope_stack.last().scope_metadata);
|
||||||
|
|
||||||
|
// The interesting things here are statements and the concluding expression.
|
||||||
|
for &@ ref statement in block.stmts.iter() {
|
||||||
|
scope_map.insert(ast_util::stmt_id(statement), scope_stack.last().scope_metadata);
|
||||||
|
|
||||||
|
match statement.node {
|
||||||
|
ast::stmt_decl(@ref decl, _) => walk_decl(cx, decl, scope_stack, scope_map),
|
||||||
|
ast::stmt_expr(@ref exp, _) |
|
||||||
|
ast::stmt_semi(@ref exp, _) => walk_expr(cx, exp, scope_stack, scope_map),
|
||||||
|
ast::stmt_mac(*) => () // ignore macros (which should be expanded anyway)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for &@ref exp in block.expr.iter() {
|
||||||
|
walk_expr(cx, exp, scope_stack, scope_map);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn walk_decl(cx: &mut CrateContext,
|
||||||
|
decl: &ast::decl,
|
||||||
|
scope_stack: &mut ~[ScopeStackEntry],
|
||||||
|
scope_map: &mut HashMap<ast::NodeId, DIScope>) {
|
||||||
|
match *decl {
|
||||||
|
codemap::spanned { node: ast::decl_local(@ref local), _ } => {
|
||||||
|
|
||||||
|
scope_map.insert(local.id, scope_stack.last().scope_metadata);
|
||||||
|
|
||||||
|
walk_pattern(cx, local.pat, scope_stack, scope_map);
|
||||||
|
|
||||||
|
for &@ref exp in local.init.iter() {
|
||||||
|
walk_expr(cx, exp, scope_stack, scope_map);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => ()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn walk_pattern(cx: &mut CrateContext,
|
||||||
|
pat: @ast::pat,
|
||||||
|
scope_stack: &mut ~[ScopeStackEntry],
|
||||||
|
scope_map: &mut HashMap<ast::NodeId, DIScope>) {
|
||||||
|
|
||||||
|
let def_map = cx.tcx.def_map;
|
||||||
|
|
||||||
|
// Unfortunately, we cannot just use pat_util::pat_bindings() or ast_util::walk_pat() here
|
||||||
|
// because we have to visit *all* nodes in order to put them into the scope map. The above
|
||||||
|
// function don't do that.
|
||||||
|
match pat.node {
|
||||||
|
ast::pat_ident(_, ref path_ref, ref sub_pat_opt) => {
|
||||||
|
|
||||||
|
// Check if this is a binding. If so we need to put it on the scope stack and maybe
|
||||||
|
// introduce an articial scope
|
||||||
|
if pat_util::pat_is_binding(def_map, pat) {
|
||||||
|
|
||||||
|
let ident = ast_util::path_to_ident(path_ref);
|
||||||
|
|
||||||
|
// LLVM does not properly generate 'DW_AT_start_scope' fields for variable DIEs.
|
||||||
|
// For this reason we have to introduce an artificial scope at bindings whenever
|
||||||
|
// a variable with the same name is declared in *any* parent scope.
|
||||||
|
//
|
||||||
|
// Otherwise the following error occurs:
|
||||||
|
//
|
||||||
|
// let x = 10;
|
||||||
|
//
|
||||||
|
// do_something(); // 'gdb print x' correctly prints 10
|
||||||
|
//
|
||||||
|
// {
|
||||||
|
// do_something(); // 'gdb print x' prints 0, because it already reads the
|
||||||
|
// // uninitialized 'x' from the next line...
|
||||||
|
// let x = 100;
|
||||||
|
// do_something(); // 'gdb print x' correctly prints 100
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Is there already a binding with that name?
|
||||||
|
let need_new_scope = scope_stack
|
||||||
|
.rev_iter()
|
||||||
|
.find_(|entry| entry.ident.iter().any(|i| *i == ident))
|
||||||
|
.is_some();
|
||||||
|
|
||||||
|
if need_new_scope {
|
||||||
|
// Create a new lexical scope and push it onto the stack
|
||||||
|
let loc = cx.sess.codemap.lookup_char_pos(pat.span.lo);
|
||||||
|
let file_metadata = file_metadata(cx, loc.file.name);
|
||||||
|
let parent_scope = scope_stack.last().scope_metadata;
|
||||||
|
|
||||||
|
let scope_metadata = unsafe {
|
||||||
|
llvm::LLVMDIBuilderCreateLexicalBlock(
|
||||||
|
DIB(cx),
|
||||||
|
parent_scope,
|
||||||
|
file_metadata,
|
||||||
|
loc.line as c_uint,
|
||||||
|
loc.col.to_uint() as c_uint)
|
||||||
|
};
|
||||||
|
|
||||||
|
scope_stack.push(ScopeStackEntry {
|
||||||
|
scope_metadata: scope_metadata,
|
||||||
|
ident: Some(ident)
|
||||||
|
});
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Push a new entry anyway so the name can be found
|
||||||
|
let prev_metadata = scope_stack.last().scope_metadata;
|
||||||
|
scope_stack.push(ScopeStackEntry {
|
||||||
|
scope_metadata: prev_metadata,
|
||||||
|
ident: Some(ident)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
scope_map.insert(pat.id, scope_stack.last().scope_metadata);
|
||||||
|
|
||||||
|
for &sub_pat in sub_pat_opt.iter() {
|
||||||
|
walk_pattern(cx, sub_pat, scope_stack, scope_map);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ast::pat_wild => {
|
||||||
|
scope_map.insert(pat.id, scope_stack.last().scope_metadata);
|
||||||
|
}
|
||||||
|
|
||||||
|
ast::pat_enum(_, ref sub_pats_opt) => {
|
||||||
|
scope_map.insert(pat.id, scope_stack.last().scope_metadata);
|
||||||
|
|
||||||
|
for ref sub_pats in sub_pats_opt.iter() {
|
||||||
|
for &p in sub_pats.iter() {
|
||||||
|
walk_pattern(cx, p, scope_stack, scope_map);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ast::pat_struct(_, ref field_pats, _) => {
|
||||||
|
scope_map.insert(pat.id, scope_stack.last().scope_metadata);
|
||||||
|
|
||||||
|
for &ast::field_pat { pat: sub_pat, _ } in field_pats.iter() {
|
||||||
|
walk_pattern(cx, sub_pat, scope_stack, scope_map);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ast::pat_tup(ref sub_pats) => {
|
||||||
|
scope_map.insert(pat.id, scope_stack.last().scope_metadata);
|
||||||
|
|
||||||
|
for &sub_pat in sub_pats.iter() {
|
||||||
|
walk_pattern(cx, sub_pat, scope_stack, scope_map);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ast::pat_box(sub_pat) |
|
||||||
|
ast::pat_uniq(sub_pat) |
|
||||||
|
ast::pat_region(sub_pat) => {
|
||||||
|
scope_map.insert(pat.id, scope_stack.last().scope_metadata);
|
||||||
|
walk_pattern(cx, sub_pat, scope_stack, scope_map);
|
||||||
|
}
|
||||||
|
|
||||||
|
ast::pat_lit(@ref exp) => {
|
||||||
|
scope_map.insert(pat.id, scope_stack.last().scope_metadata);
|
||||||
|
walk_expr(cx, exp, scope_stack, scope_map);
|
||||||
|
}
|
||||||
|
|
||||||
|
ast::pat_range(@ref exp1, @ref exp2) => {
|
||||||
|
scope_map.insert(pat.id, scope_stack.last().scope_metadata);
|
||||||
|
walk_expr(cx, exp1, scope_stack, scope_map);
|
||||||
|
walk_expr(cx, exp2, scope_stack, scope_map);
|
||||||
|
}
|
||||||
|
|
||||||
|
ast::pat_vec(ref front_sub_pats, ref middle_sub_pats, ref back_sub_pats) => {
|
||||||
|
scope_map.insert(pat.id, scope_stack.last().scope_metadata);
|
||||||
|
|
||||||
|
for &sub_pat in front_sub_pats.iter() {
|
||||||
|
walk_pattern(cx, sub_pat, scope_stack, scope_map);
|
||||||
|
}
|
||||||
|
|
||||||
|
for &sub_pat in middle_sub_pats.iter() {
|
||||||
|
walk_pattern(cx, sub_pat, scope_stack, scope_map);
|
||||||
|
}
|
||||||
|
|
||||||
|
for &sub_pat in back_sub_pats.iter() {
|
||||||
|
walk_pattern(cx, sub_pat, scope_stack, scope_map);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn walk_expr(cx: &mut CrateContext,
|
||||||
|
exp: &ast::expr,
|
||||||
|
scope_stack: &mut ~[ScopeStackEntry],
|
||||||
|
scope_map: &mut HashMap<ast::NodeId, DIScope>) {
|
||||||
|
|
||||||
|
scope_map.insert(exp.id, scope_stack.last().scope_metadata);
|
||||||
|
|
||||||
|
match exp.node {
|
||||||
|
ast::expr_self |
|
||||||
|
ast::expr_lit(_) |
|
||||||
|
ast::expr_break(_) |
|
||||||
|
ast::expr_again(_) |
|
||||||
|
ast::expr_path(_) => (),
|
||||||
|
|
||||||
|
ast::expr_vstore(@ref sub_exp, _) |
|
||||||
|
ast::expr_cast(@ref sub_exp, _) |
|
||||||
|
ast::expr_addr_of(_, @ref sub_exp) |
|
||||||
|
ast::expr_field(@ref sub_exp, _, _) |
|
||||||
|
ast::expr_paren(@ref sub_exp) => walk_expr(cx, sub_exp, scope_stack, scope_map),
|
||||||
|
|
||||||
|
ast::expr_ret(exp_opt) => match exp_opt {
|
||||||
|
Some(@ref sub_exp) => walk_expr(cx, sub_exp, scope_stack, scope_map),
|
||||||
|
None => ()
|
||||||
|
},
|
||||||
|
|
||||||
|
ast::expr_unary(node_id, _, @ref sub_exp) => {
|
||||||
|
scope_map.insert(node_id, scope_stack.last().scope_metadata);
|
||||||
|
walk_expr(cx, sub_exp, scope_stack, scope_map);
|
||||||
|
}
|
||||||
|
|
||||||
|
ast::expr_assign_op(node_id, _, @ref lhs, @ref rhs) |
|
||||||
|
ast::expr_index(node_id, @ref lhs, @ref rhs) |
|
||||||
|
ast::expr_binary(node_id, _, @ref lhs, @ref rhs) => {
|
||||||
|
scope_map.insert(node_id, scope_stack.last().scope_metadata);
|
||||||
|
walk_expr(cx, lhs, scope_stack, scope_map);
|
||||||
|
walk_expr(cx, rhs, scope_stack, scope_map);
|
||||||
|
}
|
||||||
|
|
||||||
|
ast::expr_vec(ref init_expressions, _) |
|
||||||
|
ast::expr_tup(ref init_expressions) => {
|
||||||
|
for &@ref ie in init_expressions.iter() {
|
||||||
|
walk_expr(cx, ie, scope_stack, scope_map);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ast::expr_assign(@ref sub_exp1, @ref sub_exp2) |
|
||||||
|
ast::expr_log(@ref sub_exp1, @ref sub_exp2) |
|
||||||
|
ast::expr_repeat(@ref sub_exp1, @ref sub_exp2, _) => {
|
||||||
|
walk_expr(cx, sub_exp1, scope_stack, scope_map);
|
||||||
|
walk_expr(cx, sub_exp2, scope_stack, scope_map);
|
||||||
|
}
|
||||||
|
|
||||||
|
ast::expr_if(@ref cond_exp, ref then_block, ref opt_else_exp) => {
|
||||||
|
walk_expr(cx, cond_exp, scope_stack, scope_map);
|
||||||
|
|
||||||
|
do with_new_scope(cx, then_block.span, scope_stack, scope_map) |c, s, m| {
|
||||||
|
walk_block(c, then_block, s, m);
|
||||||
|
}
|
||||||
|
|
||||||
|
match *opt_else_exp {
|
||||||
|
Some(@ref else_exp) => walk_expr(cx, else_exp, scope_stack, scope_map),
|
||||||
|
_ => ()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ast::expr_while(@ref cond_exp, ref loop_body) => {
|
||||||
|
walk_expr(cx, cond_exp, scope_stack, scope_map);
|
||||||
|
|
||||||
|
do with_new_scope(cx, loop_body.span, scope_stack, scope_map) |c, s, m| {
|
||||||
|
walk_block(c, loop_body, s, m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ast::expr_for_loop(_, _, _) => {
|
||||||
|
cx.sess.span_bug(exp.span, "debuginfo::populate_scope_map() - \
|
||||||
|
Found unexpanded for-loop.");
|
||||||
|
}
|
||||||
|
|
||||||
|
ast::expr_mac(_) => {
|
||||||
|
cx.sess.span_bug(exp.span, "debuginfo::populate_scope_map() - \
|
||||||
|
Found unexpanded macro.");
|
||||||
|
}
|
||||||
|
|
||||||
|
ast::expr_loop(ref block, _) |
|
||||||
|
ast::expr_block(ref block) => {
|
||||||
|
do with_new_scope(cx, block.span, scope_stack, scope_map) |c, s, m| {
|
||||||
|
walk_block(c, block, s, m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ast::expr_fn_block(ast::fn_decl { inputs: ref inputs, _ }, ref block) => {
|
||||||
|
|
||||||
|
do with_new_scope(cx, block.span, scope_stack, scope_map) |c, s, m| {
|
||||||
|
|
||||||
|
for &ast::arg { pat: pattern, _ } in inputs.iter() {
|
||||||
|
walk_pattern(c, pattern, s, m);
|
||||||
|
}
|
||||||
|
|
||||||
|
walk_block(c, block, s, m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ast::expr_loop_body(@ref inner_exp) |
|
||||||
|
ast::expr_do_body(@ref inner_exp) => {
|
||||||
|
let inner_expr_is_expr_fn_block = match *inner_exp {
|
||||||
|
ast::expr { node: ast::expr_fn_block(*), _ } => true,
|
||||||
|
_ => false
|
||||||
|
};
|
||||||
|
|
||||||
|
if !inner_expr_is_expr_fn_block {
|
||||||
|
cx.sess.span_bug(inner_exp.span, "debuginfo: Inner expression was expected \
|
||||||
|
to be an ast::expr_fn_block.");
|
||||||
|
}
|
||||||
|
|
||||||
|
walk_expr(cx, inner_exp, scope_stack, scope_map);
|
||||||
|
}
|
||||||
|
|
||||||
|
ast::expr_call(@ref fn_exp, ref args, _) => {
|
||||||
|
walk_expr(cx, fn_exp, scope_stack, scope_map);
|
||||||
|
|
||||||
|
for &@ref arg_exp in args.iter() {
|
||||||
|
walk_expr(cx, arg_exp, scope_stack, scope_map);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ast::expr_method_call(node_id, @ref receiver_exp, _, _, ref args, _) => {
|
||||||
|
scope_map.insert(node_id, scope_stack.last().scope_metadata);
|
||||||
|
walk_expr(cx, receiver_exp, scope_stack, scope_map);
|
||||||
|
|
||||||
|
for &@ref arg_exp in args.iter() {
|
||||||
|
walk_expr(cx, arg_exp, scope_stack, scope_map);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ast::expr_match(@ref discriminant_exp, ref arms) => {
|
||||||
|
walk_expr(cx, discriminant_exp, scope_stack, scope_map);
|
||||||
|
|
||||||
|
// for each arm we have to first walk the pattern as these might introduce new
|
||||||
|
// artificial scopes. It should be sufficient to walk only one pattern per arm, as
|
||||||
|
// they all must contain the same binding names
|
||||||
|
|
||||||
|
for arm_ref in arms.iter() {
|
||||||
|
let arm_span = arm_ref.pats[0].span;
|
||||||
|
|
||||||
|
do with_new_scope(cx, arm_span, scope_stack, scope_map) |c, s, m| {
|
||||||
|
walk_pattern(c, arm_ref.pats[0], s, m);
|
||||||
|
|
||||||
|
for &@ref guard_exp in arm_ref.guard.iter() {
|
||||||
|
walk_expr(c, guard_exp, s, m)
|
||||||
|
}
|
||||||
|
|
||||||
|
walk_block(c, &arm_ref.body, s, m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ast::expr_struct(_, ref fields, ref base_exp) => {
|
||||||
|
for &ast::Field { expr: @ref exp, _ } in fields.iter() {
|
||||||
|
walk_expr(cx, exp, scope_stack, scope_map);
|
||||||
|
}
|
||||||
|
|
||||||
|
match *base_exp {
|
||||||
|
Some(@ref exp) => walk_expr(cx, exp, scope_stack, scope_map),
|
||||||
|
None => ()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ast::expr_inline_asm(ast::inline_asm { inputs: ref inputs,
|
||||||
|
outputs: ref outputs,
|
||||||
|
_ }) => {
|
||||||
|
// inputs, outputs: ~[(@str, @expr)]
|
||||||
|
for &(_, @ref exp) in inputs.iter() {
|
||||||
|
walk_expr(cx, exp, scope_stack, scope_map);
|
||||||
|
}
|
||||||
|
|
||||||
|
for &(_, @ref exp) in outputs.iter() {
|
||||||
|
walk_expr(cx, exp, scope_stack, scope_map);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -413,7 +413,7 @@ pub fn trans_into(bcx: @mut Block, expr: @ast::expr, dest: Dest) -> @mut Block {
|
|||||||
dest.to_str(bcx.ccx()));
|
dest.to_str(bcx.ccx()));
|
||||||
let _indenter = indenter();
|
let _indenter = indenter();
|
||||||
|
|
||||||
debuginfo::update_source_pos(bcx, expr.span);
|
debuginfo::update_source_pos(bcx.fcx, expr.id, expr.span);
|
||||||
|
|
||||||
let dest = {
|
let dest = {
|
||||||
if ty::type_is_nil(ty) || ty::type_is_bot(ty) {
|
if ty::type_is_nil(ty) || ty::type_is_bot(ty) {
|
||||||
@ -485,7 +485,7 @@ fn trans_to_datum_unadjusted(bcx: @mut Block, expr: @ast::expr) -> DatumBlock {
|
|||||||
debug!("trans_to_datum_unadjusted(expr=%s)", bcx.expr_to_str(expr));
|
debug!("trans_to_datum_unadjusted(expr=%s)", bcx.expr_to_str(expr));
|
||||||
let _indenter = indenter();
|
let _indenter = indenter();
|
||||||
|
|
||||||
debuginfo::update_source_pos(bcx, expr.span);
|
debuginfo::update_source_pos(bcx.fcx, expr.id, expr.span);
|
||||||
|
|
||||||
match ty::expr_kind(bcx.tcx(), bcx.ccx().maps.method_map, expr) {
|
match ty::expr_kind(bcx.tcx(), bcx.ccx().maps.method_map, expr) {
|
||||||
ty::LvalueExpr => {
|
ty::LvalueExpr => {
|
||||||
|
77
src/test/debug-info/lexical-scope-in-for-loop.rs
Normal file
77
src/test/debug-info/lexical-scope-in-for-loop.rs
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
// Copyright 2013 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.
|
||||||
|
|
||||||
|
// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249
|
||||||
|
|
||||||
|
// compile-flags:-Z extra-debug-info
|
||||||
|
// debugger:break zzz
|
||||||
|
// debugger:run
|
||||||
|
|
||||||
|
// FIRST ITERATION
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print x
|
||||||
|
// check:$1 = 1
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print x
|
||||||
|
// check:$2 = -1
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// SECOND ITERATION
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print x
|
||||||
|
// check:$3 = 2
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print x
|
||||||
|
// check:$4 = -2
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// THIRD ITERATION
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print x
|
||||||
|
// check:$5 = 3
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print x
|
||||||
|
// check:$6 = -3
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// AFTER LOOP
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print x
|
||||||
|
// check:$7 = 1000000
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
|
||||||
|
let range = [1, 2, 3];
|
||||||
|
|
||||||
|
let x = 1000000; // wan meeeljen doollaars!
|
||||||
|
|
||||||
|
for &x in range.iter() {
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
|
||||||
|
let x = -1 * x;
|
||||||
|
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
}
|
||||||
|
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn zzz() {()}
|
||||||
|
fn sentinel() {()}
|
128
src/test/debug-info/lexical-scope-in-if.rs
Normal file
128
src/test/debug-info/lexical-scope-in-if.rs
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
// Copyright 2013 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.
|
||||||
|
|
||||||
|
// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249
|
||||||
|
|
||||||
|
// compile-flags:-Z extra-debug-info
|
||||||
|
// debugger:break zzz
|
||||||
|
// debugger:run
|
||||||
|
|
||||||
|
// BEFORE if
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print x
|
||||||
|
// check:$1 = 999
|
||||||
|
// debugger:print y
|
||||||
|
// check:$2 = -1
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// AT BEGINNING of 'then' block
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print x
|
||||||
|
// check:$3 = 999
|
||||||
|
// debugger:print y
|
||||||
|
// check:$4 = -1
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// AFTER 1st redeclaration of 'x'
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print x
|
||||||
|
// check:$5 = 1001
|
||||||
|
// debugger:print y
|
||||||
|
// check:$6 = -1
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// AFTER 2st redeclaration of 'x'
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print x
|
||||||
|
// check:$7 = 1002
|
||||||
|
// debugger:print y
|
||||||
|
// check:$8 = 1003
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// AFTER 1st if expression
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print x
|
||||||
|
// check:$9 = 999
|
||||||
|
// debugger:print y
|
||||||
|
// check:$10 = -1
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// BEGINNING of else branch
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print x
|
||||||
|
// check:$11 = 999
|
||||||
|
// debugger:print y
|
||||||
|
// check:$12 = -1
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// BEGINNING of else branch
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print x
|
||||||
|
// check:$13 = 1004
|
||||||
|
// debugger:print y
|
||||||
|
// check:$14 = 1005
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// BEGINNING of else branch
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print x
|
||||||
|
// check:$15 = 999
|
||||||
|
// debugger:print y
|
||||||
|
// check:$16 = -1
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
use std::util;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
|
||||||
|
let x = 999;
|
||||||
|
let y = -1;
|
||||||
|
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
|
||||||
|
if x < 1000 {
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
|
||||||
|
let x = 1001;
|
||||||
|
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
|
||||||
|
let x = 1002;
|
||||||
|
let y = 1003;
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
} else {
|
||||||
|
util::unreachable();
|
||||||
|
}
|
||||||
|
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
|
||||||
|
if x > 1000 {
|
||||||
|
util::unreachable();
|
||||||
|
} else {
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
|
||||||
|
let x = 1004;
|
||||||
|
let y = 1005;
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
}
|
||||||
|
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn zzz() {()}
|
||||||
|
fn sentinel() {()}
|
148
src/test/debug-info/lexical-scope-in-match.rs
Normal file
148
src/test/debug-info/lexical-scope-in-match.rs
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
// Copyright 2013 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.
|
||||||
|
|
||||||
|
// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249
|
||||||
|
|
||||||
|
// compile-flags:-Z extra-debug-info
|
||||||
|
// debugger:break zzz
|
||||||
|
// debugger:run
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print shadowed
|
||||||
|
// check:$1 = 231
|
||||||
|
// debugger:print not_shadowed
|
||||||
|
// check:$2 = 232
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print shadowed
|
||||||
|
// check:$3 = 233
|
||||||
|
// debugger:print not_shadowed
|
||||||
|
// check:$4 = 232
|
||||||
|
// debugger:print local_to_arm
|
||||||
|
// check:$5 = 234
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print shadowed
|
||||||
|
// check:$6 = 236
|
||||||
|
// debugger:print not_shadowed
|
||||||
|
// check:$7 = 232
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print shadowed
|
||||||
|
// check:$8 = 237
|
||||||
|
// debugger:print not_shadowed
|
||||||
|
// check:$9 = 232
|
||||||
|
// debugger:print local_to_arm
|
||||||
|
// check:$10 = 238
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print shadowed
|
||||||
|
// check:$11 = 239
|
||||||
|
// debugger:print not_shadowed
|
||||||
|
// check:$12 = 232
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print shadowed
|
||||||
|
// check:$13 = 241
|
||||||
|
// debugger:print not_shadowed
|
||||||
|
// check:$14 = 232
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print shadowed
|
||||||
|
// check:$15 = 243
|
||||||
|
// debugger:print *local_to_arm
|
||||||
|
// check:$16 = 244
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print shadowed
|
||||||
|
// check:$17 = 231
|
||||||
|
// debugger:print not_shadowed
|
||||||
|
// check:$18 = 232
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
struct Struct {
|
||||||
|
x: int,
|
||||||
|
y: int
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
|
||||||
|
let shadowed = 231;
|
||||||
|
let not_shadowed = 232;
|
||||||
|
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
|
||||||
|
match (233, 234) {
|
||||||
|
(shadowed, local_to_arm) => {
|
||||||
|
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match (235, 236) {
|
||||||
|
// with literal
|
||||||
|
(235, shadowed) => {
|
||||||
|
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
match Struct { x: 237, y: 238 } {
|
||||||
|
Struct { x: shadowed, y: local_to_arm } => {
|
||||||
|
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match Struct { x: 239, y: 240 } {
|
||||||
|
// ignored field
|
||||||
|
Struct { x: shadowed, _ } => {
|
||||||
|
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match Struct { x: 241, y: 242 } {
|
||||||
|
// with literal
|
||||||
|
Struct { x: shadowed, y: 242 } => {
|
||||||
|
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
match (243, 244) {
|
||||||
|
(shadowed, ref local_to_arm) => {
|
||||||
|
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn zzz() {()}
|
||||||
|
fn sentinel() {()}
|
127
src/test/debug-info/lexical-scope-in-unconditional-loop.rs
Normal file
127
src/test/debug-info/lexical-scope-in-unconditional-loop.rs
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
// Copyright 2013 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.
|
||||||
|
|
||||||
|
// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249
|
||||||
|
|
||||||
|
// compile-flags:-Z extra-debug-info
|
||||||
|
// debugger:break zzz
|
||||||
|
// debugger:run
|
||||||
|
|
||||||
|
// FIRST ITERATION
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print x
|
||||||
|
// check:$1 = 0
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print x
|
||||||
|
// check:$2 = 1
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print x
|
||||||
|
// check:$3 = 101
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print x
|
||||||
|
// check:$4 = 101
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print x
|
||||||
|
// check:$5 = -987
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print x
|
||||||
|
// check:$6 = 101
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
|
||||||
|
// SECOND ITERATION
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print x
|
||||||
|
// check:$7 = 1
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print x
|
||||||
|
// check:$8 = 2
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print x
|
||||||
|
// check:$9 = 102
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print x
|
||||||
|
// check:$10 = 102
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print x
|
||||||
|
// check:$11 = -987
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print x
|
||||||
|
// check:$12 = 102
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print x
|
||||||
|
// check:$13 = 2
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
|
||||||
|
let mut x = 0;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
if x >= 2 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
|
||||||
|
x += 1;
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
|
||||||
|
// Shadow x
|
||||||
|
let x = x + 100;
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
|
||||||
|
// open scope within loop's top level scope
|
||||||
|
{
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
|
||||||
|
let x = -987;
|
||||||
|
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that we get the x before the inner scope again
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
}
|
||||||
|
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn zzz() {()}
|
||||||
|
fn sentinel() {()}
|
123
src/test/debug-info/lexical-scope-in-while.rs
Normal file
123
src/test/debug-info/lexical-scope-in-while.rs
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
// Copyright 2013 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.
|
||||||
|
|
||||||
|
// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249
|
||||||
|
|
||||||
|
// compile-flags:-Z extra-debug-info
|
||||||
|
// debugger:break zzz
|
||||||
|
// debugger:run
|
||||||
|
|
||||||
|
// FIRST ITERATION
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print x
|
||||||
|
// check:$1 = 0
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print x
|
||||||
|
// check:$2 = 1
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print x
|
||||||
|
// check:$3 = 101
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print x
|
||||||
|
// check:$4 = 101
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print x
|
||||||
|
// check:$5 = -987
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print x
|
||||||
|
// check:$6 = 101
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
|
||||||
|
// SECOND ITERATION
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print x
|
||||||
|
// check:$7 = 1
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print x
|
||||||
|
// check:$8 = 2
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print x
|
||||||
|
// check:$9 = 102
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print x
|
||||||
|
// check:$10 = 102
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print x
|
||||||
|
// check:$11 = -987
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print x
|
||||||
|
// check:$12 = 102
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print x
|
||||||
|
// check:$13 = 2
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
|
||||||
|
let mut x = 0;
|
||||||
|
|
||||||
|
while x < 2 {
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
|
||||||
|
x += 1;
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
|
||||||
|
// Shadow x
|
||||||
|
let x = x + 100;
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
|
||||||
|
// open scope within loop's top level scope
|
||||||
|
{
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
|
||||||
|
let x = -987;
|
||||||
|
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that we get the x before the inner scope again
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
}
|
||||||
|
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn zzz() {()}
|
||||||
|
fn sentinel() {()}
|
129
src/test/debug-info/lexical-scope-with-macro.rs
Normal file
129
src/test/debug-info/lexical-scope-with-macro.rs
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
// Copyright 2013 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.
|
||||||
|
|
||||||
|
// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249
|
||||||
|
|
||||||
|
// compile-flags:-Z extra-debug-info
|
||||||
|
// debugger:break zzz
|
||||||
|
// debugger:run
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print a
|
||||||
|
// check:$1 = 10
|
||||||
|
// debugger:print b
|
||||||
|
// check:$2 = 34
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print a
|
||||||
|
// check:$3 = 890242
|
||||||
|
// debugger:print b
|
||||||
|
// check:$4 = 34
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print a
|
||||||
|
// check:$5 = 10
|
||||||
|
// debugger:print b
|
||||||
|
// check:$6 = 34
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print a
|
||||||
|
// check:$7 = 102
|
||||||
|
// debugger:print b
|
||||||
|
// check:$8 = 34
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print a
|
||||||
|
// check:$9 = 110
|
||||||
|
// debugger:print b
|
||||||
|
// check:$10 = 34
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print a
|
||||||
|
// check:$11 = 10
|
||||||
|
// debugger:print b
|
||||||
|
// check:$12 = 34
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print a
|
||||||
|
// check:$13 = 10
|
||||||
|
// debugger:print b
|
||||||
|
// check:$14 = 34
|
||||||
|
// debugger:print c
|
||||||
|
// check:$15 = 400
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
macro_rules! trivial(
|
||||||
|
($e1:expr) => ($e1)
|
||||||
|
)
|
||||||
|
|
||||||
|
macro_rules! no_new_scope(
|
||||||
|
($e1:expr) => (($e1 + 2) - 1)
|
||||||
|
)
|
||||||
|
|
||||||
|
macro_rules! new_scope(
|
||||||
|
() => ({
|
||||||
|
let a = 890242;
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
macro_rules! shadow_within_macro(
|
||||||
|
($e1:expr) => ({
|
||||||
|
let a = $e1 + 2;
|
||||||
|
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
|
||||||
|
let a = $e1 + 10;
|
||||||
|
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
macro_rules! dup_expr(
|
||||||
|
($e1:expr) => (($e1) + ($e1))
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
|
||||||
|
let a = trivial!(10);
|
||||||
|
let b = no_new_scope!(33);
|
||||||
|
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
|
||||||
|
new_scope!();
|
||||||
|
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
|
||||||
|
shadow_within_macro!(100);
|
||||||
|
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
|
||||||
|
let c = dup_expr!(10 * 20);
|
||||||
|
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn zzz() {()}
|
||||||
|
fn sentinel() {()}
|
344
src/test/debug-info/lexical-scopes-in-block-expression.rs
Normal file
344
src/test/debug-info/lexical-scopes-in-block-expression.rs
Normal file
@ -0,0 +1,344 @@
|
|||||||
|
// Copyright 2013 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.
|
||||||
|
|
||||||
|
// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249
|
||||||
|
|
||||||
|
// compile-flags:-Z extra-debug-info
|
||||||
|
// debugger:break zzz
|
||||||
|
// debugger:run
|
||||||
|
|
||||||
|
// STRUCT EXPRESSION
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print val
|
||||||
|
// check:$1 = -1
|
||||||
|
// debugger:print ten
|
||||||
|
// check:$2 = 10
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print val
|
||||||
|
// check:$3 = 11
|
||||||
|
// debugger:print ten
|
||||||
|
// check:$4 = 10
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print val
|
||||||
|
// check:$5 = -1
|
||||||
|
// debugger:print ten
|
||||||
|
// check:$6 = 10
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// FUNCTION CALL
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print val
|
||||||
|
// check:$7 = -1
|
||||||
|
// debugger:print ten
|
||||||
|
// check:$8 = 10
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print val
|
||||||
|
// check:$9 = 12
|
||||||
|
// debugger:print ten
|
||||||
|
// check:$10 = 10
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print val
|
||||||
|
// check:$11 = -1
|
||||||
|
// debugger:print ten
|
||||||
|
// check:$12 = 10
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// TUPLE EXPRESSION
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print val
|
||||||
|
// check:$13 = -1
|
||||||
|
// debugger:print ten
|
||||||
|
// check:$14 = 10
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print val
|
||||||
|
// check:$15 = 13
|
||||||
|
// debugger:print ten
|
||||||
|
// check:$16 = 10
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print val
|
||||||
|
// check:$17 = -1
|
||||||
|
// debugger:print ten
|
||||||
|
// check:$18 = 10
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// VEC EXPRESSION
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print val
|
||||||
|
// check:$19 = -1
|
||||||
|
// debugger:print ten
|
||||||
|
// check:$20 = 10
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print val
|
||||||
|
// check:$21 = 14
|
||||||
|
// debugger:print ten
|
||||||
|
// check:$22 = 10
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print val
|
||||||
|
// check:$23 = -1
|
||||||
|
// debugger:print ten
|
||||||
|
// check:$24 = 10
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// REPEAT VEC EXPRESSION
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print val
|
||||||
|
// check:$25 = -1
|
||||||
|
// debugger:print ten
|
||||||
|
// check:$26 = 10
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print val
|
||||||
|
// check:$27 = 15
|
||||||
|
// debugger:print ten
|
||||||
|
// check:$28 = 10
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print val
|
||||||
|
// check:$29 = -1
|
||||||
|
// debugger:print ten
|
||||||
|
// check:$30 = 10
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// ASSIGNMENT EXPRESSION
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print val
|
||||||
|
// check:$31 = -1
|
||||||
|
// debugger:print ten
|
||||||
|
// check:$32 = 10
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print val
|
||||||
|
// check:$33 = 16
|
||||||
|
// debugger:print ten
|
||||||
|
// check:$34 = 10
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print val
|
||||||
|
// check:$35 = -1
|
||||||
|
// debugger:print ten
|
||||||
|
// check:$36 = 10
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
|
||||||
|
// ARITHMETIC EXPRESSION
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print val
|
||||||
|
// check:$37 = -1
|
||||||
|
// debugger:print ten
|
||||||
|
// check:$38 = 10
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print val
|
||||||
|
// check:$39 = 17
|
||||||
|
// debugger:print ten
|
||||||
|
// check:$40 = 10
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print val
|
||||||
|
// check:$41 = -1
|
||||||
|
// debugger:print ten
|
||||||
|
// check:$42 = 10
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// INDEX EXPRESSION
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print val
|
||||||
|
// check:$43 = -1
|
||||||
|
// debugger:print ten
|
||||||
|
// check:$44 = 10
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print val
|
||||||
|
// check:$45 = 18
|
||||||
|
// debugger:print ten
|
||||||
|
// check:$46 = 10
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print val
|
||||||
|
// check:$47 = -1
|
||||||
|
// debugger:print ten
|
||||||
|
// check:$48 = 10
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
struct Point {
|
||||||
|
x: int,
|
||||||
|
y: int
|
||||||
|
}
|
||||||
|
|
||||||
|
fn a_function(x: int) -> int {
|
||||||
|
x + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
|
||||||
|
let val = -1;
|
||||||
|
let ten = 10;
|
||||||
|
|
||||||
|
// surrounded by struct expression
|
||||||
|
let point = Point {
|
||||||
|
x: {
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
|
||||||
|
let val = ten + 1;
|
||||||
|
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
|
||||||
|
val
|
||||||
|
},
|
||||||
|
y: 10
|
||||||
|
};
|
||||||
|
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
|
||||||
|
// surrounded by function call
|
||||||
|
let _ = a_function({
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
|
||||||
|
let val = ten + 2;
|
||||||
|
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
|
||||||
|
val
|
||||||
|
});
|
||||||
|
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
|
||||||
|
|
||||||
|
// surrounded by tup
|
||||||
|
let _ = ({
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
|
||||||
|
let val = ten + 3;
|
||||||
|
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
|
||||||
|
val
|
||||||
|
}, 0);
|
||||||
|
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
|
||||||
|
// surrounded by vec
|
||||||
|
let _ = [{
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
|
||||||
|
let val = ten + 4;
|
||||||
|
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
|
||||||
|
val
|
||||||
|
}, 0, 0];
|
||||||
|
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
|
||||||
|
// surrounded by repeat vec
|
||||||
|
let _ = [{
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
|
||||||
|
let val = ten + 5;
|
||||||
|
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
|
||||||
|
val
|
||||||
|
}, ..10];
|
||||||
|
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
|
||||||
|
// assignment expression
|
||||||
|
let mut var = 0;
|
||||||
|
var = {
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
|
||||||
|
let val = ten + 6;
|
||||||
|
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
|
||||||
|
val
|
||||||
|
};
|
||||||
|
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
|
||||||
|
// arithmetic expression
|
||||||
|
var = 10 + -{
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
|
||||||
|
let val = ten + 7;
|
||||||
|
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
|
||||||
|
val
|
||||||
|
} * 5;
|
||||||
|
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
|
||||||
|
// index expression
|
||||||
|
let a_vector = [10, ..20];
|
||||||
|
let _ = a_vector[{
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
|
||||||
|
let val = ten + 8;
|
||||||
|
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
|
||||||
|
val
|
||||||
|
}];
|
||||||
|
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn zzz() {()}
|
||||||
|
fn sentinel() {()}
|
95
src/test/debug-info/name-shadowing-and-scope-nesting.rs
Normal file
95
src/test/debug-info/name-shadowing-and-scope-nesting.rs
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
// Copyright 2013 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.
|
||||||
|
|
||||||
|
// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249
|
||||||
|
|
||||||
|
// compile-flags:-Z extra-debug-info
|
||||||
|
// debugger:break zzz
|
||||||
|
// debugger:run
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print x
|
||||||
|
// check:$1 = false
|
||||||
|
// debugger:print y
|
||||||
|
// check:$2 = true
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print x
|
||||||
|
// check:$3 = 10
|
||||||
|
// debugger:print y
|
||||||
|
// check:$4 = true
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print x
|
||||||
|
// check:$5 = 10.5
|
||||||
|
// debugger:print y
|
||||||
|
// check:$6 = 20
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print x
|
||||||
|
// check:$7 = true
|
||||||
|
// debugger:print y
|
||||||
|
// check:$8 = 2220
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print x
|
||||||
|
// check:$9 = 203203.5
|
||||||
|
// debugger:print y
|
||||||
|
// check:$10 = 2220
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print x
|
||||||
|
// check:$11 = 10.5
|
||||||
|
// debugger:print y
|
||||||
|
// check:$12 = 20
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let x = false;
|
||||||
|
let y = true;
|
||||||
|
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
|
||||||
|
let x = 10;
|
||||||
|
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
|
||||||
|
let x = 10.5;
|
||||||
|
let y = 20;
|
||||||
|
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
|
||||||
|
{
|
||||||
|
let x = true;
|
||||||
|
let y = 2220;
|
||||||
|
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
|
||||||
|
let x = 203203.5;
|
||||||
|
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
}
|
||||||
|
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn zzz() {()}
|
||||||
|
fn sentinel() {()}
|
@ -8,42 +8,51 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
// xfail-test
|
// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249
|
||||||
|
|
||||||
// compile-flags:-Z extra-debug-info
|
// compile-flags:-Z extra-debug-info
|
||||||
// debugger:break zzz
|
// debugger:break zzz
|
||||||
// debugger:run
|
// debugger:run
|
||||||
|
|
||||||
// debugger:finish
|
// debugger:finish
|
||||||
// debugger:print x
|
// debugger:print x
|
||||||
// check:$1 = false
|
// check:$1 = false
|
||||||
// debugger:print y
|
// debugger:print y
|
||||||
// check:$2 = true
|
// check:$2 = true
|
||||||
|
|
||||||
// debugger:continue
|
// debugger:continue
|
||||||
|
|
||||||
// debugger:finish
|
// debugger:finish
|
||||||
// debugger:print x
|
// debugger:print x
|
||||||
// check:$3 = 10
|
// check:$3 = 10
|
||||||
|
// debugger:print y
|
||||||
|
// check:$4 = true
|
||||||
// debugger:continue
|
// debugger:continue
|
||||||
|
|
||||||
// debugger:finish
|
// debugger:finish
|
||||||
// debugger:print x
|
// debugger:print x
|
||||||
// check:$4 = false
|
// check:$5 = 10.5
|
||||||
// debugger:print y
|
// debugger:print y
|
||||||
// check:$5 = 11
|
// check:$6 = 20
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let x = false;
|
let x = false;
|
||||||
let y = true;
|
let y = true;
|
||||||
|
|
||||||
zzz();
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
|
||||||
{
|
let x = 10;
|
||||||
let x = 10;
|
|
||||||
zzz();
|
|
||||||
}
|
|
||||||
|
|
||||||
let y = 11;
|
|
||||||
zzz();
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
|
||||||
|
let x = 10.5;
|
||||||
|
let y = 20;
|
||||||
|
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn zzz() {()}
|
fn zzz() {()}
|
||||||
|
fn sentinel() {()}
|
87
src/test/debug-info/simple-lexical-scope.rs
Normal file
87
src/test/debug-info/simple-lexical-scope.rs
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
// Copyright 2013 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.
|
||||||
|
|
||||||
|
// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249
|
||||||
|
|
||||||
|
// compile-flags:-Z extra-debug-info
|
||||||
|
// debugger:break zzz
|
||||||
|
// debugger:run
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print x
|
||||||
|
// check:$1 = false
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print x
|
||||||
|
// check:$2 = false
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print x
|
||||||
|
// check:$3 = 10
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print x
|
||||||
|
// check:$4 = 10
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print x
|
||||||
|
// check:$5 = 10.5
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print x
|
||||||
|
// check:$6 = 10
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
// debugger:finish
|
||||||
|
// debugger:print x
|
||||||
|
// check:$7 = false
|
||||||
|
// debugger:continue
|
||||||
|
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let x = false;
|
||||||
|
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
|
||||||
|
{
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
|
||||||
|
let x = 10;
|
||||||
|
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
|
||||||
|
{
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
|
||||||
|
let x = 10.5;
|
||||||
|
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
}
|
||||||
|
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
}
|
||||||
|
|
||||||
|
zzz();
|
||||||
|
sentinel();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn zzz() {()}
|
||||||
|
fn sentinel() {()}
|
Loading…
Reference in New Issue
Block a user