Skip to content

Commit 4595f03

Browse files
Make drop-glue translation collector-driven.
1 parent e5d744e commit 4595f03

File tree

11 files changed

+190
-149
lines changed

11 files changed

+190
-149
lines changed

src/librustc_trans/abi.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@ impl ArgType {
191191
///
192192
/// I will do my best to describe this structure, but these
193193
/// comments are reverse-engineered and may be inaccurate. -NDM
194+
#[derive(Clone)]
194195
pub struct FnType {
195196
/// The LLVM types of each argument.
196197
pub args: Vec<ArgType>,

src/librustc_trans/back/symbol_names.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,19 @@ impl ItemPathBuffer for SymbolPathBuffer {
304304
}
305305
}
306306

307+
pub fn exported_name_from_type_and_prefix<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
308+
t: ty::Ty<'tcx>,
309+
prefix: &str)
310+
-> String {
311+
let empty_def_path = DefPath {
312+
data: vec![],
313+
krate: cstore::LOCAL_CRATE,
314+
};
315+
let hash = get_symbol_hash(scx, &empty_def_path, t, &[]);
316+
let path = [token::intern_and_get_ident(prefix)];
317+
mangle(path.iter().cloned(), Some(&hash[..]))
318+
}
319+
307320
/// Only symbols that are invisible outside their compilation unit should use a
308321
/// name generated by this function.
309322
pub fn internal_name_from_type_and_suffix<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,

src/librustc_trans/base.rs

Lines changed: 3 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -2189,52 +2189,6 @@ pub fn llvm_linkage_by_name(name: &str) -> Option<Linkage> {
21892189
}
21902190
}
21912191

2192-
/// Set the appropriate linkage for an LLVM `ValueRef` (function or global).
2193-
/// If the `llval` is the direct translation of a specific Rust item, `id`
2194-
/// should be set to the `NodeId` of that item. (This mapping should be
2195-
/// 1-to-1, so monomorphizations and drop/visit glue should have `id` set to
2196-
/// `None`.)
2197-
pub fn update_linkage(ccx: &CrateContext,
2198-
llval: ValueRef,
2199-
id: Option<ast::NodeId>) {
2200-
if let Some(id) = id {
2201-
let item = ccx.tcx().map.get(id);
2202-
if let hir_map::NodeItem(i) = item {
2203-
if let Some(name) = attr::first_attr_value_str_by_name(&i.attrs, "linkage") {
2204-
if let Some(linkage) = llvm_linkage_by_name(&name) {
2205-
llvm::SetLinkage(llval, linkage);
2206-
} else {
2207-
ccx.sess().span_fatal(i.span, "invalid linkage specified");
2208-
}
2209-
return;
2210-
}
2211-
}
2212-
}
2213-
2214-
let (is_reachable, is_generic) = if let Some(id) = id {
2215-
(ccx.reachable().contains(&id), false)
2216-
} else {
2217-
(false, true)
2218-
};
2219-
2220-
// We need external linkage for items reachable from other translation units, this include
2221-
// other codegen units in case of parallel compilations.
2222-
if is_reachable || ccx.sess().opts.cg.codegen_units > 1 {
2223-
if is_generic {
2224-
// This only happens with multiple codegen units, in which case we need to use weak_odr
2225-
// linkage because other crates might expose the same symbol. We cannot use
2226-
// linkonce_odr here because the symbol might then get dropped before the other codegen
2227-
// units get to link it.
2228-
llvm::SetUniqueComdat(ccx.llmod(), llval);
2229-
llvm::SetLinkage(llval, llvm::WeakODRLinkage);
2230-
} else {
2231-
llvm::SetLinkage(llval, llvm::ExternalLinkage);
2232-
}
2233-
} else {
2234-
llvm::SetLinkage(llval, llvm::InternalLinkage);
2235-
}
2236-
}
2237-
22382192
pub fn set_link_section(ccx: &CrateContext,
22392193
llval: ValueRef,
22402194
attrs: &[ast::Attribute]) {
@@ -2680,24 +2634,8 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
26802634

26812635
// ... and now that we have everything pre-defined, fill out those definitions.
26822636
for ccx in crate_context_list.iter() {
2683-
for (&trans_item, _) in &ccx.codegen_unit().items {
2684-
match trans_item {
2685-
TransItem::Static(node_id) => {
2686-
let item = ccx.tcx().map.expect_item(node_id);
2687-
if let hir::ItemStatic(_, m, ref expr) = item.node {
2688-
match consts::trans_static(&ccx, m, expr, item.id, &item.attrs) {
2689-
Ok(_) => { /* Cool, everything's alright. */ },
2690-
Err(err) => ccx.tcx().sess.span_fatal(expr.span, &err.description()),
2691-
};
2692-
} else {
2693-
span_bug!(item.span, "Mismatch between hir::Item type and TransItem type")
2694-
}
2695-
}
2696-
TransItem::Fn(instance) => {
2697-
trans_instance(&ccx, instance);
2698-
}
2699-
_ => { }
2700-
}
2637+
for (trans_item, _) in &ccx.codegen_unit().items {
2638+
trans_item.define(&ccx);
27012639
}
27022640
}
27032641

@@ -2934,7 +2872,7 @@ fn collect_and_partition_translation_items<'a, 'tcx>(scx: &SharedCrateContext<'a
29342872
let mut item_keys: Vec<_> = items
29352873
.iter()
29362874
.map(|i| {
2937-
let mut output = i.to_string(scx);
2875+
let mut output = i.to_string(scx.tcx());
29382876
output.push_str(" @@");
29392877
let mut empty = Vec::new();
29402878
let mut cgus = item_to_cgus.get_mut(i).unwrap_or(&mut empty);

src/librustc_trans/collector.rs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,7 @@ fn collect_items_rec<'a, 'tcx: 'a>(scx: &SharedCrateContext<'a, 'tcx>,
325325
// We've been here already, no need to search again.
326326
return;
327327
}
328-
debug!("BEGIN collect_items_rec({})", starting_point.to_string(scx));
328+
debug!("BEGIN collect_items_rec({})", starting_point.to_string(scx.tcx()));
329329

330330
let mut neighbors = Vec::new();
331331
let recursion_depth_reset;
@@ -396,7 +396,7 @@ fn collect_items_rec<'a, 'tcx: 'a>(scx: &SharedCrateContext<'a, 'tcx>,
396396
recursion_depths.insert(def_id, depth);
397397
}
398398

399-
debug!("END collect_items_rec({})", starting_point.to_string(scx));
399+
debug!("END collect_items_rec({})", starting_point.to_string(scx.tcx()));
400400
}
401401

402402
fn record_inlining_canditates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
@@ -637,7 +637,8 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
637637
let operand_ty = monomorphize::apply_param_substs(tcx,
638638
self.param_substs,
639639
&mt.ty);
640-
self.output.push(TransItem::DropGlue(DropGlueKind::Ty(operand_ty)));
640+
let ty = glue::get_drop_glue_type(tcx, operand_ty);
641+
self.output.push(TransItem::DropGlue(DropGlueKind::Ty(ty)));
641642
} else {
642643
bug!("Has the drop_in_place() intrinsic's signature changed?")
643644
}
@@ -1052,6 +1053,14 @@ fn create_trans_items_for_vtable_methods<'a, 'tcx>(scx: &SharedCrateContext<'a,
10521053
.collect::<Vec<_>>();
10531054

10541055
output.extend(items.into_iter());
1056+
1057+
let destructor = {
1058+
let dg_type = glue::get_drop_glue_type(scx.tcx(),
1059+
trait_ref.self_ty());
1060+
TransItem::DropGlue(DropGlueKind::Ty(dg_type))
1061+
};
1062+
1063+
output.push(destructor);
10551064
}
10561065
_ => { /* */ }
10571066
}
@@ -1246,7 +1255,7 @@ pub enum TransItemState {
12461255
}
12471256

12481257
pub fn collecting_debug_information(scx: &SharedCrateContext) -> bool {
1249-
return scx.sess().opts.cg.debug_assertions == Some(true) &&
1258+
return cfg!(debug_assertions) &&
12501259
scx.sess().opts.debugging_opts.print_trans_items.is_some();
12511260
}
12521261

@@ -1270,7 +1279,7 @@ pub fn print_collection_results<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>) {
12701279
let mut item_keys = FnvHashMap();
12711280

12721281
for (item, item_state) in trans_items.iter() {
1273-
let k = item.to_string(scx);
1282+
let k = item.to_string(scx.tcx());
12741283

12751284
if item_keys.contains_key(&k) {
12761285
let prev: (TransItem, TransItemState) = item_keys[&k];
@@ -1298,7 +1307,7 @@ pub fn print_collection_results<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>) {
12981307
let mut generated = FnvHashSet();
12991308

13001309
for (item, item_state) in trans_items.iter() {
1301-
let item_key = item.to_string(scx);
1310+
let item_key = item.to_string(scx.tcx());
13021311

13031312
match *item_state {
13041313
TransItemState::PredictedAndGenerated => {

src/librustc_trans/context.rs

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ use rustc::ty::{self, Ty, TyCtxt};
3636
use session::config::NoDebugInfo;
3737
use session::Session;
3838
use util::sha2::Sha256;
39-
use util::nodemap::{NodeMap, NodeSet, DefIdMap, FnvHashMap, FnvHashSet};
39+
use util::nodemap::{NodeMap, NodeSet, DefIdMap, FnvHashMap};
4040

4141
use std::ffi::{CStr, CString};
4242
use std::cell::{Cell, RefCell};
@@ -46,6 +46,7 @@ use std::rc::Rc;
4646
use std::str;
4747
use syntax::ast;
4848
use syntax::parse::token::InternedString;
49+
use abi::FnType;
4950

5051
pub struct Stats {
5152
pub n_glues_created: Cell<usize>,
@@ -80,8 +81,6 @@ pub struct SharedCrateContext<'a, 'tcx: 'a> {
8081
mir_map: &'a MirMap<'tcx>,
8182
mir_cache: RefCell<DefIdMap<Rc<mir::Mir<'tcx>>>>,
8283

83-
available_monomorphizations: RefCell<FnvHashSet<String>>,
84-
available_drop_glues: RefCell<FnvHashMap<DropGlueKind<'tcx>, String>>,
8584
use_dll_storage_attrs: bool,
8685

8786
translation_items: RefCell<FnvHashMap<TransItem<'tcx>, TransItemState>>,
@@ -99,7 +98,7 @@ pub struct LocalCrateContext<'tcx> {
9998
codegen_unit: CodegenUnit<'tcx>,
10099
needs_unwind_cleanup_cache: RefCell<FnvHashMap<Ty<'tcx>, bool>>,
101100
fn_pointer_shims: RefCell<FnvHashMap<Ty<'tcx>, ValueRef>>,
102-
drop_glues: RefCell<FnvHashMap<DropGlueKind<'tcx>, ValueRef>>,
101+
drop_glues: RefCell<FnvHashMap<DropGlueKind<'tcx>, (ValueRef, FnType)>>,
103102
/// Track mapping of external ids to local items imported for inlining
104103
external: RefCell<DefIdMap<Option<ast::NodeId>>>,
105104
/// Backwards version of the `external` map (inlined items to where they
@@ -413,8 +412,6 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> {
413412
},
414413
check_overflow: check_overflow,
415414
check_drop_flag_for_sanity: check_drop_flag_for_sanity,
416-
available_monomorphizations: RefCell::new(FnvHashSet()),
417-
available_drop_glues: RefCell::new(FnvHashMap()),
418415
use_dll_storage_attrs: use_dll_storage_attrs,
419416
translation_items: RefCell::new(FnvHashMap()),
420417
trait_cache: RefCell::new(DepTrackingMap::new(tcx.dep_graph.clone())),
@@ -730,7 +727,8 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
730727
&self.local().fn_pointer_shims
731728
}
732729

733-
pub fn drop_glues<'a>(&'a self) -> &'a RefCell<FnvHashMap<DropGlueKind<'tcx>, ValueRef>> {
730+
pub fn drop_glues<'a>(&'a self)
731+
-> &'a RefCell<FnvHashMap<DropGlueKind<'tcx>, (ValueRef, FnType)>> {
734732
&self.local().drop_glues
735733
}
736734

@@ -816,14 +814,6 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
816814
&self.shared.stats
817815
}
818816

819-
pub fn available_monomorphizations<'a>(&'a self) -> &'a RefCell<FnvHashSet<String>> {
820-
&self.shared.available_monomorphizations
821-
}
822-
823-
pub fn available_drop_glues(&self) -> &RefCell<FnvHashMap<DropGlueKind<'tcx>, String>> {
824-
&self.shared.available_drop_glues
825-
}
826-
827817
pub fn int_type(&self) -> Type {
828818
self.local().int_type
829819
}

src/librustc_trans/declare.rs

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -138,24 +138,34 @@ pub fn define_global(ccx: &CrateContext, name: &str, ty: Type) -> Option<ValueRe
138138
}
139139
}
140140

141-
142141
/// Declare a Rust function with an intention to define it.
143142
///
144143
/// Use this function when you intend to define a function. This function will
145144
/// return panic if the name already has a definition associated with it. This
146145
/// can happen with #[no_mangle] or #[export_name], for example.
147-
pub fn define_internal_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
148-
name: &str,
149-
fn_type: ty::Ty<'tcx>) -> ValueRef {
146+
pub fn define_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
147+
name: &str,
148+
fn_type: ty::Ty<'tcx>) -> ValueRef {
150149
if get_defined_value(ccx, name).is_some() {
151150
ccx.sess().fatal(&format!("symbol `{}` already defined", name))
152151
} else {
153-
let llfn = declare_fn(ccx, name, fn_type);
154-
llvm::SetLinkage(llfn, llvm::InternalLinkage);
155-
llfn
152+
declare_fn(ccx, name, fn_type)
156153
}
157154
}
158155

156+
/// Declare a Rust function with an intention to define it.
157+
///
158+
/// Use this function when you intend to define a function. This function will
159+
/// return panic if the name already has a definition associated with it. This
160+
/// can happen with #[no_mangle] or #[export_name], for example.
161+
pub fn define_internal_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
162+
name: &str,
163+
fn_type: ty::Ty<'tcx>) -> ValueRef {
164+
let llfn = define_fn(ccx, name, fn_type);
165+
llvm::SetLinkage(llfn, llvm::InternalLinkage);
166+
llfn
167+
}
168+
159169

160170
/// Get declared value by name.
161171
pub fn get_declared_value(ccx: &CrateContext, name: &str) -> Option<ValueRef> {

src/librustc_trans/glue.rs

Lines changed: 11 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,12 @@
1414

1515
use std;
1616

17-
use back::symbol_names;
1817
use llvm;
1918
use llvm::{ValueRef, get_param};
2019
use middle::lang_items::ExchangeFreeFnLangItem;
2120
use rustc::ty::subst::{Substs};
2221
use rustc::traits;
2322
use rustc::ty::{self, Ty, TyCtxt};
24-
use abi::{Abi, FnType};
2523
use adt;
2624
use adt::GetDtorType; // for tcx.dtor_type()
2725
use base::*;
@@ -32,7 +30,6 @@ use cleanup::CleanupMethods;
3230
use collector;
3331
use common::*;
3432
use debuginfo::DebugLoc;
35-
use declare;
3633
use expr;
3734
use machine::*;
3835
use monomorphize;
@@ -233,56 +230,28 @@ impl<'tcx> DropGlueKind<'tcx> {
233230

234231
fn get_drop_glue_core<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
235232
g: DropGlueKind<'tcx>) -> ValueRef {
236-
debug!("make drop glue for {:?}", g);
237233
let g = g.map_ty(|t| get_drop_glue_type(ccx.tcx(), t));
238-
debug!("drop glue type {:?}", g);
239234
match ccx.drop_glues().borrow().get(&g) {
240-
Some(&glue) => return glue,
241-
_ => { }
235+
Some(&(glue, _)) => glue,
236+
None => { bug!("Could not find drop glue for {:?} -- {} -- {}",
237+
g,
238+
TransItem::DropGlue(g).to_raw_string(),
239+
ccx.codegen_unit().name) }
242240
}
243-
let t = g.ty();
241+
}
244242

243+
pub fn implement_drop_glue<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
244+
g: DropGlueKind<'tcx>) {
245245
let tcx = ccx.tcx();
246-
let sig = ty::FnSig {
247-
inputs: vec![tcx.mk_mut_ptr(tcx.types.i8)],
248-
output: ty::FnOutput::FnConverging(tcx.mk_nil()),
249-
variadic: false,
250-
};
251-
// Create a FnType for fn(*mut i8) and substitute the real type in
252-
// later - that prevents FnType from splitting fat pointers up.
253-
let mut fn_ty = FnType::new(ccx, Abi::Rust, &sig, &[]);
254-
fn_ty.args[0].original_ty = type_of(ccx, t).ptr_to();
255-
let llfnty = fn_ty.llvm_type(ccx);
256-
257-
// To avoid infinite recursion, don't `make_drop_glue` until after we've
258-
// added the entry to the `drop_glues` cache.
259-
if let Some(old_sym) = ccx.available_drop_glues().borrow().get(&g) {
260-
let llfn = declare::declare_cfn(ccx, &old_sym, llfnty);
261-
ccx.drop_glues().borrow_mut().insert(g, llfn);
262-
return llfn;
263-
};
264-
265-
let suffix = match g {
266-
DropGlueKind::Ty(_) => "drop",
267-
DropGlueKind::TyContents(_) => "drop_contents",
268-
};
269-
270-
let fn_nm = symbol_names::internal_name_from_type_and_suffix(ccx, t, suffix);
271-
assert!(declare::get_defined_value(ccx, &fn_nm).is_none());
272-
let llfn = declare::declare_cfn(ccx, &fn_nm, llfnty);
273-
ccx.available_drop_glues().borrow_mut().insert(g, fn_nm);
274-
ccx.drop_glues().borrow_mut().insert(g, llfn);
275-
276-
let _s = StatRecorder::new(ccx, format!("drop {:?}", t));
246+
assert_eq!(g.ty(), get_drop_glue_type(tcx, g.ty()));
247+
let (llfn, fn_ty) = ccx.drop_glues().borrow().get(&g).unwrap().clone();
277248

278249
let (arena, fcx): (TypedArena<_>, FunctionContext);
279250
arena = TypedArena::new();
280251
fcx = FunctionContext::new(ccx, llfn, fn_ty, None, &arena);
281252

282253
let bcx = fcx.init(false, None);
283254

284-
update_linkage(ccx, llfn, None);
285-
286255
ccx.stats().n_glues_created.set(ccx.stats().n_glues_created.get() + 1);
287256
// All glue functions take values passed *by alias*; this is a
288257
// requirement since in many contexts glue is invoked indirectly and
@@ -294,10 +263,9 @@ fn get_drop_glue_core<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
294263

295264
let bcx = make_drop_glue(bcx, get_param(llfn, 0), g);
296265
fcx.finish(bcx, DebugLoc::None);
297-
298-
llfn
299266
}
300267

268+
301269
fn trans_struct_drop_flag<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
302270
t: Ty<'tcx>,
303271
struct_data: ValueRef)

0 commit comments

Comments
 (0)