Skip to content

Commit 6789a77

Browse files
committed
auto merge of #10172 : pythonesque/rust/issue-9890, r=thestinger
2 parents 623daf6 + eee892c commit 6789a77

File tree

2 files changed

+126
-71
lines changed

2 files changed

+126
-71
lines changed

src/librustc/middle/trans/tvec.rs

Lines changed: 97 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use middle::trans::datum::*;
2222
use middle::trans::expr::{Dest, Ignore, SaveIn};
2323
use middle::trans::expr;
2424
use middle::trans::glue;
25-
use middle::trans::machine::{llsize_of, nonzero_llsize_of};
25+
use middle::trans::machine::{llsize_of, nonzero_llsize_of, llsize_of_alloc};
2626
use middle::trans::type_of;
2727
use middle::ty;
2828
use util::common::indenter;
@@ -144,16 +144,19 @@ pub struct VecTypes {
144144
vec_ty: ty::t,
145145
unit_ty: ty::t,
146146
llunit_ty: Type,
147-
llunit_size: ValueRef
147+
llunit_size: ValueRef,
148+
llunit_alloc_size: uint
148149
}
149150

150151
impl VecTypes {
151152
pub fn to_str(&self, ccx: &CrateContext) -> ~str {
152-
format!("VecTypes \\{vec_ty={}, unit_ty={}, llunit_ty={}, llunit_size={}\\}",
153+
format!("VecTypes \\{vec_ty={}, unit_ty={}, llunit_ty={}, llunit_size={}, \
154+
llunit_alloc_size={}\\}",
153155
ty_to_str(ccx.tcx, self.vec_ty),
154156
ty_to_str(ccx.tcx, self.unit_ty),
155157
ccx.tn.type_to_str(self.llunit_ty),
156-
ccx.tn.val_to_str(self.llunit_size))
158+
ccx.tn.val_to_str(self.llunit_size),
159+
self.llunit_alloc_size)
157160
}
158161
}
159162

@@ -416,48 +419,10 @@ pub fn write_content(bcx: @mut Block,
416419
expr::trans_to_datum(bcx, element)
417420
});
418421

419-
let next_bcx = sub_block(bcx, "expr_repeat: while next");
420-
let loop_bcx = loop_scope_block(bcx, next_bcx, None, "expr_repeat", None);
421-
let cond_bcx = scope_block(loop_bcx, None, "expr_repeat: loop cond");
422-
let set_bcx = scope_block(loop_bcx, None, "expr_repeat: body: set");
423-
let inc_bcx = scope_block(loop_bcx, None, "expr_repeat: body: inc");
424-
Br(bcx, loop_bcx.llbb);
425-
426-
let loop_counter = {
427-
// i = 0
428-
let i = alloca(loop_bcx, bcx.ccx().int_type, "__i");
429-
Store(loop_bcx, C_uint(bcx.ccx(), 0), i);
430-
431-
Br(loop_bcx, cond_bcx.llbb);
432-
i
433-
};
434-
435-
{ // i < count
436-
let lhs = Load(cond_bcx, loop_counter);
437-
let rhs = C_uint(bcx.ccx(), count);
438-
let cond_val = ICmp(cond_bcx, lib::llvm::IntULT, lhs, rhs);
439-
440-
CondBr(cond_bcx, cond_val, set_bcx.llbb, next_bcx.llbb);
441-
}
442-
443-
{ // v[i] = elem
444-
let i = Load(set_bcx, loop_counter);
445-
let lleltptr = InBoundsGEP(set_bcx, lldest, [i]);
446-
let set_bcx = elem.copy_to(set_bcx, INIT, lleltptr);
447-
448-
Br(set_bcx, inc_bcx.llbb);
449-
}
450-
451-
{ // i += 1
452-
let i = Load(inc_bcx, loop_counter);
453-
let plusone = Add(inc_bcx, i, C_uint(bcx.ccx(), 1));
454-
Store(inc_bcx, plusone, loop_counter);
455-
456-
Br(inc_bcx, cond_bcx.llbb);
457-
}
458-
459-
return next_bcx;
460-
422+
iter_vec_loop(bcx, lldest, vt,
423+
C_uint(bcx.ccx(), count), |set_bcx, lleltptr, _| {
424+
elem.copy_to(set_bcx, INIT, lleltptr)
425+
})
461426
}
462427
}
463428
}
@@ -478,11 +443,13 @@ pub fn vec_types(bcx: @mut Block, vec_ty: ty::t) -> VecTypes {
478443
let unit_ty = ty::sequence_element_type(bcx.tcx(), vec_ty);
479444
let llunit_ty = type_of::type_of(ccx, unit_ty);
480445
let llunit_size = nonzero_llsize_of(ccx, llunit_ty);
446+
let llunit_alloc_size = llsize_of_alloc(ccx, llunit_ty);
481447

482448
VecTypes {vec_ty: vec_ty,
483449
unit_ty: unit_ty,
484450
llunit_ty: llunit_ty,
485-
llunit_size: llunit_size}
451+
llunit_size: llunit_size,
452+
llunit_alloc_size: llunit_alloc_size}
486453
}
487454

488455
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
574541

575542
pub type iter_vec_block<'self> = &'self fn(@mut Block, ValueRef, ty::t) -> @mut Block;
576543

544+
pub fn iter_vec_loop(bcx: @mut Block,
545+
data_ptr: ValueRef,
546+
vt: &VecTypes,
547+
count: ValueRef,
548+
f: iter_vec_block
549+
) -> @mut Block {
550+
let _icx = push_ctxt("tvec::iter_vec_loop");
551+
552+
let next_bcx = sub_block(bcx, "iter_vec_loop: while next");
553+
let loop_bcx = loop_scope_block(bcx, next_bcx, None, "iter_vec_loop", None);
554+
let cond_bcx = scope_block(loop_bcx, None, "iter_vec_loop: loop cond");
555+
let body_bcx = scope_block(loop_bcx, None, "iter_vec_loop: body: main");
556+
let inc_bcx = scope_block(loop_bcx, None, "iter_vec_loop: loop inc");
557+
Br(bcx, loop_bcx.llbb);
558+
559+
let loop_counter = {
560+
// i = 0
561+
let i = alloca(loop_bcx, bcx.ccx().int_type, "__i");
562+
Store(loop_bcx, C_uint(bcx.ccx(), 0), i);
563+
564+
Br(loop_bcx, cond_bcx.llbb);
565+
i
566+
};
567+
568+
{ // i < count
569+
let lhs = Load(cond_bcx, loop_counter);
570+
let rhs = count;
571+
let cond_val = ICmp(cond_bcx, lib::llvm::IntULT, lhs, rhs);
572+
573+
CondBr(cond_bcx, cond_val, body_bcx.llbb, next_bcx.llbb);
574+
}
575+
576+
{ // loop body
577+
let i = Load(body_bcx, loop_counter);
578+
let lleltptr = if vt.llunit_alloc_size == 0 {
579+
data_ptr
580+
} else {
581+
InBoundsGEP(body_bcx, data_ptr, [i])
582+
};
583+
let body_bcx = f(body_bcx, lleltptr, vt.unit_ty);
584+
585+
Br(body_bcx, inc_bcx.llbb);
586+
}
587+
588+
{ // i += 1
589+
let i = Load(inc_bcx, loop_counter);
590+
let plusone = Add(inc_bcx, i, C_uint(bcx.ccx(), 1));
591+
Store(inc_bcx, plusone, loop_counter);
592+
593+
Br(inc_bcx, cond_bcx.llbb);
594+
}
595+
596+
next_bcx
597+
}
598+
577599
pub fn iter_vec_raw(bcx: @mut Block, data_ptr: ValueRef, vec_ty: ty::t,
578600
fill: ValueRef, f: iter_vec_block) -> @mut Block {
579601
let _icx = push_ctxt("tvec::iter_vec_raw");
580602

581-
let unit_ty = ty::sequence_element_type(bcx.tcx(), vec_ty);
582-
583-
// Calculate the last pointer address we want to handle.
584-
// FIXME (#3729): Optimize this when the size of the unit type is
585-
// statically known to not use pointer casts, which tend to confuse
586-
// LLVM.
587-
let data_end_ptr = pointer_add_byte(bcx, data_ptr, fill);
588-
589-
// Now perform the iteration.
590-
let header_bcx = base::sub_block(bcx, "iter_vec_loop_header");
591-
Br(bcx, header_bcx.llbb);
592-
let data_ptr =
593-
Phi(header_bcx, val_ty(data_ptr), [data_ptr], [bcx.llbb]);
594-
let not_yet_at_end =
595-
ICmp(header_bcx, lib::llvm::IntULT, data_ptr, data_end_ptr);
596-
let body_bcx = base::sub_block(header_bcx, "iter_vec_loop_body");
597-
let next_bcx = base::sub_block(header_bcx, "iter_vec_next");
598-
CondBr(header_bcx, not_yet_at_end, body_bcx.llbb, next_bcx.llbb);
599-
let body_bcx = f(body_bcx, data_ptr, unit_ty);
600-
AddIncomingToPhi(data_ptr, InBoundsGEP(body_bcx, data_ptr,
601-
[C_int(bcx.ccx(), 1)]),
602-
body_bcx.llbb);
603-
Br(body_bcx, header_bcx.llbb);
604-
return next_bcx;
603+
let vt = vec_types(bcx, vec_ty);
604+
if (vt.llunit_alloc_size == 0) {
605+
// Special-case vectors with elements of size 0 so they don't go out of bounds (#9890)
606+
iter_vec_loop(bcx, data_ptr, &vt, fill, f)
607+
} else {
608+
// Calculate the last pointer address we want to handle.
609+
// FIXME (#3729): Optimize this when the size of the unit type is
610+
// statically known to not use pointer casts, which tend to confuse
611+
// LLVM.
612+
let data_end_ptr = pointer_add_byte(bcx, data_ptr, fill);
613+
614+
// Now perform the iteration.
615+
let header_bcx = base::sub_block(bcx, "iter_vec_loop_header");
616+
Br(bcx, header_bcx.llbb);
617+
let data_ptr =
618+
Phi(header_bcx, val_ty(data_ptr), [data_ptr], [bcx.llbb]);
619+
let not_yet_at_end =
620+
ICmp(header_bcx, lib::llvm::IntULT, data_ptr, data_end_ptr);
621+
let body_bcx = base::sub_block(header_bcx, "iter_vec_loop_body");
622+
let next_bcx = base::sub_block(header_bcx, "iter_vec_next");
623+
CondBr(header_bcx, not_yet_at_end, body_bcx.llbb, next_bcx.llbb);
624+
let body_bcx = f(body_bcx, data_ptr, vt.unit_ty);
625+
AddIncomingToPhi(data_ptr, InBoundsGEP(body_bcx, data_ptr,
626+
[C_int(bcx.ccx(), 1)]),
627+
body_bcx.llbb);
628+
Br(body_bcx, header_bcx.llbb);
629+
next_bcx
605630

631+
}
606632
}
607633

608634
pub fn iter_vec_uniq(bcx: @mut Block, vptr: ValueRef, vec_ty: ty::t,
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
static mut destructions : int = 3;
12+
13+
pub fn foo() {
14+
#[unsafe_no_drop_flag]
15+
struct Foo;
16+
17+
impl Drop for Foo {
18+
fn drop(&mut self) {
19+
unsafe { destructions -= 1 };
20+
}
21+
};
22+
23+
let _x = [Foo, Foo, Foo];
24+
}
25+
26+
pub fn main() {
27+
foo();
28+
assert!((unsafe { destructions } == 0));
29+
}

0 commit comments

Comments
 (0)