Skip to content

Commit

Permalink
auto merge of #16970 : kmcallister/rust/llvm-unreachable, r=thestinger
Browse files Browse the repository at this point in the history
I'm not sure how to add an automated test for this.
  • Loading branch information
bors committed Oct 5, 2014
2 parents 3b8c528 + 675aa76 commit 5660db2
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 0 deletions.
7 changes: 7 additions & 0 deletions src/libcore/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down
4 changes: 4 additions & 0 deletions src/librustc/middle/trans/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions src/librustc/middle/typeck/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5586,6 +5586,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()),
Expand Down
15 changes: 15 additions & 0 deletions src/test/run-make/intrinsic-unreachable/Makefile
Original file line number Diff line number Diff line change
@@ -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
20 changes: 20 additions & 0 deletions src/test/run-make/intrinsic-unreachable/exit-ret.rs
Original file line number Diff line number Diff line change
@@ -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.
}
}
22 changes: 22 additions & 0 deletions src/test/run-make/intrinsic-unreachable/exit-unreachable.rs
Original file line number Diff line number Diff line change
@@ -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()
}
}
24 changes: 24 additions & 0 deletions src/test/run-pass/intrinsic-unreachable.rs
Original file line number Diff line number Diff line change
@@ -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);
}

0 comments on commit 5660db2

Please sign in to comment.