auto merge of #10172 : pythonesque/rust/issue-9890, r=thestinger

This commit is contained in:
bors 2013-10-30 13:26:29 -07:00
commit 6789a77fa0
2 changed files with 125 additions and 70 deletions

View file

@ -22,7 +22,7 @@ use middle::trans::datum::*;
use middle::trans::expr::{Dest, Ignore, SaveIn};
use middle::trans::expr;
use middle::trans::glue;
use middle::trans::machine::{llsize_of, nonzero_llsize_of};
use middle::trans::machine::{llsize_of, nonzero_llsize_of, llsize_of_alloc};
use middle::trans::type_of;
use middle::ty;
use util::common::indenter;
@ -144,16 +144,19 @@ pub struct VecTypes {
vec_ty: ty::t,
unit_ty: ty::t,
llunit_ty: Type,
llunit_size: ValueRef
llunit_size: ValueRef,
llunit_alloc_size: uint
}
impl VecTypes {
pub fn to_str(&self, ccx: &CrateContext) -> ~str {
format!("VecTypes \\{vec_ty={}, unit_ty={}, llunit_ty={}, llunit_size={}\\}",
format!("VecTypes \\{vec_ty={}, unit_ty={}, llunit_ty={}, llunit_size={}, \
llunit_alloc_size={}\\}",
ty_to_str(ccx.tcx, self.vec_ty),
ty_to_str(ccx.tcx, self.unit_ty),
ccx.tn.type_to_str(self.llunit_ty),
ccx.tn.val_to_str(self.llunit_size))
ccx.tn.val_to_str(self.llunit_size),
self.llunit_alloc_size)
}
}
@ -416,48 +419,10 @@ pub fn write_content(bcx: @mut Block,
expr::trans_to_datum(bcx, element)
});
let next_bcx = sub_block(bcx, "expr_repeat: while next");
let loop_bcx = loop_scope_block(bcx, next_bcx, None, "expr_repeat", None);
let cond_bcx = scope_block(loop_bcx, None, "expr_repeat: loop cond");
let set_bcx = scope_block(loop_bcx, None, "expr_repeat: body: set");
let inc_bcx = scope_block(loop_bcx, None, "expr_repeat: body: inc");
Br(bcx, loop_bcx.llbb);
let loop_counter = {
// i = 0
let i = alloca(loop_bcx, bcx.ccx().int_type, "__i");
Store(loop_bcx, C_uint(bcx.ccx(), 0), i);
Br(loop_bcx, cond_bcx.llbb);
i
};
{ // i < count
let lhs = Load(cond_bcx, loop_counter);
let rhs = C_uint(bcx.ccx(), count);
let cond_val = ICmp(cond_bcx, lib::llvm::IntULT, lhs, rhs);
CondBr(cond_bcx, cond_val, set_bcx.llbb, next_bcx.llbb);
}
{ // v[i] = elem
let i = Load(set_bcx, loop_counter);
let lleltptr = InBoundsGEP(set_bcx, lldest, [i]);
let set_bcx = elem.copy_to(set_bcx, INIT, lleltptr);
Br(set_bcx, inc_bcx.llbb);
}
{ // i += 1
let i = Load(inc_bcx, loop_counter);
let plusone = Add(inc_bcx, i, C_uint(bcx.ccx(), 1));
Store(inc_bcx, plusone, loop_counter);
Br(inc_bcx, cond_bcx.llbb);
}
return next_bcx;
iter_vec_loop(bcx, lldest, vt,
C_uint(bcx.ccx(), count), |set_bcx, lleltptr, _| {
elem.copy_to(set_bcx, INIT, lleltptr)
})
}
}
}
@ -478,11 +443,13 @@ pub fn vec_types(bcx: @mut Block, vec_ty: ty::t) -> VecTypes {
let unit_ty = ty::sequence_element_type(bcx.tcx(), vec_ty);
let llunit_ty = type_of::type_of(ccx, unit_ty);
let llunit_size = nonzero_llsize_of(ccx, llunit_ty);
let llunit_alloc_size = llsize_of_alloc(ccx, llunit_ty);
VecTypes {vec_ty: vec_ty,
unit_ty: unit_ty,
llunit_ty: llunit_ty,
llunit_size: llunit_size}
llunit_size: llunit_size,
llunit_alloc_size: llunit_alloc_size}
}
pub fn elements_required(bcx: @mut Block, content_expr: &ast::Expr) -> uint {
@ -574,35 +541,94 @@ pub fn get_base_and_len(bcx: @mut Block, llval: ValueRef, vec_ty: ty::t) -> (Val
pub type iter_vec_block<'self> = &'self fn(@mut Block, ValueRef, ty::t) -> @mut Block;
pub fn iter_vec_loop(bcx: @mut Block,
data_ptr: ValueRef,
vt: &VecTypes,
count: ValueRef,
f: iter_vec_block
) -> @mut Block {
let _icx = push_ctxt("tvec::iter_vec_loop");
let next_bcx = sub_block(bcx, "iter_vec_loop: while next");
let loop_bcx = loop_scope_block(bcx, next_bcx, None, "iter_vec_loop", None);
let cond_bcx = scope_block(loop_bcx, None, "iter_vec_loop: loop cond");
let body_bcx = scope_block(loop_bcx, None, "iter_vec_loop: body: main");
let inc_bcx = scope_block(loop_bcx, None, "iter_vec_loop: loop inc");
Br(bcx, loop_bcx.llbb);
let loop_counter = {
// i = 0
let i = alloca(loop_bcx, bcx.ccx().int_type, "__i");
Store(loop_bcx, C_uint(bcx.ccx(), 0), i);
Br(loop_bcx, cond_bcx.llbb);
i
};
{ // i < count
let lhs = Load(cond_bcx, loop_counter);
let rhs = count;
let cond_val = ICmp(cond_bcx, lib::llvm::IntULT, lhs, rhs);
CondBr(cond_bcx, cond_val, body_bcx.llbb, next_bcx.llbb);
}
{ // loop body
let i = Load(body_bcx, loop_counter);
let lleltptr = if vt.llunit_alloc_size == 0 {
data_ptr
} else {
InBoundsGEP(body_bcx, data_ptr, [i])
};
let body_bcx = f(body_bcx, lleltptr, vt.unit_ty);
Br(body_bcx, inc_bcx.llbb);
}
{ // i += 1
let i = Load(inc_bcx, loop_counter);
let plusone = Add(inc_bcx, i, C_uint(bcx.ccx(), 1));
Store(inc_bcx, plusone, loop_counter);
Br(inc_bcx, cond_bcx.llbb);
}
next_bcx
}
pub fn iter_vec_raw(bcx: @mut Block, data_ptr: ValueRef, vec_ty: ty::t,
fill: ValueRef, f: iter_vec_block) -> @mut Block {
let _icx = push_ctxt("tvec::iter_vec_raw");
let unit_ty = ty::sequence_element_type(bcx.tcx(), vec_ty);
let vt = vec_types(bcx, vec_ty);
if (vt.llunit_alloc_size == 0) {
// Special-case vectors with elements of size 0 so they don't go out of bounds (#9890)
iter_vec_loop(bcx, data_ptr, &vt, fill, f)
} else {
// Calculate the last pointer address we want to handle.
// FIXME (#3729): Optimize this when the size of the unit type is
// statically known to not use pointer casts, which tend to confuse
// LLVM.
let data_end_ptr = pointer_add_byte(bcx, data_ptr, fill);
// Calculate the last pointer address we want to handle.
// FIXME (#3729): Optimize this when the size of the unit type is
// statically known to not use pointer casts, which tend to confuse
// LLVM.
let data_end_ptr = pointer_add_byte(bcx, data_ptr, fill);
// Now perform the iteration.
let header_bcx = base::sub_block(bcx, "iter_vec_loop_header");
Br(bcx, header_bcx.llbb);
let data_ptr =
Phi(header_bcx, val_ty(data_ptr), [data_ptr], [bcx.llbb]);
let not_yet_at_end =
ICmp(header_bcx, lib::llvm::IntULT, data_ptr, data_end_ptr);
let body_bcx = base::sub_block(header_bcx, "iter_vec_loop_body");
let next_bcx = base::sub_block(header_bcx, "iter_vec_next");
CondBr(header_bcx, not_yet_at_end, body_bcx.llbb, next_bcx.llbb);
let body_bcx = f(body_bcx, data_ptr, unit_ty);
AddIncomingToPhi(data_ptr, InBoundsGEP(body_bcx, data_ptr,
[C_int(bcx.ccx(), 1)]),
body_bcx.llbb);
Br(body_bcx, header_bcx.llbb);
return next_bcx;
// Now perform the iteration.
let header_bcx = base::sub_block(bcx, "iter_vec_loop_header");
Br(bcx, header_bcx.llbb);
let data_ptr =
Phi(header_bcx, val_ty(data_ptr), [data_ptr], [bcx.llbb]);
let not_yet_at_end =
ICmp(header_bcx, lib::llvm::IntULT, data_ptr, data_end_ptr);
let body_bcx = base::sub_block(header_bcx, "iter_vec_loop_body");
let next_bcx = base::sub_block(header_bcx, "iter_vec_next");
CondBr(header_bcx, not_yet_at_end, body_bcx.llbb, next_bcx.llbb);
let body_bcx = f(body_bcx, data_ptr, vt.unit_ty);
AddIncomingToPhi(data_ptr, InBoundsGEP(body_bcx, data_ptr,
[C_int(bcx.ccx(), 1)]),
body_bcx.llbb);
Br(body_bcx, header_bcx.llbb);
next_bcx
}
}
pub fn iter_vec_uniq(bcx: @mut Block, vptr: ValueRef, vec_ty: ty::t,

View file

@ -0,0 +1,29 @@
// 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.
static mut destructions : int = 3;
pub fn foo() {
#[unsafe_no_drop_flag]
struct Foo;
impl Drop for Foo {
fn drop(&mut self) {
unsafe { destructions -= 1 };
}
};
let _x = [Foo, Foo, Foo];
}
pub fn main() {
foo();
assert!((unsafe { destructions } == 0));
}