From a1131748c2e86bcbcbbbec81a83ca844e58073b4 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Thu, 8 Sep 2011 12:03:07 -0700 Subject: [PATCH 01/28] Add a waitpid wrapper to std::run that interprets the exit status on unix This makes the result of running a program a little more uniform between unix and windows --- src/lib/run_program.rs | 43 +++++++++++++++++++++++++++++++++++++++-- src/test/stdtest/run.rs | 7 +++++++ 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/src/lib/run_program.rs b/src/lib/run_program.rs index a4adaace38a..6e65e5261d4 100644 --- a/src/lib/run_program.rs +++ b/src/lib/run_program.rs @@ -6,6 +6,7 @@ export run_program; export start_program; export program_output; export spawn_process; +export waitpid; native "rust" mod rustrt { fn rust_run_program(argv: *sbuf, in_fd: int, out_fd: int, err_fd: int) -> @@ -33,7 +34,7 @@ fn spawn_process(prog: &str, args: &[str], in_fd: int, out_fd: int, } fn run_program(prog: &str, args: &[str]) -> int { - ret os::waitpid(spawn_process(prog, args, 0, 0, 0)); + ret waitpid(spawn_process(prog, args, 0, 0, 0)); } type program = @@ -87,7 +88,7 @@ fn start_program(prog: &str, args: &[str]) -> @program_res { if finished { ret 0; } finished = true; self.close_input(); - ret os::waitpid(pid); + ret waitpid(pid); } fn destroy() { self.finish(); @@ -117,6 +118,44 @@ fn program_output(prog: &str, args: &[str]) -> out: read_all(pr.output()), err: read_all(pr.err())}; } + +/* Returns an exit status */ +#[cfg(target_os = "win32")] +fn waitpid(pid: int) -> int { + os::waitpid(pid) +} + +#[cfg(target_os = "linux")] +#[cfg(target_os = "macos")] +fn waitpid(pid: int) -> int { + #[cfg(target_os = "linux")] + fn WIFEXITED(status: int) -> bool { + (status & 0xff) == 0 + } + + #[cfg(target_os = "macos")] + fn WIFEXITED(status: int) -> bool { + (status & 0x7f) == 0 + } + + #[cfg(target_os = "linux")] + fn WEXITSTATUS(status: int) -> int { + (status >> 8) & 0xff + } + + #[cfg(target_os = "macos")] + fn WEXITSTATUS(status: int) -> int { + status >> 8 + } + + let status = os::waitpid(pid); + ret if WIFEXITED(status) { + WEXITSTATUS(status) + } else { + 1 + }; +} + // Local Variables: // mode: rust // fill-column: 78; diff --git a/src/test/stdtest/run.rs b/src/test/stdtest/run.rs index b60a3935500..f6cf8b5f07f 100644 --- a/src/test/stdtest/run.rs +++ b/src/test/stdtest/run.rs @@ -65,3 +65,10 @@ fn test_pipes() { ret buf; } } + +#[test] +fn waitpid() { + let pid = run::spawn_process("false", [], 0, 0, 0); + let status = run::waitpid(pid); + assert status == 1; +} From f1e348ce6ae8b80bcb3ffd81934d82dbdddc7647 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Thu, 8 Sep 2011 13:28:03 -0700 Subject: [PATCH 02/28] Change the exit status used for valgrind errors and check for it in tests --- mk/platform.mk | 2 +- src/test/compiletest/procsrv.rs | 2 +- src/test/compiletest/runtest.rs | 6 +----- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/mk/platform.mk b/mk/platform.mk index c8c4fef41fd..a647e9cb3c5 100644 --- a/mk/platform.mk +++ b/mk/platform.mk @@ -114,7 +114,7 @@ ifdef CFG_UNIXY endif ifdef CFG_VALGRIND CFG_VALGRIND += --leak-check=full \ - --error-exitcode=1 \ + --error-exitcode=100 \ --quiet --suppressions=$(CFG_SRC_DIR)src/etc/x86.supp endif endif diff --git a/src/test/compiletest/procsrv.rs b/src/test/compiletest/procsrv.rs index 63a3807f6a5..fcf611cccbf 100644 --- a/src/test/compiletest/procsrv.rs +++ b/src/test/compiletest/procsrv.rs @@ -66,7 +66,7 @@ fn run(handle: &handle, lib_path: &str, prog: &str, args: &[str], writeclose(resp.infd, input); let output = readclose(resp.outfd); let errput = readclose(resp.errfd); - let status = os::waitpid(resp.pid); + let status = run::waitpid(resp.pid); ret {status: status, out: output, err: errput}; } diff --git a/src/test/compiletest/runtest.rs b/src/test/compiletest/runtest.rs index 87ae7750e03..373db1a10ad 100644 --- a/src/test/compiletest/runtest.rs +++ b/src/test/compiletest/runtest.rs @@ -55,11 +55,7 @@ fn run_rfail_test(cx: &cx, props: &test_props, testfile: &str) { fatal_procres("run-fail test didn't produce an error!", procres); } - // This is the value valgrind returns on failure - // FIXME: Why is this value neither the value we pass to - // valgrind as --error-exitcode (1), nor the value we see as the - // exit code on the command-line (137)? - const valgrind_err: int = 9; + const valgrind_err: int = 100; if procres.status == valgrind_err { fatal_procres("run-fail test isn't valgrind-clean!", procres); } From 9f4b4d89cee40a04bf4b3227e378588e438e588a Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Wed, 7 Sep 2011 11:44:34 -0700 Subject: [PATCH 03/28] Add upcall_rust_personality This just wraps __gxx_personality_v0 with our upcall naming convention Issue #236 --- src/comp/back/upcall.rs | 7 +++++-- src/rt/rust_upcall.cpp | 22 ++++++++++++++++++++++ src/rt/rustrt.def.in | 1 + 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/comp/back/upcall.rs b/src/comp/back/upcall.rs index 774cb30c001..19cde197537 100644 --- a/src/comp/back/upcall.rs +++ b/src/comp/back/upcall.rs @@ -37,7 +37,8 @@ type upcalls = log_type: ValueRef, dynastack_mark: ValueRef, dynastack_alloc: ValueRef, - dynastack_free: ValueRef}; + dynastack_free: ValueRef, + rust_personality: ValueRef}; fn declare_upcalls(_tn: type_names, tydesc_type: TypeRef, taskptr_type: TypeRef, llmod: ModuleRef) -> @upcalls { @@ -89,7 +90,9 @@ fn declare_upcalls(_tn: type_names, tydesc_type: TypeRef, dynastack_alloc: d("dynastack_alloc_2", [T_size_t(), T_ptr(tydesc_type)], T_ptr(T_i8())), - dynastack_free: d("dynastack_free", [T_ptr(T_i8())], T_void())}; + dynastack_free: d("dynastack_free", [T_ptr(T_i8())], T_void()), + rust_personality: dr("rust_personality", [], T_i32()) + }; } // // Local Variables: diff --git a/src/rt/rust_upcall.cpp b/src/rt/rust_upcall.cpp index 2d7791e876f..0f5c11537fe 100644 --- a/src/rt/rust_upcall.cpp +++ b/src/rt/rust_upcall.cpp @@ -1,6 +1,8 @@ #include "rust_gc.h" #include "rust_internal.h" #include "rust_upcall.h" +#include +#include // Upcalls. @@ -190,6 +192,26 @@ upcall_dynastack_free(rust_task *task, void *ptr) { return task->dynastack.free(ptr); } +extern "C" _Unwind_Reason_Code +__gxx_personality_v0(int version, + _Unwind_Action actions, + uint64_t exception_class, + _Unwind_Exception *ue_header, + _Unwind_Context *context); + +extern "C" _Unwind_Reason_Code +upcall_rust_personality(int version, + _Unwind_Action actions, + uint64_t exception_class, + _Unwind_Exception *ue_header, + _Unwind_Context *context) { + return __gxx_personality_v0(version, + actions, + exception_class, + ue_header, + context); +} + // // Local Variables: // mode: C++ diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in index a0e7c972eeb..246ac261f8f 100644 --- a/src/rt/rustrt.def.in +++ b/src/rt/rustrt.def.in @@ -78,5 +78,6 @@ upcall_vec_grow upcall_vec_push upcall_log_type upcall_malloc +upcall_rust_personality upcall_shared_malloc upcall_shared_free From 4bced5e5f2fcf7e1c7725e747ac3110ef0a9c1e4 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Wed, 7 Sep 2011 11:46:53 -0700 Subject: [PATCH 04/28] Use invoke to call (most) rust functions No landing pads yet. Issue #236 --- src/comp/middle/trans.rs | 18 +++++++++++++++++- src/comp/middle/trans_build.rs | 15 +++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 893614cac9a..9a8b9bfaba1 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -3761,7 +3761,7 @@ fn trans_call(in_cx: &@block_ctxt, f: &@ast::expr, for the call itself is unreachable. */ let retval = C_nil(); if !is_terminated(bcx) { - FastCall(bcx, faddr, llargs); + bcx = invoke_fastcall(bcx, faddr, llargs).bcx; alt lliterbody { none. { if !ty::type_is_nil(bcx_tcx(cx), ret_ty) { @@ -3794,6 +3794,22 @@ fn trans_call(in_cx: &@block_ctxt, f: &@ast::expr, ret rslt(bcx, retval); } +fn invoke_fastcall(bcx: &@block_ctxt, llfn: ValueRef, + llargs: &[ValueRef]) -> result { + + let normal_bcx = new_sub_block_ctxt(bcx, "normal return"); + let unwind_bcx = new_sub_block_ctxt(bcx, "unwind"); + let retval = trans_build::FastInvoke(bcx, llfn, llargs, + normal_bcx.llbb, + unwind_bcx.llbb); + trans_landing_pad(unwind_bcx); + ret rslt(normal_bcx, retval); +} + +fn trans_landing_pad(bcx: &@block_ctxt) { + Unreachable(bcx); +} + fn trans_tup(cx: &@block_ctxt, elts: &[@ast::expr], id: ast::node_id) -> result { let bcx = cx; diff --git a/src/comp/middle/trans_build.rs b/src/comp/middle/trans_build.rs index 52b976e2844..e7deb97a982 100644 --- a/src/comp/middle/trans_build.rs +++ b/src/comp/middle/trans_build.rs @@ -68,6 +68,21 @@ fn Invoke(cx: &@block_ctxt, Fn: ValueRef, Args: &[ValueRef], }); } +fn FastInvoke(cx: &@block_ctxt, Fn: ValueRef, Args: &[ValueRef], + Then: BasicBlockRef, Catch: BasicBlockRef) -> ValueRef { + assert (!cx.terminated); + cx.terminated = true; + let v = str::as_buf("", + {|buf| + llvm::LLVMBuildInvoke(B(cx), Fn, + vec::to_ptr(Args), + vec::len(Args), Then, + Catch, buf) + }); + llvm::LLVMSetInstructionCallConv(v, lib::llvm::LLVMFastCallConv); + ret v; +} + fn Unreachable(cx: &@block_ctxt) -> ValueRef { assert (!cx.terminated); cx.terminated = true; From 5e4637b61facfb607c02026e5d605e6bb6fe1a60 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Wed, 7 Sep 2011 11:58:49 -0700 Subject: [PATCH 05/28] Add Rust definitions for new LLVM EH instructions Issue #236 --- src/comp/lib/llvm.rs | 9 +++++++++ src/comp/middle/trans_build.rs | 16 ++++++++++++++++ src/rustllvm/rustllvm.def.in | 4 ++++ 3 files changed, 29 insertions(+) diff --git a/src/comp/lib/llvm.rs b/src/comp/lib/llvm.rs index 431893b0201..198b629e251 100644 --- a/src/comp/lib/llvm.rs +++ b/src/comp/lib/llvm.rs @@ -572,6 +572,9 @@ native "cdecl" mod llvm = "rustllvm" { fn LLVMBuildInvoke(B: BuilderRef, Fn: ValueRef, Args: *ValueRef, NumArgs: uint, Then: BasicBlockRef, Catch: BasicBlockRef, Name: sbuf) -> ValueRef; + fn LLVMBuildLandingPad(B: BuilderRef, Ty: TypeRef, PersFn: ValueRef, + NumClauses: uint, Name: sbuf) -> ValueRef; + fn LLVMBuildResume(B: BuilderRef, Exn: ValueRef) -> ValueRef; fn LLVMBuildUnreachable(B: BuilderRef) -> ValueRef; /* Add a case to the switch instruction */ @@ -580,6 +583,12 @@ native "cdecl" mod llvm = "rustllvm" { /* Add a destination to the indirectbr instruction */ fn LLVMAddDestination(IndirectBr: ValueRef, Dest: BasicBlockRef); + /* Add a clause to the landing pad instruction */ + fn LLVMAddClause(LandingPad: ValueRef, ClauseVal: ValueRef); + + /* Set the cleanup on a landing pad instruction */ + fn LLVMSetCleanup(LandingPad: ValueRef, Val: Bool); + /* Arithmetic */ fn LLVMBuildAdd(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, Name: sbuf) -> ValueRef; diff --git a/src/comp/middle/trans_build.rs b/src/comp/middle/trans_build.rs index e7deb97a982..c869ebbb24c 100644 --- a/src/comp/middle/trans_build.rs +++ b/src/comp/middle/trans_build.rs @@ -545,6 +545,22 @@ fn Trap(cx: &@block_ctxt) -> ValueRef { }); } +fn LandingPad(cx: &@block_ctxt, Ty: TypeRef, PersFn: ValueRef, + NumClauses: uint) -> ValueRef { + ret str::as_buf("", + {|buf| + llvm::LLVMBuildLandingPad(B(cx), + Ty, + PersFn, + NumClauses, + buf) + }); +} + +fn SetCleanup(_cx: &@block_ctxt, LandingPad: ValueRef) { + llvm::LLVMSetCleanup(LandingPad, lib::llvm::True); +} + // // Local Variables: // mode: rust diff --git a/src/rustllvm/rustllvm.def.in b/src/rustllvm/rustllvm.def.in index 25185f3cde5..deac70f3495 100644 --- a/src/rustllvm/rustllvm.def.in +++ b/src/rustllvm/rustllvm.def.in @@ -25,6 +25,7 @@ LLVMAddAttribute LLVMAddBasicAliasAnalysisPass LLVMAddCFGSimplificationPass LLVMAddCase +LLVMAddClause LLVMAddConstantMergePass LLVMAddConstantPropagationPass LLVMAddCorrelatedValuePropagationPass @@ -122,6 +123,7 @@ LLVMBuildIntToPtr LLVMBuildInvoke LLVMBuildIsNotNull LLVMBuildIsNull +LLVMBuildLandingPad LLVMBuildLShr LLVMBuildLoad LLVMBuildMalloc @@ -141,6 +143,7 @@ LLVMBuildPhi LLVMBuildPointerCast LLVMBuildPtrDiff LLVMBuildPtrToInt +LLVMBuildResume LLVMBuildRet LLVMBuildRetVoid LLVMBuildSDiv @@ -548,6 +551,7 @@ LLVMRunPassManager LLVMRunStaticConstructors LLVMRunStaticDestructors LLVMSetAlignment +LLVMSetCleanup LLVMSetCurrentDebugLocation LLVMSetDataLayout LLVMSetFunctionCallConv From 4eb3ce32801ddd9ad335bc82f70f245c5f3c797a Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Wed, 7 Sep 2011 14:28:02 -0700 Subject: [PATCH 06/28] Add landing pads to invokes Issue #236 --- src/comp/middle/trans.rs | 25 +++++++++++++++++++++---- src/comp/middle/trans_build.rs | 7 +++++++ 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 9a8b9bfaba1..df07f104270 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -3799,15 +3799,32 @@ fn invoke_fastcall(bcx: &@block_ctxt, llfn: ValueRef, let normal_bcx = new_sub_block_ctxt(bcx, "normal return"); let unwind_bcx = new_sub_block_ctxt(bcx, "unwind"); - let retval = trans_build::FastInvoke(bcx, llfn, llargs, - normal_bcx.llbb, - unwind_bcx.llbb); + let retval = FastInvoke(bcx, llfn, llargs, + normal_bcx.llbb, + unwind_bcx.llbb); trans_landing_pad(unwind_bcx); ret rslt(normal_bcx, retval); } fn trans_landing_pad(bcx: &@block_ctxt) { - Unreachable(bcx); + // The landing pad return type (the type being propagated). Not sure what + // this represents but it's determined by the personality function and + // this is what the EH proposal example uses. + let llretty = T_struct([T_ptr(T_i8()), T_i32()]); + // The exception handling personality function. This is the C++ + // personality function __gxx_personality_v0, wrapped in our naming + // convention. + let personality = bcx_ccx(bcx).upcalls.rust_personality; + // The only landing pad clause will be 'cleanup' + let clauses = 1u; + let llpad = LandingPad(bcx, llretty, personality, clauses); + // The landing pad result is used both for modifying the landing pad + // in the C API and as the exception value + let llretval = llpad; + // The landing pad block is a cleanup + SetCleanup(bcx, llpad); + // Continue unwinding + Resume(bcx, llretval); } fn trans_tup(cx: &@block_ctxt, elts: &[@ast::expr], id: ast::node_id) -> diff --git a/src/comp/middle/trans_build.rs b/src/comp/middle/trans_build.rs index c869ebbb24c..6f801551d11 100644 --- a/src/comp/middle/trans_build.rs +++ b/src/comp/middle/trans_build.rs @@ -547,6 +547,7 @@ fn Trap(cx: &@block_ctxt) -> ValueRef { fn LandingPad(cx: &@block_ctxt, Ty: TypeRef, PersFn: ValueRef, NumClauses: uint) -> ValueRef { + assert (!cx.terminated); ret str::as_buf("", {|buf| llvm::LLVMBuildLandingPad(B(cx), @@ -561,6 +562,12 @@ fn SetCleanup(_cx: &@block_ctxt, LandingPad: ValueRef) { llvm::LLVMSetCleanup(LandingPad, lib::llvm::True); } +fn Resume(cx: &@block_ctxt, Exn: ValueRef) -> ValueRef { + assert (!cx.terminated); + cx.terminated = true; + ret llvm::LLVMBuildResume(B(cx), Exn); +} + // // Local Variables: // mode: rust From 587b86377283ba7df557b506a9b5ed4ef00e175a Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Wed, 7 Sep 2011 16:17:06 -0700 Subject: [PATCH 07/28] Zero locals that have initializers that might fail This will avoid running cleanups on uninitialized memory Issue #236 --- src/comp/middle/trans.rs | 51 +++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index df07f104270..f90c5a15fb0 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -4447,7 +4447,9 @@ fn init_local(bcx: @block_ctxt, local: &@ast::local) -> result { // Make a note to drop this slot on the way out. add_clean(bcx, llptr, ty); - if must_zero(local) { bcx = zero_alloca(bcx, llptr, ty).bcx; } + if must_zero(bcx_ccx(bcx), local) { + bcx = zero_alloca(bcx, llptr, ty).bcx; + } alt local.node.init { some(init) { @@ -4473,36 +4475,37 @@ fn init_local(bcx: @block_ctxt, local: &@ast::local) -> result { bcx.fcx.lllocals, false); ret rslt(bcx, llptr); - fn must_zero(local: &@ast::local) -> bool { + fn must_zero(ccx: &@crate_ctxt, local: &@ast::local) -> bool { alt local.node.init { - some(init) { might_not_init(init.expr) } + some(init) { might_not_init(ccx, init.expr) } none. { true } } } - fn might_not_init(expr: &@ast::expr) -> bool { - type env = @mutable bool; - let e = @mutable false; - // FIXME: Probably also need to account for expressions that - // fail but since we don't unwind yet, it doesn't seem to be a - // problem + fn might_not_init(ccx: &@crate_ctxt, expr: &@ast::expr) -> bool { + type env = {mutable mightnt: bool, + ccx: @crate_ctxt}; + let e = {mutable mightnt: false, + ccx: ccx}; + fn visit_expr(ex: &@ast::expr, e: &env, v: &vt) { + let might_not_init = alt ex.node { + ast::expr_ret(_) { true } + ast::expr_break. { true } + ast::expr_cont. { true } + _ { + let ex_ty = ty::expr_ty(e.ccx.tcx, ex); + ty::type_is_bot(e.ccx.tcx, ex_ty) + } + }; + if might_not_init { + e.mightnt = true; + } else { visit::visit_expr(ex, e, v); } + } let visitor = - visit::mk_vt( - @{visit_expr: - fn (ex: &@ast::expr, e: &env, v: &vt) { - let might_not_init = - alt ex.node { - ast::expr_ret(_) { true } - ast::expr_break. { true } - ast::expr_cont. { true } - _ { false } - }; - if might_not_init { - *e = true; - } else { visit::visit_expr(ex, e, v); } - } with *visit::default_visitor()}); + visit::mk_vt(@{visit_expr: visit_expr + with *visit::default_visitor()}); visitor.visit_expr(expr, e, visitor); - ret *e; + ret e.mightnt; } } From 4c9eee8aa42891ac2a165eb3bbae9c16e4ee438d Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Wed, 7 Sep 2011 15:12:37 -0700 Subject: [PATCH 08/28] Run cleanups during unwinding Issue #236 --- src/comp/middle/trans.rs | 12 ++++++++++++ src/test/run-fail/unwind-box.rs | 10 ++++++++++ 2 files changed, 22 insertions(+) create mode 100644 src/test/run-fail/unwind-box.rs diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index f90c5a15fb0..aa82e03d57b 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -3823,6 +3823,18 @@ fn trans_landing_pad(bcx: &@block_ctxt) { let llretval = llpad; // The landing pad block is a cleanup SetCleanup(bcx, llpad); + + let bcx = bcx; + let scope_cx = bcx; + while true { + scope_cx = find_scope_cx(scope_cx); + bcx = trans_block_cleanups(bcx, scope_cx); + scope_cx = alt scope_cx.parent { + parent_some(b) { b } + parent_none. { break; } + }; + } + // Continue unwinding Resume(bcx, llretval); } diff --git a/src/test/run-fail/unwind-box.rs b/src/test/run-fail/unwind-box.rs new file mode 100644 index 00000000000..19906bda0ae --- /dev/null +++ b/src/test/run-fail/unwind-box.rs @@ -0,0 +1,10 @@ +// error-pattern:fail + +fn failfn() { + fail; +} + +fn main() { + @0; + failfn(); +} \ No newline at end of file From 4fba02c7e99758da1773069dca2afaa7f2e9cd31 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Wed, 7 Sep 2011 16:39:08 -0700 Subject: [PATCH 09/28] Invoke upcall_fail This allows landing pads to be generated around fail statements Issue #236 --- src/comp/middle/trans.rs | 19 +++++++++++++++---- src/test/run-fail/unwind-fail.rs | 6 ++++++ 2 files changed, 21 insertions(+), 4 deletions(-) create mode 100644 src/test/run-fail/unwind-fail.rs diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index aa82e03d57b..a78b452a4bd 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -3794,14 +3794,25 @@ fn trans_call(in_cx: &@block_ctxt, f: &@ast::expr, ret rslt(bcx, retval); } +fn invoke(bcx: &@block_ctxt, llfn: ValueRef, + llargs: &[ValueRef]) -> result { + ret invoke_(bcx, llfn, llargs, Invoke); +} + fn invoke_fastcall(bcx: &@block_ctxt, llfn: ValueRef, llargs: &[ValueRef]) -> result { + ret invoke_(bcx, llfn, llargs, FastInvoke); +} +fn invoke_(bcx: &@block_ctxt, llfn: ValueRef, + llargs: &[ValueRef], + invoker: fn(&@block_ctxt, ValueRef, &[ValueRef], + BasicBlockRef, BasicBlockRef) -> ValueRef) -> result { let normal_bcx = new_sub_block_ctxt(bcx, "normal return"); let unwind_bcx = new_sub_block_ctxt(bcx, "unwind"); - let retval = FastInvoke(bcx, llfn, llargs, - normal_bcx.llbb, - unwind_bcx.llbb); + let retval = invoker(bcx, llfn, llargs, + normal_bcx.llbb, + unwind_bcx.llbb); trans_landing_pad(unwind_bcx); ret rslt(normal_bcx, retval); } @@ -4291,7 +4302,7 @@ fn trans_fail_value(cx: &@block_ctxt, sp_opt: &option::t, let V_str = PointerCast(cx, V_fail_str, T_ptr(T_i8())); V_filename = PointerCast(cx, V_filename, T_ptr(T_i8())); let args = [cx.fcx.lltaskptr, V_str, V_filename, C_int(V_line)]; - Call(cx, bcx_ccx(cx).upcalls._fail, args); + let cx = invoke(cx, bcx_ccx(cx).upcalls._fail, args).bcx; Unreachable(cx); ret rslt(cx, C_nil()); } diff --git a/src/test/run-fail/unwind-fail.rs b/src/test/run-fail/unwind-fail.rs new file mode 100644 index 00000000000..2d4f138e715 --- /dev/null +++ b/src/test/run-fail/unwind-fail.rs @@ -0,0 +1,6 @@ +// error-pattern:fail + +fn main() { + @0; + fail; +} \ No newline at end of file From f99cf2d62f5cdf1075e7e2bb100112100a75242e Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Wed, 7 Sep 2011 17:01:24 -0700 Subject: [PATCH 10/28] Add a number of unwinding tests Issue #236 --- src/test/run-fail/unwind-assert.rs | 6 ++++++ src/test/run-fail/unwind-check.rs | 8 ++++++++ src/test/run-fail/unwind-closure.rs | 10 ++++++++++ src/test/run-fail/unwind-initializer.rs | 7 +++++++ src/test/run-fail/unwind-iter.rs | 12 ++++++++++++ src/test/run-fail/unwind-nested.rs | 11 +++++++++++ src/test/run-fail/unwind-stacked.rs | 16 ++++++++++++++++ src/test/run-fail/unwind-uninitialized.rs | 10 ++++++++++ src/test/run-pass/unwind-box.rs | 13 +++++++++++++ src/test/run-pass/unwind-resource.rs | 20 ++++++++++++++++++++ src/test/run-pass/unwind-resource2.rs | 17 +++++++++++++++++ 11 files changed, 130 insertions(+) create mode 100644 src/test/run-fail/unwind-assert.rs create mode 100644 src/test/run-fail/unwind-check.rs create mode 100644 src/test/run-fail/unwind-closure.rs create mode 100644 src/test/run-fail/unwind-initializer.rs create mode 100644 src/test/run-fail/unwind-iter.rs create mode 100644 src/test/run-fail/unwind-nested.rs create mode 100644 src/test/run-fail/unwind-stacked.rs create mode 100644 src/test/run-fail/unwind-uninitialized.rs create mode 100644 src/test/run-pass/unwind-box.rs create mode 100644 src/test/run-pass/unwind-resource.rs create mode 100644 src/test/run-pass/unwind-resource2.rs diff --git a/src/test/run-fail/unwind-assert.rs b/src/test/run-fail/unwind-assert.rs new file mode 100644 index 00000000000..e7aeedcf505 --- /dev/null +++ b/src/test/run-fail/unwind-assert.rs @@ -0,0 +1,6 @@ +// error-pattern:fail + +fn main() { + let a = @0; + assert false; +} \ No newline at end of file diff --git a/src/test/run-fail/unwind-check.rs b/src/test/run-fail/unwind-check.rs new file mode 100644 index 00000000000..e01cc969cea --- /dev/null +++ b/src/test/run-fail/unwind-check.rs @@ -0,0 +1,8 @@ +// error-pattern:fail + +pure fn p(a: @int) -> bool { false } + +fn main() { + let a = @0; + check p(a); +} \ No newline at end of file diff --git a/src/test/run-fail/unwind-closure.rs b/src/test/run-fail/unwind-closure.rs new file mode 100644 index 00000000000..216ae054947 --- /dev/null +++ b/src/test/run-fail/unwind-closure.rs @@ -0,0 +1,10 @@ +// error-pattern:fail + +fn f(a: @int) { + fail; +} + +fn main() { + let g = bind f(@0); + g(); +} \ No newline at end of file diff --git a/src/test/run-fail/unwind-initializer.rs b/src/test/run-fail/unwind-initializer.rs new file mode 100644 index 00000000000..b3dc0d3eaeb --- /dev/null +++ b/src/test/run-fail/unwind-initializer.rs @@ -0,0 +1,7 @@ +// error-pattern:fail + +fn main() { + let a: @int = { + fail; + }; +} \ No newline at end of file diff --git a/src/test/run-fail/unwind-iter.rs b/src/test/run-fail/unwind-iter.rs new file mode 100644 index 00000000000..fa64b0ad78c --- /dev/null +++ b/src/test/run-fail/unwind-iter.rs @@ -0,0 +1,12 @@ +// error-pattern:fail + +iter x() -> int { + fail; + put 0; +} + +fn main() { + let a = @0; + for each x in x() { + } +} \ No newline at end of file diff --git a/src/test/run-fail/unwind-nested.rs b/src/test/run-fail/unwind-nested.rs new file mode 100644 index 00000000000..48e3063c6dd --- /dev/null +++ b/src/test/run-fail/unwind-nested.rs @@ -0,0 +1,11 @@ +// error-pattern:fail + +fn main() { + let a = @0; + { + let b = @0; + { + fail; + } + } +} \ No newline at end of file diff --git a/src/test/run-fail/unwind-stacked.rs b/src/test/run-fail/unwind-stacked.rs new file mode 100644 index 00000000000..bf5258cee7d --- /dev/null +++ b/src/test/run-fail/unwind-stacked.rs @@ -0,0 +1,16 @@ +// error-pattern:fail + +fn f() { + let a = @0; + fail; +} + +fn g() { + let b = @0; + f(); +} + +fn main() { + let a = @0; + g(); +} \ No newline at end of file diff --git a/src/test/run-fail/unwind-uninitialized.rs b/src/test/run-fail/unwind-uninitialized.rs new file mode 100644 index 00000000000..35269b38714 --- /dev/null +++ b/src/test/run-fail/unwind-uninitialized.rs @@ -0,0 +1,10 @@ +// error-pattern:fail + +fn f() { + fail; +} + +fn main() { + f(); + let a = @0; +} \ No newline at end of file diff --git a/src/test/run-pass/unwind-box.rs b/src/test/run-pass/unwind-box.rs new file mode 100644 index 00000000000..692a62c8272 --- /dev/null +++ b/src/test/run-pass/unwind-box.rs @@ -0,0 +1,13 @@ +use std; +import std::task; + +fn f() { + task::unsupervise(); + let a = @0; + fail; +} + +fn main() { + let g = f; + task::spawn(g); +} \ No newline at end of file diff --git a/src/test/run-pass/unwind-resource.rs b/src/test/run-pass/unwind-resource.rs new file mode 100644 index 00000000000..cd25e43dfce --- /dev/null +++ b/src/test/run-pass/unwind-resource.rs @@ -0,0 +1,20 @@ +use std; +import std::task; +import std::comm; + +resource complainer(c: comm::chan) { + comm::send(c, true); +} + +fn f(c: -comm::chan) { + task::unsupervise(); + let c <- complainer(c); + fail; +} + +fn main() { + let p = comm::port(); + let c = comm::chan(p); + task::spawn(bind f(c)); + assert comm::recv(p); +} \ No newline at end of file diff --git a/src/test/run-pass/unwind-resource2.rs b/src/test/run-pass/unwind-resource2.rs new file mode 100644 index 00000000000..d2797f5154a --- /dev/null +++ b/src/test/run-pass/unwind-resource2.rs @@ -0,0 +1,17 @@ +use std; +import std::task; +import std::comm; + +resource complainer(c: @int) { +} + +fn f() { + task::unsupervise(); + let c <- complainer(@0); + fail; +} + +fn main() { + let g = f; + task::spawn(g); +} \ No newline at end of file From f28bbb2f951b175e93e4ce39b48b937a096b89b5 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Wed, 7 Sep 2011 17:03:20 -0700 Subject: [PATCH 11/28] Begin valgrinding some run-fail tests that unwind correctly Issue #236 --- src/test/run-fail/explicit-fail-msg.rs | 1 - src/test/run-fail/fmt-fail.rs | 1 - src/test/run-fail/linked-failure.rs | 1 - src/test/run-fail/vec-overrun.rs | 1 - src/test/run-fail/vec-underrun.rs | 1 - 5 files changed, 5 deletions(-) diff --git a/src/test/run-fail/explicit-fail-msg.rs b/src/test/run-fail/explicit-fail-msg.rs index b45e443759c..527a103e342 100644 --- a/src/test/run-fail/explicit-fail-msg.rs +++ b/src/test/run-fail/explicit-fail-msg.rs @@ -1,3 +1,2 @@ // error-pattern:wooooo -// no-valgrind fn main() { let a = 1; if 1 == 1 { a = 2; } fail "woooo" + "o"; } diff --git a/src/test/run-fail/fmt-fail.rs b/src/test/run-fail/fmt-fail.rs index 90256271fd2..5ca0ab74147 100644 --- a/src/test/run-fail/fmt-fail.rs +++ b/src/test/run-fail/fmt-fail.rs @@ -1,5 +1,4 @@ // error-pattern:meh -// no-valgrind use std; fn main() { let str_var: str = "meh"; fail #fmt["%s", str_var]; } diff --git a/src/test/run-fail/linked-failure.rs b/src/test/run-fail/linked-failure.rs index 033a3bc9ec2..8f4f196add6 100644 --- a/src/test/run-fail/linked-failure.rs +++ b/src/test/run-fail/linked-failure.rs @@ -2,7 +2,6 @@ // error-pattern:1 == 2 // no-valgrind - use std; import std::task; import std::comm::port; diff --git a/src/test/run-fail/vec-overrun.rs b/src/test/run-fail/vec-overrun.rs index 54329ca63b5..7a429e08cae 100644 --- a/src/test/run-fail/vec-overrun.rs +++ b/src/test/run-fail/vec-overrun.rs @@ -1,7 +1,6 @@ // -*- rust -*- // error-pattern:bounds check -// no-valgrind fn main() { let v: [int] = [10]; let x: int = 0; diff --git a/src/test/run-fail/vec-underrun.rs b/src/test/run-fail/vec-underrun.rs index 87c8295840e..9caf82d1ae0 100644 --- a/src/test/run-fail/vec-underrun.rs +++ b/src/test/run-fail/vec-underrun.rs @@ -1,7 +1,6 @@ // -*- rust -*- // error-pattern:bounds check -// no-valgrind fn main() { let v: [int] = [10, 20]; let x: int = 0; From a7c9f817bbaa17231f522dba27110c9170d283e1 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Wed, 7 Sep 2011 17:13:33 -0700 Subject: [PATCH 12/28] XFAIL run-fail/linked-failure This test is hitting a bug in the runtime that makes it fail incorrectly and not valgrind-clean --- src/test/run-fail/linked-failure.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/run-fail/linked-failure.rs b/src/test/run-fail/linked-failure.rs index 8f4f196add6..82884a1d0e3 100644 --- a/src/test/run-fail/linked-failure.rs +++ b/src/test/run-fail/linked-failure.rs @@ -1,6 +1,7 @@ // -*- rust -*- // error-pattern:1 == 2 +// xfail-test // no-valgrind use std; import std::task; From e8a16353ea69d7ab5e31abaeb459adcad4bc7a36 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Wed, 7 Sep 2011 17:16:04 -0700 Subject: [PATCH 13/28] Remove the no-valgrind test directive now that unwinding is more worky Issue #236 --- src/test/compiletest/header.rs | 13 ++----------- src/test/compiletest/runtest.rs | 7 +++---- src/test/run-fail/linked-failure.rs | 1 - 3 files changed, 5 insertions(+), 16 deletions(-) diff --git a/src/test/compiletest/header.rs b/src/test/compiletest/header.rs index 8a03378742b..1d952a57e99 100644 --- a/src/test/compiletest/header.rs +++ b/src/test/compiletest/header.rs @@ -16,10 +16,7 @@ type test_props = { compile_flags: option::t, // If present, the name of a file that this test should match when // pretty-printed - pp_exact: option::t, - // FIXME: no-valgrind is a temporary directive until all of run-fail - // is valgrind-clean - no_valgrind: bool + pp_exact: option::t }; // Load any test directives embedded in the file @@ -27,7 +24,6 @@ fn load_props(testfile: &str) -> test_props { let error_patterns = []; let compile_flags = option::none; let pp_exact = option::none; - let no_valgrind = false; for each ln: str in iter_header(testfile) { alt parse_error_pattern(ln) { option::some(ep) { error_patterns += [ep]; } @@ -41,16 +37,11 @@ fn load_props(testfile: &str) -> test_props { if option::is_none(pp_exact) { pp_exact = parse_pp_exact(ln, testfile); } - - if no_valgrind == false { - no_valgrind = parse_name_directive(ln, "no-valgrind"); - } } ret { error_patterns: error_patterns, compile_flags: compile_flags, - pp_exact: pp_exact, - no_valgrind: no_valgrind + pp_exact: pp_exact }; } diff --git a/src/test/compiletest/runtest.rs b/src/test/compiletest/runtest.rs index 373db1a10ad..c98f1deba24 100644 --- a/src/test/compiletest/runtest.rs +++ b/src/test/compiletest/runtest.rs @@ -249,10 +249,9 @@ fn make_exe_name(config: &config, testfile: &str) -> str { output_base_name(config, testfile) + os::exec_suffix() } -fn make_run_args(config: &config, props: &test_props, testfile: &str) -> +fn make_run_args(config: &config, _props: &test_props, testfile: &str) -> procargs { - let toolargs = - if !props.no_valgrind { + let toolargs = { // If we've got another tool to run under (valgrind), // then split apart its command let runtool = @@ -261,7 +260,7 @@ fn make_run_args(config: &config, props: &test_props, testfile: &str) -> option::none. { option::none } }; split_maybe_args(runtool) - } else { [] }; + }; let args = toolargs + [make_exe_name(config, testfile)]; ret {prog: args[0], args: vec::slice(args, 1u, vec::len(args))}; diff --git a/src/test/run-fail/linked-failure.rs b/src/test/run-fail/linked-failure.rs index 82884a1d0e3..24cfff6edb5 100644 --- a/src/test/run-fail/linked-failure.rs +++ b/src/test/run-fail/linked-failure.rs @@ -2,7 +2,6 @@ // error-pattern:1 == 2 // xfail-test -// no-valgrind use std; import std::task; import std::comm::port; From 53f7d6119ab2cc81ccfd658c5356292b593f7602 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Wed, 7 Sep 2011 17:43:55 -0700 Subject: [PATCH 14/28] Add some FIXMEs about unwinding implementation Issue #236 --- src/comp/middle/trans.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index a78b452a4bd..4d535c48eb1 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -3808,6 +3808,8 @@ fn invoke_(bcx: &@block_ctxt, llfn: ValueRef, llargs: &[ValueRef], invoker: fn(&@block_ctxt, ValueRef, &[ValueRef], BasicBlockRef, BasicBlockRef) -> ValueRef) -> result { + // FIXME: May be worth turning this into a plain call when there are no + // cleanups to run let normal_bcx = new_sub_block_ctxt(bcx, "normal return"); let unwind_bcx = new_sub_block_ctxt(bcx, "unwind"); let retval = invoker(bcx, llfn, llargs, @@ -3835,6 +3837,9 @@ fn trans_landing_pad(bcx: &@block_ctxt) { // The landing pad block is a cleanup SetCleanup(bcx, llpad); + // FIXME: This seems like a very naive and redundant way to generate the + // landing pads, as we're re-generating all in-scope cleanups for each + // function call. Probably good optimization opportunities here. let bcx = bcx; let scope_cx = bcx; while true { From 5b7145a9f41ba54d956dc16c147a3a06ba331e72 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Wed, 7 Sep 2011 18:29:12 -0700 Subject: [PATCH 15/28] Add an XFAILed test for failing destructors Issue #236 --- src/test/run-fail/unwind-resource-fail.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 src/test/run-fail/unwind-resource-fail.rs diff --git a/src/test/run-fail/unwind-resource-fail.rs b/src/test/run-fail/unwind-resource-fail.rs new file mode 100644 index 00000000000..4ab8dc95085 --- /dev/null +++ b/src/test/run-fail/unwind-resource-fail.rs @@ -0,0 +1,12 @@ +// error-pattern:fail +// xfail-test + +resource r(i: int) { + // What happens when destructors throw? + fail; +} + +fn main() { + @0; + let r <- r(0); +} \ No newline at end of file From 118194381c646b3200f7906710d6dd1630aa0fc8 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Wed, 7 Sep 2011 18:41:57 -0700 Subject: [PATCH 16/28] Invoke put functions Issue #236 --- src/comp/middle/trans.rs | 2 +- src/test/run-fail/unwind-iter2.rs | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 src/test/run-fail/unwind-iter2.rs diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 4d535c48eb1..2c9cbb6d0dc 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -4343,7 +4343,7 @@ fn trans_put(in_cx: &@block_ctxt, e: &option::t<@ast::expr>) -> result { llargs += [r.val]; } } - FastCall(bcx, llcallee, llargs); + bcx = invoke_fastcall(bcx, llcallee, llargs).bcx; bcx = trans_block_cleanups(bcx, cx); let next_cx = new_sub_block_ctxt(in_cx, "next"); Br(bcx, next_cx.llbb); diff --git a/src/test/run-fail/unwind-iter2.rs b/src/test/run-fail/unwind-iter2.rs new file mode 100644 index 00000000000..a924bb13616 --- /dev/null +++ b/src/test/run-fail/unwind-iter2.rs @@ -0,0 +1,12 @@ +// error-pattern:fail + +iter x() -> int { + let a = @0; + put 1; +} + +fn main() { + for each x in x() { + fail; + } +} \ No newline at end of file From 6f6f36172b2e0cd86ffffd1d0ed2deb75972db72 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Thu, 8 Sep 2011 10:37:52 -0700 Subject: [PATCH 17/28] Remove unused task_exit function Issue #236 --- src/rt/rust_task.cpp | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/rt/rust_task.cpp b/src/rt/rust_task.cpp index 57b5d16e427..b861c60b521 100644 --- a/src/rt/rust_task.cpp +++ b/src/rt/rust_task.cpp @@ -137,18 +137,6 @@ struct rust_closure_env { type_desc *td; }; -extern "C" CDECL -void task_exit(rust_closure_env *env, int rval, rust_task *task) { - LOG(task, task, "task exited with value %d", rval); - if(env) { - // free the environment. - I(task->sched, 1 == env->ref_count); // the ref count better be 1 - //env->td->drop_glue(NULL, task, NULL, env->td->first_param, env); - //env->td->free_glue(NULL, task, NULL, env->td->first_param, env); - task->free(env); - } -} - extern "C" CDECL void task_start_wrapper(spawn_args *a) { From 0ea55ffdc87cd65de707d2d947cb57084be950f7 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Thu, 8 Sep 2011 13:42:04 -0700 Subject: [PATCH 18/28] Use a unique exit status when the runtime fails normally Check for it in run-fail tests --- src/rt/rust_internal.h | 3 +++ src/rt/rust_kernel.cpp | 2 +- src/rt/rust_scheduler.cpp | 2 +- src/test/compiletest/runtest.rs | 14 ++++++++++---- 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/rt/rust_internal.h b/src/rt/rust_internal.h index d2c8574280b..c01fc5f3127 100644 --- a/src/rt/rust_internal.h +++ b/src/rt/rust_internal.h @@ -99,6 +99,9 @@ static size_t const TIME_SLICE_IN_MS = 10; static size_t const BUF_BYTES = 2048; +// The error status to use when the process fails +#define PROC_FAIL_CODE 101; + // Every reference counted object should use this macro and initialize // ref_count. diff --git a/src/rt/rust_kernel.cpp b/src/rt/rust_kernel.cpp index 54b1cc98d43..e5234b9d6f5 100644 --- a/src/rt/rust_kernel.cpp +++ b/src/rt/rust_kernel.cpp @@ -140,7 +140,7 @@ rust_kernel::fail() { // Runtime to terminate it in an unusual way" when trying to shutdown // cleanly. #if defined(__WIN32__) - exit(1); + exit(rval); #endif for(size_t i = 0; i < num_threads; ++i) { rust_scheduler *thread = threads[i]; diff --git a/src/rt/rust_scheduler.cpp b/src/rt/rust_scheduler.cpp index 3a69184d3fe..b127ec77efa 100644 --- a/src/rt/rust_scheduler.cpp +++ b/src/rt/rust_scheduler.cpp @@ -71,7 +71,7 @@ rust_scheduler::fail() { log(NULL, log_err, "domain %s @0x%" PRIxPTR " root task failed", name, this); I(this, kernel->rval == 0); - kernel->rval = 1; + kernel->rval = PROC_FAIL_CODE; kernel->fail(); } diff --git a/src/test/compiletest/runtest.rs b/src/test/compiletest/runtest.rs index c98f1deba24..fdcd627811d 100644 --- a/src/test/compiletest/runtest.rs +++ b/src/test/compiletest/runtest.rs @@ -51,15 +51,21 @@ fn run_rfail_test(cx: &cx, props: &test_props, testfile: &str) { procres = exec_compiled_test(cx, props, testfile); - if procres.status == 0 { - fatal_procres("run-fail test didn't produce an error!", procres); - } - + // The value our Makefile configures valgrind to return on failure const valgrind_err: int = 100; if procres.status == valgrind_err { fatal_procres("run-fail test isn't valgrind-clean!", procres); } + // The value the rust runtime returns on failure + const rust_err: int = 101; + if procres.status != rust_err { + fatal_procres( + #fmt("run-fail test produced the wrong error code: %d", + procres.status), + procres); + } + check_error_patterns(props, testfile, procres); } From d267e7486e7158f8633424389f789d23149e1064 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Thu, 8 Sep 2011 13:45:12 -0700 Subject: [PATCH 19/28] Zero locals when the initializer might call a function The function might fail, leaving the local uninitialized Issue #236 --- src/comp/middle/trans.rs | 1 + src/test/run-fail/unwind-initializer-indirect.rs | 7 +++++++ 2 files changed, 8 insertions(+) create mode 100644 src/test/run-fail/unwind-initializer-indirect.rs diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 2c9cbb6d0dc..4f9b554f439 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -4520,6 +4520,7 @@ fn init_local(bcx: @block_ctxt, local: &@ast::local) -> result { ast::expr_ret(_) { true } ast::expr_break. { true } ast::expr_cont. { true } + ast::expr_call(_, _) { true } _ { let ex_ty = ty::expr_ty(e.ccx.tcx, ex); ty::type_is_bot(e.ccx.tcx, ex_ty) diff --git a/src/test/run-fail/unwind-initializer-indirect.rs b/src/test/run-fail/unwind-initializer-indirect.rs new file mode 100644 index 00000000000..726dc3d9040 --- /dev/null +++ b/src/test/run-fail/unwind-initializer-indirect.rs @@ -0,0 +1,7 @@ +// error-pattern:fail + +fn f() -> @int { fail; } + +fn main() { + let a: @int = f(); +} \ No newline at end of file From 22001d1dcef5d2c40a242402f75d5acc540bee2b Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Thu, 8 Sep 2011 16:59:23 -0700 Subject: [PATCH 20/28] Remove hack_allow_leaks Happy to close the loop on this one. Issue #236 --- src/lib/test.rs | 7 ------- src/rt/memory_region.cpp | 11 +++-------- src/rt/memory_region.h | 5 ----- src/rt/rust_builtin.cpp | 7 ------- src/rt/rustrt.def.in | 1 - 5 files changed, 3 insertions(+), 28 deletions(-) diff --git a/src/lib/test.rs b/src/lib/test.rs index 37fec12e9ce..cbee1f1f479 100644 --- a/src/lib/test.rs +++ b/src/lib/test.rs @@ -26,7 +26,6 @@ export configure_test_task; export joinable; native "rust" mod rustrt { - fn hack_allow_leaks(); fn sched_threads() -> uint; } @@ -325,12 +324,6 @@ fn configure_test_task() { // If this task fails we don't want that failure to propagate to the // test runner or else we couldn't keep running tests task::unsupervise(); - - // FIXME (236): Hack supreme - unwinding doesn't work yet so if this - // task fails memory will not be freed correctly. This turns off the - // sanity checks in the runtime's memory region for the task, so that - // the test runner can continue. - rustrt::hack_allow_leaks(); } // Local Variables: diff --git a/src/rt/memory_region.cpp b/src/rt/memory_region.cpp index ef8a92b427f..a55d073543d 100644 --- a/src/rt/memory_region.cpp +++ b/src/rt/memory_region.cpp @@ -15,13 +15,13 @@ memory_region::alloc_header *memory_region::get_header(void *mem) { memory_region::memory_region(rust_srv *srv, bool synchronized) : _srv(srv), _parent(NULL), _live_allocations(0), _detailed_leaks(srv->env->detailed_leaks), - _synchronized(synchronized), _hack_allow_leaks(false) { + _synchronized(synchronized) { } memory_region::memory_region(memory_region *parent) : _srv(parent->_srv), _parent(parent), _live_allocations(0), _detailed_leaks(parent->_detailed_leaks), - _synchronized(parent->_synchronized), _hack_allow_leaks(false) { + _synchronized(parent->_synchronized) { } void memory_region::add_alloc() { @@ -127,18 +127,13 @@ memory_region::~memory_region() { assert(leak_count == _live_allocations); } #endif - if (!_hack_allow_leaks && _live_allocations > 0) { + if (_live_allocations > 0) { _srv->fatal(msg, __FILE__, __LINE__, "%d objects", _live_allocations); } if (_synchronized) { _lock.unlock(); } } -void -memory_region::hack_allow_leaks() { - _hack_allow_leaks = true; -} - void memory_region::release_alloc(void *mem) { alloc_header *alloc = get_header(mem); diff --git a/src/rt/memory_region.h b/src/rt/memory_region.h index 0197057268c..9d2106c1eaf 100644 --- a/src/rt/memory_region.h +++ b/src/rt/memory_region.h @@ -32,7 +32,6 @@ private: const bool _detailed_leaks; const bool _synchronized; lock_and_signal _lock; - bool _hack_allow_leaks; void add_alloc(); void dec_alloc(); @@ -46,10 +45,6 @@ public: void *realloc(void *mem, size_t size); void free(void *mem); virtual ~memory_region(); - // FIXME (236: This is a temporary hack to allow failing tasks that leak - // to not kill the entire process, which the test runner needs. Please - // kill with prejudice once unwinding works. - void hack_allow_leaks(); void release_alloc(void *mem); void claim_alloc(void *mem); diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.cpp index 5e0c9dbf4c2..2499dea0328 100644 --- a/src/rt/rust_builtin.cpp +++ b/src/rt/rust_builtin.cpp @@ -224,13 +224,6 @@ debug_opaque(rust_task *task, type_desc *t, uint8_t *front) } } -extern "C" CDECL void -hack_allow_leaks(rust_task *task) -{ - LOG(task, stdlib, "hack_allow_leaks"); - task->local_region.hack_allow_leaks(); -} - struct rust_box { RUST_REFCOUNTED(rust_box) diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in index 246ac261f8f..bf8155b7998 100644 --- a/src/rt/rustrt.def.in +++ b/src/rt/rustrt.def.in @@ -28,7 +28,6 @@ get_task_id get_task_pointer get_task_trampoline get_time -hack_allow_leaks last_os_error leak migrate_alloc From d00be1d9621b1b00d5112a1aff56c1dc40091765 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Fri, 9 Sep 2011 13:24:06 -0700 Subject: [PATCH 21/28] Add the ability to xfail tests by platform We'll use this to xfail some unwinding tests on windows --- src/test/compiletest/header.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/test/compiletest/header.rs b/src/test/compiletest/header.rs index 1d952a57e99..27cffc4264e 100644 --- a/src/test/compiletest/header.rs +++ b/src/test/compiletest/header.rs @@ -50,11 +50,16 @@ fn is_test_ignored(config: &config, testfile: &str) -> bool { for each ln: str in iter_header(testfile) { // FIXME: Can't return or break from iterator found = found || parse_name_directive(ln, "xfail-test"); + found = found || parse_name_directive(ln, xfail_target()); if (config.mode == common::mode_pretty) { found = found || parse_name_directive(ln, "xfail-pretty"); } } ret found; + + fn xfail_target() -> str { + "xfail-" + std::os::target_os() + } } iter iter_header(testfile: &str) -> str { From be9fe24220b6e0e3355188e53e2c2cd4b6fa72a1 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Fri, 9 Sep 2011 13:25:06 -0700 Subject: [PATCH 22/28] XFAIL some run-pass unwinding tests on win32 Curiously, because of some unfortunate interaction between win32 hacks, all the run-fail unwind tests actually pass (that wouldn't be the case if we were valgrinding though). --- src/test/run-pass/unwind-box.rs | 1 + src/test/run-pass/unwind-resource.rs | 1 + src/test/run-pass/unwind-resource2.rs | 1 + 3 files changed, 3 insertions(+) diff --git a/src/test/run-pass/unwind-box.rs b/src/test/run-pass/unwind-box.rs index 692a62c8272..0c4f1e4616c 100644 --- a/src/test/run-pass/unwind-box.rs +++ b/src/test/run-pass/unwind-box.rs @@ -1,3 +1,4 @@ +// xfail-win32 use std; import std::task; diff --git a/src/test/run-pass/unwind-resource.rs b/src/test/run-pass/unwind-resource.rs index cd25e43dfce..184f3209b83 100644 --- a/src/test/run-pass/unwind-resource.rs +++ b/src/test/run-pass/unwind-resource.rs @@ -1,3 +1,4 @@ +// xfail-win32 use std; import std::task; import std::comm; diff --git a/src/test/run-pass/unwind-resource2.rs b/src/test/run-pass/unwind-resource2.rs index d2797f5154a..1d7a46151fc 100644 --- a/src/test/run-pass/unwind-resource2.rs +++ b/src/test/run-pass/unwind-resource2.rs @@ -1,3 +1,4 @@ +// xfail-win32 use std; import std::task; import std::comm; From 79403820705dd9dc37653952e95d71d78a7e2163 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Fri, 9 Sep 2011 13:34:22 -0700 Subject: [PATCH 23/28] XFAIL run-pass/task-comm-15 on win32 again Maybe it works with check-fast, but it stills fails for me --- src/test/run-pass/task-comm-15.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/run-pass/task-comm-15.rs b/src/test/run-pass/task-comm-15.rs index 2b89d8fde38..56cf41b50c3 100644 --- a/src/test/run-pass/task-comm-15.rs +++ b/src/test/run-pass/task-comm-15.rs @@ -1,3 +1,4 @@ +// xfail-win32 use std; import std::comm; import std::task; From e193c9c1d600418e5c6739e2a5f389acb53610e0 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Fri, 9 Sep 2011 13:52:49 -0700 Subject: [PATCH 24/28] Don't check-fast xfail-win32 tests --- src/etc/combine-tests.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/etc/combine-tests.py b/src/etc/combine-tests.py index 163004c4605..09b80ba448f 100755 --- a/src/etc/combine-tests.py +++ b/src/etc/combine-tests.py @@ -27,7 +27,8 @@ for t in os.listdir(run_pass): f = codecs.open(os.path.join(run_pass, t), "r", "utf8") s = f.read() if not ("xfail-test" in s or - "xfail-fast" in s): + "xfail-fast" in s or + "xfail-win32" in s): stage2_tests.append(t) if "main(args: [str])" in s: take_args[t] = True From 69d6e0d208137de067f7ee29d053be0ef4005c47 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Fri, 9 Sep 2011 16:20:11 -0700 Subject: [PATCH 25/28] Add some more unwind tests They worked without modifications, but I wrote them so we're keeping them. Issue #236 --- src/test/run-fail/unwind-lambda.rs | 16 ++++++++++++++++ src/test/run-fail/unwind-misc-1.rs | 28 ++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 src/test/run-fail/unwind-lambda.rs create mode 100644 src/test/run-fail/unwind-misc-1.rs diff --git a/src/test/run-fail/unwind-lambda.rs b/src/test/run-fail/unwind-lambda.rs new file mode 100644 index 00000000000..28907f3af9f --- /dev/null +++ b/src/test/run-fail/unwind-lambda.rs @@ -0,0 +1,16 @@ +// error-pattern:fail + +fn main() { + let cheese = "roquefort"; + let carrots = @"crunchy"; + + fn (tasties: @str, macerate: &block(&str)) { + macerate(*tasties); + } (carrots, { |&food| + let mush = food + cheese; + lambda() { + let chew = mush + cheese; + fail "so yummy" + } (); + }); +} \ No newline at end of file diff --git a/src/test/run-fail/unwind-misc-1.rs b/src/test/run-fail/unwind-misc-1.rs new file mode 100644 index 00000000000..0ae4302616a --- /dev/null +++ b/src/test/run-fail/unwind-misc-1.rs @@ -0,0 +1,28 @@ +// error-pattern:fail + +use std; +import std::map; +import std::uint; + +fn main() { + let count = @mutable 0u; + let hash = bind fn (_s: &[@str], count: @mutable uint) -> uint { + *count += 1u; + if *count == 10u { + fail; + } else { + ret *count; + } + } (_, count); + + fn eq(s: &[@str], t: &[@str]) -> bool { + ret s == t; + } + + let map = map::mk_hashmap(hash, eq); + let arr = []; + for each i in uint::range(0u, 10u) { + arr += [@"key stuff"]; + map.insert(arr, arr + [@"value stuff"]); + } +} \ No newline at end of file From fda196769a2aad38d84c79a21e1d7d692364c502 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sun, 11 Sep 2011 21:13:59 -0700 Subject: [PATCH 26/28] Actually fail the process when compiletest has a test failure We previously failed by coincidence because of memory leaks. --- src/test/compiletest/compiletest.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/compiletest/compiletest.rs b/src/test/compiletest/compiletest.rs index c931369cfc7..c89b851cdb5 100644 --- a/src/test/compiletest/compiletest.rs +++ b/src/test/compiletest/compiletest.rs @@ -110,8 +110,9 @@ fn run_tests(config: &config) { let opts = test_opts(config); let cx = {config: config, procsrv: procsrv::mk()}; let tests = make_tests(cx); - test::run_tests_console_(opts, tests.tests, tests.to_task); + let res = test::run_tests_console_(opts, tests.tests, tests.to_task); procsrv::close(cx.procsrv); + if !res { fail "Some tests failed"; } } fn test_opts(config: &config) -> test::test_opts { From cb50e4329af7091db430a74fa36737a4dd84608d Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sun, 11 Sep 2011 23:14:42 -0700 Subject: [PATCH 27/28] Add an XFAILed test for native "llvm" modules This functionality is completely broken --- src/test/run-pass/native-llvm.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 src/test/run-pass/native-llvm.rs diff --git a/src/test/run-pass/native-llvm.rs b/src/test/run-pass/native-llvm.rs new file mode 100644 index 00000000000..450f052bc62 --- /dev/null +++ b/src/test/run-pass/native-llvm.rs @@ -0,0 +1,10 @@ +// xfail-test + +native "llvm" mod llvm { + fn thesqrt(n: float) -> float = "sqrt.f64"; +} + +fn main() { + let s = llvm::thesqrt(4.0); + assert 1.9 < s && s < 2.1; +} \ No newline at end of file From 6ffcfba6b990d6f27243e4dd6ddfffab141e1f44 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sun, 11 Sep 2011 23:19:05 -0700 Subject: [PATCH 28/28] XFAIL bench/shootout-nbody This is the only file in the whole codebase that depends on the (broken) llvm native ABI. --- src/test/bench/shootout-nbody.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/bench/shootout-nbody.rs b/src/test/bench/shootout-nbody.rs index 5e888041981..d693c9161c5 100644 --- a/src/test/bench/shootout-nbody.rs +++ b/src/test/bench/shootout-nbody.rs @@ -1,3 +1,4 @@ +// xfail-test // based on: // http://shootout.alioth.debian.org/u32/benchmark.php?test=nbody&lang=java