From 401aeaf6d3a6ec712ee46151faf574adaa5ff3c6 Mon Sep 17 00:00:00 2001 From: Keegan McAllister <kmcallister@mozilla.com> Date: Wed, 3 Sep 2014 12:00:08 -0700 Subject: [PATCH 1/2] Add intrinsics::unreachable --- src/libcore/intrinsics.rs | 7 +++++++ src/librustc/middle/trans/intrinsic.rs | 4 ++++ src/librustc/middle/typeck/check/mod.rs | 1 + 3 files changed, 12 insertions(+) diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index a3d63bbe06cd1..7d86b65168f3c 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -250,6 +250,13 @@ extern "rust-intrinsic" { /// Abort the execution of the process. pub fn abort() -> !; + /// Tell LLVM that this point in the code is not reachable, + /// enabling further optimizations. + /// + /// NB: This is very different from the `unreachable!()` macro! + #[cfg(not(stage0))] + pub fn unreachable() -> !; + /// Execute a breakpoint trap, for inspection by a debugger. pub fn breakpoint(); diff --git a/src/librustc/middle/trans/intrinsic.rs b/src/librustc/middle/trans/intrinsic.rs index 628971775ae8c..f9d55143c8400 100644 --- a/src/librustc/middle/trans/intrinsic.rs +++ b/src/librustc/middle/trans/intrinsic.rs @@ -228,6 +228,10 @@ pub fn trans_intrinsic_call<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, node: ast::N Unreachable(bcx); v } + (_, "unreachable") => { + Unreachable(bcx); + C_nil(ccx) + } (_, "breakpoint") => { let llfn = ccx.get_intrinsic(&("llvm.debugtrap")); Call(bcx, llfn, [], None) diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index d4c38d48a8c56..197fd2367277a 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -5589,6 +5589,7 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) { } else { match name.get() { "abort" => (0, Vec::new(), ty::mk_bot()), + "unreachable" => (0, Vec::new(), ty::mk_bot()), "breakpoint" => (0, Vec::new(), ty::mk_nil()), "size_of" | "pref_align_of" | "min_align_of" => (1u, Vec::new(), ty::mk_uint()), From 675aa7692dd1b75e63b11cd991be5efddbdb2acd Mon Sep 17 00:00:00 2001 From: Keegan McAllister <kmcallister@mozilla.com> Date: Thu, 4 Sep 2014 16:09:18 -0700 Subject: [PATCH 2/2] Add tests for intrinsics::unreachable --- .../run-make/intrinsic-unreachable/Makefile | 15 ++++++++++++ .../intrinsic-unreachable/exit-ret.rs | 20 ++++++++++++++++ .../intrinsic-unreachable/exit-unreachable.rs | 22 +++++++++++++++++ src/test/run-pass/intrinsic-unreachable.rs | 24 +++++++++++++++++++ 4 files changed, 81 insertions(+) create mode 100644 src/test/run-make/intrinsic-unreachable/Makefile create mode 100644 src/test/run-make/intrinsic-unreachable/exit-ret.rs create mode 100644 src/test/run-make/intrinsic-unreachable/exit-unreachable.rs create mode 100644 src/test/run-pass/intrinsic-unreachable.rs diff --git a/src/test/run-make/intrinsic-unreachable/Makefile b/src/test/run-make/intrinsic-unreachable/Makefile new file mode 100644 index 0000000000000..305e8a7ddc968 --- /dev/null +++ b/src/test/run-make/intrinsic-unreachable/Makefile @@ -0,0 +1,15 @@ +-include ../tools.mk + +ifndef IS_WINDOWS +# The assembly for exit-unreachable.rs should be shorter because it's missing +# (at minimum) a return instruction. + +all: + $(RUSTC) -O --emit asm exit-ret.rs + $(RUSTC) -O --emit asm exit-unreachable.rs + test `wc -l < $(TMPDIR)/exit-unreachable.s` -lt `wc -l < $(TMPDIR)/exit-ret.s` +else +# Because of Windows exception handling, the code is not necessarily any shorter. +# https://github.com/llvm-mirror/llvm/commit/64b2297786f7fd6f5fa24cdd4db0298fbf211466 +all: +endif diff --git a/src/test/run-make/intrinsic-unreachable/exit-ret.rs b/src/test/run-make/intrinsic-unreachable/exit-ret.rs new file mode 100644 index 0000000000000..02c03445ef4e6 --- /dev/null +++ b/src/test/run-make/intrinsic-unreachable/exit-ret.rs @@ -0,0 +1,20 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <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. + +#![feature(asm)] +#![crate_type="lib"] + +pub fn exit(n: uint) { + unsafe { + // Pretend this asm is an exit() syscall. + asm!("" :: "r"(n) :: "volatile"); + // Can't actually reach this point, but rustc doesn't know that. + } +} diff --git a/src/test/run-make/intrinsic-unreachable/exit-unreachable.rs b/src/test/run-make/intrinsic-unreachable/exit-unreachable.rs new file mode 100644 index 0000000000000..835e068c15cfd --- /dev/null +++ b/src/test/run-make/intrinsic-unreachable/exit-unreachable.rs @@ -0,0 +1,22 @@ +// 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. + +#![feature(asm)] +#![crate_type="lib"] + +use std::intrinsics; + +pub fn exit(n: uint) -> ! { + unsafe { + // Pretend this asm is an exit() syscall. + asm!("" :: "r"(n) :: "volatile"); + intrinsics::unreachable() + } +} diff --git a/src/test/run-pass/intrinsic-unreachable.rs b/src/test/run-pass/intrinsic-unreachable.rs new file mode 100644 index 0000000000000..5e8b758cdf68f --- /dev/null +++ b/src/test/run-pass/intrinsic-unreachable.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. + +use std::intrinsics; + +// See also src/test/run-make/intrinsic-unreachable. + +unsafe fn f(x: uint) -> uint { + match x { + 17 => 23, + _ => intrinsics::unreachable(), + } +} + +fn main() { + assert_eq!(unsafe { f(17) }, 23); +}