diff --git a/mk/platform.mk b/mk/platform.mk index 29643ea25f707..b1128bc40cc5c 100644 --- a/mk/platform.mk +++ b/mk/platform.mk @@ -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 @@ -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)) diff --git a/src/doc/guide.md b/src/doc/guide.md index 0236cc0533fc7..a64783b8b5e21 100644 --- a/src/doc/guide.md +++ b/src/doc/guide.md @@ -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() { @@ -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 diff --git a/src/etc/gedit/share/gtksourceview-3.0/language-specs/rust.lang b/src/etc/gedit/share/gtksourceview-3.0/language-specs/rust.lang index befac48a7438e..b54de8802cf5c 100644 --- a/src/etc/gedit/share/gtksourceview-3.0/language-specs/rust.lang +++ b/src/etc/gedit/share/gtksourceview-3.0/language-specs/rust.lang @@ -266,7 +266,7 @@ '|"| - \\|n|r|t| + \\|n|r|t|0| x\%{hex_digit}{2}| u\%{hex_digit}{4}| U\%{hex_digit}{8} diff --git a/src/etc/get-snapshot.py b/src/etc/get-snapshot.py index ec87c321f56f9..c5acb69df8d73 100755 --- a/src/etc/get-snapshot.py +++ b/src/etc/get-snapshot.py @@ -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 diff --git a/src/libgreen/context.rs b/src/libgreen/context.rs index 8c60f3d9fe1dc..b63758cdcc5e7 100644 --- a/src/libgreen/context.rs +++ b/src/libgreen/context.rs @@ -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 @@ -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) } @@ -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 { box() ([0, .. 34]) } +fn new_regs() -> Box { + box() Registers { + gpr:[0,..14], + _xmm:[simd::u32x4(0,0,0,0),..10] + } +} #[cfg(not(windows), target_arch = "x86_64")] -fn new_regs() -> Box { box() ([0, .. 22]) } +fn new_regs() -> Box { + 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, @@ -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")] diff --git a/src/libnative/lib.rs b/src/libnative/lib.rs index d358aa6b6453e..c7b89b6cb9153 100644 --- a/src/libnative/lib.rs +++ b/src/libnative/lib.rs @@ -137,7 +137,7 @@ pub fn start(argc: int, argv: *const *const u8, main: proc()) -> int { task.name = Some(str::Slice("
")); 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()); diff --git a/src/libnative/task.rs b/src/libnative/task.rs index c72d6c24a7c16..55806caaf1352 100644 --- a/src/libnative/task.rs +++ b/src/libnative/task.rs @@ -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); diff --git a/src/librustdoc/html/static/main.css b/src/librustdoc/html/static/main.css index 64a0665d4008b..f579123fc462b 100644 --- a/src/librustdoc/html/static/main.css +++ b/src/librustdoc/html/static/main.css @@ -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; diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index ddd06e427d7df..fb974403858a0 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -89,7 +89,40 @@ local_data_key!(pub analysiskey: core::CrateAnalysis) type Output = (clean::Crate, Vec ); 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 { diff --git a/src/librustrt/libunwind.rs b/src/librustrt/libunwind.rs index 789723af1b133..db6308c10dcf2 100644 --- a/src/librustrt/libunwind.rs +++ b/src/librustrt/libunwind.rs @@ -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; diff --git a/src/librustrt/stack.rs b/src/librustrt/stack.rs index 6544c020e0949..c941107d7e81a 100644 --- a/src/librustrt/stack.rs +++ b/src/librustrt/stack.rs @@ -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 @@ -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"); diff --git a/src/librustrt/thread.rs b/src/librustrt/thread.rs index 7bc991cf72f3a..43364466dbe39 100644 --- a/src/librustrt/thread.rs +++ b/src/librustrt/thread.rs @@ -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 = mem::transmute(main); (*f)(); mem::transmute(0 as imp::rust_thread_return) diff --git a/src/librustrt/unwind.rs b/src/librustrt/unwind.rs index 1f170bab28e0f..117f680011e5b 100644 --- a/src/librustrt/unwind.rs +++ b/src/librustrt/unwind.rs @@ -220,14 +220,21 @@ fn rust_exception_class() -> uw::_Unwind_Exception_Class { // // This is pretty close to Rust's exception handling approach, except that Rust // does have a single "catch-all" handler at the bottom of each task's stack. -// So we have two versions: +// So we have two versions of the personality routine: // - rust_eh_personality, used by all cleanup landing pads, which never catches, // so the behavior of __gcc_personality_v0 is perfectly adequate there, and // - rust_eh_personality_catch, used only by rust_try(), which always catches. -// This is achieved by overriding the return value in search phase to always -// say "catch!". +// +// Note, however, that for implementation simplicity, rust_eh_personality_catch +// lacks code to install a landing pad, so in order to obtain exception object +// pointer (which it needs to return upstream), rust_try() employs another trick: +// it calls into the nested rust_try_inner(), whose landing pad does not resume +// unwinds. Instead, it extracts the exception pointer and performs a "normal" +// return. +// +// See also: rt/rust_try.ll -#[cfg(not(target_arch = "arm"), not(test))] +#[cfg(not(target_arch = "arm"), not(windows, target_arch = "x86_64"), not(test))] #[doc(hidden)] #[allow(visible_private_types)] pub mod eabi { @@ -244,7 +251,8 @@ pub mod eabi { } #[lang="eh_personality"] - extern fn eh_personality( + #[no_mangle] // referenced from rust_try.ll + extern fn rust_eh_personality( version: c_int, actions: uw::_Unwind_Action, exception_class: uw::_Unwind_Exception_Class, @@ -260,21 +268,19 @@ pub mod eabi { #[no_mangle] // referenced from rust_try.ll pub extern "C" fn rust_eh_personality_catch( - version: c_int, + _version: c_int, actions: uw::_Unwind_Action, - exception_class: uw::_Unwind_Exception_Class, - ue_header: *mut uw::_Unwind_Exception, - context: *mut uw::_Unwind_Context + _exception_class: uw::_Unwind_Exception_Class, + _ue_header: *mut uw::_Unwind_Exception, + _context: *mut uw::_Unwind_Context ) -> uw::_Unwind_Reason_Code { + if (actions as c_int & uw::_UA_SEARCH_PHASE as c_int) != 0 { // search phase uw::_URC_HANDLER_FOUND // catch! } else { // cleanup phase - unsafe { - __gcc_personality_v0(version, actions, exception_class, ue_header, - context) - } + uw::_URC_INSTALL_CONTEXT } } } @@ -299,7 +305,7 @@ pub mod eabi { } #[lang="eh_personality"] - #[no_mangle] // so we can reference it by name from middle/trans/base.rs + #[no_mangle] // referenced from rust_try.ll pub extern "C" fn rust_eh_personality( version: c_int, actions: uw::_Unwind_Action, @@ -316,21 +322,18 @@ pub mod eabi { #[no_mangle] // referenced from rust_try.ll pub extern "C" fn rust_eh_personality_catch( - version: c_int, + _version: c_int, actions: uw::_Unwind_Action, - exception_class: uw::_Unwind_Exception_Class, - ue_header: *mut uw::_Unwind_Exception, - context: *mut uw::_Unwind_Context + _exception_class: uw::_Unwind_Exception_Class, + _ue_header: *mut uw::_Unwind_Exception, + _context: *mut uw::_Unwind_Context ) -> uw::_Unwind_Reason_Code { if (actions as c_int & uw::_UA_SEARCH_PHASE as c_int) != 0 { // search phase uw::_URC_HANDLER_FOUND // catch! } else { // cleanup phase - unsafe { - __gcc_personality_sj0(version, actions, exception_class, ue_header, - context) - } + uw::_URC_INSTALL_CONTEXT } } } @@ -338,7 +341,8 @@ pub mod eabi { // ARM EHABI uses a slightly different personality routine signature, // but otherwise works the same. -#[cfg(target_arch = "arm", not(test), not(target_os = "ios"))] +#[cfg(target_arch = "arm", not(target_os = "ios"), not(test))] +#[doc(hidden)] #[allow(visible_private_types)] pub mod eabi { use uw = libunwind; @@ -352,7 +356,8 @@ pub mod eabi { } #[lang="eh_personality"] - extern "C" fn eh_personality( + #[no_mangle] // referenced from rust_try.ll + extern "C" fn rust_eh_personality( state: uw::_Unwind_State, ue_header: *mut uw::_Unwind_Exception, context: *mut uw::_Unwind_Context @@ -366,8 +371,8 @@ pub mod eabi { #[no_mangle] // referenced from rust_try.ll pub extern "C" fn rust_eh_personality_catch( state: uw::_Unwind_State, - ue_header: *mut uw::_Unwind_Exception, - context: *mut uw::_Unwind_Context + _ue_header: *mut uw::_Unwind_Exception, + _context: *mut uw::_Unwind_Context ) -> uw::_Unwind_Reason_Code { if (state as c_int & uw::_US_ACTION_MASK as c_int) @@ -375,10 +380,107 @@ pub mod eabi { uw::_URC_HANDLER_FOUND // catch! } else { // cleanup phase - unsafe { - __gcc_personality_v0(state, ue_header, context) + uw::_URC_INSTALL_CONTEXT + } + } +} + +// Win64 SEH (see http://msdn.microsoft.com/en-us/library/1eyas8tf.aspx) +// +// This looks a bit convoluted because rather than implementing a native SEH handler, +// GCC reuses the same personality routine as for the other architectures by wrapping it +// with an "API translator" layer (_GCC_specific_handler). + +#[cfg(windows, target_arch = "x86_64", not(test))] +#[doc(hidden)] +#[allow(visible_private_types)] +#[allow(non_camel_case_types)] +pub mod eabi { + use uw = libunwind; + use libc::{c_void, c_int}; + + struct EXCEPTION_RECORD; + struct CONTEXT; + struct DISPATCHER_CONTEXT; + + #[repr(C)] + enum EXCEPTION_DISPOSITION { + ExceptionContinueExecution, + ExceptionContinueSearch, + ExceptionNestedException, + ExceptionCollidedUnwind + } + + type _Unwind_Personality_Fn = + extern "C" fn( + version: c_int, + actions: uw::_Unwind_Action, + exception_class: uw::_Unwind_Exception_Class, + ue_header: *mut uw::_Unwind_Exception, + context: *mut uw::_Unwind_Context + ) -> uw::_Unwind_Reason_Code; + + extern "C" { + fn __gcc_personality_seh0( + exceptionRecord: *mut EXCEPTION_RECORD, + establisherFrame: *mut c_void, + contextRecord: *mut CONTEXT, + dispatcherContext: *mut DISPATCHER_CONTEXT + ) -> EXCEPTION_DISPOSITION; + + fn _GCC_specific_handler( + exceptionRecord: *mut EXCEPTION_RECORD, + establisherFrame: *mut c_void, + contextRecord: *mut CONTEXT, + dispatcherContext: *mut DISPATCHER_CONTEXT, + personality: _Unwind_Personality_Fn + ) -> EXCEPTION_DISPOSITION; + } + + #[lang="eh_personality"] + #[no_mangle] // referenced from rust_try.ll + extern "C" fn rust_eh_personality( + exceptionRecord: *mut EXCEPTION_RECORD, + establisherFrame: *mut c_void, + contextRecord: *mut CONTEXT, + dispatcherContext: *mut DISPATCHER_CONTEXT + ) -> EXCEPTION_DISPOSITION + { + unsafe { + __gcc_personality_seh0(exceptionRecord, establisherFrame, + contextRecord, dispatcherContext) + } + } + + #[no_mangle] // referenced from rust_try.ll + pub extern "C" fn rust_eh_personality_catch( + exceptionRecord: *mut EXCEPTION_RECORD, + establisherFrame: *mut c_void, + contextRecord: *mut CONTEXT, + dispatcherContext: *mut DISPATCHER_CONTEXT + ) -> EXCEPTION_DISPOSITION + { + extern "C" fn inner( + _version: c_int, + actions: uw::_Unwind_Action, + _exception_class: uw::_Unwind_Exception_Class, + _ue_header: *mut uw::_Unwind_Exception, + _context: *mut uw::_Unwind_Context + ) -> uw::_Unwind_Reason_Code + { + if (actions as c_int & uw::_UA_SEARCH_PHASE as c_int) != 0 { // search phase + uw::_URC_HANDLER_FOUND // catch! + } + else { // cleanup phase + uw::_URC_INSTALL_CONTEXT } } + + unsafe { + _GCC_specific_handler(exceptionRecord, establisherFrame, + contextRecord, dispatcherContext, + inner) + } } } diff --git a/src/libstd/rand/os.rs b/src/libstd/rand/os.rs index 60e2c4c894919..ffe8e539ffba1 100644 --- a/src/libstd/rand/os.rs +++ b/src/libstd/rand/os.rs @@ -136,10 +136,11 @@ mod imp { use rand::Rng; use result::{Ok, Err}; use rt::stack; - use self::libc::{c_ulong, DWORD, BYTE, LPCSTR, BOOL}; + use self::libc::{DWORD, BYTE, LPCSTR, BOOL}; + use self::libc::types::os::arch::extra::{LONG_PTR}; use slice::MutableVector; - type HCRYPTPROV = c_ulong; + type HCRYPTPROV = LONG_PTR; /// A random number generator that retrieves randomness straight from /// the operating system. Platform sources: diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 8f960e37de2e7..5b70ed609d98f 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -21,6 +21,7 @@ use std::gc::Gc; use std::io::File; use std::rc::Rc; use std::str; +use std::iter; pub mod lexer; pub mod parser; @@ -327,7 +328,7 @@ pub fn str_lit(lit: &str) -> String { let error = |i| format!("lexer should have rejected {} at {}", lit, i); /// Eat everything up to a non-whitespace - fn eat<'a>(it: &mut ::std::iter::Peekable<(uint, char), ::std::str::CharOffsets<'a>>) { + fn eat<'a>(it: &mut iter::Peekable<(uint, char), str::CharOffsets<'a>>) { loop { match it.peek().map(|x| x.val1()) { Some(' ') | Some('\n') | Some('\r') | Some('\t') => { @@ -471,35 +472,54 @@ pub fn binary_lit(lit: &str) -> Rc> { // FIXME #8372: This could be a for-loop if it didn't borrow the iterator let error = |i| format!("lexer should have rejected {} at {}", lit, i); + /// Eat everything up to a non-whitespace + fn eat<'a, I: Iterator<(uint, u8)>>(it: &mut iter::Peekable<(uint, u8), I>) { + loop { + match it.peek().map(|x| x.val1()) { + Some(b' ') | Some(b'\n') | Some(b'\r') | Some(b'\t') => { + it.next(); + }, + _ => { break; } + } + } + } + // binary literals *must* be ASCII, but the escapes don't have to be - let mut chars = lit.as_bytes().iter().enumerate().peekable(); + let mut chars = lit.bytes().enumerate().peekable(); loop { match chars.next() { - Some((i, &c)) => { - if c == b'\\' { - if *chars.peek().expect(error(i).as_slice()).val1() == b'\n' { - loop { - // eat everything up to a non-whitespace - match chars.peek().map(|x| *x.val1()) { - Some(b' ') | Some(b'\n') | Some(b'\r') | Some(b'\t') => { - chars.next(); - }, - _ => { break; } - } + Some((i, b'\\')) => { + let em = error(i); + match chars.peek().expect(em.as_slice()).val1() { + b'\n' => eat(&mut chars), + b'\r' => { + chars.next(); + if chars.peek().expect(em.as_slice()).val1() != b'\n' { + fail!("lexer accepted bare CR"); } - } else { + eat(&mut chars); + } + _ => { // otherwise, a normal escape let (c, n) = byte_lit(lit.slice_from(i)); - for _ in range(0, n - 1) { // we don't need to move past the first \ + // we don't need to move past the first \ + for _ in range(0, n - 1) { chars.next(); } res.push(c); } - } else { - res.push(c); } }, - None => { break; } + Some((i, b'\r')) => { + let em = error(i); + if chars.peek().expect(em.as_slice()).val1() != b'\n' { + fail!("lexer accepted bare CR"); + } + chars.next(); + res.push(b'\n'); + } + Some((_, c)) => res.push(c), + None => break, } } diff --git a/src/llvm b/src/llvm index 0d999e5b315b6..90a314162053a 160000 --- a/src/llvm +++ b/src/llvm @@ -1 +1 @@ -Subproject commit 0d999e5b315b6ff78fcea772466d985ce53fd8dc +Subproject commit 90a314162053a0c51a50a1c603c9203bef241e0d diff --git a/src/rt/rust_try.ll b/src/rt/rust_try.ll index c912aa789bf6b..33d2d31a2e0c1 100644 --- a/src/rt/rust_try.ll +++ b/src/rt/rust_try.ll @@ -11,24 +11,41 @@ ; Rust's try-catch ; When f(...) returns normally, the return value is null. ; When f(...) throws, the return value is a pointer to the caught exception object. -; See also: libstd/rt/unwind.rs + +; See also: librustrt/unwind.rs define i8* @rust_try(void (i8*,i8*)* %f, i8* %fptr, i8* %env) { - invoke void %f(i8* %fptr, i8* %env) - to label %normal - unwind label %catch + %1 = invoke i8* @rust_try_inner(void (i8*,i8*)* %f, i8* %fptr, i8* %env) + to label %normal + unwind label %catch normal: - ret i8* null + ret i8* %1 catch: - %1 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @rust_eh_personality_catch to i8*) - catch i8* null ; catch everything + landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @rust_eh_personality_catch to i8*) + catch i8* null + ; rust_try_inner's landing pad does not resume unwinds, so execution will never reach here + ret i8* null +} + +define internal i8* @rust_try_inner(void (i8*,i8*)* %f, i8* %fptr, i8* %env) { + + invoke void %f(i8* %fptr, i8* %env) + to label %normal + unwind label %catch - ; extract and return pointer to the exception object +normal: + ret i8* null + +catch: + %1 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @rust_eh_personality to i8*) + catch i8* null + ; extract and return pointer to the exception object %2 = extractvalue { i8*, i32 } %1, 0 - ret i8* %2 + ret i8* %2 } +declare i32 @rust_eh_personality(...) declare i32 @rust_eh_personality_catch(...) diff --git a/src/rt/valgrind/valgrind.h b/src/rt/valgrind/valgrind.h index 3c2098cd7bd76..af01dfd71a71c 100644 --- a/src/rt/valgrind/valgrind.h +++ b/src/rt/valgrind/valgrind.h @@ -21,16 +21,16 @@ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. The origin of this software must not be misrepresented; you must - not claim that you wrote the original software. If you use this - software in a product, an acknowledgment in the product + 2. The origin of this software must not be misrepresented; you must + not claim that you wrote the original software. If you use this + software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 3. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. - 4. The name of the author may not be used to endorse or promote - products derived from this software without specific prior written + 4. The name of the author may not be used to endorse or promote + products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS @@ -52,13 +52,13 @@ the terms of the GNU General Public License, version 2. See the COPYING file in the source distribution for details. - ---------------------------------------------------------------- + ---------------------------------------------------------------- */ /* This file is for inclusion into client (your!) code. - You can use these macros to manipulate and query Valgrind's + You can use these macros to manipulate and query Valgrind's execution inside your own programs. The resulting executables will still run without Valgrind, just a @@ -126,11 +126,11 @@ # define PLAT_x86_darwin 1 #elif defined(__APPLE__) && defined(__x86_64__) # define PLAT_amd64_darwin 1 +#elif defined(__MINGW64__) || (defined(_WIN64) && defined(_M_X64)) +# define PLAT_amd64_win64 1 #elif defined(__MINGW32__) || defined(__CYGWIN32__) \ || (defined(_WIN32) && defined(_M_IX86)) # define PLAT_x86_win32 1 -#elif defined(__MINGW64__) || (defined(_WIN64) && defined(_M_X64)) -# define PLAT_amd64_win64 1 #elif defined(__linux__) && defined(__i386__) # define PLAT_x86_linux 1 #elif defined(__linux__) && defined(__x86_64__) @@ -214,8 +214,8 @@ this is executed not under Valgrind. Args are passed in a memory block, and so there's no intrinsic limit to the number that could be passed, but it's currently five. - - The macro args are: + + The macro args are: _zzq_rlval result lvalue _zzq_default default value (result returned when running on real CPU) _zzq_request request code @@ -242,7 +242,7 @@ || (defined(PLAT_x86_win32) && defined(__GNUC__)) typedef - struct { + struct { unsigned int nraddr; /* where's the code? */ } OrigFn; @@ -306,7 +306,7 @@ typedef #if defined(PLAT_x86_win32) && !defined(__GNUC__) typedef - struct { + struct { unsigned int nraddr; /* where's the code? */ } OrigFn; @@ -374,12 +374,13 @@ valgrind_do_client_request_expr(uintptr_t _zzq_default, uintptr_t _zzq_request, #endif /* PLAT_x86_win32 */ -/* ------------------------ amd64-{linux,darwin} --------------- */ +/* -------------------- amd64-{linux,darwin,win64} ------------- */ -#if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin) +#if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin) \ + || defined(PLAT_amd64_win64) typedef - struct { + struct { unsigned long long int nraddr; /* where's the code? */ } OrigFn; @@ -443,7 +444,7 @@ typedef #if defined(PLAT_ppc32_linux) typedef - struct { + struct { unsigned int nraddr; /* where's the code? */ } OrigFn; @@ -512,7 +513,7 @@ typedef #if defined(PLAT_ppc64_linux) typedef - struct { + struct { unsigned long long int nraddr; /* where's the code? */ unsigned long long int r2; /* what tocptr do we need? */ } @@ -591,7 +592,7 @@ typedef #if defined(PLAT_arm_linux) typedef - struct { + struct { unsigned int nraddr; /* where's the code? */ } OrigFn; @@ -736,7 +737,7 @@ typedef #if defined(PLAT_mips32_linux) typedef - struct { + struct { unsigned int nraddr; /* where's the code? */ } OrigFn; @@ -750,7 +751,7 @@ typedef "srl $0, $0, 29\n\t" \ "srl $0, $0, 3\n\t" \ "srl $0, $0, 19\n\t" - + #define VALGRIND_DO_CLIENT_REQUEST_EXPR( \ _zzq_default, _zzq_request, \ _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ @@ -1999,7 +2000,7 @@ typedef #define VALGRIND_RESTORE_STACK \ "mr 1,28\n\t" -/* These CALL_FN_ macros assume that on ppc32-linux, +/* These CALL_FN_ macros assume that on ppc32-linux, sizeof(unsigned long) == 4. */ #define CALL_FN_W_v(lval, orig) \ @@ -3509,7 +3510,7 @@ typedef #define __CALLER_SAVED_REGS "0","1","2","3","4","5","14", \ "f0","f1","f2","f3","f4","f5","f6","f7" -/* Nb: Although r11 is modified in the asm snippets below (inside +/* Nb: Although r11 is modified in the asm snippets below (inside VALGRIND_CFI_PROLOGUE) it is not listed in the clobber section, for two reasons: (1) r11 is restored in VALGRIND_CFI_EPILOGUE, so effectively it is not @@ -3959,7 +3960,7 @@ typedef #endif /* PLAT_s390x_linux */ /* ------------------------- mips32-linux ----------------------- */ - + #if defined(PLAT_mips32_linux) /* These regs are trashed by the hidden call. */ @@ -4935,7 +4936,7 @@ typedef #define VG_IS_TOOL_USERREQ(a, b, v) \ (VG_USERREQ_TOOL_BASE(a,b) == ((v) & 0xffff0000)) -/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !! +/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !! This enum comprises an ABI exported by Valgrind to programs which use client requests. DO NOT CHANGE THE ORDER OF THESE ENTRIES, NOR DELETE ANY -- add new ones at the end. */ @@ -5073,7 +5074,7 @@ VALGRIND_PRINTF(const char *format, ...) _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0, VG_USERREQ__PRINTF_VALIST_BY_REF, (unsigned long)format, - (unsigned long)&vargs, + (unsigned long)&vargs, 0, 0, 0); #endif va_end(vargs); @@ -5111,7 +5112,7 @@ VALGRIND_PRINTF_BACKTRACE(const char *format, ...) _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0, VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF, (unsigned long)format, - (unsigned long)&vargs, + (unsigned long)&vargs, 0, 0, 0); #endif va_end(vargs); @@ -5122,7 +5123,7 @@ VALGRIND_PRINTF_BACKTRACE(const char *format, ...) /* These requests allow control to move from the simulated CPU to the real CPU, calling an arbitary function. - + Note that the current ThreadId is inserted as the first argument. So this call: @@ -5208,7 +5209,7 @@ VALGRIND_PRINTF_BACKTRACE(const char *format, ...) - It marks the block as being addressable and undefined (if 'is_zeroed' is not set), or addressable and defined (if 'is_zeroed' is set). This controls how accesses to the block by the program are handled. - + 'addr' is the start of the usable block (ie. after any redzone), 'sizeB' is its size. 'rzB' is the redzone size if the allocator can apply redzones -- these are blocks of padding at the start and end of @@ -5216,7 +5217,7 @@ VALGRIND_PRINTF_BACKTRACE(const char *format, ...) Valgrind will spot block overruns. `is_zeroed' indicates if the memory is zeroed (or filled with another predictable value), as is the case for calloc(). - + VALGRIND_MALLOCLIKE_BLOCK should be put immediately after the point where a heap block -- that will be used by the client program -- is allocated. It's best to put it at the outermost level of the allocator if possible; diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index 8a3e06aabc697..8051235da20aa 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -282,7 +282,7 @@ extern "C" LLVMValueRef LLVMDIBuilderCreateSubroutineType( LLVMValueRef ParameterTypes) { return wrap(Builder->createSubroutineType( unwrapDI(File), - unwrapDI(ParameterTypes))); + unwrapDI(ParameterTypes))); } extern "C" LLVMValueRef LLVMDIBuilderCreateFunction( @@ -634,7 +634,7 @@ extern "C" void LLVMDICompositeTypeSetTypeArray( LLVMValueRef CompositeType, LLVMValueRef TypeArray) { - unwrapDI(CompositeType).setTypeArray(unwrapDI(TypeArray)); + unwrapDI(CompositeType).setArrays(unwrapDI(TypeArray)); } extern "C" char *LLVMTypeToString(LLVMTypeRef Type) { diff --git a/src/rustllvm/llvm-auto-clean-trigger b/src/rustllvm/llvm-auto-clean-trigger index afba5a4dfd8c2..dd1c444119bde 100644 --- a/src/rustllvm/llvm-auto-clean-trigger +++ b/src/rustllvm/llvm-auto-clean-trigger @@ -1,4 +1,4 @@ # If this file is modified, then llvm will be forcibly cleaned and then rebuilt. # The actual contents of this file do not matter, but to trigger a change on the # build bots then the contents should be changed so git updates the mtime. -2014-07-29 +2014-08-05 diff --git a/src/test/run-pass/.gitattributes b/src/test/run-pass/.gitattributes index c6a6f23074de0..46db548a8c497 100644 --- a/src/test/run-pass/.gitattributes +++ b/src/test/run-pass/.gitattributes @@ -1 +1,2 @@ lexer-crlf-line-endings-string-literal-doc-comment.rs -text +issue-16278.rs -text diff --git a/src/test/run-pass/intrinsic-alignment.rs b/src/test/run-pass/intrinsic-alignment.rs index f90cc8146c019..edf5068184aea 100644 --- a/src/test/run-pass/intrinsic-alignment.rs +++ b/src/test/run-pass/intrinsic-alignment.rs @@ -52,6 +52,15 @@ mod m { assert_eq!(::rusti::min_align_of::(), 8u); } } + + #[main] + #[cfg(target_arch = "x86_64")] + pub fn main() { + unsafe { + assert_eq!(::rusti::pref_align_of::(), 8u); + assert_eq!(::rusti::min_align_of::(), 8u); + } + } } #[cfg(target_os = "android")] diff --git a/src/test/run-pass/issue-16278.rs b/src/test/run-pass/issue-16278.rs new file mode 100644 index 0000000000000..f92426d204c0d --- /dev/null +++ b/src/test/run-pass/issue-16278.rs @@ -0,0 +1,20 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-tidy-cr + +// this file has some special \r\n endings (use xxd to see them) + +fn main() {assert_eq!(b"", b"\ + "); +assert_eq!(b"\n", b" +"); +} + diff --git a/src/test/run-pass/rec-align-u64.rs b/src/test/run-pass/rec-align-u64.rs index da40f000ae24e..5c484dec445b1 100644 --- a/src/test/run-pass/rec-align-u64.rs +++ b/src/test/run-pass/rec-align-u64.rs @@ -62,6 +62,12 @@ mod m { pub fn align() -> uint { 8u } pub fn size() -> uint { 16u } } + + #[cfg(target_arch = "x86_64")] + pub mod m { + pub fn align() -> uint { 8u } + pub fn size() -> uint { 16u } + } } #[cfg(target_os = "android")]