Skip to content

Commit 5913d3f

Browse files
Aatchmichaelwoerister
authored andcommitted
Drive function item translation from collector
Functions and method are declared ahead-of-time, including generic ones. Closures are not considered trans items anymore, instead they are translated on demands.
1 parent 5cea43c commit 5913d3f

File tree

6 files changed

+211
-175
lines changed

6 files changed

+211
-175
lines changed

src/librustc_trans/base.rs

Lines changed: 89 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1956,6 +1956,49 @@ pub fn trans_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
19561956
closure::ClosureEnv::NotClosure);
19571957
}
19581958

1959+
pub fn trans_instance<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, instance: Instance<'tcx>) {
1960+
let instance = inline::maybe_inline_instance(ccx, instance);
1961+
1962+
let fn_node_id = ccx.tcx().map.as_local_node_id(instance.def).unwrap();
1963+
1964+
let _s = StatRecorder::new(ccx, ccx.tcx().node_path_str(fn_node_id));
1965+
debug!("trans_instance(instance={:?})", instance);
1966+
let _icx = push_ctxt("trans_instance");
1967+
1968+
let item = ccx.tcx().map.find(fn_node_id).unwrap();
1969+
1970+
let fn_ty = ccx.tcx().lookup_item_type(instance.def).ty;
1971+
let fn_ty = ccx.tcx().erase_regions(&fn_ty);
1972+
let fn_ty = monomorphize::apply_param_substs(ccx.tcx(), instance.substs, &fn_ty);
1973+
1974+
let sig = ccx.tcx().erase_late_bound_regions(fn_ty.fn_sig());
1975+
let sig = ccx.tcx().normalize_associated_type(&sig);
1976+
let abi = fn_ty.fn_abi();
1977+
1978+
let lldecl = match ccx.instances().borrow().get(&instance) {
1979+
Some(&val) => val,
1980+
None => bug!("Instance `{:?}` not already declared", instance)
1981+
};
1982+
1983+
match item {
1984+
hir_map::NodeItem(&hir::Item {
1985+
node: hir::ItemFn(ref decl, _, _, _, _, ref body), ..
1986+
}) |
1987+
hir_map::NodeTraitItem(&hir::TraitItem {
1988+
node: hir::MethodTraitItem(
1989+
hir::MethodSig { ref decl, .. }, Some(ref body)), ..
1990+
}) |
1991+
hir_map::NodeImplItem(&hir::ImplItem {
1992+
node: hir::ImplItemKind::Method(
1993+
hir::MethodSig { ref decl, .. }, ref body), ..
1994+
}) => {
1995+
trans_closure(ccx, decl, body, lldecl, instance,
1996+
fn_node_id, &sig, abi, closure::ClosureEnv::NotClosure);
1997+
}
1998+
_ => bug!("Instance is a {:?}?", item)
1999+
}
2000+
}
2001+
19592002
pub fn trans_named_tuple_constructor<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
19602003
ctor_ty: Ty<'tcx>,
19612004
disr: Disr,
@@ -2275,79 +2318,33 @@ pub fn trans_item(ccx: &CrateContext, item: &hir::Item) {
22752318
let _icx = push_ctxt("trans_item");
22762319

22772320
let tcx = ccx.tcx();
2278-
let from_external = ccx.external_srcs().borrow().contains_key(&item.id);
2279-
22802321
match item.node {
2281-
hir::ItemFn(ref decl, _, _, _, ref generics, ref body) => {
2282-
if !generics.is_type_parameterized() {
2283-
let trans_everywhere = attr::requests_inline(&item.attrs);
2284-
// Ignore `trans_everywhere` for cross-crate inlined items
2285-
// (`from_external`). `trans_item` will be called once for each
2286-
// compilation unit that references the item, so it will still get
2287-
// translated everywhere it's needed.
2288-
for (ref ccx, is_origin) in ccx.maybe_iter(!from_external && trans_everywhere) {
2289-
let def_id = tcx.map.local_def_id(item.id);
2290-
let empty_substs = ccx.empty_substs_for_def_id(def_id);
2291-
let llfn = Callee::def(ccx, def_id, empty_substs).reify(ccx).val;
2292-
trans_fn(ccx, &decl, &body, llfn, empty_substs, item.id);
2293-
set_link_section(ccx, llfn, &item.attrs);
2294-
update_linkage(ccx,
2295-
llfn,
2296-
Some(item.id),
2297-
if is_origin {
2298-
OriginalTranslation
2299-
} else {
2300-
InlinedCopy
2301-
});
2302-
2303-
if is_entry_fn(ccx.sess(), item.id) {
2304-
create_entry_wrapper(ccx, item.span, llfn);
2305-
// check for the #[rustc_error] annotation, which forces an
2306-
// error in trans. This is used to write compile-fail tests
2307-
// that actually test that compilation succeeds without
2308-
// reporting an error.
2309-
if tcx.has_attr(def_id, "rustc_error") {
2310-
tcx.sess.span_fatal(item.span, "compilation successful");
2311-
}
2312-
}
2322+
hir::ItemFn(_, _, _, _, _, _) => {
2323+
let def_id = tcx.map.local_def_id(item.id);
2324+
// check for the #[rustc_error] annotation, which forces an
2325+
// error in trans. This is used to write compile-fail tests
2326+
// that actually test that compilation succeeds without
2327+
// reporting an error.
2328+
if is_entry_fn(ccx.sess(), item.id) {
2329+
let empty_substs = ccx.empty_substs_for_def_id(def_id);
2330+
let llfn = Callee::def(ccx, def_id, empty_substs).reify(ccx).val;
2331+
create_entry_wrapper(ccx, item.span, llfn);
2332+
if tcx.has_attr(def_id, "rustc_error") {
2333+
tcx.sess.span_fatal(item.span, "compilation successful");
23132334
}
23142335
}
2315-
}
2316-
hir::ItemImpl(_, _, ref generics, _, _, ref impl_items) => {
2317-
// Both here and below with generic methods, be sure to recurse and look for
2318-
// items that we need to translate.
2319-
if !generics.ty_params.is_empty() {
2320-
return;
2321-
}
23222336

2323-
for impl_item in impl_items {
2324-
if let hir::ImplItemKind::Method(ref sig, ref body) = impl_item.node {
2325-
if sig.generics.ty_params.is_empty() {
2326-
let trans_everywhere = attr::requests_inline(&impl_item.attrs);
2327-
for (ref ccx, is_origin) in ccx.maybe_iter(trans_everywhere) {
2328-
let def_id = tcx.map.local_def_id(impl_item.id);
2329-
let empty_substs = ccx.empty_substs_for_def_id(def_id);
2330-
let llfn = Callee::def(ccx, def_id, empty_substs).reify(ccx).val;
2331-
trans_fn(ccx, &sig.decl, body, llfn, empty_substs, impl_item.id);
2332-
update_linkage(ccx, llfn, Some(impl_item.id),
2333-
if is_origin {
2334-
OriginalTranslation
2335-
} else {
2336-
InlinedCopy
2337-
});
2338-
}
2339-
}
2340-
}
2341-
}
2337+
// Function is actually translated in trans_instance
23422338
}
23432339
hir::ItemEnum(ref enum_definition, ref gens) => {
23442340
if gens.ty_params.is_empty() {
23452341
// sizes only make sense for non-generic types
23462342
enum_variant_size_lint(ccx, enum_definition, item.span, item.id);
23472343
}
23482344
}
2345+
hir::ItemImpl(..) |
23492346
hir::ItemStatic(..) => {
2350-
// Don't do anything here. Translation of statics has been moved to
2347+
// Don't do anything here. Translation has been moved to
23512348
// being "collector-driven".
23522349
}
23532350
_ => {}
@@ -2490,16 +2487,16 @@ fn internalize_symbols(cx: &CrateContextList, reachable: &HashSet<&str>) {
24902487
let linkage = llvm::LLVMGetLinkage(val);
24912488
// We only care about external declarations (not definitions)
24922489
// and available_externally definitions.
2493-
if !(linkage == llvm::ExternalLinkage as c_uint &&
2494-
llvm::LLVMIsDeclaration(val) != 0) &&
2495-
!(linkage == llvm::AvailableExternallyLinkage as c_uint) {
2496-
continue;
2490+
let is_available_externally = linkage == llvm::AvailableExternallyLinkage as c_uint;
2491+
let is_decl = llvm::LLVMIsDeclaration(val) != 0;
2492+
2493+
if is_decl || is_available_externally {
2494+
let name = CStr::from_ptr(llvm::LLVMGetValueName(val))
2495+
.to_bytes()
2496+
.to_vec();
2497+
declared.insert(name);
24972498
}
24982499

2499-
let name = CStr::from_ptr(llvm::LLVMGetValueName(val))
2500-
.to_bytes()
2501-
.to_vec();
2502-
declared.insert(name);
25032500
}
25042501
}
25052502

@@ -2509,21 +2506,27 @@ fn internalize_symbols(cx: &CrateContextList, reachable: &HashSet<&str>) {
25092506
for ccx in cx.iter() {
25102507
for val in iter_globals(ccx.llmod()).chain(iter_functions(ccx.llmod())) {
25112508
let linkage = llvm::LLVMGetLinkage(val);
2509+
2510+
let is_external = linkage == llvm::ExternalLinkage as c_uint;
2511+
let is_weak_odr = linkage == llvm::WeakODRLinkage as c_uint;
2512+
let is_decl = llvm::LLVMIsDeclaration(val) != 0;
2513+
25122514
// We only care about external definitions.
2513-
if !((linkage == llvm::ExternalLinkage as c_uint ||
2514-
linkage == llvm::WeakODRLinkage as c_uint) &&
2515-
llvm::LLVMIsDeclaration(val) == 0) {
2516-
continue;
2517-
}
2515+
if (is_external || is_weak_odr) && !is_decl {
2516+
2517+
let name = CStr::from_ptr(llvm::LLVMGetValueName(val))
2518+
.to_bytes()
2519+
.to_vec();
2520+
2521+
let is_declared = declared.contains(&name);
2522+
let reachable = reachable.contains(str::from_utf8(&name).unwrap());
2523+
2524+
if !is_declared && !reachable {
2525+
llvm::SetLinkage(val, llvm::InternalLinkage);
2526+
llvm::SetDLLStorageClass(val, llvm::DefaultStorageClass);
2527+
llvm::UnsetComdat(val);
2528+
}
25182529

2519-
let name = CStr::from_ptr(llvm::LLVMGetValueName(val))
2520-
.to_bytes()
2521-
.to_vec();
2522-
if !declared.contains(&name) &&
2523-
!reachable.contains(str::from_utf8(&name).unwrap()) {
2524-
llvm::SetLinkage(val, llvm::InternalLinkage);
2525-
llvm::SetDLLStorageClass(val, llvm::DefaultStorageClass);
2526-
llvm::UnsetComdat(val);
25272530
}
25282531
}
25292532
}
@@ -2752,6 +2755,9 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
27522755
span_bug!(item.span, "Mismatch between hir::Item type and TransItem type")
27532756
}
27542757
}
2758+
TransItem::Fn(instance) => {
2759+
trans_instance(&ccx, instance);
2760+
}
27552761
_ => { }
27562762
}
27572763
}
@@ -2988,7 +2994,7 @@ fn collect_and_partition_translation_items<'a, 'tcx>(scx: &SharedCrateContext<'a
29882994
let mut item_keys: Vec<_> = items
29892995
.iter()
29902996
.map(|i| {
2991-
let mut output = i.to_string(scx.tcx());
2997+
let mut output = i.to_string(scx);
29922998
output.push_str(" @@");
29932999
let mut empty = Vec::new();
29943000
let mut cgus = item_to_cgus.get_mut(i).unwrap_or(&mut empty);

src/librustc_trans/closure.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
use arena::TypedArena;
1212
use back::symbol_names;
13-
use llvm::{ValueRef, get_param, get_params};
13+
use llvm::{self, ValueRef, get_param, get_params};
1414
use rustc::hir::def_id::DefId;
1515
use abi::{Abi, FnType};
1616
use adt;
@@ -167,7 +167,7 @@ fn get_or_create_closure_declaration<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
167167
variadic: false
168168
})
169169
}));
170-
let llfn = declare::define_internal_fn(ccx, &symbol, function_type);
170+
let llfn = declare::declare_fn(ccx, &symbol, function_type);
171171

172172
// set an inline hint for all closures
173173
attributes::inline(llfn, attributes::InlineAttr::Hint);
@@ -210,6 +210,7 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>,
210210
id, closure_def_id, closure_substs);
211211

212212
let llfn = get_or_create_closure_declaration(ccx, closure_def_id, closure_substs);
213+
llvm::SetLinkage(llfn, llvm::WeakODRLinkage);
213214

214215
// Get the type of this closure. Use the current `param_substs` as
215216
// the closure substitutions. This makes sense because the closure
@@ -376,7 +377,7 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>(
376377
// Create the by-value helper.
377378
let function_name =
378379
symbol_names::internal_name_from_type_and_suffix(ccx, llonce_fn_ty, "once_shim");
379-
let lloncefn = declare::define_internal_fn(ccx, &function_name, llonce_fn_ty);
380+
let lloncefn = declare::declare_fn(ccx, &function_name, llonce_fn_ty);
380381

381382
let (block_arena, fcx): (TypedArena<_>, FunctionContext);
382383
block_arena = TypedArena::new();

src/librustc_trans/collector.rs

Lines changed: 27 additions & 15 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.tcx()));
328+
debug!("BEGIN collect_items_rec({})", starting_point.to_string(scx));
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.tcx()));
399+
debug!("END collect_items_rec({})", starting_point.to_string(scx));
400400
}
401401

402402
fn record_inlining_canditates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
@@ -456,12 +456,25 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
456456
match *rvalue {
457457
mir::Rvalue::Aggregate(mir::AggregateKind::Closure(def_id,
458458
ref substs), _) => {
459-
assert!(can_have_local_instance(self.scx.tcx(), def_id));
460-
let trans_item = create_fn_trans_item(self.scx.tcx(),
461-
def_id,
462-
substs.func_substs,
463-
self.param_substs);
464-
self.output.push(trans_item);
459+
let mir = errors::expect(self.scx.sess().diagnostic(), self.scx.get_mir(def_id),
460+
|| format!("Could not find MIR for closure: {:?}", def_id));
461+
462+
let concrete_substs = monomorphize::apply_param_substs(self.scx.tcx(),
463+
self.param_substs,
464+
&substs.func_substs);
465+
let concrete_substs = self.scx.tcx().erase_regions(&concrete_substs);
466+
467+
let mut visitor = MirNeighborCollector {
468+
scx: self.scx,
469+
mir: &mir,
470+
output: self.output,
471+
param_substs: concrete_substs
472+
};
473+
474+
visitor.visit_mir(&mir);
475+
for promoted in &mir.promoted {
476+
visitor.visit_mir(promoted);
477+
}
465478
}
466479
// When doing an cast from a regular pointer to a fat pointer, we
467480
// have to instantiate all methods of the trait being cast to, so we
@@ -859,6 +872,7 @@ fn do_static_trait_method_dispatch<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
859872
&callee_substs);
860873

861874
let trait_ref = ty::Binder(rcvr_substs.to_trait_ref(tcx, trait_id));
875+
let trait_ref = tcx.normalize_associated_type(&trait_ref);
862876
let vtbl = fulfill_obligation(scx, DUMMY_SP, trait_ref);
863877

864878
// Now that we know which impl is being used, we can dispatch to
@@ -1105,9 +1119,8 @@ impl<'b, 'a, 'v> hir_visit::Visitor<'v> for RootCollector<'b, 'a, 'v> {
11051119
self.scx.tcx().map.local_def_id(item.id)));
11061120
self.output.push(TransItem::Static(item.id));
11071121
}
1108-
hir::ItemFn(_, _, constness, _, ref generics, _) => {
1109-
if !generics.is_type_parameterized() &&
1110-
constness == hir::Constness::NotConst {
1122+
hir::ItemFn(_, _, _, _, ref generics, _) => {
1123+
if !generics.is_type_parameterized() {
11111124
let def_id = self.scx.tcx().map.local_def_id(item.id);
11121125

11131126
debug!("RootCollector: ItemFn({})",
@@ -1127,9 +1140,8 @@ impl<'b, 'a, 'v> hir_visit::Visitor<'v> for RootCollector<'b, 'a, 'v> {
11271140
match ii.node {
11281141
hir::ImplItemKind::Method(hir::MethodSig {
11291142
ref generics,
1130-
constness,
11311143
..
1132-
}, _) if constness == hir::Constness::NotConst => {
1144+
}, _) => {
11331145
let hir_map = &self.scx.tcx().map;
11341146
let parent_node_id = hir_map.get_parent_node(ii.id);
11351147
let is_impl_generic = match hir_map.expect_item(parent_node_id) {
@@ -1258,7 +1270,7 @@ pub fn print_collection_results<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>) {
12581270
let mut item_keys = FnvHashMap();
12591271

12601272
for (item, item_state) in trans_items.iter() {
1261-
let k = item.to_string(scx.tcx());
1273+
let k = item.to_string(scx);
12621274

12631275
if item_keys.contains_key(&k) {
12641276
let prev: (TransItem, TransItemState) = item_keys[&k];
@@ -1286,7 +1298,7 @@ pub fn print_collection_results<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>) {
12861298
let mut generated = FnvHashSet();
12871299

12881300
for (item, item_state) in trans_items.iter() {
1289-
let item_key = item.to_string(scx.tcx());
1301+
let item_key = item.to_string(scx);
12901302

12911303
match *item_state {
12921304
TransItemState::PredictedAndGenerated => {

0 commit comments

Comments
 (0)