Export adt::trans_get_discr abstractly to the type visitor.
This commit is contained in:
parent
0ca1885da1
commit
640e8ae4e5
5 changed files with 150 additions and 22 deletions
|
|
@ -15,6 +15,7 @@ Runtime type reflection
|
|||
*/
|
||||
|
||||
use intrinsic::{TyDesc, TyVisitor};
|
||||
#[cfg(not(stage0))] use intrinsic::Opaque;
|
||||
use libc::c_void;
|
||||
use sys;
|
||||
use vec;
|
||||
|
|
@ -393,6 +394,7 @@ impl<V:TyVisitor + MovePtr> TyVisitor for MovePtrAdaptor<V> {
|
|||
true
|
||||
}
|
||||
|
||||
#[cfg(stage0)]
|
||||
fn visit_enter_enum(&self, n_variants: uint, sz: uint, align: uint)
|
||||
-> bool {
|
||||
self.align(align);
|
||||
|
|
@ -402,6 +404,18 @@ impl<V:TyVisitor + MovePtr> TyVisitor for MovePtrAdaptor<V> {
|
|||
true
|
||||
}
|
||||
|
||||
#[cfg(not(stage0))]
|
||||
fn visit_enter_enum(&self, n_variants: uint,
|
||||
get_disr: extern unsafe fn(ptr: *Opaque) -> int,
|
||||
sz: uint, align: uint)
|
||||
-> bool {
|
||||
self.align(align);
|
||||
if ! self.inner.visit_enter_enum(n_variants, get_disr, sz, align) {
|
||||
return false;
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
fn visit_enter_enum_variant(&self, variant: uint,
|
||||
disr_val: int,
|
||||
n_fields: uint,
|
||||
|
|
@ -443,6 +457,7 @@ impl<V:TyVisitor + MovePtr> TyVisitor for MovePtrAdaptor<V> {
|
|||
true
|
||||
}
|
||||
|
||||
#[cfg(stage0)]
|
||||
fn visit_leave_enum(&self, n_variants: uint, sz: uint, align: uint)
|
||||
-> bool {
|
||||
if ! self.inner.visit_leave_enum(n_variants, sz, align) {
|
||||
|
|
@ -452,6 +467,17 @@ impl<V:TyVisitor + MovePtr> TyVisitor for MovePtrAdaptor<V> {
|
|||
true
|
||||
}
|
||||
|
||||
#[cfg(not(stage0))]
|
||||
fn visit_leave_enum(&self, n_variants: uint,
|
||||
get_disr: extern unsafe fn(ptr: *Opaque) -> int,
|
||||
sz: uint, align: uint) -> bool {
|
||||
if ! self.inner.visit_leave_enum(n_variants, get_disr, sz, align) {
|
||||
return false;
|
||||
}
|
||||
self.bump(sz);
|
||||
true
|
||||
}
|
||||
|
||||
fn visit_trait(&self) -> bool {
|
||||
self.align_to::<@TyVisitor>();
|
||||
if ! self.inner.visit_trait() { return false; }
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ use cast::transmute;
|
|||
use char;
|
||||
use intrinsic;
|
||||
use intrinsic::{TyDesc, TyVisitor, visit_tydesc};
|
||||
#[cfg(not(stage0))] use intrinsic::Opaque;
|
||||
use io::{Writer, WriterUtil};
|
||||
use libc::c_void;
|
||||
use managed;
|
||||
|
|
@ -137,12 +138,20 @@ impl Repr for char {
|
|||
|
||||
// New implementation using reflect::MovePtr
|
||||
|
||||
#[cfg(stage0)]
|
||||
enum VariantState {
|
||||
Degenerate,
|
||||
TagMatch,
|
||||
TagMismatch,
|
||||
}
|
||||
|
||||
#[cfg(not(stage0))]
|
||||
enum VariantState {
|
||||
SearchingFor(int),
|
||||
Matched,
|
||||
AlreadyFound
|
||||
}
|
||||
|
||||
pub struct ReprVisitor {
|
||||
mut ptr: *c_void,
|
||||
mut ptr_stk: ~[*c_void],
|
||||
|
|
@ -181,26 +190,18 @@ pub impl ReprVisitor {
|
|||
true
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[cfg(stage0)] #[inline(always)]
|
||||
fn bump(&self, sz: uint) {
|
||||
do self.move_ptr() |p| {
|
||||
((p as uint) + sz) as *c_void
|
||||
};
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[cfg(stage0)] #[inline(always)]
|
||||
fn bump_past<T>(&self) {
|
||||
self.bump(sys::size_of::<T>());
|
||||
}
|
||||
|
||||
#[cfg(stage0)] #[inline(always)]
|
||||
fn stage0_bump_past<T>(&self) {
|
||||
self.bump_past::<T>();
|
||||
}
|
||||
#[cfg(not(stage0))] #[inline(always)]
|
||||
fn stage0_bump_past<T>(&self) {
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn visit_inner(&self, inner: *TyDesc) -> bool {
|
||||
self.visit_ptr_inner(self.ptr, inner)
|
||||
|
|
@ -466,6 +467,7 @@ impl TyVisitor for ReprVisitor {
|
|||
true
|
||||
}
|
||||
|
||||
#[cfg(stage0)]
|
||||
fn visit_enter_enum(&self, n_variants: uint,
|
||||
_sz: uint, _align: uint) -> bool {
|
||||
if n_variants == 1 {
|
||||
|
|
@ -476,6 +478,16 @@ impl TyVisitor for ReprVisitor {
|
|||
true
|
||||
}
|
||||
|
||||
#[cfg(not(stage0))]
|
||||
fn visit_enter_enum(&self, n_variants: uint,
|
||||
get_disr: extern unsafe fn(ptr: *Opaque) -> int,
|
||||
_sz: uint, _align: uint) -> bool {
|
||||
let disr = unsafe { get_disr(transmute(self.ptr)) };
|
||||
self.var_stk.push(SearchingFor(disr));
|
||||
true
|
||||
}
|
||||
|
||||
#[cfg(stage0)]
|
||||
fn visit_enter_enum_variant(&self, _variant: uint,
|
||||
disr_val: int,
|
||||
n_fields: uint,
|
||||
|
|
@ -495,7 +507,36 @@ impl TyVisitor for ReprVisitor {
|
|||
self.var_stk.push(TagMismatch);
|
||||
}
|
||||
};
|
||||
self.stage0_bump_past::<int>();
|
||||
self.bump_past::<int>();
|
||||
}
|
||||
}
|
||||
|
||||
if write {
|
||||
self.writer.write_str(name);
|
||||
if n_fields > 0 {
|
||||
self.writer.write_char('(');
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
#[cfg(not(stage0))]
|
||||
fn visit_enter_enum_variant(&self, _variant: uint,
|
||||
disr_val: int,
|
||||
n_fields: uint,
|
||||
name: &str) -> bool {
|
||||
let mut write = false;
|
||||
match self.var_stk.pop() {
|
||||
SearchingFor(sought) => {
|
||||
if disr_val == sought {
|
||||
self.var_stk.push(Matched);
|
||||
write = true;
|
||||
} else {
|
||||
self.var_stk.push(SearchingFor(sought));
|
||||
}
|
||||
}
|
||||
Matched | AlreadyFound => {
|
||||
self.var_stk.push(AlreadyFound);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -527,7 +568,7 @@ impl TyVisitor for ReprVisitor {
|
|||
#[cfg(not(stage0))]
|
||||
fn visit_enum_variant_field(&self, i: uint, _offset: uint, inner: *TyDesc) -> bool {
|
||||
match self.var_stk[vec::uniq_len(&const self.var_stk) - 1] {
|
||||
Degenerate | TagMatch => {
|
||||
Matched => {
|
||||
if i != 0 {
|
||||
self.writer.write_str(", ");
|
||||
}
|
||||
|
|
@ -535,11 +576,12 @@ impl TyVisitor for ReprVisitor {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
TagMismatch => ()
|
||||
_ => ()
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
#[cfg(stage0)]
|
||||
fn visit_leave_enum_variant(&self, _variant: uint,
|
||||
_disr_val: int,
|
||||
n_fields: uint,
|
||||
|
|
@ -555,12 +597,38 @@ impl TyVisitor for ReprVisitor {
|
|||
true
|
||||
}
|
||||
|
||||
#[cfg(not(stage0))]
|
||||
fn visit_leave_enum_variant(&self, _variant: uint,
|
||||
_disr_val: int,
|
||||
n_fields: uint,
|
||||
_name: &str) -> bool {
|
||||
match self.var_stk[vec::uniq_len(&const self.var_stk) - 1] {
|
||||
Matched => {
|
||||
if n_fields > 0 {
|
||||
self.writer.write_char(')');
|
||||
}
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
#[cfg(stage0)]
|
||||
fn visit_leave_enum(&self, _n_variants: uint,
|
||||
_sz: uint, _align: uint) -> bool {
|
||||
self.var_stk.pop();
|
||||
true
|
||||
}
|
||||
|
||||
#[cfg(not(stage0))]
|
||||
fn visit_leave_enum(&self, _n_variants: uint,
|
||||
_get_disr: extern unsafe fn(ptr: *Opaque) -> int,
|
||||
_sz: uint, _align: uint) -> bool {
|
||||
// NOTE should this assert that it's not still SearchingFor the right variant?
|
||||
self.var_stk.pop();
|
||||
true
|
||||
}
|
||||
|
||||
fn visit_enter_fn(&self, _purity: uint, _proto: uint,
|
||||
_n_inputs: uint, _retstyle: uint) -> bool { true }
|
||||
fn visit_fn_input(&self, _i: uint, _mode: uint, _inner: *TyDesc) -> bool {
|
||||
|
|
|
|||
|
|
@ -28,6 +28,9 @@ pub mod intrinsic {
|
|||
// Remaining fields not listed
|
||||
}
|
||||
|
||||
// FIXME: make this a 0-variant enum; trans/reflect.rs has to match it.
|
||||
pub type Opaque = ();
|
||||
|
||||
pub trait TyVisitor {
|
||||
fn visit_bot(&self) -> bool;
|
||||
fn visit_nil(&self) -> bool;
|
||||
|
|
@ -91,6 +94,7 @@ pub mod intrinsic {
|
|||
sz: uint, align: uint) -> bool;
|
||||
|
||||
fn visit_enter_enum(&self, n_variants: uint,
|
||||
get_disr: extern unsafe fn(ptr: *Opaque) -> int,
|
||||
sz: uint, align: uint) -> bool;
|
||||
fn visit_enter_enum_variant(&self, variant: uint,
|
||||
disr_val: int,
|
||||
|
|
@ -102,6 +106,7 @@ pub mod intrinsic {
|
|||
n_fields: uint,
|
||||
name: &str) -> bool;
|
||||
fn visit_leave_enum(&self, n_variants: uint,
|
||||
get_disr: extern unsafe fn(ptr: *Opaque) -> int,
|
||||
sz: uint, align: uint) -> bool;
|
||||
|
||||
fn visit_enter_fn(&self, purity: uint, proto: uint,
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
|
||||
use lib::llvm::{TypeRef, ValueRef};
|
||||
use back::link::mangle_internal_name_by_path_and_seq;
|
||||
use lib::llvm::{TypeRef, ValueRef, llvm};
|
||||
use middle::trans::adt;
|
||||
use middle::trans::base::*;
|
||||
use middle::trans::build::*;
|
||||
|
|
@ -25,10 +25,13 @@ use middle::trans::type_of::*;
|
|||
use middle::ty;
|
||||
use util::ppaux::ty_to_str;
|
||||
|
||||
use core::libc::c_uint;
|
||||
use core::option::None;
|
||||
use core::vec;
|
||||
use syntax::ast::def_id;
|
||||
use syntax::ast;
|
||||
use syntax::ast_map::path_name;
|
||||
use syntax::parse::token::special_idents;
|
||||
|
||||
pub struct Reflector {
|
||||
visitor_val: ValueRef,
|
||||
|
|
@ -270,8 +273,28 @@ pub impl Reflector {
|
|||
let ccx = bcx.ccx();
|
||||
let repr = adt::represent_type(bcx.ccx(), t);
|
||||
let variants = ty::substd_enum_variants(ccx.tcx, did, substs);
|
||||
let llptrty = T_ptr(type_of(ccx, t));
|
||||
|
||||
let enum_args = ~[self.c_uint(vec::len(variants))]
|
||||
// Build the get_disr function. (XXX: break this out into a function)
|
||||
let sub_path = bcx.fcx.path + ~[path_name(special_idents::anon)];
|
||||
let get_disr_sym = mangle_internal_name_by_path_and_seq(ccx, sub_path, ~"get_disr");
|
||||
let get_disr_args = [ty::arg { mode: ast::expl(ast::by_copy),
|
||||
ty: ty::mk_nil_ptr(ccx.tcx) }];
|
||||
let get_disr_llfty = type_of_fn(ccx, get_disr_args, ty::mk_int(ccx.tcx));
|
||||
let get_disr_llfdecl = decl_internal_cdecl_fn(ccx.llmod, get_disr_sym, get_disr_llfty);
|
||||
let get_disr_arg = unsafe {
|
||||
llvm::LLVMGetParam(get_disr_llfdecl, first_real_arg as c_uint)
|
||||
};
|
||||
let get_disr_fcx = new_fn_ctxt(ccx, ~[], get_disr_llfdecl, None);
|
||||
let get_disr_bcx = top_scope_block(get_disr_fcx, None);
|
||||
let get_disr_arg = BitCast(get_disr_bcx, get_disr_arg, llptrty);
|
||||
let get_disr_ret = adt::trans_get_discr(get_disr_bcx, repr, get_disr_arg);
|
||||
Store(get_disr_bcx, get_disr_ret, get_disr_fcx.llretptr);
|
||||
cleanup_and_Br(get_disr_bcx, get_disr_bcx, get_disr_fcx.llreturn);
|
||||
finish_fn(get_disr_fcx, get_disr_bcx.llbb);
|
||||
|
||||
let enum_args = ~[self.c_uint(vec::len(variants)),
|
||||
get_disr_llfdecl]
|
||||
+ self.c_size_and_align(t);
|
||||
do self.bracketed(~"enum", enum_args) |this| {
|
||||
for variants.eachi |i, v| {
|
||||
|
|
@ -282,7 +305,7 @@ pub impl Reflector {
|
|||
do this.bracketed(~"enum_variant", variant_args) |this| {
|
||||
for v.args.eachi |j, a| {
|
||||
let bcx = this.bcx;
|
||||
let null = C_null(T_ptr(type_of(ccx, t)));
|
||||
let null = C_null(llptrty);
|
||||
let offset = p2i(ccx, adt::trans_field_ptr(bcx, repr, null,
|
||||
v.disr_val, j));
|
||||
let field_args = ~[this.c_uint(j),
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
use core::bool;
|
||||
use core::libc::c_void;
|
||||
use core::vec::UnboxedVecRepr;
|
||||
use intrinsic::{TyDesc, get_tydesc, visit_tydesc, TyVisitor};
|
||||
use intrinsic::{TyDesc, get_tydesc, visit_tydesc, TyVisitor, Opaque};
|
||||
|
||||
#[doc = "High-level interfaces to `intrinsic::visit_ty` reflection system."]
|
||||
|
||||
|
|
@ -376,10 +376,12 @@ impl<V:TyVisitor + movable_ptr> TyVisitor for ptr_visit_adaptor<V> {
|
|||
true
|
||||
}
|
||||
|
||||
fn visit_enter_enum(&self, n_variants: uint, sz: uint, align: uint)
|
||||
fn visit_enter_enum(&self, n_variants: uint,
|
||||
get_disr: extern unsafe fn(ptr: *Opaque) -> int,
|
||||
sz: uint, align: uint)
|
||||
-> bool {
|
||||
self.align(align);
|
||||
if ! self.inner.visit_enter_enum(n_variants, sz, align) { return false; }
|
||||
if ! self.inner.visit_enter_enum(n_variants, get_disr, sz, align) { return false; }
|
||||
true
|
||||
}
|
||||
|
||||
|
|
@ -410,9 +412,11 @@ impl<V:TyVisitor + movable_ptr> TyVisitor for ptr_visit_adaptor<V> {
|
|||
true
|
||||
}
|
||||
|
||||
fn visit_leave_enum(&self, n_variants: uint, sz: uint, align: uint)
|
||||
fn visit_leave_enum(&self, n_variants: uint,
|
||||
get_disr: extern unsafe fn(ptr: *Opaque) -> int,
|
||||
sz: uint, align: uint)
|
||||
-> bool {
|
||||
if ! self.inner.visit_leave_enum(n_variants, sz, align) { return false; }
|
||||
if ! self.inner.visit_leave_enum(n_variants, get_disr, sz, align) { return false; }
|
||||
true
|
||||
}
|
||||
|
||||
|
|
@ -586,6 +590,7 @@ impl TyVisitor for my_visitor {
|
|||
_sz: uint, _align: uint) -> bool { true }
|
||||
|
||||
fn visit_enter_enum(&self, _n_variants: uint,
|
||||
_get_disr: extern unsafe fn(ptr: *Opaque) -> int,
|
||||
_sz: uint, _align: uint) -> bool {
|
||||
// FIXME (#3732): this needs to rewind between enum variants, or something.
|
||||
true
|
||||
|
|
@ -602,6 +607,7 @@ impl TyVisitor for my_visitor {
|
|||
_n_fields: uint,
|
||||
_name: &str) -> bool { true }
|
||||
fn visit_leave_enum(&self, _n_variants: uint,
|
||||
_get_disr: extern unsafe fn(ptr: *Opaque) -> int,
|
||||
_sz: uint, _align: uint) -> bool { true }
|
||||
|
||||
fn visit_enter_fn(&self, _purity: uint, _proto: uint,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue