Skip to content

Commit 70c7c06

Browse files
authored
Merge pull request rust-lang#203 from rust-lang/feature/visibility
Support symbol visibility
2 parents a227994 + 672eec3 commit 70c7c06

File tree

6 files changed

+145
-11
lines changed

6 files changed

+145
-11
lines changed

Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/allocator.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#[cfg(feature="master")]
2+
use gccjit::FnAttribute;
13
use gccjit::{FunctionType, GlobalKind, ToRValue};
24
use rustc_ast::expand::allocator::{AllocatorKind, AllocatorTy, ALLOCATOR_METHODS};
35
use rustc_middle::bug;
@@ -50,7 +52,8 @@ pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut GccContext, _module_nam
5052
let func = context.new_function(None, FunctionType::Exported, output.unwrap_or(void), &args, name, false);
5153

5254
if tcx.sess.target.options.default_hidden_visibility {
53-
// TODO(antoyo): set visibility.
55+
#[cfg(feature="master")]
56+
func.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden));
5457
}
5558
if tcx.sess.must_emit_unwind_tables() {
5659
// TODO(antoyo): emit unwind tables.
@@ -61,7 +64,8 @@ pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut GccContext, _module_nam
6164
.map(|(index, typ)| context.new_parameter(None, *typ, &format!("param{}", index)))
6265
.collect();
6366
let callee = context.new_function(None, FunctionType::Extern, output.unwrap_or(void), &args, callee, false);
64-
// TODO(antoyo): set visibility.
67+
#[cfg(feature="master")]
68+
callee.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden));
6569

6670
let block = func.new_block("entry");
6771

@@ -90,6 +94,11 @@ pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut GccContext, _module_nam
9094
.collect();
9195
let func = context.new_function(None, FunctionType::Exported, void, &args, name, false);
9296

97+
if tcx.sess.target.default_hidden_visibility {
98+
#[cfg(feature="master")]
99+
func.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden));
100+
}
101+
93102
let kind =
94103
if has_alloc_error_handler {
95104
AllocatorKind::Global
@@ -102,7 +111,8 @@ pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut GccContext, _module_nam
102111
.map(|(index, typ)| context.new_parameter(None, *typ, &format!("param{}", index)))
103112
.collect();
104113
let callee = context.new_function(None, FunctionType::Extern, void, &args, callee, false);
105-
//llvm::LLVMRustSetVisibility(callee, llvm::Visibility::Hidden);
114+
#[cfg(feature="master")]
115+
callee.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden));
106116

107117
let block = func.new_block("entry");
108118

src/attributes.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#[cfg_attr(not(feature="master"), allow(unused_imports))]
1+
#[cfg(feature="master")]
22
use gccjit::FnAttribute;
33
use gccjit::Function;
44
use rustc_attr::InstructionSetAttr;
@@ -107,6 +107,6 @@ pub fn from_fn_attrs<'gcc, 'tcx>(
107107
let target_features = function_features.join(",");
108108
if !target_features.is_empty() {
109109
#[cfg(feature="master")]
110-
func.add_attribute(FnAttribute::Target, &target_features);
110+
func.add_attribute(FnAttribute::Target(&target_features));
111111
}
112112
}

src/base.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ use gccjit::{
88
};
99
use rustc_middle::dep_graph;
1010
use rustc_middle::ty::TyCtxt;
11+
#[cfg(feature="master")]
12+
use rustc_middle::mir::mono::Visibility;
1113
use rustc_middle::mir::mono::Linkage;
1214
use rustc_codegen_ssa::{ModuleCodegen, ModuleKind};
1315
use rustc_codegen_ssa::base::maybe_create_entry_wrapper;
@@ -20,6 +22,15 @@ use crate::GccContext;
2022
use crate::builder::Builder;
2123
use crate::context::CodegenCx;
2224

25+
#[cfg(feature="master")]
26+
pub fn visibility_to_gcc(linkage: Visibility) -> gccjit::Visibility {
27+
match linkage {
28+
Visibility::Default => gccjit::Visibility::Default,
29+
Visibility::Hidden => gccjit::Visibility::Hidden,
30+
Visibility::Protected => gccjit::Visibility::Protected,
31+
}
32+
}
33+
2334
pub fn global_linkage_to_gcc(linkage: Linkage) -> GlobalKind {
2435
match linkage {
2536
Linkage::External => GlobalKind::Imported,

src/callee.rs

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#[cfg(feature="master")]
2+
use gccjit::{FnAttribute, Visibility};
13
use gccjit::{FunctionType, RValue};
24
use rustc_codegen_ssa::traits::BaseTypeMethods;
35
use rustc_middle::ty::{self, Instance, TypeFoldable};
@@ -70,8 +72,97 @@ pub fn get_fn<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, instance: Instance<'tcx>)
7072

7173
attributes::from_fn_attrs(cx, func, instance);
7274

75+
let instance_def_id = instance.def_id();
76+
7377
// TODO(antoyo): set linkage and attributes.
7478

79+
// Apply an appropriate linkage/visibility value to our item that we
80+
// just declared.
81+
//
82+
// This is sort of subtle. Inside our codegen unit we started off
83+
// compilation by predefining all our own `MonoItem` instances. That
84+
// is, everything we're codegenning ourselves is already defined. That
85+
// means that anything we're actually codegenning in this codegen unit
86+
// will have hit the above branch in `get_declared_value`. As a result,
87+
// we're guaranteed here that we're declaring a symbol that won't get
88+
// defined, or in other words we're referencing a value from another
89+
// codegen unit or even another crate.
90+
//
91+
// So because this is a foreign value we blanket apply an external
92+
// linkage directive because it's coming from a different object file.
93+
// The visibility here is where it gets tricky. This symbol could be
94+
// referencing some foreign crate or foreign library (an `extern`
95+
// block) in which case we want to leave the default visibility. We may
96+
// also, though, have multiple codegen units. It could be a
97+
// monomorphization, in which case its expected visibility depends on
98+
// whether we are sharing generics or not. The important thing here is
99+
// that the visibility we apply to the declaration is the same one that
100+
// has been applied to the definition (wherever that definition may be).
101+
let is_generic = instance.substs.non_erasable_generics().next().is_some();
102+
103+
if is_generic {
104+
// This is a monomorphization. Its expected visibility depends
105+
// on whether we are in share-generics mode.
106+
107+
if cx.tcx.sess.opts.share_generics() {
108+
// We are in share_generics mode.
109+
110+
if let Some(instance_def_id) = instance_def_id.as_local() {
111+
// This is a definition from the current crate. If the
112+
// definition is unreachable for downstream crates or
113+
// the current crate does not re-export generics, the
114+
// definition of the instance will have been declared
115+
// as `hidden`.
116+
if cx.tcx.is_unreachable_local_definition(instance_def_id)
117+
|| !cx.tcx.local_crate_exports_generics()
118+
{
119+
#[cfg(feature="master")]
120+
func.add_attribute(FnAttribute::Visibility(Visibility::Hidden));
121+
}
122+
} else {
123+
// This is a monomorphization of a generic function
124+
// defined in an upstream crate.
125+
if instance.upstream_monomorphization(tcx).is_some() {
126+
// This is instantiated in another crate. It cannot
127+
// be `hidden`.
128+
} else {
129+
// This is a local instantiation of an upstream definition.
130+
// If the current crate does not re-export it
131+
// (because it is a C library or an executable), it
132+
// will have been declared `hidden`.
133+
if !cx.tcx.local_crate_exports_generics() {
134+
#[cfg(feature="master")]
135+
func.add_attribute(FnAttribute::Visibility(Visibility::Hidden));
136+
}
137+
}
138+
}
139+
} else {
140+
// When not sharing generics, all instances are in the same
141+
// crate and have hidden visibility
142+
#[cfg(feature="master")]
143+
func.add_attribute(FnAttribute::Visibility(Visibility::Hidden));
144+
}
145+
} else {
146+
// This is a non-generic function
147+
if cx.tcx.is_codegened_item(instance_def_id) {
148+
// This is a function that is instantiated in the local crate
149+
150+
if instance_def_id.is_local() {
151+
// This is function that is defined in the local crate.
152+
// If it is not reachable, it is hidden.
153+
if !cx.tcx.is_reachable_non_generic(instance_def_id) {
154+
#[cfg(feature="master")]
155+
func.add_attribute(FnAttribute::Visibility(Visibility::Hidden));
156+
}
157+
} else {
158+
// This is a function from an upstream crate that has
159+
// been instantiated here. These are always hidden.
160+
#[cfg(feature="master")]
161+
func.add_attribute(FnAttribute::Visibility(Visibility::Hidden));
162+
}
163+
}
164+
}
165+
75166
// FIXME(antoyo): this is a wrong cast. That requires changing the compiler API.
76167
unsafe { std::mem::transmute(func) }
77168
};

src/mono_item.rs

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,36 @@
1+
#[cfg(feature="master")]
2+
use gccjit::{VarAttribute, FnAttribute};
13
use rustc_codegen_ssa::traits::PreDefineMethods;
4+
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
25
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
36
use rustc_middle::mir::mono::{Linkage, Visibility};
47
use rustc_middle::ty::{self, Instance, TypeFoldable};
58
use rustc_middle::ty::layout::{FnAbiOf, LayoutOf};
6-
use rustc_span::def_id::DefId;
79

810
use crate::attributes;
911
use crate::base;
1012
use crate::context::CodegenCx;
1113
use crate::type_of::LayoutGccExt;
1214

1315
impl<'gcc, 'tcx> PreDefineMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
14-
fn predefine_static(&self, def_id: DefId, _linkage: Linkage, _visibility: Visibility, symbol_name: &str) {
16+
#[cfg_attr(not(feature="master"), allow(unused_variables))]
17+
fn predefine_static(&self, def_id: DefId, _linkage: Linkage, visibility: Visibility, symbol_name: &str) {
1518
let attrs = self.tcx.codegen_fn_attrs(def_id);
1619
let instance = Instance::mono(self.tcx, def_id);
1720
let ty = instance.ty(self.tcx, ty::ParamEnv::reveal_all());
1821
let gcc_type = self.layout_of(ty).gcc_type(self);
1922

2023
let is_tls = attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL);
2124
let global = self.define_global(symbol_name, gcc_type, is_tls, attrs.link_section);
25+
#[cfg(feature="master")]
26+
global.add_attribute(VarAttribute::Visibility(base::visibility_to_gcc(visibility)));
2227

23-
// TODO(antoyo): set linkage and visibility.
28+
// TODO(antoyo): set linkage.
2429
self.instances.borrow_mut().insert(instance, global);
2530
}
2631

27-
fn predefine_fn(&self, instance: Instance<'tcx>, linkage: Linkage, _visibility: Visibility, symbol_name: &str) {
32+
#[cfg_attr(not(feature="master"), allow(unused_variables))]
33+
fn predefine_fn(&self, instance: Instance<'tcx>, linkage: Linkage, visibility: Visibility, symbol_name: &str) {
2834
assert!(!instance.substs.needs_infer());
2935

3036
let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty());
@@ -34,6 +40,22 @@ impl<'gcc, 'tcx> PreDefineMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
3440

3541
attributes::from_fn_attrs(self, decl, instance);
3642

43+
// If we're compiling the compiler-builtins crate, e.g., the equivalent of
44+
// compiler-rt, then we want to implicitly compile everything with hidden
45+
// visibility as we're going to link this object all over the place but
46+
// don't want the symbols to get exported.
47+
if linkage != Linkage::Internal
48+
&& linkage != Linkage::Private
49+
&& self.tcx.is_compiler_builtins(LOCAL_CRATE)
50+
{
51+
#[cfg(feature="master")]
52+
decl.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden));
53+
}
54+
else {
55+
#[cfg(feature="master")]
56+
decl.add_attribute(FnAttribute::Visibility(base::visibility_to_gcc(visibility)));
57+
}
58+
3759
// TODO(antoyo): call set_link_section() to allow initializing argc/argv.
3860
// TODO(antoyo): set unique comdat.
3961
// TODO(antoyo): use inline attribute from there in linkage.set() above.

0 commit comments

Comments
 (0)