Skip to content

Commit 375c522

Browse files
Make drop-glue translation collector-driven.
1 parent 1621b49 commit 375c522

File tree

9 files changed

+178
-150
lines changed

9 files changed

+178
-150
lines changed

src/librustc_trans/abi.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,7 @@ impl ArgType {
229229
///
230230
/// I will do my best to describe this structure, but these
231231
/// comments are reverse-engineered and may be inaccurate. -NDM
232+
#[derive(Clone)]
232233
pub struct FnType {
233234
/// The LLVM types of each argument.
234235
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
@@ -2183,52 +2183,6 @@ pub fn llvm_linkage_by_name(name: &str) -> Option<Linkage> {
21832183
}
21842184
}
21852185

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

26752629
// ... and now that we have everything pre-defined, fill out those definitions.
26762630
for ccx in crate_context_list.iter() {
2677-
for (&trans_item, _) in &ccx.codegen_unit().items {
2678-
match trans_item {
2679-
TransItem::Static(node_id) => {
2680-
let item = ccx.tcx().map.expect_item(node_id);
2681-
if let hir::ItemStatic(_, m, ref expr) = item.node {
2682-
match consts::trans_static(&ccx, m, expr, item.id, &item.attrs) {
2683-
Ok(_) => { /* Cool, everything's alright. */ },
2684-
Err(err) => ccx.tcx().sess.span_fatal(expr.span, &err.description()),
2685-
};
2686-
} else {
2687-
span_bug!(item.span, "Mismatch between hir::Item type and TransItem type")
2688-
}
2689-
}
2690-
TransItem::Fn(instance) => {
2691-
trans_instance(&ccx, instance);
2692-
}
2693-
_ => { }
2694-
}
2631+
for (trans_item, _) in &ccx.codegen_unit().items {
2632+
trans_item.define(&ccx);
26952633
}
26962634
}
26972635

@@ -2928,7 +2866,7 @@ fn collect_and_partition_translation_items<'a, 'tcx>(scx: &SharedCrateContext<'a
29282866
let mut item_keys: Vec<_> = items
29292867
.iter()
29302868
.map(|i| {
2931-
let mut output = i.to_string(scx);
2869+
let mut output = i.to_string(scx.tcx());
29322870
output.push_str(" @@");
29332871
let mut empty = Vec::new();
29342872
let mut cgus = item_to_cgus.get_mut(i).unwrap_or(&mut empty);

src/librustc_trans/collector.rs

Lines changed: 6 additions & 5 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
}
@@ -1271,7 +1272,7 @@ pub fn print_collection_results<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>) {
12711272
let mut item_keys = FnvHashMap();
12721273

12731274
for (item, item_state) in trans_items.iter() {
1274-
let k = item.to_string(scx);
1275+
let k = item.to_string(scx.tcx());
12751276

12761277
if item_keys.contains_key(&k) {
12771278
let prev: (TransItem, TransItemState) = item_keys[&k];
@@ -1299,7 +1300,7 @@ pub fn print_collection_results<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>) {
12991300
let mut generated = FnvHashSet();
13001301

13011302
for (item, item_state) in trans_items.iter() {
1302-
let item_key = item.to_string(scx);
1303+
let item_key = item.to_string(scx.tcx());
13031304

13041305
match *item_state {
13051306
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 & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,12 @@
1414

1515
use std;
1616

17-
use attributes;
18-
use back::symbol_names;
1917
use llvm;
2018
use llvm::{ValueRef, get_param};
2119
use middle::lang_items::ExchangeFreeFnLangItem;
2220
use rustc::ty::subst::{Substs};
2321
use rustc::traits;
2422
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
25-
use abi::{Abi, FnType};
2623
use adt;
2724
use adt::GetDtorType; // for tcx.dtor_type()
2825
use base::*;
@@ -33,7 +30,6 @@ use cleanup::CleanupMethods;
3330
use collector;
3431
use common::*;
3532
use debuginfo::DebugLoc;
36-
use declare;
3733
use expr;
3834
use machine::*;
3935
use monomorphize;
@@ -236,57 +232,28 @@ impl<'tcx> DropGlueKind<'tcx> {
236232

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

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

282251
let (arena, fcx): (TypedArena<_>, FunctionContext);
283252
arena = TypedArena::new();
284253
fcx = FunctionContext::new(ccx, llfn, fn_ty, None, &arena);
285254

286255
let bcx = fcx.init(false, None);
287256

288-
update_linkage(ccx, llfn, None);
289-
290257
ccx.stats().n_glues_created.set(ccx.stats().n_glues_created.get() + 1);
291258
// All glue functions take values passed *by alias*; this is a
292259
// 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>,
298265

299266
let bcx = make_drop_glue(bcx, get_param(llfn, 0), g);
300267
fcx.finish(bcx, DebugLoc::None);
301-
302-
llfn
303268
}
304269

270+
305271
fn trans_struct_drop_flag<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
306272
t: Ty<'tcx>,
307273
struct_data: ValueRef)

0 commit comments

Comments
 (0)