From dc94ccc4a4060e97389cd2cfd8a8cdb25668a3b1 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Fri, 8 Jun 2012 13:26:06 -0700 Subject: [PATCH] More work on reflect, only missing enum and class substructures. --- src/rustc/front/intrinsic.rs | 37 ++++++++ src/rustc/middle/trans/common.rs | 5 ++ src/rustc/middle/trans/reflect.rs | 110 ++++++++++++++++++++++-- src/rustc/middle/trans/tvec.rs | 3 +- src/test/run-pass/reflect-visit-type.rs | 37 ++++++++ 5 files changed, 183 insertions(+), 9 deletions(-) diff --git a/src/rustc/front/intrinsic.rs b/src/rustc/front/intrinsic.rs index 4f24f9dccf2c..cac3b4f5416b 100644 --- a/src/rustc/front/intrinsic.rs +++ b/src/rustc/front/intrinsic.rs @@ -54,6 +54,43 @@ mod intrinsic { fn visit_leave_evec_slice(mtbl: uint) -> bool; fn visit_enter_evec_fixed(mtbl: uint, sz: uint) -> bool; fn visit_leave_evec_fixed(mtbl: uint, sz: uint) -> bool; + + fn visit_enter_rec(n_fields: uint) -> bool; + fn visit_enter_rec_field(mtbl: uint, i: uint + /*, name: str/& */) -> bool; + fn visit_leave_rec_field(mtbl: uint, i: uint + /*, name: str/& */) -> bool; + fn visit_leave_rec(n_fields: uint) -> bool; + + fn visit_enter_tup(n_fields: uint) -> bool; + fn visit_enter_tup_field(i: uint) -> bool; + fn visit_leave_tup_field(i: uint) -> bool; + fn visit_leave_tup(n_fields: uint) -> bool; + + fn visit_enter_fn(purity: uint, proto: uint, + n_inputs: uint, retstyle: uint) -> bool; + fn visit_enter_fn_input(i: uint, mode: uint) -> bool; + fn visit_leave_fn_input(i: uint, mode: uint) -> bool; + fn visit_enter_fn_output(retstyle: uint) -> bool; + fn visit_leave_fn_output(retstyle: uint) -> bool; + fn visit_leave_fn(purity: uint, proto: uint, + n_inputs: uint, retstyle: uint) -> bool; + + fn visit_class() -> bool; + fn visit_enum() -> bool; + + fn visit_iface() -> bool; + fn visit_enter_res() -> bool; + fn visit_leave_res() -> bool; + fn visit_var() -> bool; + fn visit_var_integral() -> bool; + fn visit_param(i: uint) -> bool; + fn visit_self() -> bool; + fn visit_type() -> bool; + fn visit_opaque_box() -> bool; + fn visit_enter_constr() -> bool; + fn visit_leave_constr() -> bool; + fn visit_closure_ptr(ck: uint) -> bool; } #[abi = "rust-intrinsic"] diff --git a/src/rustc/middle/trans/common.rs b/src/rustc/middle/trans/common.rs index 3bd4838d220f..da650eea7927 100644 --- a/src/rustc/middle/trans/common.rs +++ b/src/rustc/middle/trans/common.rs @@ -815,6 +815,11 @@ fn C_cstr(cx: @crate_ctxt, s: str) -> ValueRef { ret g; } +fn C_estr_slice(cx: @crate_ctxt, s: str) -> ValueRef { + let cs = llvm::LLVMConstPointerCast(C_cstr(cx, s), T_ptr(T_i8())); + C_struct([cs, C_uint(cx, str::len(s) + 1u /* +1 for null */)]) +} + // Returns a Plain Old LLVM String: fn C_postr(s: str) -> ValueRef { ret str::as_c_str(s) {|buf| diff --git a/src/rustc/middle/trans/reflect.rs b/src/rustc/middle/trans/reflect.rs index cf929353ab4e..12b1d28dbc90 100644 --- a/src/rustc/middle/trans/reflect.rs +++ b/src/rustc/middle/trans/reflect.rs @@ -42,12 +42,15 @@ impl methods for reflector { abi::tydesc_field_visit_glue); } + fn bracketed_t(bracket_name: str, t: ty::t, extra: [ValueRef]) { + self.visit("enter_" + bracket_name, extra); + self.visit_tydesc(t); + self.visit("leave_" + bracket_name, extra); + } + fn bracketed_mt(bracket_name: str, mt: ty::mt, extra: [ValueRef]) { - self.visit("enter_" + bracket_name, - [self.c_uint(mt.mutbl as uint)] + extra); - self.visit_tydesc(mt.ty); - self.visit("leave_" + bracket_name, - [self.c_uint(mt.mutbl as uint)] + extra); + self.bracketed_t(bracket_name, mt.ty, + [self.c_uint(mt.mutbl as uint)] + extra); } fn vstore_name_and_extra(vstore: ty::vstore, @@ -67,6 +70,10 @@ impl methods for reflector { // Entrypoint fn visit_ty(t: ty::t) { + let bcx = self.bcx; + #debug("reflect::visit_ty %s", + ty_to_str(bcx.ccx().tcx, t)); + alt ty::get(t).struct { ty::ty_bot { self.leaf("bot") } ty::ty_nil { self.leaf("nil") } @@ -103,8 +110,97 @@ impl methods for reflector { ty::ty_ptr(mt) { self.bracketed_mt("ptr", mt, []) } ty::ty_rptr(_, mt) { self.bracketed_mt("rptr", mt, []) } - // FIXME: finish these. - _ { self.visit("bot", []) } + ty::ty_rec(fields) { + self.visit("enter_rec", [self.c_uint(vec::len(fields))]); + for fields.eachi {|i, field| + self.bracketed_mt("rec_field", field.mt, + [self.c_uint(i) + /* + FIXME: doesn't work presently. + C_estr_slice(self.bcx.ccx(), + field.ident) + */ + ]); + } + self.visit("leave_rec", [self.c_uint(vec::len(fields))]); + } + + ty::ty_tup(tys) { + self.visit("enter_tup", [self.c_uint(vec::len(tys))]); + for tys.eachi {|i, t| + self.bracketed_t("tup_field", t, [self.c_uint(i)]); + } + self.visit("leave_tup", [self.c_uint(vec::len(tys))]); + } + + // FIXME: fetch constants out of intrinsic:: for the numbers. + ty::ty_fn(fty) { + let pureval = alt fty.purity { + ast::pure_fn { 0u } + ast::unsafe_fn { 1u } + ast::impure_fn { 2u } + ast::crust_fn { 3u } + }; + let protoval = alt fty.proto { + ast::proto_bare { 0u } + ast::proto_any { 1u } + ast::proto_uniq { 2u } + ast::proto_box { 3u } + ast::proto_block { 4u } + }; + let retval = alt fty.ret_style { + ast::noreturn { 0u } + ast::return_val { 1u } + }; + let extra = [self.c_uint(pureval), + self.c_uint(protoval), + self.c_uint(vec::len(fty.inputs)), + self.c_uint(retval)]; + self.visit("enter_fn", extra); + for fty.inputs.eachi {|i, arg| + let modeval = alt arg.mode { + ast::infer(_) { 0u } + ast::expl(e) { + alt e { + ast::by_ref { 1u } + ast::by_val { 2u } + ast::by_mutbl_ref { 3u } + ast::by_move { 4u } + ast::by_copy { 5u } + } + } + }; + self.bracketed_t("fn_input", arg.ty, + [self.c_uint(i), + self.c_uint(modeval)]); + } + self.bracketed_t("fn_output", fty.output, + [self.c_uint(retval)]); + self.visit("leave_fn", extra); + } + + // FIXME: these need substructure-walks + ty::ty_class(_, _) { self.leaf("class") } + ty::ty_enum(_, _) { self.leaf("enum") } + + // Miscallaneous extra types + ty::ty_iface(_, _) { self.leaf("iface") } + ty::ty_res(_, t, _) { self.bracketed_t("res", t, []) } + ty::ty_var(_) { self.leaf("var") } + ty::ty_var_integral(_) { self.leaf("var_integral") } + ty::ty_param(n, _) { self.visit("param", [self.c_uint(n)]) } + ty::ty_self { self.leaf("self") } + ty::ty_type { self.leaf("type") } + ty::ty_opaque_box { self.leaf("opaque_box") } + ty::ty_constr(t, _) { self.bracketed_t("constr", t, []) } + ty::ty_opaque_closure_ptr(ck) { + let ckval = alt ck { + ty::ck_block { 0u } + ty::ck_box { 1u } + ty::ck_uniq { 2u } + }; + self.visit("closure_ptr", [self.c_uint(ckval)]) + } } } } diff --git a/src/rustc/middle/trans/tvec.rs b/src/rustc/middle/trans/tvec.rs index e53b5ff4886d..fa21927d7432 100644 --- a/src/rustc/middle/trans/tvec.rs +++ b/src/rustc/middle/trans/tvec.rs @@ -276,8 +276,7 @@ fn trans_estr(bcx: block, s: str, vstore: ast::vstore, ast::vstore_slice(_) { // "hello" => (*i8, 6u) in llvm #debug("trans_estr: slice '%s'", s); - let cs = PointerCast(bcx, C_cstr(ccx, s), T_ptr(T_i8())); - C_struct([cs, C_uint(ccx, str::len(s) + 1u /* +1 for null */)]) + C_estr_slice(ccx, s) } ast::vstore_uniq { diff --git a/src/test/run-pass/reflect-visit-type.rs b/src/test/run-pass/reflect-visit-type.rs index 7cd373756f7d..599e8fd99b7d 100644 --- a/src/test/run-pass/reflect-visit-type.rs +++ b/src/test/run-pass/reflect-visit-type.rs @@ -79,6 +79,43 @@ impl of intrinsic::ty_visitor for my_visitor { fn visit_leave_evec_slice(_mtbl: uint) -> bool { true } fn visit_enter_evec_fixed(_mtbl: uint, _sz: uint) -> bool { true } fn visit_leave_evec_fixed(_mtbl: uint, _sz: uint) -> bool { true } + + fn visit_enter_rec(_n_fields: uint) -> bool { true } + fn visit_enter_rec_field(_mtbl: uint, _i: uint + /*,name: str/&*/) -> bool { true } + fn visit_leave_rec_field(_mtbl: uint, _i: uint + /*,name: str/&*/) -> bool { true } + fn visit_leave_rec(_n_fields: uint) -> bool { true } + + fn visit_enter_tup(_n_fields: uint) -> bool { true } + fn visit_enter_tup_field(_i: uint) -> bool { true } + fn visit_leave_tup_field(_i: uint) -> bool { true } + fn visit_leave_tup(_n_fields: uint) -> bool { true } + + fn visit_enter_fn(_purity: uint, _proto: uint, + _n_inputs: uint, _retstyle: uint) -> bool { true } + fn visit_enter_fn_input(_i: uint, _mode: uint) -> bool { true } + fn visit_leave_fn_input(_i: uint, _mode: uint) -> bool { true } + fn visit_enter_fn_output(_retstyle: uint) -> bool { true } + fn visit_leave_fn_output(_retstyle: uint) -> bool { true } + fn visit_leave_fn(_purity: uint, _proto: uint, + _n_inputs: uint, _retstyle: uint) -> bool { true } + + fn visit_class() -> bool { true } + fn visit_enum() -> bool { true } + + fn visit_iface() -> bool { true } + fn visit_enter_res() -> bool { true } + fn visit_leave_res() -> bool { true } + fn visit_var() -> bool { true } + fn visit_var_integral() -> bool { true } + fn visit_param(_i: uint) -> bool { true } + fn visit_self() -> bool { true } + fn visit_type() -> bool { true } + fn visit_opaque_box() -> bool { true } + fn visit_enter_constr() -> bool { true } + fn visit_leave_constr() -> bool { true } + fn visit_closure_ptr(_ck: uint) -> bool { true } } fn main() {