Merge commit '881bfb1a18' into rollup
This commit is contained in:
commit
720746a139
17 changed files with 273 additions and 103 deletions
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ if len(sys.argv) == 3:
|
|||
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
|
||||
|
|
|
|||
|
|
@ -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<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,
|
||||
|
|
@ -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")]
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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,9 +380,106 @@ 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
2
src/llvm
2
src/llvm
|
|
@ -1 +1 @@
|
|||
Subproject commit 0d999e5b315b6ff78fcea772466d985ce53fd8dc
|
||||
Subproject commit 90a314162053a0c51a50a1c603c9203bef241e0d
|
||||
|
|
@ -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
|
||||
|
||||
; extract and return pointer to the exception object
|
||||
%2 = extractvalue { i8*, i32 } %1, 0
|
||||
ret i8* %2
|
||||
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
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
declare i32 @rust_eh_personality(...)
|
||||
declare i32 @rust_eh_personality_catch(...)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -282,7 +282,7 @@ extern "C" LLVMValueRef LLVMDIBuilderCreateSubroutineType(
|
|||
LLVMValueRef ParameterTypes) {
|
||||
return wrap(Builder->createSubroutineType(
|
||||
unwrapDI<DIFile>(File),
|
||||
unwrapDI<DIArray>(ParameterTypes)));
|
||||
unwrapDI<DITypeArray>(ParameterTypes)));
|
||||
}
|
||||
|
||||
extern "C" LLVMValueRef LLVMDIBuilderCreateFunction(
|
||||
|
|
@ -634,7 +634,7 @@ extern "C" void LLVMDICompositeTypeSetTypeArray(
|
|||
LLVMValueRef CompositeType,
|
||||
LLVMValueRef TypeArray)
|
||||
{
|
||||
unwrapDI<DICompositeType>(CompositeType).setTypeArray(unwrapDI<DIArray>(TypeArray));
|
||||
unwrapDI<DICompositeType>(CompositeType).setArrays(unwrapDI<DIArray>(TypeArray));
|
||||
}
|
||||
|
||||
extern "C" char *LLVMTypeToString(LLVMTypeRef Type) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -52,6 +52,15 @@ mod m {
|
|||
assert_eq!(::rusti::min_align_of::<u64>(), 8u);
|
||||
}
|
||||
}
|
||||
|
||||
#[main]
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
pub fn main() {
|
||||
unsafe {
|
||||
assert_eq!(::rusti::pref_align_of::<u64>(), 8u);
|
||||
assert_eq!(::rusti::min_align_of::<u64>(), 8u);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
|
|
|
|||
|
|
@ -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")]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue