diff options
| author | bors <bors@rust-lang.org> | 2014-10-10 07:52:00 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2014-10-10 07:52:00 +0000 |
| commit | 45797a0765e74d6972f194c5c79425cd65474d53 (patch) | |
| tree | ed735d2e6ba239ccac645e393bb58030944aa62f | |
| parent | b74208bc12390b168e4a342de27d806639d89ffe (diff) | |
| parent | bc3831b7303b10781327d270dca2524cefdbff3d (diff) | |
| download | rust-45797a0765e74d6972f194c5c79425cd65474d53.tar.gz rust-45797a0765e74d6972f194c5c79425cd65474d53.zip | |
auto merge of #17037 : kmcallister/rust/no-stack-check, r=thestinger
r? @brson Fixes #16980.
| -rw-r--r-- | src/librustc/driver/config.rs | 2 | ||||
| -rw-r--r-- | src/librustc/lint/builtin.rs | 1 | ||||
| -rw-r--r-- | src/librustc/middle/trans/base.rs | 38 | ||||
| -rw-r--r-- | src/librustc/middle/trans/foreign.rs | 2 | ||||
| -rw-r--r-- | src/librustc/middle/trans/monomorphize.rs | 2 | ||||
| -rw-r--r-- | src/librustrt/thread.rs | 4 | ||||
| -rw-r--r-- | src/test/debuginfo/function-prologue-stepping-no-stack-check.rs (renamed from src/test/debuginfo/function-prologue-stepping-no-split-stack.rs) | 24 | ||||
| -rw-r--r-- | src/test/run-make/no-stack-check/Makefile | 15 | ||||
| -rw-r--r-- | src/test/run-make/no-stack-check/attr.rs | 25 | ||||
| -rw-r--r-- | src/test/run-make/no-stack-check/flag.rs | 24 | ||||
| -rw-r--r-- | src/test/run-pass/deprecated-no-split-stack.rs | 14 | ||||
| -rw-r--r-- | src/test/run-pass/smallest-hello-world.rs | 2 |
12 files changed, 121 insertions, 32 deletions
diff --git a/src/librustc/driver/config.rs b/src/librustc/driver/config.rs index fdd3c5b5a26..f5423b22fe2 100644 --- a/src/librustc/driver/config.rs +++ b/src/librustc/driver/config.rs @@ -390,6 +390,8 @@ cgoptions!( "divide crate into N units to optimize in parallel"), remark: Passes = (SomePasses(Vec::new()), parse_passes, "print remarks for these optimization passes (space separated, or \"all\")"), + no_stack_check: bool = (false, parse_bool, + "disable checks for stack exhaustion (a memory-safety hazard!)"), ) pub fn build_codegen_options(matches: &getopts::Matches) -> CodegenOptions diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index 451d39fbc3d..e0e16390e35 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -571,6 +571,7 @@ impl LintPass for UnusedAttribute { "no_builtins", "no_mangle", "no_split_stack", + "no_stack_check", "packed", "static_assert", "thread_local", diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 8df5b375a81..692017b6750 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -204,7 +204,7 @@ pub fn decl_fn(ccx: &CrateContext, name: &str, cc: llvm::CallConv, // Function addresses in Rust are never significant, allowing functions to be merged. llvm::SetUnnamedAddr(llfn, true); - if ccx.is_split_stack_supported() { + if ccx.is_split_stack_supported() && !ccx.sess().opts.cg.no_stack_check { set_split_stack(llfn); } @@ -245,7 +245,7 @@ fn get_extern_rust_fn(ccx: &CrateContext, fn_ty: ty::t, name: &str, did: ast::De let f = decl_rust_fn(ccx, fn_ty, name); csearch::get_item_attrs(&ccx.sess().cstore, did, |attrs| { - set_llvm_fn_attrs(attrs.as_slice(), f) + set_llvm_fn_attrs(ccx, attrs.as_slice(), f) }); ccx.externs().borrow_mut().insert(name.to_string(), f); @@ -450,7 +450,7 @@ pub fn set_inline_hint(f: ValueRef) { llvm::SetFunctionAttribute(f, llvm::InlineHintAttribute) } -pub fn set_llvm_fn_attrs(attrs: &[ast::Attribute], llfn: ValueRef) { +pub fn set_llvm_fn_attrs(ccx: &CrateContext, attrs: &[ast::Attribute], llfn: ValueRef) { use syntax::attr::*; // Set the inline hint if there is one match find_inline_attr(attrs) { @@ -460,16 +460,24 @@ pub fn set_llvm_fn_attrs(attrs: &[ast::Attribute], llfn: ValueRef) { InlineNone => { /* fallthrough */ } } - // Add the no-split-stack attribute if requested - if contains_name(attrs, "no_split_stack") { - unset_split_stack(llfn); - } - - if contains_name(attrs, "cold") { - unsafe { - llvm::LLVMAddFunctionAttribute(llfn, - llvm::FunctionIndex as c_uint, - llvm::ColdAttribute as uint64_t) + for attr in attrs.iter() { + let mut used = true; + match attr.name().get() { + "no_stack_check" => unset_split_stack(llfn), + "no_split_stack" => { + unset_split_stack(llfn); + ccx.sess().span_warn(attr.span, + "no_split_stack is a deprecated synonym for no_stack_check"); + } + "cold" => unsafe { + llvm::LLVMAddFunctionAttribute(llfn, + llvm::FunctionIndex as c_uint, + llvm::ColdAttribute as uint64_t) + }, + _ => used = false, + } + if used { + attr::mark_used(attr); } } } @@ -2732,7 +2740,7 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef { sym, i.id) }; - set_llvm_fn_attrs(i.attrs.as_slice(), llfn); + set_llvm_fn_attrs(ccx, i.attrs.as_slice(), llfn); llfn } @@ -2874,7 +2882,7 @@ fn register_method(ccx: &CrateContext, id: ast::NodeId, let sym = exported_name(ccx, id, mty, m.attrs.as_slice()); let llfn = register_fn(ccx, m.span, sym, id, mty); - set_llvm_fn_attrs(m.attrs.as_slice(), llfn); + set_llvm_fn_attrs(ccx, m.attrs.as_slice(), llfn); llfn } diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs index 9cff7261806..e47adb6bc0e 100644 --- a/src/librustc/middle/trans/foreign.rs +++ b/src/librustc/middle/trans/foreign.rs @@ -640,7 +640,7 @@ pub fn trans_rust_fn_with_foreign_abi(ccx: &CrateContext, id, t.repr(tcx)); let llfn = base::decl_internal_rust_fn(ccx, t, ps.as_slice()); - base::set_llvm_fn_attrs(attrs, llfn); + base::set_llvm_fn_attrs(ccx, attrs, llfn); base::trans_fn(ccx, decl, body, llfn, param_substs, id, []); llfn } diff --git a/src/librustc/middle/trans/monomorphize.rs b/src/librustc/middle/trans/monomorphize.rs index 12a2815cfef..e2c1bf1d8d1 100644 --- a/src/librustc/middle/trans/monomorphize.rs +++ b/src/librustc/middle/trans/monomorphize.rs @@ -149,7 +149,7 @@ pub fn monomorphic_fn(ccx: &CrateContext, }; let setup_lldecl = |lldecl, attrs: &[ast::Attribute]| { base::update_linkage(ccx, lldecl, None, base::OriginalTranslation); - set_llvm_fn_attrs(attrs, lldecl); + set_llvm_fn_attrs(ccx, attrs, lldecl); let is_first = !ccx.available_monomorphizations().borrow().contains(&s); if is_first { diff --git a/src/librustrt/thread.rs b/src/librustrt/thread.rs index bef799d4178..9a67e5c72ac 100644 --- a/src/librustrt/thread.rs +++ b/src/librustrt/thread.rs @@ -39,9 +39,9 @@ static DEFAULT_STACK_SIZE: uint = 1024 * 1024; // This is the starting point of rust os threads. The first thing we do // is make sure that we don't trigger __morestack (also why this has a -// no_split_stack annotation), and then we extract the main function +// no_stack_check annotation), and then we extract the main function // and invoke it. -#[no_split_stack] +#[no_stack_check] extern fn thread_start(main: *mut libc::c_void) -> imp::rust_thread_return { unsafe { stack::record_os_managed_stack_bounds(0, uint::MAX); diff --git a/src/test/debuginfo/function-prologue-stepping-no-split-stack.rs b/src/test/debuginfo/function-prologue-stepping-no-stack-check.rs index 05e2c5eb6c7..b68eec386a5 100644 --- a/src/test/debuginfo/function-prologue-stepping-no-split-stack.rs +++ b/src/test/debuginfo/function-prologue-stepping-no-stack-check.rs @@ -11,7 +11,7 @@ // ignore-android: FIXME(#10381) // This test case checks if function arguments already have the correct value when breaking at the -// beginning of a function. Functions with the #[no_split_stack] attribute have the same prologue as +// beginning of a function. Functions with the #[no_stack_check] attribute have the same prologue as // regular C functions compiled with GCC or Clang and therefore are better handled by GDB. As a // consequence, and as opposed to regular Rust functions, we can set the breakpoints via the // function name (and don't have to fall back on using line numbers). For LLDB this shouldn't make @@ -246,7 +246,7 @@ #![allow(unused_variable)] -#[no_split_stack] +#[no_stack_check] fn immediate_args(a: int, b: bool, c: f64) { () } @@ -262,42 +262,42 @@ struct BigStruct { h: u64 } -#[no_split_stack] +#[no_stack_check] fn non_immediate_args(a: BigStruct, b: BigStruct) { () } -#[no_split_stack] +#[no_stack_check] fn binding(a: i64, b: u64, c: f64) { let x = 0i; } -#[no_split_stack] +#[no_stack_check] fn assignment(mut a: u64, b: u64, c: f64) { a = b; } -#[no_split_stack] +#[no_stack_check] fn function_call(x: u64, y: u64, z: f64) { std::io::stdio::print("Hi!") } -#[no_split_stack] +#[no_stack_check] fn identifier(x: u64, y: u64, z: f64) -> u64 { x } -#[no_split_stack] +#[no_stack_check] fn return_expr(x: u64, y: u64, z: f64) -> u64 { return x; } -#[no_split_stack] +#[no_stack_check] fn arithmetic_expr(x: u64, y: u64, z: f64) -> u64 { x + y } -#[no_split_stack] +#[no_stack_check] fn if_expr(x: u64, y: u64, z: f64) -> u64 { if x + y < 1000 { x @@ -306,7 +306,7 @@ fn if_expr(x: u64, y: u64, z: f64) -> u64 { } } -#[no_split_stack] +#[no_stack_check] fn while_expr(mut x: u64, y: u64, z: u64) -> u64 { while x + y < 1000 { x += z @@ -314,7 +314,7 @@ fn while_expr(mut x: u64, y: u64, z: u64) -> u64 { return x; } -#[no_split_stack] +#[no_stack_check] fn loop_expr(mut x: u64, y: u64, z: u64) -> u64 { loop { x += z; diff --git a/src/test/run-make/no-stack-check/Makefile b/src/test/run-make/no-stack-check/Makefile new file mode 100644 index 00000000000..561056d719e --- /dev/null +++ b/src/test/run-make/no-stack-check/Makefile @@ -0,0 +1,15 @@ +-include ../tools.mk + +ifndef IS_WINDOWS +all: + $(RUSTC) -O --emit asm attr.rs + ! grep -q morestack $(TMPDIR)/attr.s + $(RUSTC) -O --emit asm flag.rs + grep -q morestack $(TMPDIR)/flag.s + $(RUSTC) -O --emit asm -C no-stack-check flag.rs + ! grep -q morestack $(TMPDIR)/flag.s +else +# On Windows we use __chkstk and it only appears in functions with large allocations, +# so this test wouldn't be reliable. +all: +endif diff --git a/src/test/run-make/no-stack-check/attr.rs b/src/test/run-make/no-stack-check/attr.rs new file mode 100644 index 00000000000..ef2db932b41 --- /dev/null +++ b/src/test/run-make/no-stack-check/attr.rs @@ -0,0 +1,25 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_type="lib"] + +extern { + // Prevents optimizing away the stack buffer. + // This symbol is undefined, but the code doesn't need to pass + // the linker. + fn black_box(ptr: *const u8); +} + +#[no_stack_check] +pub unsafe fn foo() { + // Make sure we use the stack + let x: [u8, ..50] = [0, ..50]; + black_box(x.as_ptr()); +} diff --git a/src/test/run-make/no-stack-check/flag.rs b/src/test/run-make/no-stack-check/flag.rs new file mode 100644 index 00000000000..ee0364001e1 --- /dev/null +++ b/src/test/run-make/no-stack-check/flag.rs @@ -0,0 +1,24 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_type="lib"] + +extern { + // Prevents optimizing away the stack buffer. + // This symbol is undefined, but the code doesn't need to pass + // the linker. + fn black_box(ptr: *const u8); +} + +pub unsafe fn foo() { + // Make sure we use the stack + let x: [u8, ..50] = [0, ..50]; + black_box(x.as_ptr()); +} diff --git a/src/test/run-pass/deprecated-no-split-stack.rs b/src/test/run-pass/deprecated-no-split-stack.rs new file mode 100644 index 00000000000..31ba5dde815 --- /dev/null +++ b/src/test/run-pass/deprecated-no-split-stack.rs @@ -0,0 +1,14 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//~ WARNING no_split_stack is a deprecated synonym for no_stack_check +#[no_split_stack] +fn main() { +} diff --git a/src/test/run-pass/smallest-hello-world.rs b/src/test/run-pass/smallest-hello-world.rs index fdddac6bc37..65307c5e7b5 100644 --- a/src/test/run-pass/smallest-hello-world.rs +++ b/src/test/run-pass/smallest-hello-world.rs @@ -25,7 +25,7 @@ extern "rust-intrinsic" { fn transmute<T, U>(t: T) -> U; } #[lang = "fail_fmt"] fn fail_fmt() -> ! { loop {} } #[start] -#[no_split_stack] +#[no_stack_check] fn main(_: int, _: *const *const u8) -> int { unsafe { let (ptr, _): (*const u8, uint) = transmute("Hello!\0"); |
