mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-27 09:14:20 +00:00
Implement debug printing for tcx interner sty's.
This commit is contained in:
parent
25fb12b8a5
commit
7cd6bf67a2
@ -779,6 +779,77 @@ bitflags! {
|
||||
}
|
||||
}
|
||||
|
||||
impl Copy for TypeFlags {}
|
||||
|
||||
macro_rules! sty_debug_print {
|
||||
($ctxt: expr, $($variant: ident),*) => {{
|
||||
// curious inner module to allow variant names to be used as
|
||||
// variable names.
|
||||
mod inner {
|
||||
use middle::ty;
|
||||
struct DebugStat {
|
||||
total: uint,
|
||||
region_infer: uint,
|
||||
ty_infer: uint,
|
||||
both_infer: uint,
|
||||
}
|
||||
|
||||
pub fn go(tcx: &ty::ctxt) {
|
||||
let mut total = DebugStat {
|
||||
total: 0,
|
||||
region_infer: 0, ty_infer: 0, both_infer: 0,
|
||||
};
|
||||
$(let mut $variant = total;)*
|
||||
|
||||
|
||||
for (_, t) in tcx.interner.borrow().iter() {
|
||||
let variant = match t.sty {
|
||||
ty::ty_bool | ty::ty_char | ty::ty_int(..) | ty::ty_uint(..) |
|
||||
ty::ty_float(..) | ty::ty_str => continue,
|
||||
ty::ty_err => /* unimportant */ continue,
|
||||
$(ty::$variant(..) => &mut $variant,)*
|
||||
};
|
||||
let region = t.flags.intersects(ty::HAS_RE_INFER);
|
||||
let ty = t.flags.intersects(ty::HAS_TY_INFER);
|
||||
|
||||
variant.total += 1;
|
||||
total.total += 1;
|
||||
if region { total.region_infer += 1; variant.region_infer += 1 }
|
||||
if ty { total.ty_infer += 1; variant.ty_infer += 1 }
|
||||
if region && ty { total.both_infer += 1; variant.both_infer += 1 }
|
||||
}
|
||||
println!("Ty interner total ty region both");
|
||||
$(println!(" {:18}: {uses:6} {usespc:4.1}%, \
|
||||
{ty:4.1}% {region:5.1}% {both:4.1}%",
|
||||
stringify!($variant),
|
||||
uses = $variant.total,
|
||||
usespc = $variant.total as f64 * 100.0 / total.total as f64,
|
||||
ty = $variant.ty_infer as f64 * 100.0 / total.total as f64,
|
||||
region = $variant.region_infer as f64 * 100.0 / total.total as f64,
|
||||
both = $variant.both_infer as f64 * 100.0 / total.total as f64);
|
||||
)*
|
||||
println!(" total {uses:6} \
|
||||
{ty:4.1}% {region:5.1}% {both:4.1}%",
|
||||
uses = total.total,
|
||||
ty = total.ty_infer as f64 * 100.0 / total.total as f64,
|
||||
region = total.region_infer as f64 * 100.0 / total.total as f64,
|
||||
both = total.both_infer as f64 * 100.0 / total.total as f64)
|
||||
}
|
||||
}
|
||||
|
||||
inner::go($ctxt)
|
||||
}}
|
||||
}
|
||||
|
||||
impl<'tcx> ctxt<'tcx> {
|
||||
pub fn print_debug_stats(&self) {
|
||||
sty_debug_print!(
|
||||
self,
|
||||
ty_enum, ty_uniq, ty_vec, ty_ptr, ty_rptr, ty_bare_fn, ty_closure, ty_trait,
|
||||
ty_struct, ty_unboxed_closure, ty_tup, ty_param, ty_open, ty_infer);
|
||||
}
|
||||
}
|
||||
|
||||
#[deriving(Show)]
|
||||
pub struct TyS<'tcx> {
|
||||
pub sty: sty<'tcx>,
|
||||
|
@ -82,9 +82,20 @@ pub fn compile_input(sess: Session,
|
||||
let type_arena = TypedArena::new();
|
||||
let analysis = phase_3_run_analysis_passes(sess, ast_map, &type_arena, id);
|
||||
phase_save_analysis(&analysis.ty_cx.sess, analysis.ty_cx.map.krate(), &analysis, outdir);
|
||||
|
||||
if log_enabled!(::log::INFO) {
|
||||
println!("Pre-trans")
|
||||
analysis.ty_cx.print_debug_stats();
|
||||
}
|
||||
|
||||
if stop_after_phase_3(&analysis.ty_cx.sess) { return; }
|
||||
let (tcx, trans) = phase_4_translate_to_llvm(analysis);
|
||||
|
||||
if log_enabled!(::log::INFO) {
|
||||
println!("Post-trans")
|
||||
tcx.print_debug_stats();
|
||||
}
|
||||
|
||||
// Discard interned strings as they are no longer required.
|
||||
token::get_ident_interner().clear();
|
||||
|
||||
|
@ -2125,14 +2125,20 @@ fn trans_enum_variant_or_tuple_like_struct<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx
|
||||
fn enum_variant_size_lint(ccx: &CrateContext, enum_def: &ast::EnumDef, sp: Span, id: ast::NodeId) {
|
||||
let mut sizes = Vec::new(); // does no allocation if no pushes, thankfully
|
||||
|
||||
let print_info = log_enabled!(::log::INFO);
|
||||
|
||||
let levels = ccx.tcx().node_lint_levels.borrow();
|
||||
let lint_id = lint::LintId::of(lint::builtin::VARIANT_SIZE_DIFFERENCES);
|
||||
let lvlsrc = match levels.get(&(id, lint_id)) {
|
||||
None | Some(&(lint::Allow, _)) => return,
|
||||
Some(&lvlsrc) => lvlsrc,
|
||||
};
|
||||
let lvlsrc = levels.get(&(id, lint_id));
|
||||
let is_allow = lvlsrc.map_or(true, |&(lvl, _)| lvl == lint::Allow);
|
||||
|
||||
let avar = adt::represent_type(ccx, ty::node_id_to_type(ccx.tcx(), id));
|
||||
if is_allow && !print_info {
|
||||
// we're not interested in anything here
|
||||
return
|
||||
}
|
||||
|
||||
let ty = ty::node_id_to_type(ccx.tcx(), id);
|
||||
let avar = adt::represent_type(ccx, ty);
|
||||
match *avar {
|
||||
adt::General(_, ref variants, _) => {
|
||||
for var in variants.iter() {
|
||||
@ -2158,13 +2164,29 @@ fn enum_variant_size_lint(ccx: &CrateContext, enum_def: &ast::EnumDef, sp: Span,
|
||||
}
|
||||
);
|
||||
|
||||
if print_info {
|
||||
let llty = type_of::sizing_type_of(ccx, ty);
|
||||
|
||||
let sess = &ccx.tcx().sess;
|
||||
sess.span_note(sp, &*format!("total size: {} bytes", llsize_of_real(ccx, llty)));
|
||||
match *avar {
|
||||
adt::General(..) => {
|
||||
for (i, var) in enum_def.variants.iter().enumerate() {
|
||||
ccx.tcx().sess.span_note(var.span,
|
||||
&*format!("variant data: {} bytes", sizes[i]));
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
// we only warn if the largest variant is at least thrice as large as
|
||||
// the second-largest.
|
||||
if largest > slargest * 3 && slargest > 0 {
|
||||
if !is_allow && largest > slargest * 3 && slargest > 0 {
|
||||
// Use lint::raw_emit_lint rather than sess.add_lint because the lint-printing
|
||||
// pass for the latter already ran.
|
||||
lint::raw_emit_lint(&ccx.tcx().sess, lint::builtin::VARIANT_SIZE_DIFFERENCES,
|
||||
lvlsrc, Some(sp),
|
||||
*lvlsrc.unwrap(), Some(sp),
|
||||
format!("enum variant is more than three times larger \
|
||||
({} bytes) than the next largest (ignoring padding)",
|
||||
largest)[]);
|
||||
@ -2332,8 +2354,12 @@ pub fn trans_item(ccx: &CrateContext, item: &ast::Item) {
|
||||
ast::ItemMod(ref m) => {
|
||||
trans_mod(&ccx.rotate(), m);
|
||||
}
|
||||
ast::ItemEnum(ref enum_definition, _) => {
|
||||
enum_variant_size_lint(ccx, enum_definition, item.span, item.id);
|
||||
ast::ItemEnum(ref enum_definition, ref gens) => {
|
||||
if gens.ty_params.is_empty() {
|
||||
// sizes only make sense for non-generic types
|
||||
|
||||
enum_variant_size_lint(ccx, enum_definition, item.span, item.id);
|
||||
}
|
||||
}
|
||||
ast::ItemConst(_, ref expr) => {
|
||||
// Recurse on the expression to catch items in blocks
|
||||
|
Loading…
Reference in New Issue
Block a user