Skip to content

Commit

Permalink
rustc: handle allocas and LoadRangeAsserts in unreachable blocks corr…
Browse files Browse the repository at this point in the history
…ectly.

An alloca in an unreachable block would shortcircuit with Undef, but with type
`Type`, rather than type `*Type` (i.e. a plain value, not a pointer) but it is
expected to return a pointer into the stack, leading to confusion and LLVM
asserts later.

Similarly, attaching the range metadata to a Load in an unreachable block
makes LLVM unhappy, since the Load returns Undef.

Fixes #7344.
  • Loading branch information
huonw committed Jul 16, 2013
1 parent e4f7561 commit e252277
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 11 deletions.
2 changes: 1 addition & 1 deletion src/librustc/middle/trans/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1549,7 +1549,7 @@ pub fn alloca_maybe_zeroed(cx: block, ty: Type, name: &str, zero: bool) -> Value
let _icx = push_ctxt("alloca");
if cx.unreachable {
unsafe {
return llvm::LLVMGetUndef(ty.to_ref());
return llvm::LLVMGetUndef(ty.ptr_to().to_ref());
}
}
let initcx = base::raw_block(cx.fcx, false, cx.fcx.get_llstaticallocas());
Expand Down
20 changes: 11 additions & 9 deletions src/librustc/middle/trans/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -569,15 +569,17 @@ pub fn LoadRangeAssert(cx: block, PointerVal: ValueRef, lo: c_ulonglong,
hi: c_ulonglong, signed: lib::llvm::Bool) -> ValueRef {
let value = Load(cx, PointerVal);

unsafe {
let t = llvm::LLVMGetElementType(llvm::LLVMTypeOf(PointerVal));
let min = llvm::LLVMConstInt(t, lo, signed);
let max = llvm::LLVMConstInt(t, hi, signed);

do [min, max].as_imm_buf |ptr, len| {
llvm::LLVMSetMetadata(value, lib::llvm::MD_range as c_uint,
llvm::LLVMMDNodeInContext(cx.fcx.ccx.llcx,
ptr, len as c_uint));
if !cx.unreachable {
unsafe {
let t = llvm::LLVMGetElementType(llvm::LLVMTypeOf(PointerVal));
let min = llvm::LLVMConstInt(t, lo, signed);
let max = llvm::LLVMConstInt(t, hi, signed);

do [min, max].as_imm_buf |ptr, len| {
llvm::LLVMSetMetadata(value, lib::llvm::MD_range as c_uint,
llvm::LLVMMDNodeInContext(cx.fcx.ccx.llcx,
ptr, len as c_uint));
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/trans/datum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,7 @@ impl Datum {
pub fn to_value_datum(&self, bcx: block) -> Datum {
/*!
*
* Yields a by-ref form of this datum. This may involve
* Yields a by-value form of this datum. This may involve
* creation of a temporary stack slot. The value returned by
* this function is not separately rooted from this datum, so
* it will not live longer than the current datum. */
Expand Down
28 changes: 28 additions & 0 deletions src/test/run-pass/issue-7344.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright 2013 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.

#[allow(unreachable_code)];

fn foo() -> bool { false }

fn bar() {
return;
!foo();
}

fn baz() {
return;
if "" == "" {}
}

fn main() {
bar();
baz();
}

0 comments on commit e252277

Please sign in to comment.