Skip to content

Commit d02714a

Browse files
committed
---
yaml --- r: 130331 b: refs/heads/auto c: da96062 h: refs/heads/master i: 130329: 2edd9fa 130327: 1d06e9e v: v3
1 parent 267e0c0 commit d02714a

File tree

9 files changed

+150
-51
lines changed

9 files changed

+150
-51
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ refs/heads/try3: 9387340aab40a73e8424c48fd42f0c521a4875c0
1313
refs/tags/release-0.3.1: 495bae036dfe5ec6ceafd3312b4dca48741e845b
1414
refs/tags/release-0.4: e828ea2080499553b97dfe33b3f4d472b4562ad7
1515
refs/tags/release-0.5: 7e3bcfbf21278251ee936ad53e92e9b719702d73
16-
refs/heads/auto: 2e7bc0f808d9ad874010ac610ad796d07127c458
16+
refs/heads/auto: da9606247d5ddd0edebafaffd0367c541fbaee7e
1717
refs/heads/servo: af82457af293e2a842ba6b7759b70288da276167
1818
refs/tags/release-0.6: b4ebcfa1812664df5e142f0134a5faea3918544c
1919
refs/tags/0.1: b19db808c2793fe2976759b85a355c3ad8c8b336

branches/auto/src/librustc/middle/trans/base.rs

Lines changed: 32 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2124,8 +2124,17 @@ impl<'a> Visitor<()> for TransItemVisitor<'a> {
21242124
}
21252125
}
21262126

2127+
pub fn update_linkage(ccx: &CrateContext, llval: ValueRef, id: ast::NodeId) {
2128+
if ccx.reachable().contains(&id) || ccx.sess().opts.cg.codegen_units > 1 {
2129+
llvm::SetLinkage(llval, llvm::ExternalLinkage);
2130+
} else {
2131+
llvm::SetLinkage(llval, llvm::InternalLinkage);
2132+
}
2133+
}
2134+
21272135
pub fn trans_item(ccx: &CrateContext, item: &ast::Item) {
21282136
let _icx = push_ctxt("trans_item");
2137+
21292138
match item.node {
21302139
ast::ItemFn(ref decl, _fn_style, abi, ref generics, ref body) => {
21312140
if !generics.is_type_parameterized() {
@@ -2148,6 +2157,7 @@ pub fn trans_item(ccx: &CrateContext, item: &ast::Item) {
21482157
item.id,
21492158
item.attrs.as_slice());
21502159
}
2160+
update_linkage(ccx, llfn, item.id);
21512161
}
21522162

21532163
// Be sure to travel more than just one layer deep to catch nested
@@ -2163,7 +2173,7 @@ pub fn trans_item(ccx: &CrateContext, item: &ast::Item) {
21632173
item.id);
21642174
}
21652175
ast::ItemMod(ref m) => {
2166-
trans_mod(ccx, m);
2176+
trans_mod(&ccx.rotate(), m);
21672177
}
21682178
ast::ItemEnum(ref enum_definition, _) => {
21692179
enum_variant_size_lint(ccx, enum_definition, item.span, item.id);
@@ -2173,6 +2183,10 @@ pub fn trans_item(ccx: &CrateContext, item: &ast::Item) {
21732183
let mut v = TransItemVisitor{ ccx: ccx };
21742184
v.visit_expr(&**expr, ());
21752185
consts::trans_const(ccx, m, item.id);
2186+
2187+
let g = get_item_val(ccx, item.id);
2188+
update_linkage(ccx, g, item.id);
2189+
21762190
// Do static_assert checking. It can't really be done much earlier
21772191
// because we need to get the value of the bool out of LLVM
21782192
if attr::contains_name(item.attrs.as_slice(), "static_assert") {
@@ -2221,10 +2235,6 @@ fn finish_register_fn(ccx: &CrateContext, sp: Span, sym: String, node_id: ast::N
22212235
llfn: ValueRef) {
22222236
ccx.item_symbols().borrow_mut().insert(node_id, sym);
22232237

2224-
if !ccx.reachable().contains(&node_id) {
2225-
llvm::SetLinkage(llfn, llvm::InternalLinkage);
2226-
}
2227-
22282238
// The stack exhaustion lang item shouldn't have a split stack because
22292239
// otherwise it would continue to be exhausted (bad), and both it and the
22302240
// eh_personality functions need to be externally linkable.
@@ -2592,7 +2602,6 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
25922602
None => {}
25932603
}
25942604

2595-
let mut foreign = false;
25962605
let item = ccx.tcx().map.get(id);
25972606
let val = match item {
25982607
ast_map::NodeItem(i) => {
@@ -2620,10 +2629,6 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
26202629
llvm::LLVMAddGlobal(ccx.llmod(), llty, buf)
26212630
});
26222631

2623-
if !ccx.reachable().contains(&id) {
2624-
llvm::SetLinkage(g, llvm::InternalLinkage);
2625-
}
2626-
26272632
// Apply the `unnamed_addr` attribute if
26282633
// requested
26292634
if !ast_util::static_has_significant_address(
@@ -2714,8 +2719,6 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
27142719
}
27152720

27162721
ast_map::NodeForeignItem(ni) => {
2717-
foreign = true;
2718-
27192722
match ni.node {
27202723
ast::ForeignItemFn(..) => {
27212724
let abi = ccx.tcx().map.get_foreign_abi(id);
@@ -2787,12 +2790,14 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
27872790
}
27882791
};
27892792

2790-
// foreign items (extern fns and extern statics) don't have internal
2791-
// linkage b/c that doesn't quite make sense. Otherwise items can
2792-
// have internal linkage if they're not reachable.
2793-
if !foreign && !ccx.reachable().contains(&id) {
2794-
llvm::SetLinkage(val, llvm::InternalLinkage);
2795-
}
2793+
// All LLVM globals and functions are initially created as external-linkage
2794+
// declarations. If `trans_item`/`trans_fn` later turns the declaration
2795+
// into a definition, it adjusts the linkage then (using `update_linkage`).
2796+
//
2797+
// The exception is foreign items, which have their linkage set inside the
2798+
// call to `foreign::register_*` above. We don't touch the linkage after
2799+
// that (`foreign::trans_foreign_mod` doesn't adjust the linkage like the
2800+
// other item translation functions do).
27962801

27972802
ccx.item_vals().borrow_mut().insert(id, val);
27982803
val
@@ -2815,7 +2820,8 @@ pub fn p2i(ccx: &CrateContext, v: ValueRef) -> ValueRef {
28152820
}
28162821
}
28172822

2818-
pub fn crate_ctxt_to_encode_parms<'r>(cx: &'r CrateContext, ie: encoder::EncodeInlinedItem<'r>)
2823+
pub fn crate_ctxt_to_encode_parms<'r>(cx: &'r SharedCrateContext,
2824+
ie: encoder::EncodeInlinedItem<'r>)
28192825
-> encoder::EncodeParams<'r> {
28202826
encoder::EncodeParams {
28212827
diag: cx.sess().diagnostic(),
@@ -2830,7 +2836,7 @@ pub fn crate_ctxt_to_encode_parms<'r>(cx: &'r CrateContext, ie: encoder::EncodeI
28302836
}
28312837
}
28322838

2833-
pub fn write_metadata(cx: &CrateContext, krate: &ast::Crate) -> Vec<u8> {
2839+
pub fn write_metadata(cx: &SharedCrateContext, krate: &ast::Crate) -> Vec<u8> {
28342840
use flate;
28352841

28362842
let any_library = cx.sess().crate_types.borrow().iter().any(|ty| {
@@ -2905,7 +2911,7 @@ pub fn trans_crate(krate: ast::Crate,
29052911
link_meta.clone(),
29062912
reachable);
29072913

2908-
let metadata = {
2914+
{
29092915
let ccx = shared_ccx.get_ccx(0);
29102916

29112917
// First, verify intrinsics.
@@ -2916,15 +2922,17 @@ pub fn trans_crate(krate: ast::Crate,
29162922
let _icx = push_ctxt("text");
29172923
trans_mod(&ccx, &krate.module);
29182924
}
2925+
}
29192926

2927+
for ccx in shared_ccx.iter() {
29202928
glue::emit_tydescs(&ccx);
29212929
if ccx.sess().opts.debuginfo != NoDebugInfo {
29222930
debuginfo::finalize(&ccx);
29232931
}
2932+
}
29242933

2925-
// Translate the metadata.
2926-
write_metadata(&ccx, &krate)
2927-
};
2934+
// Translate the metadata.
2935+
let metadata = write_metadata(&shared_ccx, &krate);
29282936

29292937
if shared_ccx.sess().trans_stats() {
29302938
let stats = shared_ccx.stats();

branches/auto/src/librustc/middle/trans/builder.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ impl<'a> Builder<'a> {
5050
.n_llvm_insns
5151
.get() + 1);
5252
}
53+
self.ccx.count_llvm_insn();
5354
if self.ccx.sess().count_llvm_insns() {
5455
base::with_insn_ctxt(|v| {
5556
let mut h = self.ccx.stats().llvm_insns.borrow_mut();

branches/auto/src/librustc/middle/trans/consts.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -692,6 +692,15 @@ pub fn trans_const(ccx: &CrateContext, m: ast::Mutability, id: ast::NodeId) {
692692
// constant's initializer to determine its LLVM type.
693693
let v = ccx.const_values().borrow().get_copy(&id);
694694
llvm::LLVMSetInitializer(g, v);
695+
696+
// `get_item_val` left `g` with external linkage, but we just set an
697+
// initializer for it. But we don't know yet if `g` should really be
698+
// defined in this compilation unit, so we set its linkage to
699+
// `AvailableExternallyLinkage`. (It's still a definition, but acts
700+
// like a declaration for most purposes.) If `g` really should be
701+
// declared here, then `trans_item` will fix up the linkage later on.
702+
llvm::SetLinkage(g, llvm::AvailableExternallyLinkage);
703+
695704
if m != ast::MutMutable {
696705
llvm::LLVMSetGlobalConstant(g, True);
697706
}

branches/auto/src/librustc/middle/trans/context.rs

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,11 @@ pub struct LocalCrateContext {
141141
eh_personality: RefCell<Option<ValueRef>>,
142142

143143
intrinsics: RefCell<HashMap<&'static str, ValueRef>>,
144+
145+
/// Number of LLVM instructions translated into this `LocalCrateContext`.
146+
/// This is used to perform some basic load-balancing to keep all LLVM
147+
/// contexts around the same size.
148+
n_llvm_insns: Cell<uint>,
144149
}
145150

146151
pub struct CrateContext<'a> {
@@ -261,6 +266,18 @@ impl SharedCrateContext {
261266
}
262267
}
263268

269+
fn get_smallest_ccx<'a>(&'a self) -> CrateContext<'a> {
270+
let local_ccx =
271+
self.local_ccxs
272+
.iter()
273+
.min_by(|&local_ccx| local_ccx.n_llvm_insns.get())
274+
.unwrap();
275+
CrateContext {
276+
shared: self,
277+
local: local_ccx,
278+
}
279+
}
280+
264281

265282
pub fn metadata_llmod(&self) -> ModuleRef {
266283
self.metadata_llmod
@@ -364,6 +381,7 @@ impl LocalCrateContext {
364381
dbg_cx: dbg_cx,
365382
eh_personality: RefCell::new(None),
366383
intrinsics: RefCell::new(HashMap::new()),
384+
n_llvm_insns: Cell::new(0u),
367385
};
368386

369387
local_ccx.int_type = Type::int(&local_ccx.dummy_ccx(shared));
@@ -415,6 +433,12 @@ impl<'b> CrateContext<'b> {
415433
}
416434

417435

436+
/// Get a (possibly) different `CrateContext` from the same
437+
/// `SharedCrateContext`.
438+
pub fn rotate(&self) -> CrateContext<'b> {
439+
self.shared.get_smallest_ccx()
440+
}
441+
418442
pub fn tcx<'a>(&'a self) -> &'a ty::ctxt {
419443
&self.shared.tcx
420444
}
@@ -467,14 +491,6 @@ impl<'b> CrateContext<'b> {
467491
self.local.llcx
468492
}
469493

470-
pub fn metadata_llmod(&self) -> ModuleRef {
471-
self.shared.metadata_llmod
472-
}
473-
474-
pub fn metadata_llcx(&self) -> ContextRef {
475-
self.shared.metadata_llcx
476-
}
477-
478494
pub fn td<'a>(&'a self) -> &'a TargetData {
479495
&self.local.td
480496
}
@@ -619,6 +635,10 @@ impl<'b> CrateContext<'b> {
619635
fn intrinsics<'a>(&'a self) -> &'a RefCell<HashMap<&'static str, ValueRef>> {
620636
&self.local.intrinsics
621637
}
638+
639+
pub fn count_llvm_insn(&self) {
640+
self.local.n_llvm_insns.set(self.local.n_llvm_insns.get() + 1);
641+
}
622642
}
623643

624644
fn declare_intrinsic(ccx: &CrateContext, key: & &'static str) -> Option<ValueRef> {

branches/auto/src/librustc/middle/trans/expr.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -817,13 +817,28 @@ fn trans_def<'a>(bcx: &'a Block<'a>,
817817
trans_def_fn_unadjusted(bcx, ref_expr, def)
818818
}
819819
def::DefStatic(did, _) => {
820+
// There are three things that may happen here:
821+
// 1) If the static item is defined in this crate, it will be
822+
// translated using `get_item_val`, and we return a pointer to
823+
// the result.
824+
// 2) If the static item is defined in another crate, but is
825+
// marked inlineable, then it will be inlined into this crate
826+
// and then translated with `get_item_val`. Again, we return a
827+
// pointer to the result.
828+
// 3) If the static item is defined in another crate and is not
829+
// marked inlineable, then we add (or reuse) a declaration of
830+
// an external global, and return a pointer to that.
820831
let const_ty = expr_ty(bcx, ref_expr);
821832

822833
fn get_did(ccx: &CrateContext, did: ast::DefId)
823834
-> ast::DefId {
824835
if did.krate != ast::LOCAL_CRATE {
836+
// Case 2 or 3. Which one we're in is determined by
837+
// whether the DefId produced by `maybe_instantiate_inline`
838+
// is in the LOCAL_CRATE or not.
825839
inline::maybe_instantiate_inline(ccx, did)
826840
} else {
841+
// Case 1.
827842
did
828843
}
829844
}
@@ -832,13 +847,17 @@ fn trans_def<'a>(bcx: &'a Block<'a>,
832847
-> ValueRef {
833848
// For external constants, we don't inline.
834849
if did.krate == ast::LOCAL_CRATE {
850+
// Case 1 or 2. (The inlining in case 2 produces a new
851+
// DefId in LOCAL_CRATE.)
852+
835853
// The LLVM global has the type of its initializer,
836854
// which may not be equal to the enum's type for
837855
// non-C-like enums.
838856
let val = base::get_item_val(bcx.ccx(), did.node);
839857
let pty = type_of::type_of(bcx.ccx(), const_ty).ptr_to();
840858
PointerCast(bcx, val, pty)
841859
} else {
860+
// Case 3.
842861
match bcx.ccx().extern_const_values().borrow().find(&did) {
843862
None => {} // Continue.
844863
Some(llval) => {

branches/auto/src/librustc/middle/trans/foreign.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,11 +159,18 @@ pub fn register_static(ccx: &CrateContext,
159159
}
160160
};
161161
unsafe {
162+
// Declare a symbol `foo` with the desired linkage.
162163
let g1 = ident.get().with_c_str(|buf| {
163164
llvm::LLVMAddGlobal(ccx.llmod(), llty2.to_ref(), buf)
164165
});
165166
llvm::SetLinkage(g1, linkage);
166167

168+
// Declare an internal global `extern_with_linkage_foo` which
169+
// is initialized with the address of `foo`. If `foo` is
170+
// discarded during linking (for example, if `foo` has weak
171+
// linkage and there are no definitions), then
172+
// `extern_with_linkage_foo` will instead be initialized to
173+
// zero.
167174
let mut real_name = "_rust_extern_with_linkage_".to_string();
168175
real_name.push_str(ident.get());
169176
let g2 = real_name.with_c_str(|buf| {
@@ -175,6 +182,7 @@ pub fn register_static(ccx: &CrateContext,
175182
}
176183
}
177184
None => unsafe {
185+
// Generate an external declaration.
178186
ident.get().with_c_str(|buf| {
179187
llvm::LLVMAddGlobal(ccx.llmod(), llty.to_ref(), buf)
180188
})
@@ -490,6 +498,10 @@ pub fn trans_foreign_mod(ccx: &CrateContext, foreign_mod: &ast::ForeignMod) {
490498
register_foreign_item_fn(ccx, abi, ty,
491499
lname.get().as_slice(),
492500
Some(foreign_item.span));
501+
// Unlike for other items, we shouldn't call
502+
// `base::update_linkage` here. Foreign items have
503+
// special linkage requirements, which are handled
504+
// inside `foreign::register_*`.
493505
}
494506
}
495507
}

0 commit comments

Comments
 (0)