Skip to content

Commit ae94d18

Browse files
committed
Merge pull request #28802 from alexcrichton/beta-backport
Backporting accepted PRs to beta
2 parents d2e13e8 + 773cf0f commit ae94d18

File tree

4 files changed

+149
-32
lines changed

4 files changed

+149
-32
lines changed

src/libcollections/vec_deque.rs

+40-1
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,11 @@
2121
use core::cmp::Ordering;
2222
use core::fmt;
2323
use core::iter::{repeat, FromIterator};
24+
use core::mem;
2425
use core::ops::{Index, IndexMut};
2526
use core::ptr;
2627
use core::slice;
28+
use core::usize;
2729

2830
use core::hash::{Hash, Hasher};
2931
use core::cmp;
@@ -32,6 +34,7 @@ use alloc::raw_vec::RawVec;
3234

3335
const INITIAL_CAPACITY: usize = 7; // 2^3 - 1
3436
const MINIMUM_CAPACITY: usize = 1; // 2 - 1
37+
const MAXIMUM_ZST_CAPACITY: usize = 1 << (usize::BITS - 1); // Largest possible power of two
3538

3639
/// `VecDeque` is a growable ring buffer, which can be used as a
3740
/// double-ended queue efficiently.
@@ -83,7 +86,12 @@ impl<T> VecDeque<T> {
8386
/// Marginally more convenient
8487
#[inline]
8588
fn cap(&self) -> usize {
86-
self.buf.cap()
89+
if mem::size_of::<T>() == 0 {
90+
// For zero sized types, we are always at maximum capacity
91+
MAXIMUM_ZST_CAPACITY
92+
} else {
93+
self.buf.cap()
94+
}
8795
}
8896

8997
/// Turn ptr into a slice
@@ -1465,6 +1473,7 @@ impl<T: Clone> VecDeque<T> {
14651473
#[inline]
14661474
fn wrap_index(index: usize, size: usize) -> usize {
14671475
// size is always a power of 2
1476+
debug_assert!(size.is_power_of_two());
14681477
index & (size - 1)
14691478
}
14701479

@@ -2032,4 +2041,34 @@ mod tests {
20322041
}
20332042
}
20342043
}
2044+
2045+
#[test]
2046+
fn test_zst_push() {
2047+
const N: usize = 8;
2048+
2049+
// Zero sized type
2050+
struct Zst;
2051+
2052+
// Test that for all possible sequences of push_front / push_back,
2053+
// we end up with a deque of the correct size
2054+
2055+
for len in 0..N {
2056+
let mut tester = VecDeque::with_capacity(len);
2057+
assert_eq!(tester.len(), 0);
2058+
assert!(tester.capacity() >= len);
2059+
for case in 0..(1 << len) {
2060+
assert_eq!(tester.len(), 0);
2061+
for bit in 0..len {
2062+
if case & (1 << bit) != 0 {
2063+
tester.push_front(Zst);
2064+
} else {
2065+
tester.push_back(Zst);
2066+
}
2067+
}
2068+
assert_eq!(tester.len(), len);
2069+
assert_eq!(tester.iter().count(), len);
2070+
tester.clear();
2071+
}
2072+
}
2073+
}
20352074
}

src/librustc_trans/trans/base.rs

+77-31
Original file line numberDiff line numberDiff line change
@@ -2570,20 +2570,6 @@ fn internalize_symbols(cx: &SharedCrateContext, reachable: &HashSet<&str>) {
25702570
unsafe {
25712571
let mut declared = HashSet::new();
25722572

2573-
let iter_globals = |llmod| {
2574-
ValueIter {
2575-
cur: llvm::LLVMGetFirstGlobal(llmod),
2576-
step: llvm::LLVMGetNextGlobal,
2577-
}
2578-
};
2579-
2580-
let iter_functions = |llmod| {
2581-
ValueIter {
2582-
cur: llvm::LLVMGetFirstFunction(llmod),
2583-
step: llvm::LLVMGetNextFunction,
2584-
}
2585-
};
2586-
25872573
// Collect all external declarations in all compilation units.
25882574
for ccx in cx.iter() {
25892575
for val in iter_globals(ccx.llmod()).chain(iter_functions(ccx.llmod())) {
@@ -2623,28 +2609,83 @@ fn internalize_symbols(cx: &SharedCrateContext, reachable: &HashSet<&str>) {
26232609
}
26242610
}
26252611
}
2612+
}
2613+
2614+
// Create a `__imp_<symbol> = &symbol` global for every public static `symbol`.
2615+
// This is required to satisfy `dllimport` references to static data in .rlibs
2616+
// when using MSVC linker. We do this only for data, as linker can fix up
2617+
// code references on its own.
2618+
// See #26591, #27438
2619+
fn create_imps(cx: &SharedCrateContext) {
2620+
// The x86 ABI seems to require that leading underscores are added to symbol
2621+
// names, so we need an extra underscore on 32-bit. There's also a leading
2622+
// '\x01' here which disables LLVM's symbol mangling (e.g. no extra
2623+
// underscores added in front).
2624+
let prefix = if cx.sess().target.target.target_pointer_width == "32" {
2625+
"\x01__imp__"
2626+
} else {
2627+
"\x01__imp_"
2628+
};
2629+
unsafe {
2630+
for ccx in cx.iter() {
2631+
let exported: Vec<_> = iter_globals(ccx.llmod())
2632+
.filter(|&val| llvm::LLVMGetLinkage(val) == llvm::ExternalLinkage as c_uint &&
2633+
llvm::LLVMIsDeclaration(val) == 0)
2634+
.collect();
2635+
2636+
let i8p_ty = Type::i8p(&ccx);
2637+
for val in exported {
2638+
let name = CStr::from_ptr(llvm::LLVMGetValueName(val));
2639+
let mut imp_name = prefix.as_bytes().to_vec();
2640+
imp_name.extend(name.to_bytes());
2641+
let imp_name = CString::new(imp_name).unwrap();
2642+
let imp = llvm::LLVMAddGlobal(ccx.llmod(), i8p_ty.to_ref(),
2643+
imp_name.as_ptr() as *const _);
2644+
let init = llvm::LLVMConstBitCast(val, i8p_ty.to_ref());
2645+
llvm::LLVMSetInitializer(imp, init);
2646+
llvm::SetLinkage(imp, llvm::ExternalLinkage);
2647+
}
2648+
}
2649+
}
2650+
}
26262651

2652+
struct ValueIter {
2653+
cur: ValueRef,
2654+
step: unsafe extern "C" fn(ValueRef) -> ValueRef,
2655+
}
2656+
2657+
impl Iterator for ValueIter {
2658+
type Item = ValueRef;
26272659

2628-
struct ValueIter {
2629-
cur: ValueRef,
2630-
step: unsafe extern "C" fn(ValueRef) -> ValueRef,
2660+
fn next(&mut self) -> Option<ValueRef> {
2661+
let old = self.cur;
2662+
if !old.is_null() {
2663+
self.cur = unsafe {
2664+
let step: unsafe extern "C" fn(ValueRef) -> ValueRef =
2665+
mem::transmute_copy(&self.step);
2666+
step(old)
2667+
};
2668+
Some(old)
2669+
} else {
2670+
None
2671+
}
26312672
}
2673+
}
26322674

2633-
impl Iterator for ValueIter {
2634-
type Item = ValueRef;
2675+
fn iter_globals(llmod: llvm::ModuleRef) -> ValueIter {
2676+
unsafe {
2677+
ValueIter {
2678+
cur: llvm::LLVMGetFirstGlobal(llmod),
2679+
step: llvm::LLVMGetNextGlobal,
2680+
}
2681+
}
2682+
}
26352683

2636-
fn next(&mut self) -> Option<ValueRef> {
2637-
let old = self.cur;
2638-
if !old.is_null() {
2639-
self.cur = unsafe {
2640-
let step: unsafe extern "C" fn(ValueRef) -> ValueRef =
2641-
mem::transmute_copy(&self.step);
2642-
step(old)
2643-
};
2644-
Some(old)
2645-
} else {
2646-
None
2647-
}
2684+
fn iter_functions(llmod: llvm::ModuleRef) -> ValueIter {
2685+
unsafe {
2686+
ValueIter {
2687+
cur: llvm::LLVMGetFirstFunction(llmod),
2688+
step: llvm::LLVMGetNextFunction,
26482689
}
26492690
}
26502691
}
@@ -2824,6 +2865,11 @@ pub fn trans_crate(tcx: &ty::ctxt, analysis: ty::CrateAnalysis) -> CrateTranslat
28242865
&reachable_symbols.iter().map(|x| &x[..]).collect());
28252866
}
28262867

2868+
if sess.target.target.options.is_like_msvc &&
2869+
sess.crate_types.borrow().iter().any(|ct| *ct == config::CrateTypeRlib) {
2870+
create_imps(&shared_ccx);
2871+
}
2872+
28272873
let metadata_module = ModuleTranslation {
28282874
llcx: shared_ccx.metadata_llcx(),
28292875
llmod: shared_ccx.metadata_llmod(),
+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright 2015 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-prefer-dynamic
12+
13+
#![crate_type = "rlib"]
14+
15+
pub static FOO: i32 = 42;

src/test/run-pass/msvc-data-only.rs

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright 2015 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+
// aux-build:msvc-data-only-lib.rs
12+
13+
extern crate msvc_data_only_lib;
14+
15+
fn main() {
16+
println!("The answer is {} !", msvc_data_only_lib::FOO);
17+
}

0 commit comments

Comments
 (0)