mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-26 08:44:35 +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::tvec;
|
||||
use middle::trans::type_of;
|
||||
use middle::trans::debuginfo;
|
||||
use middle::ty;
|
||||
use util::common::indenter;
|
||||
use util::ppaux::{Repr, vec_map_to_str};
|
||||
@ -385,6 +386,7 @@ struct BindingInfo {
|
||||
llmatch: ValueRef,
|
||||
trmode: TransBindingMode,
|
||||
id: ast::NodeId,
|
||||
span: span,
|
||||
ty: ty::t,
|
||||
}
|
||||
|
||||
@ -1305,7 +1307,7 @@ fn insert_lllocals(bcx: @mut Block,
|
||||
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 {
|
||||
// By value bindings: use the stack slot that we
|
||||
// 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));
|
||||
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;
|
||||
}
|
||||
@ -1771,7 +1781,7 @@ fn create_bindings_map(bcx: @mut Block, pat: @ast::pat) -> BindingsMap {
|
||||
let ccx = bcx.ccx();
|
||||
let tcx = bcx.tcx();
|
||||
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 variable_ty = node_id_type(bcx, p_id);
|
||||
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 {
|
||||
llmatch: llmatch, trmode: trmode,
|
||||
id: p_id, ty: variable_ty
|
||||
llmatch: llmatch,
|
||||
trmode: trmode,
|
||||
id: p_id,
|
||||
span: span,
|
||||
ty: variable_ty
|
||||
});
|
||||
}
|
||||
return bindings_map;
|
||||
|
@ -1103,7 +1103,6 @@ pub fn trans_stmt(cx: @mut Block, s: &ast::stmt) -> @mut Block {
|
||||
}
|
||||
|
||||
let mut bcx = cx;
|
||||
debuginfo::update_source_pos(cx, s.span);
|
||||
|
||||
match s.node {
|
||||
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,
|
||||
span: sp,
|
||||
path: path,
|
||||
ccx: ccx
|
||||
ccx: ccx,
|
||||
debug_context: None,
|
||||
};
|
||||
fcx.llenv = unsafe {
|
||||
llvm::LLVMGetParam(llfndecl, fcx.env_arg_pos() as c_uint)
|
||||
@ -1933,7 +1933,7 @@ pub fn trans_fn(ccx: @mut CrateContext,
|
||||
attrs,
|
||||
output_type,
|
||||
|fcx| {
|
||||
if ccx.sess.opts.extra_debuginfo
|
||||
if ccx.sess.opts.debuginfo
|
||||
&& fcx_has_nonzero_span(fcx) {
|
||||
debuginfo::create_function_metadata(fcx);
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ use middle::trans::build;
|
||||
use middle::trans::datum;
|
||||
use middle::trans::glue;
|
||||
use middle::trans::write_guard;
|
||||
use middle::trans::debuginfo;
|
||||
use middle::ty::substs;
|
||||
use middle::ty;
|
||||
use middle::typeck;
|
||||
@ -226,7 +227,12 @@ pub struct FunctionContext {
|
||||
path: path,
|
||||
|
||||
// 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 {
|
||||
|
@ -19,7 +19,6 @@ use middle::trans::base::*;
|
||||
use middle::trans::build::*;
|
||||
use middle::trans::callee;
|
||||
use middle::trans::common::*;
|
||||
use middle::trans::debuginfo;
|
||||
use middle::trans::expr;
|
||||
use middle::trans::type_of::*;
|
||||
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 mut bcx = bcx;
|
||||
for s in b.stmts.iter() {
|
||||
debuginfo::update_source_pos(bcx, b.span);
|
||||
bcx = trans_stmt(bcx, *s);
|
||||
}
|
||||
match b.expr {
|
||||
Some(e) => {
|
||||
debuginfo::update_source_pos(bcx, e.span);
|
||||
bcx = expr::trans_into(bcx, e, dest);
|
||||
}
|
||||
None => {
|
||||
|
@ -99,9 +99,7 @@ pub struct DebugContext {
|
||||
priv created_files: HashMap<~str, DIFile>,
|
||||
priv created_functions: HashMap<ast::NodeId, DISubprogram>,
|
||||
priv created_blocks: HashMap<ast::NodeId, DILexicalBlock>,
|
||||
priv created_types: HashMap<uint, DIType>,
|
||||
priv last_function_context_id: ast::NodeId,
|
||||
priv argument_counter: uint,
|
||||
priv created_types: HashMap<uint, DIType>
|
||||
}
|
||||
|
||||
impl DebugContext {
|
||||
@ -118,8 +116,21 @@ impl DebugContext {
|
||||
created_files: HashMap::new(),
|
||||
created_functions: HashMap::new(),
|
||||
created_blocks: HashMap::new(),
|
||||
created_types: HashMap::new(),
|
||||
last_function_context_id: -1, // magic value :(
|
||||
created_types: HashMap::new()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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,
|
||||
};
|
||||
}
|
||||
@ -141,61 +152,24 @@ pub fn finalize(cx: @mut CrateContext) {
|
||||
pub fn create_local_var_metadata(bcx: @mut Block, local: &ast::Local) {
|
||||
let cx = bcx.ccx();
|
||||
let def_map = cx.tcx.def_map;
|
||||
let pattern = local.pat;
|
||||
|
||||
let scope = match bcx.parent {
|
||||
None => create_function_metadata(bcx.fcx),
|
||||
Some(_) => lexical_block_metadata(bcx)
|
||||
};
|
||||
do pat_util::pat_bindings(def_map, local.pat) |_, node_id, span, path_ref| {
|
||||
|
||||
let filename = span_start(cx, local.span).file.name;
|
||||
let file_metadata = file_metadata(cx, filename);
|
||||
let var_ident = ast_util::path_to_ident(path_ref);
|
||||
let var_type = node_id_type(bcx, node_id);
|
||||
|
||||
do pat_util::pat_bindings(def_map, pattern) |_, node_id, span, path_ref| {
|
||||
|
||||
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);
|
||||
}
|
||||
declare_local(bcx, var_ident, node_id, var_type, span);
|
||||
}
|
||||
}
|
||||
|
||||
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.
|
||||
///
|
||||
/// Adds the created metadata nodes directly to the crate's IR.
|
||||
@ -213,20 +187,6 @@ pub fn create_argument_metadata(bcx: @mut Block,
|
||||
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 file_metadata = file_metadata(cx, filename);
|
||||
let scope = create_function_metadata(fcx);
|
||||
@ -241,9 +201,9 @@ pub fn create_argument_metadata(bcx: @mut Block,
|
||||
debug!("create_argument_metadata: %s", name);
|
||||
|
||||
let argument_index = {
|
||||
let debug_context = dbg_cx(cx);
|
||||
let argument_index = debug_context.argument_counter;
|
||||
debug_context.argument_counter += 1;
|
||||
let counter = &mut fcx.debug_context.get_mut_ref().argument_counter;
|
||||
let argument_index = *counter;
|
||||
*counter += 1;
|
||||
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 {
|
||||
let instr = llvm::LLVMDIBuilderInsertDeclareAtEnd(
|
||||
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
|
||||
///
|
||||
/// Maps to a call to llvm::LLVMSetCurrentDebugLocation(...)
|
||||
pub fn update_source_pos(bcx: @mut Block, span: span) {
|
||||
if !bcx.sess().opts.debuginfo || (*span.lo == 0 && *span.hi == 0) {
|
||||
pub fn update_source_pos(fcx: &FunctionContext,
|
||||
node_id: ast::NodeId,
|
||||
span: span) {
|
||||
let cx: &mut CrateContext = fcx.ccx;
|
||||
|
||||
if !cx.sess.opts.debuginfo || (*span.lo == 0 && *span.hi == 0) {
|
||||
return;
|
||||
}
|
||||
debug!("update_source_pos: %s", bcx.sess().codemap.span_to_str(span));
|
||||
let loc = span_start(bcx.ccx(), span);
|
||||
set_debug_location(bcx.ccx(), lexical_block_metadata(bcx), loc.line, loc.col.to_uint())
|
||||
|
||||
debug!("update_source_pos: %s", cx.sess.codemap.span_to_str(span));
|
||||
|
||||
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.
|
||||
///
|
||||
/// Adds the created metadata nodes directly to the crate's IR.
|
||||
/// The return value should be ignored if called from outside of the debuginfo module.
|
||||
pub fn create_function_metadata(fcx: &FunctionContext) -> DISubprogram {
|
||||
pub fn create_function_metadata(fcx: &mut FunctionContext) -> DISubprogram {
|
||||
let cx = fcx.ccx;
|
||||
|
||||
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))
|
||||
};
|
||||
|
||||
match dbg_cx(cx).created_functions.find(&id) {
|
||||
Some(fn_metadata) => return *fn_metadata,
|
||||
match dbg_cx(cx).created_functions.find_copy(&id) {
|
||||
Some(fn_metadata) => return fn_metadata,
|
||||
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);
|
||||
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 {
|
||||
match dbg_cx(cx).created_files.find_equiv(&full_path) {
|
||||
Some(file_metadata) => return *file_metadata,
|
||||
@ -473,50 +510,26 @@ fn file_metadata(cx: &mut CrateContext, full_path: &str) -> DIFile {
|
||||
return file_metadata;
|
||||
}
|
||||
|
||||
/// Get or create the lexical block metadata node for the given LLVM basic block.
|
||||
fn lexical_block_metadata(bcx: @mut Block) -> DILexicalBlock {
|
||||
let cx = bcx.ccx();
|
||||
let mut bcx = bcx;
|
||||
/// Finds the scope metadata node for the given AST node.
|
||||
fn scope_metadata(fcx: &FunctionContext,
|
||||
node_id: ast::NodeId,
|
||||
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.
|
||||
while bcx.node_info.is_none() {
|
||||
match bcx.parent {
|
||||
Some(b) => bcx = b,
|
||||
None => cx.sess.bug("debuginfo: Could not find lexical block for LLVM basic block.")
|
||||
let scope_map = &fcx.debug_context.get_ref().scope_map;
|
||||
|
||||
match scope_map.find_copy(&node_id) {
|
||||
Some(scope_metadata) => scope_metadata,
|
||||
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 {
|
||||
@ -1206,7 +1219,7 @@ fn type_metadata(cx: &mut CrateContext,
|
||||
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) {
|
||||
return;
|
||||
}
|
||||
@ -1224,7 +1237,6 @@ fn set_debug_location(cx: @mut CrateContext, scope: DIScope, line: uint, col: ui
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//=-------------------------------------------------------------------------------------------------
|
||||
// Utility Functions
|
||||
//=-------------------------------------------------------------------------------------------------
|
||||
@ -1256,3 +1268,436 @@ fn dbg_cx<'a>(cx: &'a mut CrateContext) -> &'a mut DebugContext {
|
||||
fn DIB(cx: &CrateContext) -> DIBuilderRef {
|
||||
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()));
|
||||
let _indenter = indenter();
|
||||
|
||||
debuginfo::update_source_pos(bcx, expr.span);
|
||||
debuginfo::update_source_pos(bcx.fcx, expr.id, expr.span);
|
||||
|
||||
let dest = {
|
||||
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));
|
||||
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) {
|
||||
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
|
||||
// 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
|
||||
// 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:$4 = false
|
||||
// check:$5 = 10.5
|
||||
// debugger:print y
|
||||
// check:$5 = 11
|
||||
// check:$6 = 20
|
||||
// debugger:continue
|
||||
|
||||
fn main() {
|
||||
let x = false;
|
||||
let y = true;
|
||||
|
||||
zzz();
|
||||
sentinel();
|
||||
|
||||
{
|
||||
let x = 10;
|
||||
zzz();
|
||||
}
|
||||
let x = 10;
|
||||
|
||||
let y = 11;
|
||||
zzz();
|
||||
sentinel();
|
||||
|
||||
let x = 10.5;
|
||||
let y = 20;
|
||||
|
||||
zzz();
|
||||
sentinel();
|
||||
}
|
||||
|
||||
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