Make drop-glue translation collector-driven.

This commit is contained in:
Michael Woerister 2016-05-09 23:56:49 -04:00
parent 6c8c94b848
commit 87c1c87dd7
9 changed files with 178 additions and 150 deletions

View File

@ -229,6 +229,7 @@ impl ArgType {
///
/// I will do my best to describe this structure, but these
/// comments are reverse-engineered and may be inaccurate. -NDM
#[derive(Clone)]
pub struct FnType {
/// The LLVM types of each argument.
pub args: Vec<ArgType>,

View File

@ -304,6 +304,19 @@ impl ItemPathBuffer for SymbolPathBuffer {
}
}
pub fn exported_name_from_type_and_prefix<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
t: ty::Ty<'tcx>,
prefix: &str)
-> String {
let empty_def_path = DefPath {
data: vec![],
krate: cstore::LOCAL_CRATE,
};
let hash = get_symbol_hash(scx, &empty_def_path, t, &[]);
let path = [token::intern_and_get_ident(prefix)];
mangle(path.iter().cloned(), Some(&hash[..]))
}
/// Only symbols that are invisible outside their compilation unit should use a
/// name generated by this function.
pub fn internal_name_from_type_and_suffix<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,

View File

@ -2182,52 +2182,6 @@ pub fn llvm_linkage_by_name(name: &str) -> Option<Linkage> {
}
}
/// Set the appropriate linkage for an LLVM `ValueRef` (function or global).
/// If the `llval` is the direct translation of a specific Rust item, `id`
/// should be set to the `NodeId` of that item. (This mapping should be
/// 1-to-1, so monomorphizations and drop/visit glue should have `id` set to
/// `None`.)
pub fn update_linkage(ccx: &CrateContext,
llval: ValueRef,
id: Option<ast::NodeId>) {
if let Some(id) = id {
let item = ccx.tcx().map.get(id);
if let hir_map::NodeItem(i) = item {
if let Some(name) = attr::first_attr_value_str_by_name(&i.attrs, "linkage") {
if let Some(linkage) = llvm_linkage_by_name(&name) {
llvm::SetLinkage(llval, linkage);
} else {
ccx.sess().span_fatal(i.span, "invalid linkage specified");
}
return;
}
}
}
let (is_reachable, is_generic) = if let Some(id) = id {
(ccx.reachable().contains(&id), false)
} else {
(false, true)
};
// We need external linkage for items reachable from other translation units, this include
// other codegen units in case of parallel compilations.
if is_reachable || ccx.sess().opts.cg.codegen_units > 1 {
if is_generic {
// This only happens with multiple codegen units, in which case we need to use weak_odr
// linkage because other crates might expose the same symbol. We cannot use
// linkonce_odr here because the symbol might then get dropped before the other codegen
// units get to link it.
llvm::SetUniqueComdat(ccx.llmod(), llval);
llvm::SetLinkage(llval, llvm::WeakODRLinkage);
} else {
llvm::SetLinkage(llval, llvm::ExternalLinkage);
}
} else {
llvm::SetLinkage(llval, llvm::InternalLinkage);
}
}
pub fn set_link_section(ccx: &CrateContext,
llval: ValueRef,
attrs: &[ast::Attribute]) {
@ -2673,24 +2627,8 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
// ... and now that we have everything pre-defined, fill out those definitions.
for ccx in crate_context_list.iter() {
for (&trans_item, _) in &ccx.codegen_unit().items {
match trans_item {
TransItem::Static(node_id) => {
let item = ccx.tcx().map.expect_item(node_id);
if let hir::ItemStatic(_, m, ref expr) = item.node {
match consts::trans_static(&ccx, m, expr, item.id, &item.attrs) {
Ok(_) => { /* Cool, everything's alright. */ },
Err(err) => ccx.tcx().sess.span_fatal(expr.span, &err.description()),
};
} else {
span_bug!(item.span, "Mismatch between hir::Item type and TransItem type")
}
}
TransItem::Fn(instance) => {
trans_instance(&ccx, instance);
}
_ => { }
}
for (trans_item, _) in &ccx.codegen_unit().items {
trans_item.define(&ccx);
}
}
@ -2927,7 +2865,7 @@ fn collect_and_partition_translation_items<'a, 'tcx>(scx: &SharedCrateContext<'a
let mut item_keys: Vec<_> = items
.iter()
.map(|i| {
let mut output = i.to_string(scx);
let mut output = i.to_string(scx.tcx());
output.push_str(" @@");
let mut empty = Vec::new();
let mut cgus = item_to_cgus.get_mut(i).unwrap_or(&mut empty);

View File

@ -325,7 +325,7 @@ fn collect_items_rec<'a, 'tcx: 'a>(scx: &SharedCrateContext<'a, 'tcx>,
// We've been here already, no need to search again.
return;
}
debug!("BEGIN collect_items_rec({})", starting_point.to_string(scx));
debug!("BEGIN collect_items_rec({})", starting_point.to_string(scx.tcx()));
let mut neighbors = Vec::new();
let recursion_depth_reset;
@ -396,7 +396,7 @@ fn collect_items_rec<'a, 'tcx: 'a>(scx: &SharedCrateContext<'a, 'tcx>,
recursion_depths.insert(def_id, depth);
}
debug!("END collect_items_rec({})", starting_point.to_string(scx));
debug!("END collect_items_rec({})", starting_point.to_string(scx.tcx()));
}
fn record_inlining_canditates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
@ -637,7 +637,8 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
let operand_ty = monomorphize::apply_param_substs(tcx,
self.param_substs,
&mt.ty);
self.output.push(TransItem::DropGlue(DropGlueKind::Ty(operand_ty)));
let ty = glue::get_drop_glue_type(tcx, operand_ty);
self.output.push(TransItem::DropGlue(DropGlueKind::Ty(ty)));
} else {
bug!("Has the drop_in_place() intrinsic's signature changed?")
}
@ -1271,7 +1272,7 @@ pub fn print_collection_results<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>) {
let mut item_keys = FnvHashMap();
for (item, item_state) in trans_items.iter() {
let k = item.to_string(scx);
let k = item.to_string(scx.tcx());
if item_keys.contains_key(&k) {
let prev: (TransItem, TransItemState) = item_keys[&k];
@ -1299,7 +1300,7 @@ pub fn print_collection_results<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>) {
let mut generated = FnvHashSet();
for (item, item_state) in trans_items.iter() {
let item_key = item.to_string(scx);
let item_key = item.to_string(scx.tcx());
match *item_state {
TransItemState::PredictedAndGenerated => {

View File

@ -36,7 +36,7 @@ use rustc::ty::{self, Ty, TyCtxt};
use session::config::NoDebugInfo;
use session::Session;
use util::sha2::Sha256;
use util::nodemap::{NodeMap, NodeSet, DefIdMap, FnvHashMap, FnvHashSet};
use util::nodemap::{NodeMap, NodeSet, DefIdMap, FnvHashMap};
use std::ffi::{CStr, CString};
use std::cell::{Cell, RefCell};
@ -46,6 +46,7 @@ use std::rc::Rc;
use std::str;
use syntax::ast;
use syntax::parse::token::InternedString;
use abi::FnType;
pub struct Stats {
pub n_glues_created: Cell<usize>,
@ -80,8 +81,6 @@ pub struct SharedCrateContext<'a, 'tcx: 'a> {
mir_map: &'a MirMap<'tcx>,
mir_cache: RefCell<DefIdMap<Rc<mir::Mir<'tcx>>>>,
available_monomorphizations: RefCell<FnvHashSet<String>>,
available_drop_glues: RefCell<FnvHashMap<DropGlueKind<'tcx>, String>>,
use_dll_storage_attrs: bool,
translation_items: RefCell<FnvHashMap<TransItem<'tcx>, TransItemState>>,
@ -99,7 +98,7 @@ pub struct LocalCrateContext<'tcx> {
codegen_unit: CodegenUnit<'tcx>,
needs_unwind_cleanup_cache: RefCell<FnvHashMap<Ty<'tcx>, bool>>,
fn_pointer_shims: RefCell<FnvHashMap<Ty<'tcx>, ValueRef>>,
drop_glues: RefCell<FnvHashMap<DropGlueKind<'tcx>, ValueRef>>,
drop_glues: RefCell<FnvHashMap<DropGlueKind<'tcx>, (ValueRef, FnType)>>,
/// Track mapping of external ids to local items imported for inlining
external: RefCell<DefIdMap<Option<ast::NodeId>>>,
/// Backwards version of the `external` map (inlined items to where they
@ -413,8 +412,6 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> {
},
check_overflow: check_overflow,
check_drop_flag_for_sanity: check_drop_flag_for_sanity,
available_monomorphizations: RefCell::new(FnvHashSet()),
available_drop_glues: RefCell::new(FnvHashMap()),
use_dll_storage_attrs: use_dll_storage_attrs,
translation_items: RefCell::new(FnvHashMap()),
trait_cache: RefCell::new(DepTrackingMap::new(tcx.dep_graph.clone())),
@ -730,7 +727,8 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
&self.local().fn_pointer_shims
}
pub fn drop_glues<'a>(&'a self) -> &'a RefCell<FnvHashMap<DropGlueKind<'tcx>, ValueRef>> {
pub fn drop_glues<'a>(&'a self)
-> &'a RefCell<FnvHashMap<DropGlueKind<'tcx>, (ValueRef, FnType)>> {
&self.local().drop_glues
}
@ -816,14 +814,6 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
&self.shared.stats
}
pub fn available_monomorphizations<'a>(&'a self) -> &'a RefCell<FnvHashSet<String>> {
&self.shared.available_monomorphizations
}
pub fn available_drop_glues(&self) -> &RefCell<FnvHashMap<DropGlueKind<'tcx>, String>> {
&self.shared.available_drop_glues
}
pub fn int_type(&self) -> Type {
self.local().int_type
}

View File

@ -138,6 +138,20 @@ pub fn define_global(ccx: &CrateContext, name: &str, ty: Type) -> Option<ValueRe
}
}
/// Declare a Rust function with an intention to define it.
///
/// Use this function when you intend to define a function. This function will
/// return panic if the name already has a definition associated with it. This
/// can happen with #[no_mangle] or #[export_name], for example.
pub fn define_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
name: &str,
fn_type: ty::Ty<'tcx>) -> ValueRef {
if get_defined_value(ccx, name).is_some() {
ccx.sess().fatal(&format!("symbol `{}` already defined", name))
} else {
declare_fn(ccx, name, fn_type)
}
}
/// Declare a Rust function with an intention to define it.
///
@ -147,13 +161,9 @@ pub fn define_global(ccx: &CrateContext, name: &str, ty: Type) -> Option<ValueRe
pub fn define_internal_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
name: &str,
fn_type: ty::Ty<'tcx>) -> ValueRef {
if get_defined_value(ccx, name).is_some() {
ccx.sess().fatal(&format!("symbol `{}` already defined", name))
} else {
let llfn = declare_fn(ccx, name, fn_type);
llvm::SetLinkage(llfn, llvm::InternalLinkage);
llfn
}
let llfn = define_fn(ccx, name, fn_type);
llvm::SetLinkage(llfn, llvm::InternalLinkage);
llfn
}

View File

@ -14,15 +14,12 @@
use std;
use attributes;
use back::symbol_names;
use llvm;
use llvm::{ValueRef, get_param};
use middle::lang_items::ExchangeFreeFnLangItem;
use rustc::ty::subst::{Substs};
use rustc::traits;
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
use abi::{Abi, FnType};
use adt;
use adt::GetDtorType; // for tcx.dtor_type()
use base::*;
@ -33,7 +30,6 @@ use cleanup::CleanupMethods;
use collector;
use common::*;
use debuginfo::DebugLoc;
use declare;
use expr;
use machine::*;
use monomorphize;
@ -236,48 +232,21 @@ impl<'tcx> DropGlueKind<'tcx> {
fn get_drop_glue_core<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
g: DropGlueKind<'tcx>) -> ValueRef {
debug!("make drop glue for {:?}", g);
let g = g.map_ty(|t| get_drop_glue_type(ccx.tcx(), t));
debug!("drop glue type {:?}", g);
match ccx.drop_glues().borrow().get(&g) {
Some(&glue) => return glue,
_ => { }
Some(&(glue, _)) => glue,
None => { bug!("Could not find drop glue for {:?} -- {} -- {}",
g,
TransItem::DropGlue(g).to_raw_string(),
ccx.codegen_unit().name) }
}
let t = g.ty();
}
pub fn implement_drop_glue<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
g: DropGlueKind<'tcx>) {
let tcx = ccx.tcx();
let sig = ty::FnSig {
inputs: vec![tcx.mk_mut_ptr(tcx.types.i8)],
output: ty::FnOutput::FnConverging(tcx.mk_nil()),
variadic: false,
};
// Create a FnType for fn(*mut i8) and substitute the real type in
// later - that prevents FnType from splitting fat pointers up.
let mut fn_ty = FnType::new(ccx, Abi::Rust, &sig, &[]);
fn_ty.args[0].original_ty = type_of(ccx, t).ptr_to();
let llfnty = fn_ty.llvm_type(ccx);
// To avoid infinite recursion, don't `make_drop_glue` until after we've
// added the entry to the `drop_glues` cache.
if let Some(old_sym) = ccx.available_drop_glues().borrow().get(&g) {
let llfn = declare::declare_cfn(ccx, &old_sym, llfnty);
ccx.drop_glues().borrow_mut().insert(g, llfn);
return llfn;
};
let suffix = match g {
DropGlueKind::Ty(_) => "drop",
DropGlueKind::TyContents(_) => "drop_contents",
};
let fn_nm = symbol_names::internal_name_from_type_and_suffix(ccx, t, suffix);
assert!(declare::get_defined_value(ccx, &fn_nm).is_none());
let llfn = declare::declare_cfn(ccx, &fn_nm, llfnty);
attributes::set_frame_pointer_elimination(ccx, llfn);
ccx.available_drop_glues().borrow_mut().insert(g, fn_nm);
ccx.drop_glues().borrow_mut().insert(g, llfn);
let _s = StatRecorder::new(ccx, format!("drop {:?}", t));
assert_eq!(g.ty(), get_drop_glue_type(tcx, g.ty()));
let (llfn, fn_ty) = ccx.drop_glues().borrow().get(&g).unwrap().clone();
let (arena, fcx): (TypedArena<_>, FunctionContext);
arena = TypedArena::new();
@ -285,8 +254,6 @@ fn get_drop_glue_core<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
let bcx = fcx.init(false, None);
update_linkage(ccx, llfn, None);
ccx.stats().n_glues_created.set(ccx.stats().n_glues_created.get() + 1);
// All glue functions take values passed *by alias*; this is a
// requirement since in many contexts glue is invoked indirectly and
@ -298,10 +265,9 @@ fn get_drop_glue_core<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
let bcx = make_drop_glue(bcx, get_param(llfn, 0), g);
fcx.finish(bcx, DebugLoc::None);
llfn
}
fn trans_struct_drop_flag<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
t: Ty<'tcx>,
struct_data: ValueRef)

View File

@ -165,10 +165,14 @@ pub fn partition<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
trans_items,
reachable);
debug_dump(tcx, "INITIAL PARTITONING:", initial_partitioning.codegen_units.iter());
// If the partitioning should produce a fixed count of codegen units, merge
// until that count is reached.
if let PartitioningStrategy::FixedUnitCount(count) = strategy {
merge_codegen_units(&mut initial_partitioning, count, &tcx.crate_name[..]);
debug_dump(tcx, "POST MERGING:", initial_partitioning.codegen_units.iter());
}
// In the next step, we use the inlining map to determine which addtional
@ -177,6 +181,9 @@ pub fn partition<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
// local functions the definition of which is marked with #[inline].
let post_inlining = place_inlined_translation_items(initial_partitioning,
inlining_map);
debug_dump(tcx, "POST INLINING:", post_inlining.0.iter());
post_inlining.0
}
@ -484,3 +491,23 @@ fn numbered_codegen_unit_name(crate_name: &str, index: usize) -> InternedString
NUMBERED_CODEGEN_UNIT_MARKER,
index)[..])
}
fn debug_dump<'a, 'b, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
label: &str,
cgus: I)
where I: Iterator<Item=&'b CodegenUnit<'tcx>>,
'tcx: 'a + 'b
{
if cfg!(debug_assertions) {
debug!("{}", label);
for cgu in cgus {
debug!("CodegenUnit {}:", cgu.name);
for (trans_item, linkage) in &cgu.items {
debug!(" - {} [{:?}]", trans_item.to_string(tcx), linkage);
}
debug!("");
}
}
}

View File

@ -16,7 +16,8 @@
use attributes;
use base;
use context::{SharedCrateContext, CrateContext};
use consts;
use context::CrateContext;
use declare;
use glue::DropGlueKind;
use llvm;
@ -32,7 +33,9 @@ use syntax::ast::{self, NodeId};
use syntax::{attr,errors};
use syntax::parse::token;
use type_of;
use glue;
use abi::{Abi, FnType};
use back::symbol_names;
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub enum TransItem<'tcx> {
@ -64,9 +67,47 @@ impl<'tcx> Hash for TransItem<'tcx> {
impl<'a, 'tcx> TransItem<'tcx> {
pub fn define(&self, ccx: &CrateContext<'a, 'tcx>) {
debug!("BEGIN IMPLEMENTING '{} ({})' in cgu {}",
self.to_string(ccx.tcx()),
self.to_raw_string(),
ccx.codegen_unit().name);
match *self {
TransItem::Static(node_id) => {
let item = ccx.tcx().map.expect_item(node_id);
if let hir::ItemStatic(_, m, ref expr) = item.node {
match consts::trans_static(&ccx, m, expr, item.id, &item.attrs) {
Ok(_) => { /* Cool, everything's alright. */ },
Err(err) => ccx.tcx().sess.span_fatal(expr.span, &err.description()),
};
} else {
span_bug!(item.span, "Mismatch between hir::Item type and TransItem type")
}
}
TransItem::Fn(instance) => {
base::trans_instance(&ccx, instance);
}
TransItem::DropGlue(dg) => {
glue::implement_drop_glue(&ccx, dg);
}
}
debug!("END IMPLEMENTING '{} ({})' in cgu {}",
self.to_string(ccx.tcx()),
self.to_raw_string(),
ccx.codegen_unit().name);
}
pub fn predefine(&self,
ccx: &CrateContext<'a, 'tcx>,
linkage: llvm::Linkage) {
debug!("BEGIN PREDEFINING '{} ({})' in cgu {}",
self.to_string(ccx.tcx()),
self.to_raw_string(),
ccx.codegen_unit().name);
match *self {
TransItem::Static(node_id) => {
TransItem::predefine_static(ccx, node_id, linkage);
@ -74,10 +115,15 @@ impl<'a, 'tcx> TransItem<'tcx> {
TransItem::Fn(instance) => {
TransItem::predefine_fn(ccx, instance, linkage);
}
_ => {
// Not yet implemented
TransItem::DropGlue(dg) => {
TransItem::predefine_drop_glue(ccx, dg, linkage);
}
}
debug!("END PREDEFINING '{} ({})' in cgu {}",
self.to_string(ccx.tcx()),
self.to_raw_string(),
ccx.codegen_unit().name);
}
fn predefine_static(ccx: &CrateContext<'a, 'tcx>,
@ -93,7 +139,7 @@ impl<'a, 'tcx> TransItem<'tcx> {
}) => {
let instance = Instance::mono(ccx.shared(), def_id);
let sym = instance.symbol_name(ccx.shared());
debug!("making {}", sym);
debug!("symbol {}", sym);
let g = declare::define_global(ccx, &sym, llty).unwrap_or_else(|| {
ccx.sess().span_fatal(span,
@ -110,8 +156,6 @@ impl<'a, 'tcx> TransItem<'tcx> {
fn predefine_fn(ccx: &CrateContext<'a, 'tcx>,
instance: Instance<'tcx>,
linkage: llvm::Linkage) {
let unit = ccx.codegen_unit();
debug!("predefine_fn[cg={}](instance={:?})", &unit.name[..], instance);
assert!(!instance.substs.types.needs_infer() &&
!instance.substs.types.has_param_types());
@ -143,10 +187,11 @@ impl<'a, 'tcx> TransItem<'tcx> {
ref attrs, node: hir::ImplItemKind::Method(..), ..
}) => {
let symbol = instance.symbol_name(ccx.shared());
let lldecl = declare::declare_fn(ccx, &symbol, mono_ty);
debug!("symbol {}", symbol);
attributes::from_fn_attrs(ccx, attrs, lldecl);
let lldecl = declare::declare_fn(ccx, &symbol, mono_ty);
llvm::SetLinkage(lldecl, linkage);
attributes::from_fn_attrs(ccx, attrs, lldecl);
base::set_link_section(ccx, lldecl, attrs);
ccx.instances().borrow_mut().insert(instance, lldecl);
@ -156,6 +201,39 @@ impl<'a, 'tcx> TransItem<'tcx> {
}
fn predefine_drop_glue(ccx: &CrateContext<'a, 'tcx>,
dg: glue::DropGlueKind<'tcx>,
linkage: llvm::Linkage) {
let tcx = ccx.tcx();
assert_eq!(dg.ty(), glue::get_drop_glue_type(tcx, dg.ty()));
let t = dg.ty();
let sig = ty::FnSig {
inputs: vec![tcx.mk_mut_ptr(tcx.types.i8)],
output: ty::FnOutput::FnConverging(tcx.mk_nil()),
variadic: false,
};
// Create a FnType for fn(*mut i8) and substitute the real type in
// later - that prevents FnType from splitting fat pointers up.
let mut fn_ty = FnType::new(ccx, Abi::Rust, &sig, &[]);
fn_ty.args[0].original_ty = type_of::type_of(ccx, t).ptr_to();
let llfnty = fn_ty.llvm_type(ccx);
let prefix = match dg {
DropGlueKind::Ty(_) => "drop",
DropGlueKind::TyContents(_) => "drop_contents",
};
let symbol =
symbol_names::exported_name_from_type_and_prefix(ccx.shared(), t, prefix);
debug!(" symbol: {}", symbol);
assert!(declare::get_defined_value(ccx, &symbol).is_none());
let llfn = declare::declare_cfn(ccx, &symbol, llfnty);
attributes::set_frame_pointer_elimination(ccx, llfn);
llvm::SetLinkage(llfn, linkage);
ccx.drop_glues().borrow_mut().insert(dg, (llfn, fn_ty));
}
pub fn requests_inline(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> bool {
match *self {
@ -216,8 +294,7 @@ impl<'a, 'tcx> TransItem<'tcx> {
}
}
pub fn to_string(&self, scx: &SharedCrateContext<'a, 'tcx>) -> String {
let tcx = scx.tcx();
pub fn to_string(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> String {
let hir_map = &tcx.map;
return match *self {
@ -235,7 +312,8 @@ impl<'a, 'tcx> TransItem<'tcx> {
},
TransItem::Static(node_id) => {
let def_id = hir_map.local_def_id(node_id);
let instance = Instance::mono(scx, def_id);
let instance = Instance::new(def_id,
tcx.mk_substs(subst::Substs::empty()));
to_string_internal(tcx, "static ", instance)
},
};
@ -254,7 +332,11 @@ impl<'a, 'tcx> TransItem<'tcx> {
pub fn to_raw_string(&self) -> String {
match *self {
TransItem::DropGlue(dg) => {
format!("DropGlue({})", dg.ty() as *const _ as usize)
let prefix = match dg {
DropGlueKind::Ty(_) => "Ty",
DropGlueKind::TyContents(_) => "TyContents",
};
format!("DropGlue({}: {})", prefix, dg.ty() as *const _ as usize)
}
TransItem::Fn(instance) => {
format!("Fn({:?}, {})",