From 024e86fad591b1057d5d36315860ede235721fd0 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 24 Apr 2015 16:08:11 +1200 Subject: [PATCH] debuginfo: extract types.rs --- src/librustc_trans/trans/debuginfo/mod.rs | 216 +----------------- src/librustc_trans/trans/debuginfo/types.rs | 230 ++++++++++++++++++++ 2 files changed, 233 insertions(+), 213 deletions(-) create mode 100644 src/librustc_trans/trans/debuginfo/types.rs diff --git a/src/librustc_trans/trans/debuginfo/mod.rs b/src/librustc_trans/trans/debuginfo/mod.rs index ea0bbfd73ae2..fc7a0475f48a 100644 --- a/src/librustc_trans/trans/debuginfo/mod.rs +++ b/src/librustc_trans/trans/debuginfo/mod.rs @@ -15,12 +15,14 @@ pub mod gdb; mod utils; mod create; mod namespace; +mod types; use self::utils::{debug_context, DIB, span_start, bytes_to_bits, size_and_align_of, assert_type_for_node_id, get_namespace_and_span_for_item, fn_should_be_ignored, contains_nodebug_attribute, create_scope_map}; use self::create::{declare_local, create_DIArray, is_node_local_to_unit}; -use self::namespace::{namespace_for_item, NamespaceTreeNode, crate_root_namespace}; +use self::namespace::{namespace_for_item, NamespaceTreeNode}; +use self::types::{compute_debuginfo_type_name, push_debuginfo_type_name}; use self::VariableAccess::*; use self::VariableKind::*; @@ -2893,215 +2895,3 @@ fn set_debug_location(cx: &CrateContext, debug_location: InternalDebugLocation) debug_context(cx).current_debug_location.set(debug_location); } - -//=----------------------------------------------------------------------------- -// Type Names for Debug Info -//=----------------------------------------------------------------------------- - -// Compute the name of the type as it should be stored in debuginfo. Does not do -// any caching, i.e. calling the function twice with the same type will also do -// the work twice. The `qualified` parameter only affects the first level of the -// type name, further levels (i.e. type parameters) are always fully qualified. -fn compute_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, - t: Ty<'tcx>, - qualified: bool) - -> String { - let mut result = String::with_capacity(64); - push_debuginfo_type_name(cx, t, qualified, &mut result); - result -} - -// Pushes the name of the type as it should be stored in debuginfo on the -// `output` String. See also compute_debuginfo_type_name(). -fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, - t: Ty<'tcx>, - qualified: bool, - output: &mut String) { - match t.sty { - ty::ty_bool => output.push_str("bool"), - ty::ty_char => output.push_str("char"), - ty::ty_str => output.push_str("str"), - ty::ty_int(ast::TyIs) => output.push_str("isize"), - ty::ty_int(ast::TyI8) => output.push_str("i8"), - ty::ty_int(ast::TyI16) => output.push_str("i16"), - ty::ty_int(ast::TyI32) => output.push_str("i32"), - ty::ty_int(ast::TyI64) => output.push_str("i64"), - ty::ty_uint(ast::TyUs) => output.push_str("usize"), - ty::ty_uint(ast::TyU8) => output.push_str("u8"), - ty::ty_uint(ast::TyU16) => output.push_str("u16"), - ty::ty_uint(ast::TyU32) => output.push_str("u32"), - ty::ty_uint(ast::TyU64) => output.push_str("u64"), - ty::ty_float(ast::TyF32) => output.push_str("f32"), - ty::ty_float(ast::TyF64) => output.push_str("f64"), - ty::ty_struct(def_id, substs) | - ty::ty_enum(def_id, substs) => { - push_item_name(cx, def_id, qualified, output); - push_type_params(cx, substs, output); - }, - ty::ty_tup(ref component_types) => { - output.push('('); - for &component_type in component_types { - push_debuginfo_type_name(cx, component_type, true, output); - output.push_str(", "); - } - if !component_types.is_empty() { - output.pop(); - output.pop(); - } - output.push(')'); - }, - ty::ty_uniq(inner_type) => { - output.push_str("Box<"); - push_debuginfo_type_name(cx, inner_type, true, output); - output.push('>'); - }, - ty::ty_ptr(ty::mt { ty: inner_type, mutbl } ) => { - output.push('*'); - match mutbl { - ast::MutImmutable => output.push_str("const "), - ast::MutMutable => output.push_str("mut "), - } - - push_debuginfo_type_name(cx, inner_type, true, output); - }, - ty::ty_rptr(_, ty::mt { ty: inner_type, mutbl }) => { - output.push('&'); - if mutbl == ast::MutMutable { - output.push_str("mut "); - } - - push_debuginfo_type_name(cx, inner_type, true, output); - }, - ty::ty_vec(inner_type, optional_length) => { - output.push('['); - push_debuginfo_type_name(cx, inner_type, true, output); - - match optional_length { - Some(len) => { - output.push_str(&format!("; {}", len)); - } - None => { /* nothing to do */ } - }; - - output.push(']'); - }, - ty::ty_trait(ref trait_data) => { - let principal = ty::erase_late_bound_regions(cx.tcx(), &trait_data.principal); - push_item_name(cx, principal.def_id, false, output); - push_type_params(cx, principal.substs, output); - }, - ty::ty_bare_fn(_, &ty::BareFnTy{ unsafety, abi, ref sig } ) => { - if unsafety == ast::Unsafety::Unsafe { - output.push_str("unsafe "); - } - - if abi != ::syntax::abi::Rust { - output.push_str("extern \""); - output.push_str(abi.name()); - output.push_str("\" "); - } - - output.push_str("fn("); - - let sig = ty::erase_late_bound_regions(cx.tcx(), sig); - if !sig.inputs.is_empty() { - for ¶meter_type in &sig.inputs { - push_debuginfo_type_name(cx, parameter_type, true, output); - output.push_str(", "); - } - output.pop(); - output.pop(); - } - - if sig.variadic { - if !sig.inputs.is_empty() { - output.push_str(", ..."); - } else { - output.push_str("..."); - } - } - - output.push(')'); - - match sig.output { - ty::FnConverging(result_type) if ty::type_is_nil(result_type) => {} - ty::FnConverging(result_type) => { - output.push_str(" -> "); - push_debuginfo_type_name(cx, result_type, true, output); - } - ty::FnDiverging => { - output.push_str(" -> !"); - } - } - }, - ty::ty_closure(..) => { - output.push_str("closure"); - } - ty::ty_err | - ty::ty_infer(_) | - ty::ty_projection(..) | - ty::ty_param(_) => { - cx.sess().bug(&format!("debuginfo: Trying to create type name for \ - unexpected type: {}", ppaux::ty_to_string(cx.tcx(), t))); - } - } - - fn push_item_name(cx: &CrateContext, - def_id: ast::DefId, - qualified: bool, - output: &mut String) { - ty::with_path(cx.tcx(), def_id, |path| { - if qualified { - if def_id.krate == ast::LOCAL_CRATE { - output.push_str(crate_root_namespace(cx)); - output.push_str("::"); - } - - let mut path_element_count = 0; - for path_element in path { - let name = token::get_name(path_element.name()); - output.push_str(&name); - output.push_str("::"); - path_element_count += 1; - } - - if path_element_count == 0 { - cx.sess().bug("debuginfo: Encountered empty item path!"); - } - - output.pop(); - output.pop(); - } else { - let name = token::get_name(path.last() - .expect("debuginfo: Empty item path?") - .name()); - output.push_str(&name); - } - }); - } - - // Pushes the type parameters in the given `Substs` to the output string. - // This ignores region parameters, since they can't reliably be - // reconstructed for items from non-local crates. For local crates, this - // would be possible but with inlining and LTO we have to use the least - // common denominator - otherwise we would run into conflicts. - fn push_type_params<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, - substs: &subst::Substs<'tcx>, - output: &mut String) { - if substs.types.is_empty() { - return; - } - - output.push('<'); - - for &type_parameter in substs.types.iter() { - push_debuginfo_type_name(cx, type_parameter, true, output); - output.push_str(", "); - } - - output.pop(); - output.pop(); - - output.push('>'); - } -} diff --git a/src/librustc_trans/trans/debuginfo/types.rs b/src/librustc_trans/trans/debuginfo/types.rs new file mode 100644 index 000000000000..586dd1526cd2 --- /dev/null +++ b/src/librustc_trans/trans/debuginfo/types.rs @@ -0,0 +1,230 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://!rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Type Names for Debug Info + +use super::namespace::crate_root_namespace; + +use trans::common::CrateContext; +use middle::subst::{self, Substs}; +use middle::ty::{self, Ty, ClosureTyper}; +use syntax::ast; +use syntax::parse::token; +use util::ppaux; + + +// Compute the name of the type as it should be stored in debuginfo. Does not do +// any caching, i.e. calling the function twice with the same type will also do +// the work twice. The `qualified` parameter only affects the first level of the +// type name, further levels (i.e. type parameters) are always fully qualified. +pub fn compute_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, + t: Ty<'tcx>, + qualified: bool) + -> String { + let mut result = String::with_capacity(64); + push_debuginfo_type_name(cx, t, qualified, &mut result); + result +} + +// Pushes the name of the type as it should be stored in debuginfo on the +// `output` String. See also compute_debuginfo_type_name(). +pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, + t: Ty<'tcx>, + qualified: bool, + output: &mut String) { + match t.sty { + ty::ty_bool => output.push_str("bool"), + ty::ty_char => output.push_str("char"), + ty::ty_str => output.push_str("str"), + ty::ty_int(ast::TyIs) => output.push_str("isize"), + ty::ty_int(ast::TyI8) => output.push_str("i8"), + ty::ty_int(ast::TyI16) => output.push_str("i16"), + ty::ty_int(ast::TyI32) => output.push_str("i32"), + ty::ty_int(ast::TyI64) => output.push_str("i64"), + ty::ty_uint(ast::TyUs) => output.push_str("usize"), + ty::ty_uint(ast::TyU8) => output.push_str("u8"), + ty::ty_uint(ast::TyU16) => output.push_str("u16"), + ty::ty_uint(ast::TyU32) => output.push_str("u32"), + ty::ty_uint(ast::TyU64) => output.push_str("u64"), + ty::ty_float(ast::TyF32) => output.push_str("f32"), + ty::ty_float(ast::TyF64) => output.push_str("f64"), + ty::ty_struct(def_id, substs) | + ty::ty_enum(def_id, substs) => { + push_item_name(cx, def_id, qualified, output); + push_type_params(cx, substs, output); + }, + ty::ty_tup(ref component_types) => { + output.push('('); + for &component_type in component_types { + push_debuginfo_type_name(cx, component_type, true, output); + output.push_str(", "); + } + if !component_types.is_empty() { + output.pop(); + output.pop(); + } + output.push(')'); + }, + ty::ty_uniq(inner_type) => { + output.push_str("Box<"); + push_debuginfo_type_name(cx, inner_type, true, output); + output.push('>'); + }, + ty::ty_ptr(ty::mt { ty: inner_type, mutbl } ) => { + output.push('*'); + match mutbl { + ast::MutImmutable => output.push_str("const "), + ast::MutMutable => output.push_str("mut "), + } + + push_debuginfo_type_name(cx, inner_type, true, output); + }, + ty::ty_rptr(_, ty::mt { ty: inner_type, mutbl }) => { + output.push('&'); + if mutbl == ast::MutMutable { + output.push_str("mut "); + } + + push_debuginfo_type_name(cx, inner_type, true, output); + }, + ty::ty_vec(inner_type, optional_length) => { + output.push('['); + push_debuginfo_type_name(cx, inner_type, true, output); + + match optional_length { + Some(len) => { + output.push_str(&format!("; {}", len)); + } + None => { /* nothing to do */ } + }; + + output.push(']'); + }, + ty::ty_trait(ref trait_data) => { + let principal = ty::erase_late_bound_regions(cx.tcx(), &trait_data.principal); + push_item_name(cx, principal.def_id, false, output); + push_type_params(cx, principal.substs, output); + }, + ty::ty_bare_fn(_, &ty::BareFnTy{ unsafety, abi, ref sig } ) => { + if unsafety == ast::Unsafety::Unsafe { + output.push_str("unsafe "); + } + + if abi != ::syntax::abi::Rust { + output.push_str("extern \""); + output.push_str(abi.name()); + output.push_str("\" "); + } + + output.push_str("fn("); + + let sig = ty::erase_late_bound_regions(cx.tcx(), sig); + if !sig.inputs.is_empty() { + for ¶meter_type in &sig.inputs { + push_debuginfo_type_name(cx, parameter_type, true, output); + output.push_str(", "); + } + output.pop(); + output.pop(); + } + + if sig.variadic { + if !sig.inputs.is_empty() { + output.push_str(", ..."); + } else { + output.push_str("..."); + } + } + + output.push(')'); + + match sig.output { + ty::FnConverging(result_type) if ty::type_is_nil(result_type) => {} + ty::FnConverging(result_type) => { + output.push_str(" -> "); + push_debuginfo_type_name(cx, result_type, true, output); + } + ty::FnDiverging => { + output.push_str(" -> !"); + } + } + }, + ty::ty_closure(..) => { + output.push_str("closure"); + } + ty::ty_err | + ty::ty_infer(_) | + ty::ty_projection(..) | + ty::ty_param(_) => { + cx.sess().bug(&format!("debuginfo: Trying to create type name for \ + unexpected type: {}", ppaux::ty_to_string(cx.tcx(), t))); + } + } + + fn push_item_name(cx: &CrateContext, + def_id: ast::DefId, + qualified: bool, + output: &mut String) { + ty::with_path(cx.tcx(), def_id, |path| { + if qualified { + if def_id.krate == ast::LOCAL_CRATE { + output.push_str(crate_root_namespace(cx)); + output.push_str("::"); + } + + let mut path_element_count = 0; + for path_element in path { + let name = token::get_name(path_element.name()); + output.push_str(&name); + output.push_str("::"); + path_element_count += 1; + } + + if path_element_count == 0 { + cx.sess().bug("debuginfo: Encountered empty item path!"); + } + + output.pop(); + output.pop(); + } else { + let name = token::get_name(path.last() + .expect("debuginfo: Empty item path?") + .name()); + output.push_str(&name); + } + }); + } + + // Pushes the type parameters in the given `Substs` to the output string. + // This ignores region parameters, since they can't reliably be + // reconstructed for items from non-local crates. For local crates, this + // would be possible but with inlining and LTO we have to use the least + // common denominator - otherwise we would run into conflicts. + fn push_type_params<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, + substs: &subst::Substs<'tcx>, + output: &mut String) { + if substs.types.is_empty() { + return; + } + + output.push('<'); + + for &type_parameter in substs.types.iter() { + push_debuginfo_type_name(cx, type_parameter, true, output); + output.push_str(", "); + } + + output.pop(); + output.pop(); + + output.push('>'); + } +} +