Skip to content

Commit 9863211

Browse files
committed
---
yaml --- r: 108943 b: refs/heads/dist-snap c: 3bede9f h: refs/heads/master i: 108941: ebe31cb 108939: c0205f6 108935: e9ac693 108927: a27c7e4 v: v3
1 parent 3b66f74 commit 9863211

File tree

12 files changed

+244
-79
lines changed

12 files changed

+244
-79
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ refs/heads/try: f64fdf524a434f0e5cd0bc91d09c144723f3c90d
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/ndm: f3868061cd7988080c30d6d5bf352a5a5fe2460b
88
refs/heads/try2: 147ecfdd8221e4a4d4e090486829a06da1e0ca3c
9-
refs/heads/dist-snap: 9e0cfa23e8b3d2d17302eefd9d728e63e7c6c108
9+
refs/heads/dist-snap: 3bede9fd310540a0fd72371008f8aa606b23b11b
1010
refs/tags/release-0.2: c870d2dffb391e14efb05aa27898f1f6333a9596
1111
refs/tags/release-0.3: b5f0d0f648d9a6153664837026ba1be43d3e2503
1212
refs/heads/try3: 9387340aab40a73e8424c48fd42f0c521a4875c0

branches/dist-snap/src/librustc/front/feature_gate.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ static KNOWN_FEATURES: &'static [(&'static str, Status)] = &[
5353
("simd", Active),
5454
("default_type_params", Active),
5555
("quote", Active),
56+
("linkage", Active),
5657

5758
// These are used to test this portion of the compiler, they don't actually
5859
// mean anything
@@ -238,6 +239,19 @@ impl Visitor<()> for Context {
238239
}
239240
}
240241

242+
fn visit_foreign_item(&mut self, i: &ast::ForeignItem, _: ()) {
243+
match i.node {
244+
ast::ForeignItemFn(..) | ast::ForeignItemStatic(..) => {
245+
if attr::contains_name(i.attrs.as_slice(), "linkage") {
246+
self.gate_feature("linkage", i.span,
247+
"the `linkage` attribute is experimental \
248+
and not portable across platforms")
249+
}
250+
}
251+
}
252+
visit::walk_foreign_item(self, i, ())
253+
}
254+
241255
fn visit_ty(&mut self, t: &ast::Ty, _: ()) {
242256
match t.node {
243257
ast::TyClosure(closure) if closure.onceness == ast::Once &&

branches/dist-snap/src/librustc/middle/lint.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -983,7 +983,7 @@ static other_attrs: &'static [&'static str] = &[
983983

984984
// fn-level
985985
"test", "bench", "should_fail", "ignore", "inline", "lang", "main", "start",
986-
"no_split_stack", "cold", "macro_registrar",
986+
"no_split_stack", "cold", "macro_registrar", "linkage",
987987

988988
// internal attribute: bypass privacy inside items
989989
"!resolve_unexported",

branches/dist-snap/src/librustc/middle/trans/base.rs

Lines changed: 1 addition & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2107,7 +2107,6 @@ pub fn get_item_val(ccx: @CrateContext, id: ast::NodeId) -> ValueRef {
21072107
}
21082108

21092109
ast_map::NodeForeignItem(ni) => {
2110-
let ty = ty::node_id_to_type(ccx.tcx, ni.id);
21112110
foreign = true;
21122111

21132112
match ni.node {
@@ -2116,41 +2115,7 @@ pub fn get_item_val(ccx: @CrateContext, id: ast::NodeId) -> ValueRef {
21162115
foreign::register_foreign_item_fn(ccx, abis, ni)
21172116
}
21182117
ast::ForeignItemStatic(..) => {
2119-
// Treat the crate map static specially in order to
2120-
// a weak-linkage-like functionality where it's
2121-
// dynamically resolved at runtime. If we're
2122-
// building a library, then we declare the static
2123-
// with weak linkage, but if we're building a
2124-
// library then we've already declared the crate map
2125-
// so use that instead.
2126-
if attr::contains_name(ni.attrs.as_slice(),
2127-
"crate_map") {
2128-
if ccx.sess.building_library.get() {
2129-
let s = "_rust_crate_map_toplevel";
2130-
let g = unsafe {
2131-
s.with_c_str(|buf| {
2132-
let ty = type_of(ccx, ty);
2133-
llvm::LLVMAddGlobal(ccx.llmod,
2134-
ty.to_ref(),
2135-
buf)
2136-
})
2137-
};
2138-
lib::llvm::SetLinkage(g,
2139-
lib::llvm::ExternalWeakLinkage);
2140-
g
2141-
} else {
2142-
ccx.crate_map
2143-
}
2144-
} else {
2145-
let ident = foreign::link_name(ni);
2146-
unsafe {
2147-
ident.get().with_c_str(|buf| {
2148-
let ty = type_of(ccx, ty);
2149-
llvm::LLVMAddGlobal(ccx.llmod,
2150-
ty.to_ref(), buf)
2151-
})
2152-
}
2153-
}
2118+
foreign::register_static(ccx, ni)
21542119
}
21552120
}
21562121
}

branches/dist-snap/src/librustc/middle/trans/foreign.rs

Lines changed: 100 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
use back::{link};
1313
use lib::llvm::llvm;
14-
use lib::llvm::{ValueRef, CallConv, StructRetAttribute};
14+
use lib::llvm::{ValueRef, CallConv, StructRetAttribute, Linkage};
1515
use lib;
1616
use middle::trans::base::push_ctxt;
1717
use middle::trans::base;
@@ -105,6 +105,105 @@ pub fn llvm_calling_convention(ccx: &CrateContext,
105105
})
106106
}
107107

108+
pub fn llvm_linkage_by_name(name: &str) -> Option<Linkage> {
109+
// Use the names from src/llvm/docs/LangRef.rst here. Most types are only
110+
// applicable to variable declarations and may not really make sense for
111+
// Rust code in the first place but whitelist them anyway and trust that
112+
// the user knows what s/he's doing. Who knows, unanticipated use cases
113+
// may pop up in the future.
114+
//
115+
// ghost, dllimport, dllexport and linkonce_odr_autohide are not supported
116+
// and don't have to be, LLVM treats them as no-ops.
117+
match name {
118+
"appending" => Some(lib::llvm::AppendingLinkage),
119+
"available_externally" => Some(lib::llvm::AvailableExternallyLinkage),
120+
"common" => Some(lib::llvm::CommonLinkage),
121+
"extern_weak" => Some(lib::llvm::ExternalWeakLinkage),
122+
"external" => Some(lib::llvm::ExternalLinkage),
123+
"internal" => Some(lib::llvm::InternalLinkage),
124+
"linker_private" => Some(lib::llvm::LinkerPrivateLinkage),
125+
"linker_private_weak" => Some(lib::llvm::LinkerPrivateWeakLinkage),
126+
"linkonce" => Some(lib::llvm::LinkOnceAnyLinkage),
127+
"linkonce_odr" => Some(lib::llvm::LinkOnceODRLinkage),
128+
"private" => Some(lib::llvm::PrivateLinkage),
129+
"weak" => Some(lib::llvm::WeakAnyLinkage),
130+
"weak_odr" => Some(lib::llvm::WeakODRLinkage),
131+
_ => None,
132+
}
133+
}
134+
135+
pub fn register_static(ccx: @CrateContext,
136+
foreign_item: @ast::ForeignItem) -> ValueRef {
137+
let ty = ty::node_id_to_type(ccx.tcx, foreign_item.id);
138+
let llty = type_of::type_of(ccx, ty);
139+
140+
// Treat the crate map static specially in order to
141+
// a weak-linkage-like functionality where it's
142+
// dynamically resolved at runtime. If we're
143+
// building a library, then we declare the static
144+
// with weak linkage, but if we're building a
145+
// library then we've already declared the crate map
146+
// so use that instead.
147+
if attr::contains_name(foreign_item.attrs.as_slice(), "crate_map") {
148+
return if ccx.sess.building_library.get() {
149+
let s = "_rust_crate_map_toplevel";
150+
let g = unsafe {
151+
s.with_c_str(|buf| {
152+
llvm::LLVMAddGlobal(ccx.llmod, llty.to_ref(), buf)
153+
})
154+
};
155+
lib::llvm::SetLinkage(g, lib::llvm::ExternalWeakLinkage);
156+
g
157+
} else {
158+
ccx.crate_map
159+
}
160+
}
161+
162+
let ident = link_name(foreign_item);
163+
match attr::first_attr_value_str_by_name(foreign_item.attrs.as_slice(),
164+
"linkage") {
165+
// If this is a static with a linkage specified, then we need to handle
166+
// it a little specially. The typesystem prevents things like &T and
167+
// extern "C" fn() from being non-null, so we can't just declare a
168+
// static and call it a day. Some linkages (like weak) will make it such
169+
// that the static actually has a null value.
170+
Some(name) => {
171+
let linkage = match llvm_linkage_by_name(name.get()) {
172+
Some(linkage) => linkage,
173+
None => {
174+
ccx.sess.span_fatal(foreign_item.span,
175+
"invalid linkage specified");
176+
}
177+
};
178+
let llty2 = match ty::get(ty).sty {
179+
ty::ty_ptr(ref mt) => type_of::type_of(ccx, mt.ty),
180+
_ => {
181+
ccx.sess.span_fatal(foreign_item.span,
182+
"must have type `*T` or `*mut T`");
183+
}
184+
};
185+
unsafe {
186+
let g1 = ident.get().with_c_str(|buf| {
187+
llvm::LLVMAddGlobal(ccx.llmod, llty2.to_ref(), buf)
188+
});
189+
lib::llvm::SetLinkage(g1, linkage);
190+
191+
let real_name = "_rust_extern_with_linkage_" + ident.get();
192+
let g2 = real_name.with_c_str(|buf| {
193+
llvm::LLVMAddGlobal(ccx.llmod, llty.to_ref(), buf)
194+
});
195+
lib::llvm::SetLinkage(g2, lib::llvm::InternalLinkage);
196+
llvm::LLVMSetInitializer(g2, g1);
197+
g2
198+
}
199+
}
200+
None => unsafe {
201+
ident.get().with_c_str(|buf| {
202+
llvm::LLVMAddGlobal(ccx.llmod, llty.to_ref(), buf)
203+
})
204+
}
205+
}
206+
}
108207

109208
pub fn register_foreign_item_fn(ccx: @CrateContext, abis: AbiSet,
110209
foreign_item: @ast::ForeignItem) -> ValueRef {

branches/dist-snap/src/libstd/lib.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,9 @@
5252
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
5353
html_root_url = "http://static.rust-lang.org/doc/master")];
5454

55-
#[feature(macro_rules, globs, asm, managed_boxes, thread_local, link_args, simd)];
55+
#[feature(macro_rules, globs, asm, managed_boxes, thread_local, link_args,
56+
simd, linkage, default_type_params)];
5657

57-
// Turn on default type parameters.
58-
#[feature(default_type_params)];
5958
// NOTE remove the following two attributes after the next snapshot.
6059
#[allow(unrecognized_lint)];
6160
#[allow(default_type_param_usage)];

branches/dist-snap/src/libstd/rt/thread.rs

Lines changed: 26 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ mod imp {
221221
PTHREAD_CREATE_JOINABLE), 0);
222222

223223
// Reserve room for the red zone, the runtime's stack of last resort.
224-
let stack_size = cmp::max(stack, RED_ZONE + __pthread_get_minstack(&attr) as uint);
224+
let stack_size = cmp::max(stack, RED_ZONE + min_stack_size(&attr) as uint);
225225
match pthread_attr_setstacksize(&mut attr, stack_size as libc::size_t) {
226226
0 => {
227227
},
@@ -261,51 +261,39 @@ mod imp {
261261
#[cfg(not(target_os = "macos"), not(target_os = "android"))]
262262
pub unsafe fn yield_now() { assert_eq!(pthread_yield(), 0); }
263263

264-
#[cfg(not(target_os = "linux"))]
265-
unsafe fn __pthread_get_minstack(_: *libc::pthread_attr_t) -> libc::size_t {
266-
libc::PTHREAD_STACK_MIN
267-
}
268-
269264
// glibc >= 2.15 has a __pthread_get_minstack() function that returns
270265
// PTHREAD_STACK_MIN plus however many bytes are needed for thread-local
271266
// storage. We need that information to avoid blowing up when a small stack
272267
// is created in an application with big thread-local storage requirements.
273268
// See #6233 for rationale and details.
274269
//
275-
// Dynamically resolve the symbol for compatibility with older versions
276-
// of glibc. Assumes that we've been dynamically linked to libpthread
277-
// but that is currently always the case. Note that this means we take
278-
// a dlopen/dlsym/dlclose hit for every new thread. Mitigating that by
279-
// caching the symbol or the function's return value has its drawbacks:
280-
//
281-
// * Caching the symbol breaks when libpthread.so is reloaded because
282-
// its address changes.
283-
//
284-
// * Caching the return value assumes that it's a fixed quantity.
285-
// Not very future-proof and untrue in the presence of guard pages
286-
// The reason __pthread_get_minstack() takes a *libc::pthread_attr_t
287-
// as its argument is because it takes pthread_attr_setguardsize() into
288-
// account.
289-
//
290-
// A better solution is to define __pthread_get_minstack() as a weak symbol
291-
// but there is currently no way to express that in Rust code.
292-
#[cfg(target_os = "linux")]
293-
unsafe fn __pthread_get_minstack(attr: *libc::pthread_attr_t) -> libc::size_t {
294-
use option::None;
295-
use result::{Err, Ok};
296-
use unstable::dynamic_lib;
297-
match dynamic_lib::DynamicLibrary::open(None) {
298-
Err(err) => fail!("DynamicLibrary::open(): {}", err),
299-
Ok(handle) => {
300-
match handle.symbol::<extern "C" fn(*libc::pthread_attr_t) ->
301-
libc::size_t>("__pthread_get_minstack") {
302-
Err(_) => libc::PTHREAD_STACK_MIN,
303-
Ok(__pthread_get_minstack) => __pthread_get_minstack(attr),
304-
}
305-
}
270+
// Link weakly to the symbol for compatibility with older versions of glibc.
271+
// Assumes that we've been dynamically linked to libpthread but that is
272+
// currently always the case. Note that you need to check that the symbol
273+
// is non-null before calling it!
274+
#[cfg(target_os = "linux", not(stage0))]
275+
fn min_stack_size(attr: *libc::pthread_attr_t) -> libc::size_t {
276+
use ptr::RawPtr;
277+
type F = extern "C" unsafe fn(*libc::pthread_attr_t) -> libc::size_t;
278+
extern {
279+
#[linkage = "extern_weak"]
280+
static __pthread_get_minstack: *();
281+
}
282+
if __pthread_get_minstack.is_null() {
283+
PTHREAD_STACK_MIN
284+
} else {
285+
unsafe { cast::transmute::<*(), F>(__pthread_get_minstack)(attr) }
306286
}
307287
}
308288

289+
// __pthread_get_minstack() is marked as weak but extern_weak linkage is
290+
// not supported on OS X, hence this kludge...
291+
#[cfg(not(target_os = "linux"))]
292+
#[cfg(stage0)]
293+
fn min_stack_size(_: *libc::pthread_attr_t) -> libc::size_t {
294+
PTHREAD_STACK_MIN
295+
}
296+
309297
extern {
310298
fn pthread_create(native: *mut libc::pthread_t,
311299
attr: *libc::pthread_attr_t,
@@ -347,3 +335,4 @@ mod tests {
347335
assert_eq!(42, Thread::start_stack(1, proc () 42).join());
348336
}
349337
}
338+
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#[no_mangle]
12+
pub static foo: int = 3;
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
extern {
12+
#[linkage = "extern_weak"] static foo: int;
13+
//~^ ERROR: the `linkage` attribute is experimental and not portable
14+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#[feature(linkage)];
12+
13+
extern {
14+
#[linkage = "extern_weak"] static foo: i32;
15+
//~^ ERROR: must have type `*T`
16+
}
17+
18+
fn main() {
19+
println!("{}", foo);
20+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#[feature(linkage)];
12+
13+
extern {
14+
#[linkage = "foo"] static foo: *i32;
15+
//~^ ERROR: invalid linkage specified
16+
}
17+
18+
fn main() {
19+
println!("{}", foo);
20+
}
21+

0 commit comments

Comments
 (0)