auto merge of #10172 : pythonesque/rust/issue-9890, r=thestinger
This commit is contained in:
commit
6789a77fa0
@ -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,
|
||||
|
29
src/test/run-pass/zero-size-type-destructors.rs
Normal file
29
src/test/run-pass/zero-size-type-destructors.rs
Normal 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));
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user