Merge branch 'master' of github.com:graydon/rust
This commit is contained in:
commit
39b1657b2c
97 changed files with 674 additions and 114 deletions
|
|
@ -260,7 +260,7 @@ options:
|
|||
--pretty [type] pretty-print the input instead of compiling
|
||||
--ls list the symbols defined by a crate file
|
||||
-L <path> add a directory to the library search path
|
||||
--noverify suppress LLVM verification step (slight speedup)
|
||||
--no-verify suppress LLVM verification step (slight speedup)
|
||||
--parse-only parse only; do not compile, assemble, or link
|
||||
--no-trans run all passes except translation; no output
|
||||
-g produce debug info
|
||||
|
|
@ -362,7 +362,7 @@ fn build_session_options(match: getopts::match)
|
|||
} else if opt_present(match, "emit-llvm") {
|
||||
link::output_type_bitcode
|
||||
} else { link::output_type_exe };
|
||||
let verify = !opt_present(match, "noverify");
|
||||
let verify = !opt_present(match, "no-verify");
|
||||
let save_temps = opt_present(match, "save-temps");
|
||||
let debuginfo = opt_present(match, "g");
|
||||
let stats = opt_present(match, "stats");
|
||||
|
|
@ -463,7 +463,7 @@ fn opts() -> [getopts::opt] {
|
|||
optflag("c"), optopt("o"), optflag("g"), optflag("save-temps"),
|
||||
optopt("sysroot"), optopt("target"), optflag("stats"),
|
||||
optflag("time-passes"), optflag("time-llvm-passes"),
|
||||
optflag("noverify"),
|
||||
optflag("no-verify"),
|
||||
optmulti("cfg"), optflag("test"),
|
||||
optflag("lib"), optflag("static"), optflag("gc"),
|
||||
optflag("stack-growth"),
|
||||
|
|
|
|||
|
|
@ -1,42 +0,0 @@
|
|||
/*
|
||||
Module: ctypes
|
||||
|
||||
Definitions useful for C interop
|
||||
*/
|
||||
|
||||
type c_int = i32;
|
||||
type c_uint = u32;
|
||||
|
||||
type void = int; // Not really the same as C
|
||||
type long = int;
|
||||
type unsigned = u32;
|
||||
type ulong = uint;
|
||||
|
||||
type intptr_t = uint;
|
||||
type uintptr_t = uint;
|
||||
type uint32_t = u32;
|
||||
|
||||
// machine type equivalents of rust int, uint, float
|
||||
|
||||
#[cfg(target_arch="x86")]
|
||||
type m_int = i32;
|
||||
#[cfg(target_arch="x86_64")]
|
||||
type m_int = i64;
|
||||
|
||||
#[cfg(target_arch="x86")]
|
||||
type m_uint = u32;
|
||||
#[cfg(target_arch="x86_64")]
|
||||
type m_uint = u64;
|
||||
|
||||
// This *must* match with "import m_float = fXX" in std::math per arch
|
||||
type m_float = f64;
|
||||
|
||||
type size_t = uint;
|
||||
type ssize_t = int;
|
||||
type off_t = uint;
|
||||
|
||||
type fd_t = i32; // not actually a C type, but should be.
|
||||
type pid_t = i32;
|
||||
|
||||
// enum is implementation-defined, but is 32-bits in practice
|
||||
type enum = u32;
|
||||
17
src/libcore/core.rc
Normal file
17
src/libcore/core.rc
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
#[link(name = "core",
|
||||
vers = "0.1",
|
||||
uuid = "c70c24a7-5551-4f73-8e37-380b11d80be8",
|
||||
url = "http://rust-lang.org/src/core")];
|
||||
|
||||
#[comment = "The Rust core library"];
|
||||
#[license = "BSD"];
|
||||
|
||||
|
||||
// Local Variables:
|
||||
// mode: rust;
|
||||
// fill-column: 78;
|
||||
// indent-tabs-mode: nil
|
||||
// c-basic-offset: 4
|
||||
// buffer-file-coding-system: utf-8-unix
|
||||
// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
|
||||
// End:
|
||||
|
|
@ -57,6 +57,16 @@ resource dtor_res(dtor: option::t<fn@()>) {
|
|||
Section: Introduction forms
|
||||
*/
|
||||
|
||||
/*
|
||||
Function: create
|
||||
|
||||
Create a c_vec::t from a native buffer with a given size.
|
||||
|
||||
Parameters:
|
||||
|
||||
base - A native pointer to a buffer
|
||||
size - The number of elements in the buffer
|
||||
*/
|
||||
unsafe fn create<T>(base: *mutable T, size: uint) -> t<T> {
|
||||
ret t({base: base,
|
||||
size: size,
|
||||
|
|
@ -64,6 +74,19 @@ unsafe fn create<T>(base: *mutable T, size: uint) -> t<T> {
|
|||
});
|
||||
}
|
||||
|
||||
/*
|
||||
Function: create_with_dtor
|
||||
|
||||
Create a c_vec::t from a native buffer, with a given size,
|
||||
and a function to run upon destruction.
|
||||
|
||||
Parameters:
|
||||
|
||||
base - A native pointer to a buffer
|
||||
size - The number of elements in the buffer
|
||||
dtor - A function to run when the value is destructed, useful
|
||||
for freeing the buffer, etc.
|
||||
*/
|
||||
unsafe fn create_with_dtor<T>(base: *mutable T, size: uint, dtor: fn@())
|
||||
-> t<T> {
|
||||
ret t({base: base,
|
||||
|
|
@ -76,11 +99,29 @@ unsafe fn create_with_dtor<T>(base: *mutable T, size: uint, dtor: fn@())
|
|||
Section: Operations
|
||||
*/
|
||||
|
||||
/*
|
||||
Function: get
|
||||
|
||||
Retrieves an element at a given index
|
||||
|
||||
Failure:
|
||||
|
||||
If `ofs` is greater or equal to the length of the vector
|
||||
*/
|
||||
fn get<copy T>(t: t<T>, ofs: uint) -> T {
|
||||
assert ofs < (*t).size;
|
||||
ret unsafe { *ptr::mut_offset((*t).base, ofs) };
|
||||
}
|
||||
|
||||
/*
|
||||
Function: set
|
||||
|
||||
Sets the value of an element at a given index
|
||||
|
||||
Failure:
|
||||
|
||||
If `ofs` is greater or equal to the length of the vector
|
||||
*/
|
||||
fn set<copy T>(t: t<T>, ofs: uint, v: T) {
|
||||
assert ofs < (*t).size;
|
||||
unsafe { *ptr::mut_offset((*t).base, ofs) = v };
|
||||
|
|
@ -90,10 +131,21 @@ fn set<copy T>(t: t<T>, ofs: uint, v: T) {
|
|||
Section: Elimination forms
|
||||
*/
|
||||
|
||||
// FIXME: Rename to len
|
||||
/*
|
||||
Function: size
|
||||
|
||||
Returns the length of the vector
|
||||
*/
|
||||
fn size<T>(t: t<T>) -> uint {
|
||||
ret (*t).size;
|
||||
}
|
||||
|
||||
/*
|
||||
Function: ptr
|
||||
|
||||
Returns a pointer to the first element of the vector
|
||||
*/
|
||||
unsafe fn ptr<T>(t: t<T>) -> *mutable T {
|
||||
ret (*t).base;
|
||||
}
|
||||
146
src/libstd/ctypes.rs
Normal file
146
src/libstd/ctypes.rs
Normal file
|
|
@ -0,0 +1,146 @@
|
|||
/*
|
||||
Module: ctypes
|
||||
|
||||
Definitions useful for C interop
|
||||
*/
|
||||
|
||||
/*
|
||||
FIXME: Add a test that uses some native code to verify these sizes,
|
||||
which are not obviously correct for all potential platforms.
|
||||
*/
|
||||
|
||||
/*
|
||||
Type: c_int
|
||||
|
||||
A signed integer with the same size as a C `int`
|
||||
*/
|
||||
type c_int = i32;
|
||||
|
||||
/*
|
||||
Type: c_uint
|
||||
|
||||
An unsigned integer with the same size as a C `unsigned int`
|
||||
*/
|
||||
type c_uint = u32;
|
||||
|
||||
/*
|
||||
Type: long
|
||||
|
||||
A signed integer with the same size as a C `long`
|
||||
*/
|
||||
type long = int;
|
||||
|
||||
/*
|
||||
Type: unsigned
|
||||
|
||||
An unsigned integer with the same size as a C `unsigned int`
|
||||
*/
|
||||
type unsigned = u32;
|
||||
|
||||
/*
|
||||
Type: ulong
|
||||
|
||||
An unsigned integer with the same size as a C `unsigned long`
|
||||
*/
|
||||
type ulong = uint;
|
||||
|
||||
/*
|
||||
Type: intptr_t
|
||||
|
||||
A signed integer with the same size as a pointer. This is
|
||||
guaranteed to always be the same type as a Rust `int`
|
||||
*/
|
||||
type intptr_t = uint; // FIXME: int
|
||||
|
||||
/*
|
||||
Type: uintptr_t
|
||||
|
||||
An unsigned integer with the same size as a pointer. This is
|
||||
guaranteed to always be the same type as a Rust `uint`.
|
||||
*/
|
||||
type uintptr_t = uint;
|
||||
type uint32_t = u32;
|
||||
|
||||
/*
|
||||
Type: void
|
||||
|
||||
A type, a pointer to which can be used as C `void *`
|
||||
|
||||
Note that this does not directly correspond to the C `void` type,
|
||||
which is an incomplete type. Using pointers to this type
|
||||
when interoperating with C void pointers can help in documentation.
|
||||
*/
|
||||
type void = int;
|
||||
|
||||
// machine type equivalents of rust int, uint, float
|
||||
|
||||
/*
|
||||
Type: m_int
|
||||
|
||||
FIXME: What C type does this represent?
|
||||
*/
|
||||
#[cfg(target_arch="x86")]
|
||||
type m_int = i32;
|
||||
#[cfg(target_arch="x86_64")]
|
||||
type m_int = i64;
|
||||
|
||||
/*
|
||||
Type: m_uint
|
||||
|
||||
FIXME: What C type does this represent?
|
||||
*/
|
||||
#[cfg(target_arch="x86")]
|
||||
type m_uint = u32;
|
||||
#[cfg(target_arch="x86_64")]
|
||||
type m_uint = u64;
|
||||
|
||||
// This *must* match with "import m_float = fXX" in std::math per arch
|
||||
/*
|
||||
Type: m_float
|
||||
|
||||
FIXME: What C type does this represent?
|
||||
*/
|
||||
type m_float = f64;
|
||||
|
||||
/*
|
||||
Type: size_t
|
||||
|
||||
An unsigned integer corresponding to the C `size_t`
|
||||
*/
|
||||
type size_t = uint;
|
||||
|
||||
/*
|
||||
Type: ssize_t
|
||||
|
||||
A signed integer correpsonding to the C `ssize_t`
|
||||
*/
|
||||
type ssize_t = int;
|
||||
|
||||
/*
|
||||
Type: off_t
|
||||
|
||||
An unsigned integer corresponding to the C `off_t`
|
||||
*/
|
||||
type off_t = uint;
|
||||
|
||||
/*
|
||||
Type: fd_t
|
||||
|
||||
A type that can be used for C file descriptors
|
||||
*/
|
||||
type fd_t = i32; // not actually a C type, but should be.
|
||||
|
||||
/*
|
||||
Type: pid_t
|
||||
|
||||
A type for representing process ID's, corresponding to C `pid_t`
|
||||
*/
|
||||
type pid_t = i32;
|
||||
|
||||
// enum is implementation-defined, but is 32-bits in practice
|
||||
/*
|
||||
Type: enum
|
||||
|
||||
An unsigned integer with the same size as a C enum
|
||||
*/
|
||||
type enum = u32;
|
||||
|
|
@ -253,25 +253,18 @@ fn pow_uint_to_uint_as_float(x: uint, pow: uint) -> float {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Section: Constants
|
||||
*/
|
||||
|
||||
//TODO: Once this is possible, replace the body of these functions
|
||||
//by an actual constant.
|
||||
|
||||
/* Const: NaN */
|
||||
const NaN: float = 0./0.;
|
||||
|
||||
/* Predicate: isNaN */
|
||||
pure fn isNaN(f: float) -> bool { f != f }
|
||||
|
||||
/* Const: infinity */
|
||||
const infinity: float = 1./0.;
|
||||
|
||||
/* Const: neg_infinity */
|
||||
const neg_infinity: float = -1./0.;
|
||||
|
||||
/* Predicate: isNaN */
|
||||
pure fn isNaN(f: float) -> bool { f != f }
|
||||
|
||||
/* Function: add */
|
||||
pure fn add(x: float, y: float) -> float { ret x + y; }
|
||||
|
||||
|
|
@ -1,3 +1,9 @@
|
|||
/*
|
||||
Module: io
|
||||
|
||||
Basic input/output
|
||||
*/
|
||||
|
||||
import ctypes::fd_t;
|
||||
import ctypes::c_int;
|
||||
|
||||
|
|
@ -23,6 +23,9 @@ import ctypes::c_int;
|
|||
import m_float = math_f64;
|
||||
|
||||
// FIXME replace with redirect to m_float::consts::FOO as soon as it works
|
||||
/*
|
||||
Module: consts
|
||||
*/
|
||||
mod consts {
|
||||
/*
|
||||
Const: pi
|
||||
|
|
@ -17,6 +17,7 @@ export
|
|||
|
||||
export consts;
|
||||
|
||||
/* Module: consts */
|
||||
mod consts {
|
||||
|
||||
/*
|
||||
|
|
@ -17,6 +17,7 @@ export
|
|||
|
||||
export consts;
|
||||
|
||||
/* Module: consts */
|
||||
mod consts {
|
||||
|
||||
/*
|
||||
|
|
@ -174,7 +174,8 @@ fn byte_len_range(s: str, byte_offset: uint, char_len: uint) -> uint {
|
|||
/*
|
||||
Function: bytes
|
||||
|
||||
Converts a string to a vector of bytes
|
||||
Converts a string to a vector of bytes. The result vector is not
|
||||
null-terminated.
|
||||
*/
|
||||
fn bytes(s: str) -> [u8] unsafe {
|
||||
let v = unsafe::reinterpret_cast(s);
|
||||
|
|
@ -9,6 +9,9 @@ import option;
|
|||
import option::{none, some};
|
||||
import rand;
|
||||
|
||||
/*
|
||||
Function: mkdtemp
|
||||
*/
|
||||
fn mkdtemp(prefix: str, suffix: str) -> option::t<str> {
|
||||
let r = rand::mk_rng();
|
||||
let i = 0u;
|
||||
|
|
@ -7,7 +7,7 @@
|
|||
#include <inttypes.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "../../memcheck.h"
|
||||
#include "vg/memcheck.h"
|
||||
|
||||
template<typename T>
|
||||
T align_down(T sp)
|
||||
|
|
@ -51,9 +51,7 @@ public:
|
|||
uint32_t bot = regs.esp;
|
||||
uint32_t top = align_down(bot - nbytes);
|
||||
|
||||
#ifdef HAVE_VALGRIND
|
||||
(void)VALGRIND_MAKE_MEM_UNDEFINED(top - 4, bot - top + 4);
|
||||
#endif
|
||||
|
||||
return reinterpret_cast<void *>(top);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,11 +75,12 @@ MORESTACK:
|
|||
|
||||
// The arguments to rust_new_stack2
|
||||
movl 40(%esp),%eax // Size of stack arguments
|
||||
movl %eax,16(%esp)
|
||||
movl %eax,20(%esp)
|
||||
leal 48(%esp),%eax // Address of stack arguments
|
||||
movl %eax,12(%esp)
|
||||
movl %eax,16(%esp)
|
||||
movl 36(%esp),%eax // The amount of stack needed
|
||||
movl %eax,8(%esp)
|
||||
movl %eax,12(%esp)
|
||||
movl $0, 8(%esp) // Out pointer
|
||||
|
||||
#ifdef __APPLE__
|
||||
call 1f
|
||||
|
|
@ -97,7 +98,7 @@ MORESTACK:
|
|||
movl 32(%esp),%edx // Grab the return pointer.
|
||||
inc %edx // Skip past the ret instruction in the parent fn
|
||||
|
||||
movl %eax,%esp // Switch stacks.
|
||||
movl 8(%esp),%esp // Switch stacks.
|
||||
call *%edx // Re-enter the function that called us.
|
||||
|
||||
// Now the function that called us has returned, so we need to delete the
|
||||
|
|
|
|||
|
|
@ -8,9 +8,7 @@
|
|||
#include <stdint.h>
|
||||
#include <xmmintrin.h>
|
||||
|
||||
#ifdef HAVE_VALGRIND
|
||||
#include <valgrind/memcheck.h>
|
||||
#endif
|
||||
#include "vg/memcheck.h"
|
||||
|
||||
template<typename T>
|
||||
T align_down(T sp)
|
||||
|
|
@ -51,9 +49,7 @@ public:
|
|||
uint64_t bot = regs.data[RUSTRT_RSP];
|
||||
uint64_t top = align_down(bot - nbytes);
|
||||
|
||||
#ifdef HAVE_VALGRIND
|
||||
(void)VALGRIND_MAKE_MEM_UNDEFINED(top - 4, bot - top + 4);
|
||||
#endif
|
||||
|
||||
return reinterpret_cast<void *>(top);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -81,9 +81,12 @@ MORESTACK:
|
|||
movq %rbp, %rcx
|
||||
addq $24, %rcx // Base pointer, return address x2
|
||||
|
||||
pushq $0 // Alignment
|
||||
|
||||
pushq %r11 // Size of stack arguments
|
||||
pushq %rcx // Address of stack arguments
|
||||
pushq %r10 // The amount of stack needed
|
||||
pushq $0 // Out pointer
|
||||
|
||||
movq UPCALL_NEW_STACK@GOTPCREL(%rip), %rsi
|
||||
movq %rsp, %rdi
|
||||
|
|
@ -95,7 +98,8 @@ MORESTACK:
|
|||
#endif
|
||||
|
||||
// Pop the new_stack_args struct
|
||||
addq $24, %rsp
|
||||
popq %rax
|
||||
addq $32, %rsp
|
||||
|
||||
// Pop the saved arguments
|
||||
popq %r9
|
||||
|
|
|
|||
|
|
@ -273,6 +273,12 @@ debug_ptrcast(type_desc *from_ty,
|
|||
return ptr;
|
||||
}
|
||||
|
||||
extern "C" CDECL void *
|
||||
debug_get_stk_seg() {
|
||||
rust_task *task = rust_scheduler::get_task();
|
||||
return task->stk;
|
||||
}
|
||||
|
||||
extern "C" CDECL rust_vec*
|
||||
rust_list_files(rust_str *path) {
|
||||
rust_task *task = rust_scheduler::get_task();
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@
|
|||
#include "rust_internal.h"
|
||||
#include "rust_cc.h"
|
||||
|
||||
#include "valgrind.h"
|
||||
#include "memcheck.h"
|
||||
#include "vg/valgrind.h"
|
||||
#include "vg/memcheck.h"
|
||||
|
||||
#ifndef __WIN32__
|
||||
#include <execinfo.h>
|
||||
|
|
@ -131,6 +131,9 @@ rust_task::~rust_task()
|
|||
// (ref_count == 1 && this == sched->root_task));
|
||||
|
||||
// Delete all the stacks. There may be more than one if the task failed
|
||||
// FIXME: This is not correct. During unwinding we need to delete
|
||||
// the stacks and record the stack limit, otherwise the stack
|
||||
// stack is corrupted when destructors are running.
|
||||
while (stk != NULL) {
|
||||
del_stk(this, stk);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
#include "rust_internal.h"
|
||||
#include "valgrind.h"
|
||||
#include "vg/valgrind.h"
|
||||
|
||||
// The mechanism in this file is very crude; every domain (thread) spawns its
|
||||
// own secondary timer thread, and that timer thread *never idles*. It
|
||||
|
|
|
|||
|
|
@ -209,28 +209,48 @@ upcall_dynastack_free(void *ptr) {
|
|||
return rust_scheduler::get_task()->dynastack.free(ptr);
|
||||
}
|
||||
|
||||
extern "C" void record_sp(void *limit);
|
||||
|
||||
/**
|
||||
* Allocates |nbytes| bytes in the C stack and returns a pointer to the start
|
||||
* of the allocated space.
|
||||
* Switch to the C stack and call the given function, passing a single pointer
|
||||
* argument.
|
||||
*/
|
||||
extern "C" CDECL void
|
||||
upcall_call_shim_on_c_stack(void *args, void *fn_ptr) {
|
||||
rust_scheduler *sched = rust_scheduler::get_task()->sched;
|
||||
sched->c_context.call_shim_on_c_stack(args, fn_ptr);
|
||||
rust_task *task = rust_scheduler::get_task();
|
||||
|
||||
// FIXME (1226) - The shim functions generated by rustc contain the
|
||||
// morestack prologue, so we need to let them know they have enough
|
||||
// stack.
|
||||
record_sp(0);
|
||||
|
||||
rust_scheduler *sched = task->sched;
|
||||
try {
|
||||
sched->c_context.call_shim_on_c_stack(args, fn_ptr);
|
||||
} catch (...) {
|
||||
task = rust_scheduler::get_task();
|
||||
task->record_stack_limit();
|
||||
throw;
|
||||
}
|
||||
task = rust_scheduler::get_task();
|
||||
task->record_stack_limit();
|
||||
}
|
||||
|
||||
struct rust_new_stack2_args {
|
||||
size_t stk_sz;
|
||||
void *args_addr;
|
||||
size_t args_sz;
|
||||
void *new_stack;
|
||||
size_t stk_sz;
|
||||
void *args_addr;
|
||||
size_t args_sz;
|
||||
};
|
||||
|
||||
// A new stack function suitable for calling through
|
||||
// upcall_call_shim_on_c_stack
|
||||
extern "C" CDECL void *
|
||||
extern "C" CDECL void
|
||||
upcall_new_stack(struct rust_new_stack2_args *args) {
|
||||
rust_task *task = rust_scheduler::get_task();
|
||||
return task->new_stack(args->stk_sz, args->args_addr, args->args_sz);
|
||||
args->new_stack = task->new_stack(args->stk_sz,
|
||||
args->args_addr,
|
||||
args->args_sz);
|
||||
}
|
||||
|
||||
extern "C" CDECL void
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ del_port
|
|||
debug_ptrcast
|
||||
debug_tag
|
||||
debug_tydesc
|
||||
debug_get_stk_seg
|
||||
do_gc
|
||||
drop_task
|
||||
get_port_id
|
||||
|
|
|
|||
41
src/test/run-fail/morestack2.rs
Normal file
41
src/test/run-fail/morestack2.rs
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
// xfail-test
|
||||
// error-pattern:explicit failure
|
||||
// compile-flags:--stack-growth
|
||||
|
||||
// This time we're testing that the stack limits are restored
|
||||
// correctly after calling into the C stack and unwinding.
|
||||
// See the hack in upcall_call_shim_on_c_stack where it messes
|
||||
// with the stack limit.
|
||||
|
||||
use std;
|
||||
|
||||
native mod rustrt {
|
||||
fn set_min_stack(size: uint);
|
||||
fn pin_task();
|
||||
}
|
||||
|
||||
fn getbig_call_c_and_fail(i: int) {
|
||||
if i != 0 {
|
||||
getbig_call_c_and_fail(i - 1);
|
||||
} else {
|
||||
rustrt::pin_task();
|
||||
fail;
|
||||
}
|
||||
}
|
||||
|
||||
resource and_then_get_big_again(_i: ()) {
|
||||
fn getbig(i: int) {
|
||||
if i != 0 {
|
||||
getbig(i - 1);
|
||||
}
|
||||
}
|
||||
getbig(10000);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
rustrt::set_min_stack(256u);
|
||||
std::task::spawn((), fn (&&_i: ()) {
|
||||
let r = and_then_get_big_again(());
|
||||
getbig_call_c_and_fail(10000);
|
||||
});
|
||||
}
|
||||
34
src/test/run-fail/morestack3.rs
Normal file
34
src/test/run-fail/morestack3.rs
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
// xfail-test
|
||||
// error-pattern:explicit failure
|
||||
// compile-flags:--stack-growth
|
||||
|
||||
// Just testing unwinding
|
||||
|
||||
use std;
|
||||
|
||||
native mod rustrt {
|
||||
fn set_min_stack(size: uint);
|
||||
}
|
||||
|
||||
fn getbig_and_fail(&&i: int) {
|
||||
let r = and_then_get_big_again(@0);
|
||||
if i != 0 {
|
||||
getbig_and_fail(i - 1);
|
||||
} else {
|
||||
fail;
|
||||
}
|
||||
}
|
||||
|
||||
resource and_then_get_big_again(_i: @int) {
|
||||
fn getbig(i: int) {
|
||||
if i != 0 {
|
||||
getbig(i - 1);
|
||||
}
|
||||
}
|
||||
getbig(1000);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
rustrt::set_min_stack(256u);
|
||||
std::task::spawn(1000, getbig_and_fail);
|
||||
}
|
||||
100
src/test/run-pass/morestack4.rs
Normal file
100
src/test/run-pass/morestack4.rs
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
// xfail-test
|
||||
// compile-flags:--stack-growth
|
||||
|
||||
// This is testing for stack frames greater than 256 bytes,
|
||||
// for which function prologues are generated differently
|
||||
|
||||
type biggy = {
|
||||
a00: u64,
|
||||
a01: u64,
|
||||
a02: u64,
|
||||
a03: u64,
|
||||
a04: u64,
|
||||
a05: u64,
|
||||
a06: u64,
|
||||
a07: u64,
|
||||
a08: u64,
|
||||
a09: u64,
|
||||
a10: u64,
|
||||
a11: u64,
|
||||
a12: u64,
|
||||
a13: u64,
|
||||
a14: u64,
|
||||
a15: u64,
|
||||
a16: u64,
|
||||
a17: u64,
|
||||
a18: u64,
|
||||
a19: u64,
|
||||
a20: u64,
|
||||
a21: u64,
|
||||
a22: u64,
|
||||
a23: u64,
|
||||
a24: u64,
|
||||
a25: u64,
|
||||
a26: u64,
|
||||
a27: u64,
|
||||
a28: u64,
|
||||
a29: u64,
|
||||
a30: u64,
|
||||
a31: u64,
|
||||
a32: u64,
|
||||
a33: u64,
|
||||
a34: u64,
|
||||
a35: u64,
|
||||
a36: u64,
|
||||
a37: u64,
|
||||
a38: u64,
|
||||
a39: u64,
|
||||
};
|
||||
|
||||
|
||||
fn getbig(i: biggy) {
|
||||
if i.a00 != 0u64 {
|
||||
getbig({a00: i.a00 - 1u64 with i});
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
getbig({
|
||||
a00: 100000u64,
|
||||
a01: 100000u64,
|
||||
a02: 100000u64,
|
||||
a03: 100000u64,
|
||||
a04: 100000u64,
|
||||
a05: 100000u64,
|
||||
a06: 100000u64,
|
||||
a07: 100000u64,
|
||||
a08: 100000u64,
|
||||
a09: 100000u64,
|
||||
a10: 100000u64,
|
||||
a11: 100000u64,
|
||||
a12: 100000u64,
|
||||
a13: 100000u64,
|
||||
a14: 100000u64,
|
||||
a15: 100000u64,
|
||||
a16: 100000u64,
|
||||
a17: 100000u64,
|
||||
a18: 100000u64,
|
||||
a19: 100000u64,
|
||||
a20: 100000u64,
|
||||
a21: 100000u64,
|
||||
a22: 100000u64,
|
||||
a23: 100000u64,
|
||||
a24: 100000u64,
|
||||
a25: 100000u64,
|
||||
a26: 100000u64,
|
||||
a27: 100000u64,
|
||||
a28: 100000u64,
|
||||
a29: 100000u64,
|
||||
a30: 100000u64,
|
||||
a31: 100000u64,
|
||||
a32: 100000u64,
|
||||
a33: 100000u64,
|
||||
a34: 100000u64,
|
||||
a35: 100000u64,
|
||||
a36: 100000u64,
|
||||
a37: 100000u64,
|
||||
a38: 100000u64,
|
||||
a39: 100000u64,
|
||||
});
|
||||
}
|
||||
26
src/test/run-pass/morestack5.rs
Normal file
26
src/test/run-pass/morestack5.rs
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
// xfail-test
|
||||
// compile-flags:--stack-growth
|
||||
|
||||
// This test will call __morestack with various minimum stack sizes
|
||||
|
||||
use std;
|
||||
import std::task;
|
||||
|
||||
native mod rustrt {
|
||||
fn set_min_stack(size: uint);
|
||||
}
|
||||
|
||||
fn getbig(&&i: int) {
|
||||
if i != 0 {
|
||||
getbig(i - 1);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let sz = 400u;
|
||||
while sz < 500u {
|
||||
rustrt::set_min_stack(sz);
|
||||
task::join(task::spawn_joinable(200, getbig));
|
||||
sz += 1u;
|
||||
}
|
||||
}
|
||||
81
src/test/run-pass/morestack6.rs
Normal file
81
src/test/run-pass/morestack6.rs
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
// xfail-test
|
||||
// compile-flags:--stack-growth
|
||||
|
||||
// This test attempts to force the dynamic linker to resolve
|
||||
// external symbols as close to the red zone as possible.
|
||||
|
||||
use std;
|
||||
import std::task;
|
||||
import std::rand;
|
||||
|
||||
native mod rustrt {
|
||||
fn set_min_stack(size: uint);
|
||||
fn debug_get_stk_seg() -> *u8;
|
||||
|
||||
fn unsupervise();
|
||||
fn last_os_error() -> str;
|
||||
fn rust_getcwd() -> str;
|
||||
fn refcount(box: @int);
|
||||
fn do_gc();
|
||||
fn pin_task();
|
||||
fn unpin_task();
|
||||
fn get_task_id();
|
||||
fn sched_threads();
|
||||
fn rust_get_task();
|
||||
}
|
||||
|
||||
fn calllink01() { rustrt::unsupervise(); }
|
||||
fn calllink02() { rustrt::last_os_error(); }
|
||||
fn calllink03() { rustrt::rust_getcwd(); }
|
||||
fn calllink04() { rustrt::refcount(@0); }
|
||||
fn calllink05() { rustrt::do_gc(); }
|
||||
fn calllink06() { rustrt::pin_task(); }
|
||||
fn calllink07() { rustrt::unpin_task(); }
|
||||
fn calllink08() { rustrt::get_task_id(); }
|
||||
fn calllink09() { rustrt::sched_threads(); }
|
||||
fn calllink10() { rustrt::rust_get_task(); }
|
||||
|
||||
fn runtest(&&args:(fn(), u32)) {
|
||||
let (f, frame_backoff) = args;
|
||||
runtest2(f, frame_backoff, 0 as *u8);
|
||||
}
|
||||
|
||||
fn runtest2(f: fn(), frame_backoff: u32, last_stk: *u8) -> u32 {
|
||||
let curr_stk = rustrt::debug_get_stk_seg();
|
||||
if (last_stk != curr_stk && last_stk != 0 as *u8) {
|
||||
// We switched stacks, go back and try to hit the dynamic linker
|
||||
frame_backoff
|
||||
} else {
|
||||
let frame_backoff = runtest2(f, frame_backoff, curr_stk);
|
||||
if frame_backoff > 1u32 {
|
||||
frame_backoff - 1u32
|
||||
} else if frame_backoff == 1u32 {
|
||||
f();
|
||||
0u32
|
||||
} else {
|
||||
0u32
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let fns = [
|
||||
calllink01,
|
||||
calllink02,
|
||||
calllink03,
|
||||
calllink04,
|
||||
calllink05,
|
||||
calllink06,
|
||||
calllink07,
|
||||
calllink08,
|
||||
calllink09,
|
||||
calllink10
|
||||
];
|
||||
let rng = rand::mk_rng();
|
||||
for f in fns {
|
||||
let sz = rng.next() % 256u32 + 256u32;
|
||||
let frame_backoff = rng.next() % 10u32 + 1u32;
|
||||
rustrt::set_min_stack(sz as uint);
|
||||
task::join(task::spawn_joinable((f, frame_backoff), runtest));
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue