Skip to content

Commit 6b45886

Browse files
committed
---
yaml --- r: 15813 b: refs/heads/try c: fa5cc5b h: refs/heads/master i: 15811: 25cdaba v: v3
1 parent 2dfdcdd commit 6b45886

File tree

12 files changed

+172
-31
lines changed

12 files changed

+172
-31
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
refs/heads/master: 61b1875c16de39c166b0f4d54bba19f9c6777d1a
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
44
refs/heads/snap-stage3: 4a81779abd786ff22d71434c6d9a5917ea4cdfff
5-
refs/heads/try: 5d625af9f944c7b6567c443a6f796e30dbb01bf2
5+
refs/heads/try: fa5cc5bcd0e370a677de141d46455d4ee518dcfc
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105

branches/try/src/librustsyntax/ast_util.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -363,8 +363,11 @@ fn operator_prec(op: ast::binop) -> uint {
363363
}
364364

365365
fn dtor_dec() -> fn_decl {
366-
{inputs: [], output: @{id: 0, node: ty_nil, span: dummy_sp()},
367-
purity: impure_fn, cf: return_val, constraints: []}
366+
let nil_t = @{id: 0, node: ty_nil, span: dummy_sp()};
367+
// dtor has one argument, of type ()
368+
{inputs: [{mode: ast::expl(ast::by_ref),
369+
ty: nil_t, ident: "_", id: 0}],
370+
output: nil_t, purity: impure_fn, cf: return_val, constraints: []}
368371
}
369372

370373
// Local Variables:

branches/try/src/rustc/metadata/common.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ const tag_mod_impl_iface: uint = 0x47u;
9595
different tags.
9696
*/
9797
const tag_item_impl_method: uint = 0x48u;
98+
const tag_item_dtor: uint = 0x49u;
9899

99100
// used to encode crate_ctxt side tables
100101
enum astencode_tag { // Reserves 0x50 -- 0x6f

branches/try/src/rustc/metadata/csearch.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import driver::session::expect;
1010
import common::*;
1111
import std::map::hashmap;
1212

13+
export class_dtor;
1314
export get_symbol;
1415
export get_class_fields;
1516
export get_class_method;
@@ -185,6 +186,12 @@ fn get_class_method(cstore: cstore::cstore, def: ast::def_id, mname: str)
185186
decoder::get_class_method(cdata, def.node, mname)
186187
}
187188

189+
/* If def names a class with a dtor, return it. Otherwise, return none. */
190+
fn class_dtor(cstore: cstore::cstore, def: ast::def_id)
191+
-> option<ast::def_id> {
192+
let cdata = cstore::get_crate_data(cstore, def.crate);
193+
decoder::class_dtor(cdata, def.node)
194+
}
188195
// Local Variables:
189196
// mode: rust
190197
// fill-column: 78;

branches/try/src/rustc/metadata/decoder.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import util::ppaux::ty_to_str;
1616
import ebml::deserializer;
1717
import syntax::diagnostic::span_handler;
1818

19+
export class_dtor;
1920
export get_class_fields;
2021
export get_symbol;
2122
export get_enum_variants;
@@ -331,6 +332,19 @@ fn get_class_method(cdata: cmd, id: ast::node_id, name: str) -> ast::def_id {
331332
}
332333
}
333334

335+
fn class_dtor(cdata: cmd, id: ast::node_id) -> option<ast::def_id> {
336+
let items = ebml::get_doc(ebml::doc(cdata.data), tag_items);
337+
let cls_items = alt maybe_find_item(id, items) {
338+
some(it) { it }
339+
none { ret none; }};
340+
let mut rslt = none;
341+
ebml::tagged_docs(cls_items, tag_item_dtor) {|f|
342+
let did = parse_def_id(ebml::doc_data(f));
343+
rslt = some(translate_def_id(cdata, did));
344+
}
345+
rslt
346+
}
347+
334348
fn get_symbol(data: @[u8], id: ast::node_id) -> str {
335349
ret item_symbol(lookup_item(id, data));
336350
}

branches/try/src/rustc/metadata/encoder.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -201,8 +201,7 @@ fn encode_module_item_paths(ebml_w: ebml::writer, ecx: @encode_ctxt,
201201
encode_def_id(ebml_w, local_def(it.id));
202202
ebml_w.end_tag();
203203
}
204-
// FIXME: I don't *think* dtor needs to be serialized?
205-
item_class(_, _, items, ctor, _dtor, _) {
204+
item_class(_, _, items, ctor, m_dtor, _) {
206205
add_to_index(ebml_w, path, index, it.ident);
207206
ebml_w.start_tag(tag_paths_data_item);
208207
encode_name(ebml_w, it.ident);
@@ -212,6 +211,12 @@ fn encode_module_item_paths(ebml_w: ebml::writer, ecx: @encode_ctxt,
212211
add_to_index(ebml_w, path, index, it.ident);
213212
#debug("ctor id: %d", ctor.node.id);
214213
encode_named_def_id(ebml_w, it.ident, local_def(ctor.node.id));
214+
/* Encode id for dtor */
215+
option::iter(m_dtor) {|dtor|
216+
ebml_w.start_tag(tag_item_dtor);
217+
encode_def_id(ebml_w, local_def(dtor.node.id));
218+
ebml_w.end_tag();
219+
};
215220
encode_class_item_paths(ebml_w, items, path + [it.ident],
216221
index);
217222
ebml_w.end_tag();

branches/try/src/rustc/middle/ast_map.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,6 @@ fn node_id_to_str(map: map, id: node_id) -> str {
302302
}
303303
}
304304
}
305-
306305
// Local Variables:
307306
// mode: rust
308307
// fill-column: 78;

branches/try/src/rustc/middle/trans/base.rs

Lines changed: 77 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -717,6 +717,48 @@ fn make_drop_glue(bcx: block, v0: ValueRef, t: ty::t) {
717717
ty::ty_res(did, inner, substs) {
718718
trans_res_drop(bcx, v0, did, inner, substs.tps)
719719
}
720+
ty::ty_class(did, substs) {
721+
let tcx = bcx.tcx();
722+
alt ty::ty_dtor(tcx, did) {
723+
some(dtor) {
724+
let drop_flag = GEPi(bcx, v0, [0u, 0u]);
725+
with_cond(bcx, IsNotNull(bcx, Load(bcx, drop_flag))) {|cx|
726+
let mut bcx = cx;
727+
// we have to cast v0
728+
let classptr = GEPi(bcx, v0, [0u, 1u]);
729+
// Find and call the actual destructor
730+
let dtor_addr = get_res_dtor(bcx.ccx(), dtor, substs.tps);
731+
// The second argument is the "self" argument for drop
732+
let params = lib::llvm::fn_ty_param_tys
733+
(llvm::LLVMGetElementType
734+
(llvm::LLVMTypeOf(dtor_addr)));
735+
let self_arg = PointerCast(bcx, v0, params[1u]);
736+
let args = [bcx.fcx.llretptr, self_arg];
737+
let val_llty = lib::llvm::fn_ty_param_tys
738+
(llvm::LLVMGetElementType
739+
(llvm::LLVMTypeOf(dtor_addr)))[args.len()];
740+
let val_cast = BitCast(bcx, classptr, val_llty);
741+
#debug("fn_ty: %s", ty_str(bcx.ccx().tn,
742+
(llvm::LLVMGetElementType
743+
(llvm::LLVMTypeOf(dtor_addr)))));
744+
#debug("self's ty: %s", val_str(bcx.ccx().tn, v0));
745+
Call(bcx, dtor_addr, args + [val_cast]);
746+
// Drop the fields
747+
for vec::eachi(ty::class_items_as_fields(tcx, did, substs))
748+
{|i, fld|
749+
let llfld_a = GEPi(bcx, classptr, [0u, i]);
750+
bcx = drop_ty(bcx, llfld_a, fld.mt.ty);
751+
}
752+
Store(bcx, C_u8(0u), drop_flag);
753+
bcx
754+
}
755+
}
756+
none {
757+
// No dtor? Just the default case
758+
iter_structural_ty(bcx, v0, t, drop_ty)
759+
}
760+
}
761+
}
720762
ty::ty_fn(_) {
721763
closure::make_fn_glue(bcx, v0, t, drop_ty)
722764
}
@@ -1015,11 +1057,12 @@ fn iter_structural_ty(cx: block, av: ValueRef, t: ty::t,
10151057
ret next_cx;
10161058
}
10171059
ty::ty_class(did, substs) {
1018-
// a class is like a record type
1019-
for vec::eachi(ty::class_items_as_fields(cx.tcx(), did, substs))
1060+
assert(ty::ty_dtor(cx.tcx(), did) == none);
1061+
// a class w/ no dtor is like a record type
1062+
for vec::eachi(ty::class_items_as_fields(cx.tcx(), did, substs))
10201063
{|i, fld|
1021-
let llfld_a = GEPi(cx, av, [0u, i]);
1022-
cx = f(cx, llfld_a, fld.mt.ty);
1064+
let llfld_a = GEPi(cx, av, [0u, i]);
1065+
cx = f(cx, llfld_a, fld.mt.ty);
10231066
}
10241067
}
10251068
_ { cx.sess().unimpl("type in iter_structural_ty"); }
@@ -2340,16 +2383,24 @@ fn trans_rec_field(bcx: block, base: @ast::expr,
23402383

23412384
fn trans_rec_field_inner(bcx: block, val: ValueRef, ty: ty::t,
23422385
field: ast::ident, sp: span) -> lval_result {
2386+
let mut is_class_with_dtor = false;
23432387
let fields = alt ty::get(ty).struct {
2344-
ty::ty_rec(fs) { fs }
2345-
ty::ty_class(did, substs) {
2346-
ty::class_items_as_fields(bcx.tcx(), did, substs) }
2347-
// Constraint?
2348-
_ { bcx.tcx().sess.span_bug(sp, "trans_rec_field:\
2388+
ty::ty_rec(fs) { fs }
2389+
ty::ty_class(did, substs) {
2390+
if option::is_some(ty::ty_dtor(bcx.tcx(), did)) {
2391+
is_class_with_dtor = true;
2392+
}
2393+
ty::class_items_as_fields(bcx.tcx(), did, substs)
2394+
}
2395+
// Constraint?
2396+
_ { bcx.tcx().sess.span_bug(sp, "trans_rec_field:\
23492397
base expr has non-record type"); }
2350-
};
2398+
};
23512399
let ix = field_idx_strict(bcx.tcx(), sp, field, fields);
2352-
let val = GEPi(bcx, val, [0u, ix]);
2400+
let val = GEPi(bcx, if is_class_with_dtor {
2401+
GEPi(bcx, val, [0u, 1u])
2402+
}
2403+
else { val }, [0u, ix]);
23532404
ret {bcx: bcx, val: val, kind: owned};
23542405
}
23552406

@@ -4596,6 +4647,19 @@ fn trans_class_ctor(ccx: @crate_ctxt, path: path, decl: ast::fn_decl,
45964647
// So we initialize it here
45974648

45984649
let selfptr = alloc_ty(bcx_top, rslt_ty);
4650+
// If we have a dtor, we have a two-word representation with a drop
4651+
// flag, then a pointer to the class itself
4652+
let valptr = if option::is_some(ty::ty_dtor(bcx_top.tcx(),
4653+
parent_id)) {
4654+
// Initialize the drop flag
4655+
let one = C_u8(1u);
4656+
let flag = GEPi(bcx_top, selfptr, [0u, 0u]);
4657+
Store(bcx_top, one, flag);
4658+
// Select the pointer to the class itself
4659+
GEPi(bcx_top, selfptr, [0u, 1u])
4660+
}
4661+
else { selfptr };
4662+
45994663
// initialize fields to zero
46004664
let fields = ty::class_items_as_fields(bcx_top.tcx(), parent_id,
46014665
dummy_substs(psubsts.tys));
@@ -4604,7 +4668,7 @@ fn trans_class_ctor(ccx: @crate_ctxt, path: path, decl: ast::fn_decl,
46044668
// drop their LHS
46054669
for fields.each {|field|
46064670
let ix = field_idx_strict(bcx.tcx(), sp, field.ident, fields);
4607-
bcx = zero_alloca(bcx, GEPi(bcx, selfptr, [0u, ix]),
4671+
bcx = zero_alloca(bcx, GEPi(bcx, valptr, [0u, ix]),
46084672
field.mt.ty);
46094673
}
46104674

@@ -4626,7 +4690,7 @@ fn trans_class_dtor(ccx: @crate_ctxt, path: path,
46264690
body: ast::blk, lldtor_decl: ValueRef,
46274691
dtor_id: ast::node_id,
46284692
parent_id: ast::def_id) {
4629-
let class_ty = ty::lookup_item_type(ccx.tcx, parent_id).ty;
4693+
let class_ty = ty::lookup_item_type(ccx.tcx, parent_id).ty;
46304694
trans_fn(ccx, path, ast_util::dtor_dec(),
46314695
body, lldtor_decl, impl_self(class_ty), none, dtor_id);
46324696
}

branches/try/src/rustc/middle/trans/shape.rs

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -414,10 +414,25 @@ fn shape_of(ccx: @crate_ctxt, t: ty::t, ty_param_map: [uint]) -> [u8] {
414414
s
415415
}
416416
ty::ty_iface(_, _) { [shape_box_fn] }
417-
ty::ty_class(did, ts) {
418-
// same as records
419-
let mut s = [shape_struct], sub = [];
420-
for ty::class_items_as_fields(ccx.tcx, did, ts).each {|f|
417+
ty::ty_class(did, substs) {
418+
// same as records, unless there's a dtor
419+
let tps = substs.tps;
420+
let m_dtor_did = ty::ty_dtor(ccx.tcx, did);
421+
let mut s = if option::is_some(m_dtor_did) {
422+
[shape_res]
423+
}
424+
else { [shape_struct] };
425+
let mut sub = [];
426+
option::iter(m_dtor_did) {|dtor_did|
427+
let ri = {did: dtor_did, tps: tps};
428+
let id = interner::intern(ccx.shape_cx.resources, ri);
429+
add_u16(s, id as u16);
430+
add_u16(s, vec::len(tps) as u16);
431+
for vec::each(tps) {|tp|
432+
add_substr(s, shape_of(ccx, tp, ty_param_map));
433+
}
434+
};
435+
for ty::class_items_as_fields(ccx.tcx, did, substs).each {|f|
421436
sub += shape_of(ccx, f.mt.ty, ty_param_map);
422437
}
423438
add_substr(s, sub);
@@ -571,14 +586,11 @@ fn gen_enum_shapes(ccx: @crate_ctxt) -> ValueRef {
571586

572587
fn gen_resource_shapes(ccx: @crate_ctxt) -> ValueRef {
573588
let mut dtors = [];
574-
let mut i = 0u;
575589
let len = interner::len(ccx.shape_cx.resources);
576-
while i < len {
577-
let ri = interner::get(ccx.shape_cx.resources, i);
578-
dtors += [trans::base::get_res_dtor(ccx, ri.did, ri.tps)];
579-
i += 1u;
590+
uint::range(0u, len) {|i|
591+
let ri = interner::get(ccx.shape_cx.resources, i);
592+
dtors += [trans::base::get_res_dtor(ccx, ri.did, ri.tps)];
580593
}
581-
582594
ret mk_global(ccx, "resource_shapes", C_struct(dtors), true);
583595
}
584596

branches/try/src/rustc/middle/trans/type_of.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,13 @@ fn type_of(cx: @crate_ctxt, t: ty::t) -> TypeRef {
147147
let t = ty::lookup_field_type(cx.tcx, did, f.id, ts);
148148
type_of(cx, t)
149149
};
150-
T_struct(tys)
150+
if ty::ty_dtor(cx.tcx, did) == none {
151+
T_struct(tys)
152+
}
153+
else {
154+
// resource type
155+
T_struct([T_i8(), T_struct(tys)])
156+
}
151157
}
152158
ty::ty_self { cx.tcx.sess.unimpl("type_of: ty_self"); }
153159
ty::ty_var(_) { cx.tcx.sess.bug("type_of shouldn't see a ty_var"); }

branches/try/src/rustc/middle/ty.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import session::session;
66
import syntax::ast;
77
import syntax::ast::*;
88
import syntax::ast_util;
9-
import syntax::ast_util::{is_local, split_class_items};
9+
import syntax::ast_util::{is_local, local_def, split_class_items};
1010
import syntax::codemap::span;
1111
import metadata::csearch;
1212
import util::common::*;
@@ -69,6 +69,7 @@ export new_ty_hash;
6969
export enum_variants, substd_enum_variants;
7070
export iface_methods, store_iface_methods, impl_iface;
7171
export enum_variant_with_id;
72+
export ty_dtor;
7273
export ty_param_bounds_and_ty;
7374
export ty_bool, mk_bool, type_is_bool;
7475
export ty_bot, mk_bot, type_is_bot;
@@ -2377,6 +2378,22 @@ fn item_path_str(cx: ctxt, id: ast::def_id) -> str {
23772378
ast_map::path_to_str(item_path(cx, id))
23782379
}
23792380

2381+
/* If class_id names a class with a dtor, return some(the dtor's id).
2382+
Otherwise return none. */
2383+
fn ty_dtor(cx: ctxt, class_id: def_id) -> option<def_id> {
2384+
if is_local(class_id) {
2385+
alt cx.items.find(class_id.node) {
2386+
some(ast_map::node_item(@{node: ast::item_class(_, _, _, _,
2387+
some(dtor), _), _}, _))
2388+
{ some(local_def(dtor.node.id)) }
2389+
_ { none }
2390+
}
2391+
}
2392+
else {
2393+
csearch::class_dtor(cx.sess.cstore, class_id)
2394+
}
2395+
}
2396+
23802397
fn item_path(cx: ctxt, id: ast::def_id) -> ast_map::path {
23812398
if id.crate != ast::local_crate {
23822399
csearch::get_item_path(cx, id)
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
class shrinky_pointer {
2+
let i: @@mut int;
3+
fn look_at() -> int { ret **(self.i); }
4+
new(i: @@mut int) { self.i = i; }
5+
drop { log(error, "Hello!"); **(self.i) -= 1; }
6+
}
7+
8+
fn main() {
9+
let my_total = @@mut 10;
10+
{ let pt <- shrinky_pointer(my_total); assert (pt.look_at() == 10); }
11+
log(error, #fmt("my_total = %d", **my_total));
12+
assert (**my_total == 9);
13+
}

0 commit comments

Comments
 (0)