Skip to content

Commit

Permalink
auto merge of #16308 : alexcrichton/rust/rollup, r=alexcrichton
Browse files Browse the repository at this point in the history
  • Loading branch information
bors committed Aug 6, 2014
2 parents dd20f09 + ffa2588 commit 51e19e7
Show file tree
Hide file tree
Showing 24 changed files with 372 additions and 123 deletions.
4 changes: 2 additions & 2 deletions mk/platform.mk
Expand Up @@ -377,7 +377,7 @@ RUSTC_CROSS_FLAGS_arm-unknown-linux-gnueabi :=
# mipsel-linux configuration
CC_mipsel-linux=mipsel-linux-gcc
CXX_mipsel-linux=mipsel-linux-g++
CPP_mipsel-linux=mipsel-linux-gcc
CPP_mipsel-linux=mipsel-linux-gcc
AR_mipsel-linux=mipsel-linux-ar
CFG_LIB_NAME_mipsel-linux=lib$(1).so
CFG_STATIC_LIB_NAME_mipsel-linux=lib$(1).a
Expand Down Expand Up @@ -641,7 +641,7 @@ define CFG_MAKE_TOOLCHAIN
CXX_$(1)=$(CROSS_PREFIX_$(1))$(CXX_$(1))
CPP_$(1)=$(CROSS_PREFIX_$(1))$(CPP_$(1))
AR_$(1)=$(CROSS_PREFIX_$(1))$(AR_$(1))
RUSTC_CROSS_FLAGS_$(1)=-C linker=$$(call FIND_COMPILER,$$(CXX_$(1))) \
RUSTC_CROSS_FLAGS_$(1)=-C linker=$$(call FIND_COMPILER,$$(CC_$(1))) \
-C ar=$$(call FIND_COMPILER,$$(AR_$(1))) $(RUSTC_CROSS_FLAGS_$(1))

RUSTC_FLAGS_$(1)=$$(RUSTC_CROSS_FLAGS_$(1)) $(RUSTC_FLAGS_$(1))
Expand Down
4 changes: 2 additions & 2 deletions src/doc/guide.md
Expand Up @@ -3295,7 +3295,7 @@ fn times_four(x: int) -> int { x * 4 }
#[cfg(test)]
mod test {
use super::add_three;
use super::add_four;
use super::times_four;
#[test]
fn test_add_three() {
Expand Down Expand Up @@ -3344,7 +3344,7 @@ about yet, and that's these lines:

```{rust,ignore}
use super::add_three;
use super::add_four;
use super::times_four;
```

Because we've made a nested module, we can import functions from the parent
Expand Down
Expand Up @@ -266,7 +266,7 @@

<define-regex id="common_escape" extended="true">
'|"|
\\|n|r|t|
\\|n|r|t|0|
x\%{hex_digit}{2}|
u\%{hex_digit}{4}|
U\%{hex_digit}{8}
Expand Down
2 changes: 1 addition & 1 deletion src/etc/get-snapshot.py
Expand Up @@ -53,7 +53,7 @@ def unpack_snapshot(triple, dl_path):
dl_path = sys.argv[2]
else:
# There are no 64-bit Windows snapshots yet, so we'll use 32-bit ones instead, for now
snap_triple = triple if triple != "x86_64-w64-mingw32" else "i686-pc-mingw32"
snap_triple = triple if triple != "x86_64-w64-mingw32" else "i686-w64-mingw32"
snap = determine_curr_snapshot(snap_triple)
dl = os.path.join(download_dir_base, snap)
url = download_url_base + "/" + snap
Expand Down
44 changes: 31 additions & 13 deletions src/libgreen/context.rs
Expand Up @@ -13,6 +13,8 @@ use std::uint;
use std::mem::transmute;
use std::rt::stack;
use std::raw;
#[cfg(target_arch = "x86_64")]
use std::simd;

// FIXME #7761: Registers is boxed so that it is 16-byte aligned, for storing
// SSE regs. It would be marginally better not to do this. In C++ we
Expand Down Expand Up @@ -103,11 +105,11 @@ impl Context {
// invalid for the current task. Lucky for us `rust_swap_registers`
// is a C function so we don't have to worry about that!
match in_context.stack_bounds {
Some((lo, hi)) => stack::record_stack_bounds(lo, hi),
Some((lo, hi)) => stack::record_rust_managed_stack_bounds(lo, hi),
// If we're going back to one of the original contexts or
// something that's possibly not a "normal task", then reset
// the stack limit to 0 to make morestack never fail
None => stack::record_stack_bounds(0, uint::MAX),
None => stack::record_rust_managed_stack_bounds(0, uint::MAX),
}
rust_swap_registers(out_regs, in_regs)
}
Expand Down Expand Up @@ -186,14 +188,30 @@ fn initialize_call_frame(regs: &mut Registers, fptr: InitFn, arg: uint,
// windows requires saving more registers (both general and XMM), so the windows
// register context must be larger.
#[cfg(windows, target_arch = "x86_64")]
type Registers = [uint, ..34];
struct Registers {
gpr:[uint, ..14],
_xmm:[simd::u32x4, ..10]
}
#[cfg(not(windows), target_arch = "x86_64")]
type Registers = [uint, ..22];
struct Registers {
gpr:[uint, ..10],
_xmm:[simd::u32x4, ..6]
}

#[cfg(windows, target_arch = "x86_64")]
fn new_regs() -> Box<Registers> { box() ([0, .. 34]) }
fn new_regs() -> Box<Registers> {
box() Registers {
gpr:[0,..14],
_xmm:[simd::u32x4(0,0,0,0),..10]
}
}
#[cfg(not(windows), target_arch = "x86_64")]
fn new_regs() -> Box<Registers> { box() ([0, .. 22]) }
fn new_regs() -> Box<Registers> {
box() Registers {
gpr:[0,..10],
_xmm:[simd::u32x4(0,0,0,0),..6]
}
}

#[cfg(target_arch = "x86_64")]
fn initialize_call_frame(regs: &mut Registers, fptr: InitFn, arg: uint,
Expand Down Expand Up @@ -222,20 +240,20 @@ fn initialize_call_frame(regs: &mut Registers, fptr: InitFn, arg: uint,

// These registers are frobbed by rust_bootstrap_green_task into the right
// location so we can invoke the "real init function", `fptr`.
regs[RUSTRT_R12] = arg as uint;
regs[RUSTRT_R13] = procedure.code as uint;
regs[RUSTRT_R14] = procedure.env as uint;
regs[RUSTRT_R15] = fptr as uint;
regs.gpr[RUSTRT_R12] = arg as uint;
regs.gpr[RUSTRT_R13] = procedure.code as uint;
regs.gpr[RUSTRT_R14] = procedure.env as uint;
regs.gpr[RUSTRT_R15] = fptr as uint;

// These registers are picked up by the regular context switch paths. These
// will put us in "mostly the right context" except for frobbing all the
// arguments to the right place. We have the small trampoline code inside of
// rust_bootstrap_green_task to do that.
regs[RUSTRT_RSP] = sp as uint;
regs[RUSTRT_IP] = rust_bootstrap_green_task as uint;
regs.gpr[RUSTRT_RSP] = sp as uint;
regs.gpr[RUSTRT_IP] = rust_bootstrap_green_task as uint;

// Last base pointer on the stack should be 0
regs[RUSTRT_RBP] = 0;
regs.gpr[RUSTRT_RBP] = 0;
}

#[cfg(target_arch = "arm")]
Expand Down
2 changes: 1 addition & 1 deletion src/libnative/lib.rs
Expand Up @@ -137,7 +137,7 @@ pub fn start(argc: int, argv: *const *const u8, main: proc()) -> int {
task.name = Some(str::Slice("<main>"));
drop(task.run(|| {
unsafe {
rt::stack::record_stack_bounds(my_stack_bottom, my_stack_top);
rt::stack::record_os_managed_stack_bounds(my_stack_bottom, my_stack_top);
}
exit_code = Some(run(main.take_unwrap()));
}).destroy());
Expand Down
2 changes: 1 addition & 1 deletion src/libnative/task.rs
Expand Up @@ -84,7 +84,7 @@ pub fn spawn_opts(opts: TaskOpts, f: proc():Send) {
let addr = &something_around_the_top_of_the_stack as *const int;
let my_stack = addr as uint;
unsafe {
stack::record_stack_bounds(my_stack - stack + 1024, my_stack);
stack::record_os_managed_stack_bounds(my_stack - stack + 1024, my_stack);
}
let mut ops = ops;
ops.stack_bounds = (my_stack - stack + 1024, my_stack);
Expand Down
5 changes: 5 additions & 0 deletions src/librustdoc/html/static/main.css
Expand Up @@ -120,6 +120,11 @@ code, pre {
font-family: "Source Code Pro", Menlo, Monaco, Consolas, "DejaVu Sans Mono", Inconsolata, monospace;
white-space: pre-wrap;
}
.docblock code {
background-color: #F5F5F5;
border-radius: 3px;
padding: 0 0.2em;
}
pre {
background-color: #F5F5F5;
padding: 14px;
Expand Down
35 changes: 34 additions & 1 deletion src/librustdoc/lib.rs
Expand Up @@ -89,7 +89,40 @@ local_data_key!(pub analysiskey: core::CrateAnalysis)
type Output = (clean::Crate, Vec<plugins::PluginJson> );

pub fn main() {
std::os::set_exit_status(main_args(std::os::args().as_slice()));
// Why run rustdoc in a separate task? That's a good question!
//
// We first begin our adventure at the ancient commit of e7c4fb69. In this
// commit it was discovered that the stack limit frobbing on windows ended
// up causing some syscalls to fail. This was worked around manually in the
// relevant location.
//
// Our journey now continues with #13259 where it was discovered that this
// stack limit frobbing has the ability to affect nearly any syscall. Note
// that the key idea here is that there is currently no knowledge as to why
// this is happening or how to preserve it, fun times!
//
// Now we continue along to #16275 where it was discovered that --test on
// windows didn't work at all! Yet curiously rustdoc worked without --test.
// The exact reason that #16275 cropped up is that during the expansion
// phase the compiler attempted to open libstd to read out its macros. This
// invoked the LLVMRustOpenArchive shim which in turned went to LLVM to go
// open a file and read it. Lo and behold this function returned an error!
// It was then discovered that when the same fix mentioned in #13259 was
// applied, the error went away. The plot thickens!
//
// Remember that rustdoc works without --test, which raises the question of
// how because the --test and non --test paths are almost identical. The
// first thing both paths do is parse and expand a crate! It turns out that
// the difference is that --test runs on the *main task* while the normal
// path runs in subtask. It turns out that running --test in a sub task also
// fixes the problem!
//
// So, in summary, it is unknown why this is necessary, what it is
// preventing, or what the actual bug is. In the meantime, this allows
// --test to work on windows, which seems good, right? Fun times.
spawn(proc() {
std::os::set_exit_status(main_args(std::os::args().as_slice()));
});
}

pub fn opts() -> Vec<getopts::OptGroup> {
Expand Down
2 changes: 1 addition & 1 deletion src/librustrt/libunwind.rs
Expand Up @@ -60,7 +60,7 @@ pub type _Unwind_Word = libc::uintptr_t;
pub static unwinder_private_data_size: uint = 5;

#[cfg(target_arch = "x86_64")]
pub static unwinder_private_data_size: uint = 2;
pub static unwinder_private_data_size: uint = 6;

#[cfg(target_arch = "arm", not(target_os = "ios"))]
pub static unwinder_private_data_size: uint = 20;
Expand Down
32 changes: 24 additions & 8 deletions src/librustrt/stack.rs
Expand Up @@ -124,8 +124,23 @@ extern fn stack_exhausted() {
}
}

// Windows maintains a record of upper and lower stack bounds in the Thread Information
// Block (TIB), and some syscalls do check that addresses which are supposed to be in
// the stack, indeed lie between these two values.
// (See https://github.com/rust-lang/rust/issues/3445#issuecomment-26114839)
//
// When using Rust-managed stacks (libgreen), we must maintain these values accordingly.
// For OS-managed stacks (libnative), we let the OS manage them for us.
//
// On all other platforms both variants behave identically.

#[inline(always)]
pub unsafe fn record_stack_bounds(stack_lo: uint, stack_hi: uint) {
pub unsafe fn record_os_managed_stack_bounds(stack_lo: uint, _stack_hi: uint) {
record_sp_limit(stack_lo + RED_ZONE);
}

#[inline(always)]
pub unsafe fn record_rust_managed_stack_bounds(stack_lo: uint, stack_hi: uint) {
// When the old runtime had segmented stacks, it used a calculation that was
// "limit + RED_ZONE + FUDGE". The red zone was for things like dynamic
// symbol resolution, llvm function calls, etc. In theory this red zone
Expand All @@ -138,16 +153,17 @@ pub unsafe fn record_stack_bounds(stack_lo: uint, stack_hi: uint) {

return target_record_stack_bounds(stack_lo, stack_hi);

#[cfg(not(windows))] #[cfg(not(target_arch = "x86_64"))] #[inline(always)]
#[cfg(not(windows))] #[inline(always)]
unsafe fn target_record_stack_bounds(_stack_lo: uint, _stack_hi: uint) {}

#[cfg(windows, target_arch = "x86")] #[inline(always)]
unsafe fn target_record_stack_bounds(stack_lo: uint, stack_hi: uint) {
// stack range is at TIB: %fs:0x04 (top) and %fs:0x08 (bottom)
asm!("mov $0, %fs:0x04" :: "r"(stack_hi) :: "volatile");
asm!("mov $0, %fs:0x08" :: "r"(stack_lo) :: "volatile");
}
#[cfg(windows, target_arch = "x86_64")] #[inline(always)]
unsafe fn target_record_stack_bounds(stack_lo: uint, stack_hi: uint) {
// Windows compiles C functions which may check the stack bounds. This
// means that if we want to perform valid FFI on windows, then we need
// to ensure that the stack bounds are what they truly are for this
// task. More info can be found at:
// https://github.com/rust-lang/rust/issues/3445#issuecomment-26114839
//
// stack range is at TIB: %gs:0x08 (top) and %gs:0x10 (bottom)
asm!("mov $0, %gs:0x08" :: "r"(stack_hi) :: "volatile");
asm!("mov $0, %gs:0x10" :: "r"(stack_lo) :: "volatile");
Expand Down
2 changes: 1 addition & 1 deletion src/librustrt/thread.rs
Expand Up @@ -44,7 +44,7 @@ static DEFAULT_STACK_SIZE: uint = 1024 * 1024;
#[no_split_stack]
extern fn thread_start(main: *mut libc::c_void) -> imp::rust_thread_return {
unsafe {
stack::record_stack_bounds(0, uint::MAX);
stack::record_os_managed_stack_bounds(0, uint::MAX);
let f: Box<proc()> = mem::transmute(main);
(*f)();
mem::transmute(0 as imp::rust_thread_return)
Expand Down

0 comments on commit 51e19e7

Please sign in to comment.