Implement debug printing for tcx interner sty's.
This commit is contained in:
parent
25fb12b8a5
commit
7cd6bf67a2
3 changed files with 117 additions and 9 deletions
|
@ -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)]
|
#[deriving(Show)]
|
||||||
pub struct TyS<'tcx> {
|
pub struct TyS<'tcx> {
|
||||||
pub sty: sty<'tcx>,
|
pub sty: sty<'tcx>,
|
||||||
|
|
|
@ -82,9 +82,20 @@ pub fn compile_input(sess: Session,
|
||||||
let type_arena = TypedArena::new();
|
let type_arena = TypedArena::new();
|
||||||
let analysis = phase_3_run_analysis_passes(sess, ast_map, &type_arena, id);
|
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);
|
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; }
|
if stop_after_phase_3(&analysis.ty_cx.sess) { return; }
|
||||||
let (tcx, trans) = phase_4_translate_to_llvm(analysis);
|
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.
|
// Discard interned strings as they are no longer required.
|
||||||
token::get_ident_interner().clear();
|
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) {
|
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 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 levels = ccx.tcx().node_lint_levels.borrow();
|
||||||
let lint_id = lint::LintId::of(lint::builtin::VARIANT_SIZE_DIFFERENCES);
|
let lint_id = lint::LintId::of(lint::builtin::VARIANT_SIZE_DIFFERENCES);
|
||||||
let lvlsrc = match levels.get(&(id, lint_id)) {
|
let lvlsrc = levels.get(&(id, lint_id));
|
||||||
None | Some(&(lint::Allow, _)) => return,
|
let is_allow = lvlsrc.map_or(true, |&(lvl, _)| lvl == lint::Allow);
|
||||||
Some(&lvlsrc) => lvlsrc,
|
|
||||||
};
|
|
||||||
|
|
||||||
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 {
|
match *avar {
|
||||||
adt::General(_, ref variants, _) => {
|
adt::General(_, ref variants, _) => {
|
||||||
for var in variants.iter() {
|
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
|
// we only warn if the largest variant is at least thrice as large as
|
||||||
// the second-largest.
|
// 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
|
// Use lint::raw_emit_lint rather than sess.add_lint because the lint-printing
|
||||||
// pass for the latter already ran.
|
// pass for the latter already ran.
|
||||||
lint::raw_emit_lint(&ccx.tcx().sess, lint::builtin::VARIANT_SIZE_DIFFERENCES,
|
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 \
|
format!("enum variant is more than three times larger \
|
||||||
({} bytes) than the next largest (ignoring padding)",
|
({} bytes) than the next largest (ignoring padding)",
|
||||||
largest)[]);
|
largest)[]);
|
||||||
|
@ -2332,9 +2354,13 @@ pub fn trans_item(ccx: &CrateContext, item: &ast::Item) {
|
||||||
ast::ItemMod(ref m) => {
|
ast::ItemMod(ref m) => {
|
||||||
trans_mod(&ccx.rotate(), m);
|
trans_mod(&ccx.rotate(), m);
|
||||||
}
|
}
|
||||||
ast::ItemEnum(ref enum_definition, _) => {
|
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);
|
enum_variant_size_lint(ccx, enum_definition, item.span, item.id);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
ast::ItemConst(_, ref expr) => {
|
ast::ItemConst(_, ref expr) => {
|
||||||
// Recurse on the expression to catch items in blocks
|
// Recurse on the expression to catch items in blocks
|
||||||
let mut v = TransItemVisitor{ ccx: ccx };
|
let mut v = TransItemVisitor{ ccx: ccx };
|
||||||
|
|
Loading…
Reference in a new issue