From 0ca1885da133cb7e4a1f4d557cfde5d16ac68231 Mon Sep 17 00:00:00 2001 From: Jed Davis Date: Sat, 6 Apr 2013 14:01:56 -0700 Subject: [PATCH 1/5] Feed enum field offsets to type vistors. --- src/libcore/reflect.rs | 14 +++++++++-- src/libcore/repr.rs | 27 ++++++++++++++++++++- src/librustc/front/intrinsic.rs | 2 +- src/librustc/middle/trans/reflect.rs | 32 +++++++++++++++---------- src/test/run-pass/reflect-visit-data.rs | 6 ++--- 5 files changed, 61 insertions(+), 20 deletions(-) diff --git a/src/libcore/reflect.rs b/src/libcore/reflect.rs index a449c4e73cf7e..a38e51b38134b 100644 --- a/src/libcore/reflect.rs +++ b/src/libcore/reflect.rs @@ -406,7 +406,7 @@ impl TyVisitor for MovePtrAdaptor { disr_val: int, n_fields: uint, name: &str) -> bool { - self.inner.push_ptr(); + self.inner.push_ptr(); // NOTE remove after next snapshot if ! self.inner.visit_enter_enum_variant(variant, disr_val, n_fields, name) { return false; @@ -414,6 +414,7 @@ impl TyVisitor for MovePtrAdaptor { true } + #[cfg(stage0)] fn visit_enum_variant_field(&self, i: uint, inner: *TyDesc) -> bool { unsafe { self.align((*inner).align); } if ! self.inner.visit_enum_variant_field(i, inner) { return false; } @@ -421,6 +422,15 @@ impl TyVisitor for MovePtrAdaptor { true } + #[cfg(not(stage0))] + fn visit_enum_variant_field(&self, i: uint, offset: uint, inner: *TyDesc) -> bool { + self.inner.push_ptr(); + self.bump(offset); + if ! self.inner.visit_enum_variant_field(i, offset, inner) { return false; } + self.inner.pop_ptr(); + true + } + fn visit_leave_enum_variant(&self, variant: uint, disr_val: int, n_fields: uint, @@ -429,7 +439,7 @@ impl TyVisitor for MovePtrAdaptor { n_fields, name) { return false; } - self.inner.pop_ptr(); + self.inner.pop_ptr(); // NOTE remove after next snapshot true } diff --git a/src/libcore/repr.rs b/src/libcore/repr.rs index a51f874f3712c..3d42f06483178 100644 --- a/src/libcore/repr.rs +++ b/src/libcore/repr.rs @@ -193,6 +193,14 @@ pub impl ReprVisitor { self.bump(sys::size_of::()); } + #[cfg(stage0)] #[inline(always)] + fn stage0_bump_past(&self) { + self.bump_past::(); + } + #[cfg(not(stage0))] #[inline(always)] + fn stage0_bump_past(&self) { + } + #[inline(always)] fn visit_inner(&self, inner: *TyDesc) -> bool { self.visit_ptr_inner(self.ptr, inner) @@ -487,7 +495,7 @@ impl TyVisitor for ReprVisitor { self.var_stk.push(TagMismatch); } }; - self.bump_past::(); + self.stage0_bump_past::(); } } @@ -500,6 +508,7 @@ impl TyVisitor for ReprVisitor { true } + #[cfg(stage0)] fn visit_enum_variant_field(&self, i: uint, inner: *TyDesc) -> bool { match self.var_stk[vec::uniq_len(&const self.var_stk) - 1] { Degenerate | TagMatch => { @@ -515,6 +524,22 @@ impl TyVisitor for ReprVisitor { true } + #[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 => { + if i != 0 { + self.writer.write_str(", "); + } + if ! self.visit_inner(inner) { + return false; + } + } + TagMismatch => () + } + true + } + fn visit_leave_enum_variant(&self, _variant: uint, _disr_val: int, n_fields: uint, diff --git a/src/librustc/front/intrinsic.rs b/src/librustc/front/intrinsic.rs index 7d5177a6dfb5d..7a07ce1251616 100644 --- a/src/librustc/front/intrinsic.rs +++ b/src/librustc/front/intrinsic.rs @@ -96,7 +96,7 @@ pub mod intrinsic { disr_val: int, n_fields: uint, name: &str) -> bool; - fn visit_enum_variant_field(&self, i: uint, inner: *TyDesc) -> bool; + fn visit_enum_variant_field(&self, i: uint, offset: uint, inner: *TyDesc) -> bool; fn visit_leave_enum_variant(&self, variant: uint, disr_val: int, n_fields: uint, diff --git a/src/librustc/middle/trans/reflect.rs b/src/librustc/middle/trans/reflect.rs index 224981d6e759a..9d62231905eea 100644 --- a/src/librustc/middle/trans/reflect.rs +++ b/src/librustc/middle/trans/reflect.rs @@ -10,6 +10,7 @@ use lib::llvm::{TypeRef, ValueRef}; +use middle::trans::adt; use middle::trans::base::*; use middle::trans::build::*; use middle::trans::callee::{ArgVals, DontAutorefArg}; @@ -266,23 +267,28 @@ pub impl Reflector { // variant? ty::ty_enum(did, ref substs) => { let bcx = self.bcx; - let tcx = bcx.ccx().tcx; - let variants = ty::substd_enum_variants(tcx, did, substs); + let ccx = bcx.ccx(); + let repr = adt::represent_type(bcx.ccx(), t); + let variants = ty::substd_enum_variants(ccx.tcx, did, substs); - let extra = ~[self.c_uint(vec::len(variants))] + let enum_args = ~[self.c_uint(vec::len(variants))] + self.c_size_and_align(t); - do self.bracketed(~"enum", extra) |this| { + do self.bracketed(~"enum", enum_args) |this| { for variants.eachi |i, v| { - let extra1 = ~[this.c_uint(i), - this.c_int(v.disr_val), - this.c_uint(vec::len(v.args)), - this.c_slice( - bcx.ccx().sess.str_of(v.name))]; - do this.bracketed(~"enum_variant", extra1) |this| { + let variant_args = ~[this.c_uint(i), + this.c_int(v.disr_val), + this.c_uint(vec::len(v.args)), + this.c_slice(ccx.sess.str_of(v.name))]; + do this.bracketed(~"enum_variant", variant_args) |this| { for v.args.eachi |j, a| { - let extra = ~[this.c_uint(j), - this.c_tydesc(*a)]; - this.visit(~"enum_variant_field", extra); + let bcx = this.bcx; + let null = C_null(T_ptr(type_of(ccx, t))); + let offset = p2i(ccx, adt::trans_field_ptr(bcx, repr, null, + v.disr_val, j)); + let field_args = ~[this.c_uint(j), + offset, + this.c_tydesc(*a)]; + this.visit(~"enum_variant_field", field_args); } } } diff --git a/src/test/run-pass/reflect-visit-data.rs b/src/test/run-pass/reflect-visit-data.rs index a27599e6ed00a..8ddc845f50cbc 100644 --- a/src/test/run-pass/reflect-visit-data.rs +++ b/src/test/run-pass/reflect-visit-data.rs @@ -394,8 +394,8 @@ impl TyVisitor for ptr_visit_adaptor { true } - fn visit_enum_variant_field(&self, i: uint, inner: *TyDesc) -> bool { - if ! self.inner.visit_enum_variant_field(i, inner) { return false; } + fn visit_enum_variant_field(&self, i: uint, offset: uint, inner: *TyDesc) -> bool { + if ! self.inner.visit_enum_variant_field(i, offset, inner) { return false; } true } @@ -594,7 +594,7 @@ impl TyVisitor for my_visitor { _disr_val: int, _n_fields: uint, _name: &str) -> bool { true } - fn visit_enum_variant_field(&self, _i: uint, inner: *TyDesc) -> bool { + fn visit_enum_variant_field(&self, _i: uint, _offset: uint, inner: *TyDesc) -> bool { self.visit_inner(inner) } fn visit_leave_enum_variant(&self, _variant: uint, From 640e8ae4e583057e7a4e694063bf704c02f816c1 Mon Sep 17 00:00:00 2001 From: Jed Davis Date: Sat, 6 Apr 2013 16:47:01 -0700 Subject: [PATCH 2/5] Export adt::trans_get_discr abstractly to the type visitor. --- src/libcore/reflect.rs | 26 +++++++ src/libcore/repr.rs | 94 +++++++++++++++++++++---- src/librustc/front/intrinsic.rs | 5 ++ src/librustc/middle/trans/reflect.rs | 31 ++++++-- src/test/run-pass/reflect-visit-data.rs | 16 +++-- 5 files changed, 150 insertions(+), 22 deletions(-) diff --git a/src/libcore/reflect.rs b/src/libcore/reflect.rs index a38e51b38134b..9a0526b4351ba 100644 --- a/src/libcore/reflect.rs +++ b/src/libcore/reflect.rs @@ -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 TyVisitor for MovePtrAdaptor { true } + #[cfg(stage0)] fn visit_enter_enum(&self, n_variants: uint, sz: uint, align: uint) -> bool { self.align(align); @@ -402,6 +404,18 @@ impl TyVisitor for MovePtrAdaptor { 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 TyVisitor for MovePtrAdaptor { 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 TyVisitor for MovePtrAdaptor { 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; } diff --git a/src/libcore/repr.rs b/src/libcore/repr.rs index 3d42f06483178..30ae3c3b8331e 100644 --- a/src/libcore/repr.rs +++ b/src/libcore/repr.rs @@ -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(&self) { self.bump(sys::size_of::()); } - #[cfg(stage0)] #[inline(always)] - fn stage0_bump_past(&self) { - self.bump_past::(); - } - #[cfg(not(stage0))] #[inline(always)] - fn stage0_bump_past(&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::(); + self.bump_past::(); + } + } + + 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,8 +597,34 @@ 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 } diff --git a/src/librustc/front/intrinsic.rs b/src/librustc/front/intrinsic.rs index 7a07ce1251616..ccb7e3ffd55fc 100644 --- a/src/librustc/front/intrinsic.rs +++ b/src/librustc/front/intrinsic.rs @@ -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, diff --git a/src/librustc/middle/trans/reflect.rs b/src/librustc/middle/trans/reflect.rs index 9d62231905eea..163fc7b84e7a4 100644 --- a/src/librustc/middle/trans/reflect.rs +++ b/src/librustc/middle/trans/reflect.rs @@ -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)); + + // 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))] + 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), diff --git a/src/test/run-pass/reflect-visit-data.rs b/src/test/run-pass/reflect-visit-data.rs index 8ddc845f50cbc..8f3a1dd90c24c 100644 --- a/src/test/run-pass/reflect-visit-data.rs +++ b/src/test/run-pass/reflect-visit-data.rs @@ -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 TyVisitor for ptr_visit_adaptor { 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 TyVisitor for ptr_visit_adaptor { 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, From 2589eba957ee5632dc9060022b5ca09cbfb782f9 Mon Sep 17 00:00:00 2001 From: Jed Davis Date: Sun, 7 Apr 2013 20:26:48 -0700 Subject: [PATCH 3/5] When repr'ing an enum value, assert that it matched some variant. --- src/libcore/repr.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/libcore/repr.rs b/src/libcore/repr.rs index 30ae3c3b8331e..530f80ef764cd 100644 --- a/src/libcore/repr.rs +++ b/src/libcore/repr.rs @@ -624,9 +624,10 @@ impl TyVisitor for ReprVisitor { 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 + match self.var_stk.pop() { + SearchingFor(*) => fail!(~"enum value matched no variant"), + _ => true + } } fn visit_enter_fn(&self, _purity: uint, _proto: uint, From 04b2c26f39782ba30ad8868f971d5d8a606fcf88 Mon Sep 17 00:00:00 2001 From: Jed Davis Date: Sun, 7 Apr 2013 20:47:44 -0700 Subject: [PATCH 4/5] Make the enum visit callback generator more readable --- src/librustc/middle/trans/reflect.rs | 37 ++++++++++++++-------------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/src/librustc/middle/trans/reflect.rs b/src/librustc/middle/trans/reflect.rs index 163fc7b84e7a4..e64914afd88cc 100644 --- a/src/librustc/middle/trans/reflect.rs +++ b/src/librustc/middle/trans/reflect.rs @@ -275,26 +275,27 @@ pub impl Reflector { let variants = ty::substd_enum_variants(ccx.tcx, did, substs); let llptrty = T_ptr(type_of(ccx, t)); - // 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 make_get_disr = || { + let sub_path = bcx.fcx.path + ~[path_name(special_idents::anon)]; + let sym = mangle_internal_name_by_path_and_seq(ccx, sub_path, ~"get_disr"); + let args = [ty::arg { mode: ast::expl(ast::by_copy), + ty: ty::mk_nil_ptr(ccx.tcx) }]; + let llfty = type_of_fn(ccx, args, ty::mk_int(ccx.tcx)); + let llfdecl = decl_internal_cdecl_fn(ccx.llmod, sym, llfty); + let arg = unsafe { + llvm::LLVMGetParam(llfdecl, first_real_arg as c_uint) + }; + let fcx = new_fn_ctxt(ccx, ~[], llfdecl, None); + let bcx = top_scope_block(fcx, None); + let arg = BitCast(bcx, arg, llptrty); + let ret = adt::trans_get_discr(bcx, repr, arg); + Store(bcx, ret, fcx.llretptr); + cleanup_and_Br(bcx, bcx, fcx.llreturn); + finish_fn(fcx, bcx.llbb); + llfdecl }; - 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] + let enum_args = ~[self.c_uint(vec::len(variants)), make_get_disr()] + self.c_size_and_align(t); do self.bracketed(~"enum", enum_args) |this| { for variants.eachi |i, v| { From e9a52f5af576ffd517284813858b6d06910460ea Mon Sep 17 00:00:00 2001 From: Jed Davis Date: Sun, 7 Apr 2013 22:35:26 -0700 Subject: [PATCH 5/5] Make intrinsic::Opaque more opaque --- src/librustc/front/intrinsic.rs | 3 +-- src/librustc/middle/trans/reflect.rs | 5 ++++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/librustc/front/intrinsic.rs b/src/librustc/front/intrinsic.rs index ccb7e3ffd55fc..dcf300bd31da6 100644 --- a/src/librustc/front/intrinsic.rs +++ b/src/librustc/front/intrinsic.rs @@ -28,8 +28,7 @@ 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 enum Opaque { } pub trait TyVisitor { fn visit_bot(&self) -> bool; diff --git a/src/librustc/middle/trans/reflect.rs b/src/librustc/middle/trans/reflect.rs index e64914afd88cc..596c55a68f872 100644 --- a/src/librustc/middle/trans/reflect.rs +++ b/src/librustc/middle/trans/reflect.rs @@ -274,12 +274,15 @@ pub impl Reflector { 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 (_, opaquety) = *(ccx.tcx.intrinsic_defs.find(&ccx.sess.ident_of(~"Opaque")) + .expect("Failed to resolve intrinsic::Opaque")); + let opaqueptrty = ty::mk_ptr(ccx.tcx, ty::mt { ty: opaquety, mutbl: ast::m_imm }); let make_get_disr = || { let sub_path = bcx.fcx.path + ~[path_name(special_idents::anon)]; let sym = mangle_internal_name_by_path_and_seq(ccx, sub_path, ~"get_disr"); let args = [ty::arg { mode: ast::expl(ast::by_copy), - ty: ty::mk_nil_ptr(ccx.tcx) }]; + ty: opaqueptrty }]; let llfty = type_of_fn(ccx, args, ty::mk_int(ccx.tcx)); let llfdecl = decl_internal_cdecl_fn(ccx.llmod, sym, llfty); let arg = unsafe {