From a2cc5d68a7d4a739b3da62540cb09f313de2f452 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 30 Jan 2018 11:54:07 -0800 Subject: [PATCH] rustc: Add an option to default hidden visibility This commit adds a new option to target specifictions to specify that symbols should be "hidden" visibility by default in LLVM. While there are no existing targets that take advantage of this the `wasm32-unknown-unknown` target will soon start to use this visibility. The LLD linker currently interprets `hidden` as "don't export this from the wasm module" which is what we want for 90% of our functions. While the LLD linker does have a "export this symbol" argument which is what we use for other linkers, it was also somewhat easier to do this change instead which'll involve less arguments flying around. Additionally there's no need for non-`hidden` visibility for most of our symbols! This change should not immediately impact the wasm targets as-is, but rather this is laying the foundations for soon integrating LLD as a linker for wasm code. --- src/libpanic_abort/lib.rs | 3 +++ src/librustc/dep_graph/dep_node.rs | 3 +++ src/librustc/ty/maps/mod.rs | 1 + src/librustc/ty/maps/plumbing.rs | 2 ++ src/librustc_back/target/mod.rs | 7 +++++++ .../target/wasm32_unknown_unknown.rs | 3 +++ src/librustc_mir/monomorphize/partitioning.rs | 18 +++++++++++++++--- src/librustc_trans/allocator.rs | 4 ++++ src/librustc_trans/back/symbol_export.rs | 3 +++ 9 files changed, 41 insertions(+), 3 deletions(-) diff --git a/src/libpanic_abort/lib.rs b/src/libpanic_abort/lib.rs index c3bd6a2bc187d..5f768ef4399e8 100644 --- a/src/libpanic_abort/lib.rs +++ b/src/libpanic_abort/lib.rs @@ -27,10 +27,12 @@ #![feature(libc)] #![feature(panic_runtime)] #![feature(staged_api)] +#![feature(rustc_attrs)] // Rust's "try" function, but if we're aborting on panics we just call the // function as there's nothing else we need to do here. #[no_mangle] +#[rustc_std_internal_symbol] pub unsafe extern fn __rust_maybe_catch_panic(f: fn(*mut u8), data: *mut u8, _data_ptr: *mut usize, @@ -50,6 +52,7 @@ pub unsafe extern fn __rust_maybe_catch_panic(f: fn(*mut u8), // will kill us with an illegal instruction, which will do a good enough job for // now hopefully. #[no_mangle] +#[rustc_std_internal_symbol] pub unsafe extern fn __rust_start_panic(_data: usize, _vtable: usize) -> u32 { abort(); diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 1de9091b5df7d..4034055d04155 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -639,6 +639,9 @@ define_dep_nodes!( <'tcx> [] TargetFeaturesEnabled(DefId), [] InstanceDefSizeEstimate { instance_def: InstanceDef<'tcx> }, + + [] GetSymbolExportLevel(DefId), + ); trait DepNodeParams<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> : fmt::Debug { diff --git a/src/librustc/ty/maps/mod.rs b/src/librustc/ty/maps/mod.rs index 6c79f6a62fa0b..85fca68187fe6 100644 --- a/src/librustc/ty/maps/mod.rs +++ b/src/librustc/ty/maps/mod.rs @@ -343,6 +343,7 @@ define_maps! { <'tcx> -> (Arc, Arc>>>), [] fn export_name: ExportName(DefId) -> Option, [] fn contains_extern_indicator: ContainsExternIndicator(DefId) -> bool, + [] fn symbol_export_level: GetSymbolExportLevel(DefId) -> SymbolExportLevel, [] fn is_translated_function: IsTranslatedFunction(DefId) -> bool, [] fn codegen_unit: CodegenUnit(InternedString) -> Arc>, [] fn compile_codegen_unit: CompileCodegenUnit(InternedString) -> Stats, diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs index c9eebc3d2a0a7..0ab6ee1a54a9b 100644 --- a/src/librustc/ty/maps/plumbing.rs +++ b/src/librustc/ty/maps/plumbing.rs @@ -921,6 +921,8 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>, DepKind::TargetFeaturesWhitelist => { force!(target_features_whitelist, LOCAL_CRATE); } DepKind::TargetFeaturesEnabled => { force!(target_features_enabled, def_id!()); } + + DepKind::GetSymbolExportLevel => { force!(symbol_export_level, def_id!()); } } true diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs index 3c8a676dcc200..2872c59157d6b 100644 --- a/src/librustc_back/target/mod.rs +++ b/src/librustc_back/target/mod.rs @@ -468,6 +468,10 @@ pub struct TargetOptions { /// The codegen backend to use for this target, typically "llvm" pub codegen_backend: String, + + /// The default visibility for symbols in this target should be "hidden" + /// rather than "default" + pub default_hidden_visibility: bool, } impl Default for TargetOptions { @@ -538,6 +542,7 @@ impl Default for TargetOptions { no_builtins: false, i128_lowering: false, codegen_backend: "llvm".to_string(), + default_hidden_visibility: false, } } } @@ -785,6 +790,7 @@ impl Target { key!(singlethread, bool); key!(no_builtins, bool); key!(codegen_backend); + key!(default_hidden_visibility, bool); if let Some(array) = obj.find("abi-blacklist").and_then(Json::as_array) { for name in array.iter().filter_map(|abi| abi.as_string()) { @@ -982,6 +988,7 @@ impl ToJson for Target { target_option_val!(singlethread); target_option_val!(no_builtins); target_option_val!(codegen_backend); + target_option_val!(default_hidden_visibility); if default.abi_blacklist != self.options.abi_blacklist { d.insert("abi-blacklist".to_string(), self.options.abi_blacklist.iter() diff --git a/src/librustc_back/target/wasm32_unknown_unknown.rs b/src/librustc_back/target/wasm32_unknown_unknown.rs index 7e1011ab8af96..242860e5c6e92 100644 --- a/src/librustc_back/target/wasm32_unknown_unknown.rs +++ b/src/librustc_back/target/wasm32_unknown_unknown.rs @@ -83,6 +83,9 @@ pub fn target() -> Result { // performing LTO with compiler-builtins. no_builtins: true, + // no dynamic linking, no need for default visibility! + default_hidden_visibility: true, + .. Default::default() }; Ok(Target { diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs index 806d787c84522..e9471cdb4f949 100644 --- a/src/librustc_mir/monomorphize/partitioning.rs +++ b/src/librustc_mir/monomorphize/partitioning.rs @@ -107,6 +107,7 @@ use rustc::dep_graph::WorkProductId; use rustc::hir::def_id::DefId; use rustc::hir::map::DefPathData; use rustc::mir::mono::{Linkage, Visibility}; +use rustc::middle::exported_symbols::SymbolExportLevel; use rustc::ty::{self, TyCtxt, InstanceDef}; use rustc::ty::item_path::characteristic_def_id_of_type; use rustc::util::nodemap::{FxHashMap, FxHashSet}; @@ -322,7 +323,16 @@ fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>, .or_insert_with(make_codegen_unit); let mut can_be_internalized = true; - let (linkage, visibility) = match trans_item.explicit_linkage(tcx) { + let default_visibility = |id: DefId| { + if tcx.sess.target.target.options.default_hidden_visibility && + tcx.symbol_export_level(id) != SymbolExportLevel::C + { + Visibility::Hidden + } else { + Visibility::Default + } + }; + let (linkage, mut visibility) = match trans_item.explicit_linkage(tcx) { Some(explicit_linkage) => (explicit_linkage, Visibility::Default), None => { match trans_item { @@ -352,7 +362,8 @@ fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>, Visibility::Hidden } else if def_id.is_local() { if tcx.is_exported_symbol(def_id) { - Visibility::Default + can_be_internalized = false; + default_visibility(def_id) } else { Visibility::Hidden } @@ -375,7 +386,8 @@ fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>, MonoItem::GlobalAsm(node_id) => { let def_id = tcx.hir.local_def_id(node_id); let visibility = if tcx.is_exported_symbol(def_id) { - Visibility::Default + can_be_internalized = false; + default_visibility(def_id) } else { Visibility::Hidden }; diff --git a/src/librustc_trans/allocator.rs b/src/librustc_trans/allocator.rs index fd5aa1364d381..e1c145b122d76 100644 --- a/src/librustc_trans/allocator.rs +++ b/src/librustc_trans/allocator.rs @@ -86,6 +86,10 @@ pub(crate) unsafe fn trans(tcx: TyCtxt, mods: &ModuleLlvm, kind: AllocatorKind) name.as_ptr(), ty); + if tcx.sess.target.target.options.default_hidden_visibility { + llvm::LLVMRustSetVisibility(llfn, llvm::Visibility::Hidden); + } + let callee = CString::new(kind.fn_name(method.name)).unwrap(); let callee = llvm::LLVMRustGetOrInsertFunction(llmod, callee.as_ptr(), diff --git a/src/librustc_trans/back/symbol_export.rs b/src/librustc_trans/back/symbol_export.rs index 15ff59c7df998..989ef8a953746 100644 --- a/src/librustc_trans/back/symbol_export.rs +++ b/src/librustc_trans/back/symbol_export.rs @@ -133,6 +133,8 @@ pub fn provide(providers: &mut Providers) { Arc::new(local_crate) }; + + providers.symbol_export_level = export_level; } pub fn provide_extern(providers: &mut Providers) { @@ -203,6 +205,7 @@ pub fn provide_extern(providers: &mut Providers) { Arc::new(crate_exports) }; + providers.symbol_export_level = export_level; } fn export_level(tcx: TyCtxt, sym_def_id: DefId) -> SymbolExportLevel {