Skip to content

Commit 640e8ae

Browse files
committed
Export adt::trans_get_discr abstractly to the type visitor.
1 parent 0ca1885 commit 640e8ae

File tree

5 files changed

+150
-22
lines changed

5 files changed

+150
-22
lines changed

src/libcore/reflect.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ Runtime type reflection
1515
*/
1616

1717
use intrinsic::{TyDesc, TyVisitor};
18+
#[cfg(not(stage0))] use intrinsic::Opaque;
1819
use libc::c_void;
1920
use sys;
2021
use vec;
@@ -393,6 +394,7 @@ impl<V:TyVisitor + MovePtr> TyVisitor for MovePtrAdaptor<V> {
393394
true
394395
}
395396

397+
#[cfg(stage0)]
396398
fn visit_enter_enum(&self, n_variants: uint, sz: uint, align: uint)
397399
-> bool {
398400
self.align(align);
@@ -402,6 +404,18 @@ impl<V:TyVisitor + MovePtr> TyVisitor for MovePtrAdaptor<V> {
402404
true
403405
}
404406

407+
#[cfg(not(stage0))]
408+
fn visit_enter_enum(&self, n_variants: uint,
409+
get_disr: extern unsafe fn(ptr: *Opaque) -> int,
410+
sz: uint, align: uint)
411+
-> bool {
412+
self.align(align);
413+
if ! self.inner.visit_enter_enum(n_variants, get_disr, sz, align) {
414+
return false;
415+
}
416+
true
417+
}
418+
405419
fn visit_enter_enum_variant(&self, variant: uint,
406420
disr_val: int,
407421
n_fields: uint,
@@ -443,6 +457,7 @@ impl<V:TyVisitor + MovePtr> TyVisitor for MovePtrAdaptor<V> {
443457
true
444458
}
445459

460+
#[cfg(stage0)]
446461
fn visit_leave_enum(&self, n_variants: uint, sz: uint, align: uint)
447462
-> bool {
448463
if ! self.inner.visit_leave_enum(n_variants, sz, align) {
@@ -452,6 +467,17 @@ impl<V:TyVisitor + MovePtr> TyVisitor for MovePtrAdaptor<V> {
452467
true
453468
}
454469

470+
#[cfg(not(stage0))]
471+
fn visit_leave_enum(&self, n_variants: uint,
472+
get_disr: extern unsafe fn(ptr: *Opaque) -> int,
473+
sz: uint, align: uint) -> bool {
474+
if ! self.inner.visit_leave_enum(n_variants, get_disr, sz, align) {
475+
return false;
476+
}
477+
self.bump(sz);
478+
true
479+
}
480+
455481
fn visit_trait(&self) -> bool {
456482
self.align_to::<@TyVisitor>();
457483
if ! self.inner.visit_trait() { return false; }

src/libcore/repr.rs

Lines changed: 81 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use cast::transmute;
1818
use char;
1919
use intrinsic;
2020
use intrinsic::{TyDesc, TyVisitor, visit_tydesc};
21+
#[cfg(not(stage0))] use intrinsic::Opaque;
2122
use io::{Writer, WriterUtil};
2223
use libc::c_void;
2324
use managed;
@@ -137,12 +138,20 @@ impl Repr for char {
137138

138139
// New implementation using reflect::MovePtr
139140

141+
#[cfg(stage0)]
140142
enum VariantState {
141143
Degenerate,
142144
TagMatch,
143145
TagMismatch,
144146
}
145147

148+
#[cfg(not(stage0))]
149+
enum VariantState {
150+
SearchingFor(int),
151+
Matched,
152+
AlreadyFound
153+
}
154+
146155
pub struct ReprVisitor {
147156
mut ptr: *c_void,
148157
mut ptr_stk: ~[*c_void],
@@ -181,26 +190,18 @@ pub impl ReprVisitor {
181190
true
182191
}
183192

184-
#[inline(always)]
193+
#[cfg(stage0)] #[inline(always)]
185194
fn bump(&self, sz: uint) {
186195
do self.move_ptr() |p| {
187196
((p as uint) + sz) as *c_void
188197
};
189198
}
190199

191-
#[inline(always)]
200+
#[cfg(stage0)] #[inline(always)]
192201
fn bump_past<T>(&self) {
193202
self.bump(sys::size_of::<T>());
194203
}
195204

196-
#[cfg(stage0)] #[inline(always)]
197-
fn stage0_bump_past<T>(&self) {
198-
self.bump_past::<T>();
199-
}
200-
#[cfg(not(stage0))] #[inline(always)]
201-
fn stage0_bump_past<T>(&self) {
202-
}
203-
204205
#[inline(always)]
205206
fn visit_inner(&self, inner: *TyDesc) -> bool {
206207
self.visit_ptr_inner(self.ptr, inner)
@@ -466,6 +467,7 @@ impl TyVisitor for ReprVisitor {
466467
true
467468
}
468469

470+
#[cfg(stage0)]
469471
fn visit_enter_enum(&self, n_variants: uint,
470472
_sz: uint, _align: uint) -> bool {
471473
if n_variants == 1 {
@@ -476,6 +478,16 @@ impl TyVisitor for ReprVisitor {
476478
true
477479
}
478480

481+
#[cfg(not(stage0))]
482+
fn visit_enter_enum(&self, n_variants: uint,
483+
get_disr: extern unsafe fn(ptr: *Opaque) -> int,
484+
_sz: uint, _align: uint) -> bool {
485+
let disr = unsafe { get_disr(transmute(self.ptr)) };
486+
self.var_stk.push(SearchingFor(disr));
487+
true
488+
}
489+
490+
#[cfg(stage0)]
479491
fn visit_enter_enum_variant(&self, _variant: uint,
480492
disr_val: int,
481493
n_fields: uint,
@@ -495,7 +507,36 @@ impl TyVisitor for ReprVisitor {
495507
self.var_stk.push(TagMismatch);
496508
}
497509
};
498-
self.stage0_bump_past::<int>();
510+
self.bump_past::<int>();
511+
}
512+
}
513+
514+
if write {
515+
self.writer.write_str(name);
516+
if n_fields > 0 {
517+
self.writer.write_char('(');
518+
}
519+
}
520+
true
521+
}
522+
523+
#[cfg(not(stage0))]
524+
fn visit_enter_enum_variant(&self, _variant: uint,
525+
disr_val: int,
526+
n_fields: uint,
527+
name: &str) -> bool {
528+
let mut write = false;
529+
match self.var_stk.pop() {
530+
SearchingFor(sought) => {
531+
if disr_val == sought {
532+
self.var_stk.push(Matched);
533+
write = true;
534+
} else {
535+
self.var_stk.push(SearchingFor(sought));
536+
}
537+
}
538+
Matched | AlreadyFound => {
539+
self.var_stk.push(AlreadyFound);
499540
}
500541
}
501542

@@ -527,19 +568,20 @@ impl TyVisitor for ReprVisitor {
527568
#[cfg(not(stage0))]
528569
fn visit_enum_variant_field(&self, i: uint, _offset: uint, inner: *TyDesc) -> bool {
529570
match self.var_stk[vec::uniq_len(&const self.var_stk) - 1] {
530-
Degenerate | TagMatch => {
571+
Matched => {
531572
if i != 0 {
532573
self.writer.write_str(", ");
533574
}
534575
if ! self.visit_inner(inner) {
535576
return false;
536577
}
537578
}
538-
TagMismatch => ()
579+
_ => ()
539580
}
540581
true
541582
}
542583

584+
#[cfg(stage0)]
543585
fn visit_leave_enum_variant(&self, _variant: uint,
544586
_disr_val: int,
545587
n_fields: uint,
@@ -555,8 +597,34 @@ impl TyVisitor for ReprVisitor {
555597
true
556598
}
557599

600+
#[cfg(not(stage0))]
601+
fn visit_leave_enum_variant(&self, _variant: uint,
602+
_disr_val: int,
603+
n_fields: uint,
604+
_name: &str) -> bool {
605+
match self.var_stk[vec::uniq_len(&const self.var_stk) - 1] {
606+
Matched => {
607+
if n_fields > 0 {
608+
self.writer.write_char(')');
609+
}
610+
}
611+
_ => ()
612+
}
613+
true
614+
}
615+
616+
#[cfg(stage0)]
617+
fn visit_leave_enum(&self, _n_variants: uint,
618+
_sz: uint, _align: uint) -> bool {
619+
self.var_stk.pop();
620+
true
621+
}
622+
623+
#[cfg(not(stage0))]
558624
fn visit_leave_enum(&self, _n_variants: uint,
625+
_get_disr: extern unsafe fn(ptr: *Opaque) -> int,
559626
_sz: uint, _align: uint) -> bool {
627+
// NOTE should this assert that it's not still SearchingFor the right variant?
560628
self.var_stk.pop();
561629
true
562630
}

src/librustc/front/intrinsic.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ pub mod intrinsic {
2828
// Remaining fields not listed
2929
}
3030

31+
// FIXME: make this a 0-variant enum; trans/reflect.rs has to match it.
32+
pub type Opaque = ();
33+
3134
pub trait TyVisitor {
3235
fn visit_bot(&self) -> bool;
3336
fn visit_nil(&self) -> bool;
@@ -91,6 +94,7 @@ pub mod intrinsic {
9194
sz: uint, align: uint) -> bool;
9295

9396
fn visit_enter_enum(&self, n_variants: uint,
97+
get_disr: extern unsafe fn(ptr: *Opaque) -> int,
9498
sz: uint, align: uint) -> bool;
9599
fn visit_enter_enum_variant(&self, variant: uint,
96100
disr_val: int,
@@ -102,6 +106,7 @@ pub mod intrinsic {
102106
n_fields: uint,
103107
name: &str) -> bool;
104108
fn visit_leave_enum(&self, n_variants: uint,
109+
get_disr: extern unsafe fn(ptr: *Opaque) -> int,
105110
sz: uint, align: uint) -> bool;
106111

107112
fn visit_enter_fn(&self, purity: uint, proto: uint,

src/librustc/middle/trans/reflect.rs

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
12-
use lib::llvm::{TypeRef, ValueRef};
11+
use back::link::mangle_internal_name_by_path_and_seq;
12+
use lib::llvm::{TypeRef, ValueRef, llvm};
1313
use middle::trans::adt;
1414
use middle::trans::base::*;
1515
use middle::trans::build::*;
@@ -25,10 +25,13 @@ use middle::trans::type_of::*;
2525
use middle::ty;
2626
use util::ppaux::ty_to_str;
2727

28+
use core::libc::c_uint;
2829
use core::option::None;
2930
use core::vec;
3031
use syntax::ast::def_id;
3132
use syntax::ast;
33+
use syntax::ast_map::path_name;
34+
use syntax::parse::token::special_idents;
3235

3336
pub struct Reflector {
3437
visitor_val: ValueRef,
@@ -270,8 +273,28 @@ pub impl Reflector {
270273
let ccx = bcx.ccx();
271274
let repr = adt::represent_type(bcx.ccx(), t);
272275
let variants = ty::substd_enum_variants(ccx.tcx, did, substs);
276+
let llptrty = T_ptr(type_of(ccx, t));
277+
278+
// Build the get_disr function. (XXX: break this out into a function)
279+
let sub_path = bcx.fcx.path + ~[path_name(special_idents::anon)];
280+
let get_disr_sym = mangle_internal_name_by_path_and_seq(ccx, sub_path, ~"get_disr");
281+
let get_disr_args = [ty::arg { mode: ast::expl(ast::by_copy),
282+
ty: ty::mk_nil_ptr(ccx.tcx) }];
283+
let get_disr_llfty = type_of_fn(ccx, get_disr_args, ty::mk_int(ccx.tcx));
284+
let get_disr_llfdecl = decl_internal_cdecl_fn(ccx.llmod, get_disr_sym, get_disr_llfty);
285+
let get_disr_arg = unsafe {
286+
llvm::LLVMGetParam(get_disr_llfdecl, first_real_arg as c_uint)
287+
};
288+
let get_disr_fcx = new_fn_ctxt(ccx, ~[], get_disr_llfdecl, None);
289+
let get_disr_bcx = top_scope_block(get_disr_fcx, None);
290+
let get_disr_arg = BitCast(get_disr_bcx, get_disr_arg, llptrty);
291+
let get_disr_ret = adt::trans_get_discr(get_disr_bcx, repr, get_disr_arg);
292+
Store(get_disr_bcx, get_disr_ret, get_disr_fcx.llretptr);
293+
cleanup_and_Br(get_disr_bcx, get_disr_bcx, get_disr_fcx.llreturn);
294+
finish_fn(get_disr_fcx, get_disr_bcx.llbb);
273295

274-
let enum_args = ~[self.c_uint(vec::len(variants))]
296+
let enum_args = ~[self.c_uint(vec::len(variants)),
297+
get_disr_llfdecl]
275298
+ self.c_size_and_align(t);
276299
do self.bracketed(~"enum", enum_args) |this| {
277300
for variants.eachi |i, v| {
@@ -282,7 +305,7 @@ pub impl Reflector {
282305
do this.bracketed(~"enum_variant", variant_args) |this| {
283306
for v.args.eachi |j, a| {
284307
let bcx = this.bcx;
285-
let null = C_null(T_ptr(type_of(ccx, t)));
308+
let null = C_null(llptrty);
286309
let offset = p2i(ccx, adt::trans_field_ptr(bcx, repr, null,
287310
v.disr_val, j));
288311
let field_args = ~[this.c_uint(j),

src/test/run-pass/reflect-visit-data.rs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
use core::bool;
1414
use core::libc::c_void;
1515
use core::vec::UnboxedVecRepr;
16-
use intrinsic::{TyDesc, get_tydesc, visit_tydesc, TyVisitor};
16+
use intrinsic::{TyDesc, get_tydesc, visit_tydesc, TyVisitor, Opaque};
1717

1818
#[doc = "High-level interfaces to `intrinsic::visit_ty` reflection system."]
1919

@@ -376,10 +376,12 @@ impl<V:TyVisitor + movable_ptr> TyVisitor for ptr_visit_adaptor<V> {
376376
true
377377
}
378378

379-
fn visit_enter_enum(&self, n_variants: uint, sz: uint, align: uint)
379+
fn visit_enter_enum(&self, n_variants: uint,
380+
get_disr: extern unsafe fn(ptr: *Opaque) -> int,
381+
sz: uint, align: uint)
380382
-> bool {
381383
self.align(align);
382-
if ! self.inner.visit_enter_enum(n_variants, sz, align) { return false; }
384+
if ! self.inner.visit_enter_enum(n_variants, get_disr, sz, align) { return false; }
383385
true
384386
}
385387

@@ -410,9 +412,11 @@ impl<V:TyVisitor + movable_ptr> TyVisitor for ptr_visit_adaptor<V> {
410412
true
411413
}
412414

413-
fn visit_leave_enum(&self, n_variants: uint, sz: uint, align: uint)
415+
fn visit_leave_enum(&self, n_variants: uint,
416+
get_disr: extern unsafe fn(ptr: *Opaque) -> int,
417+
sz: uint, align: uint)
414418
-> bool {
415-
if ! self.inner.visit_leave_enum(n_variants, sz, align) { return false; }
419+
if ! self.inner.visit_leave_enum(n_variants, get_disr, sz, align) { return false; }
416420
true
417421
}
418422

@@ -586,6 +590,7 @@ impl TyVisitor for my_visitor {
586590
_sz: uint, _align: uint) -> bool { true }
587591

588592
fn visit_enter_enum(&self, _n_variants: uint,
593+
_get_disr: extern unsafe fn(ptr: *Opaque) -> int,
589594
_sz: uint, _align: uint) -> bool {
590595
// FIXME (#3732): this needs to rewind between enum variants, or something.
591596
true
@@ -602,6 +607,7 @@ impl TyVisitor for my_visitor {
602607
_n_fields: uint,
603608
_name: &str) -> bool { true }
604609
fn visit_leave_enum(&self, _n_variants: uint,
610+
_get_disr: extern unsafe fn(ptr: *Opaque) -> int,
605611
_sz: uint, _align: uint) -> bool { true }
606612

607613
fn visit_enter_fn(&self, _purity: uint, _proto: uint,

0 commit comments

Comments
 (0)