auto merge of #7254 : Blei/rust/intrinsic-overhaul, r=cmr

This sets the `get_tydesc()` return type correctly and removes the intrinsic module. See #3730, #3475.

Update: this now also removes the unused shape fields in tydescs.
This commit is contained in:
bors 2013-06-25 04:38:06 -07:00
commit 7aee5da08d
35 changed files with 558 additions and 647 deletions

View file

@ -8,9 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
pub static rc_base_field_refcnt: uint = 0u;
pub static task_field_refcnt: uint = 0u;
@ -49,9 +46,7 @@ pub static tydesc_field_take_glue: uint = 2u;
pub static tydesc_field_drop_glue: uint = 3u;
pub static tydesc_field_free_glue: uint = 4u;
pub static tydesc_field_visit_glue: uint = 5u;
pub static tydesc_field_shape: uint = 6u;
pub static tydesc_field_shape_tables: uint = 7u;
pub static n_tydesc_fields: uint = 8u;
pub static n_tydesc_fields: uint = 6u;
// The two halves of a closure: code and environment.
pub static fn_field_code: uint = 0u;
@ -71,14 +66,4 @@ pub static vec_elt_elems: uint = 2u;
pub static slice_elt_base: uint = 0u;
pub static slice_elt_len: uint = 1u;
pub static worst_case_glue_call_args: uint = 7u;
pub static abi_version: uint = 1u;
pub fn memcpy_glue_name() -> ~str { return ~"rust_memcpy_glue"; }
pub fn bzero_glue_name() -> ~str { return ~"rust_bzero_glue"; }
pub fn yield_glue_name() -> ~str { return ~"rust_yield_glue"; }
pub fn no_op_type_glue_name() -> ~str { return ~"rust_no_op_type_glue"; }

View file

@ -206,9 +206,6 @@ pub fn compile_rest(sess: Session,
let mut crate = crate_opt.unwrap();
let (llcx, llmod, link_meta) = {
crate = time(time_passes, ~"intrinsic injection", ||
front::intrinsic_inject::inject_intrinsic(sess, crate));
crate = time(time_passes, ~"extra injection", ||
front::std_inject::maybe_inject_libstd_ref(sess, crate));

View file

@ -1,140 +0,0 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// NB: this file is include_str!'ed into the compiler, re-parsed
// and injected into each crate the compiler builds. Keep it small.
pub mod intrinsic {
#[allow(missing_doc)];
pub use intrinsic::rusti::visit_tydesc;
// FIXME (#3727): remove this when the interface has settled and the
// version in sys is no longer present.
pub fn get_tydesc<T>() -> *TyDesc {
unsafe {
rusti::get_tydesc::<T>() as *TyDesc
}
}
pub struct TyDesc {
size: uint,
align: uint
// Remaining fields not listed
}
pub enum Opaque { }
pub trait TyVisitor {
fn visit_bot(&self) -> bool;
fn visit_nil(&self) -> bool;
fn visit_bool(&self) -> bool;
fn visit_int(&self) -> bool;
fn visit_i8(&self) -> bool;
fn visit_i16(&self) -> bool;
fn visit_i32(&self) -> bool;
fn visit_i64(&self) -> bool;
fn visit_uint(&self) -> bool;
fn visit_u8(&self) -> bool;
fn visit_u16(&self) -> bool;
fn visit_u32(&self) -> bool;
fn visit_u64(&self) -> bool;
fn visit_float(&self) -> bool;
fn visit_f32(&self) -> bool;
fn visit_f64(&self) -> bool;
fn visit_char(&self) -> bool;
fn visit_str(&self) -> bool;
fn visit_estr_box(&self) -> bool;
fn visit_estr_uniq(&self) -> bool;
fn visit_estr_slice(&self) -> bool;
fn visit_estr_fixed(&self, n: uint, sz: uint, align: uint) -> bool;
fn visit_box(&self, mtbl: uint, inner: *TyDesc) -> bool;
fn visit_uniq(&self, mtbl: uint, inner: *TyDesc) -> bool;
fn visit_ptr(&self, mtbl: uint, inner: *TyDesc) -> bool;
fn visit_rptr(&self, mtbl: uint, inner: *TyDesc) -> bool;
fn visit_vec(&self, mtbl: uint, inner: *TyDesc) -> bool;
fn visit_unboxed_vec(&self, mtbl: uint, inner: *TyDesc) -> bool;
fn visit_evec_box(&self, mtbl: uint, inner: *TyDesc) -> bool;
fn visit_evec_uniq(&self, mtbl: uint, inner: *TyDesc) -> bool;
fn visit_evec_slice(&self, mtbl: uint, inner: *TyDesc) -> bool;
fn visit_evec_fixed(&self, n: uint, sz: uint, align: uint,
mtbl: uint, inner: *TyDesc) -> bool;
fn visit_enter_rec(&self, n_fields: uint,
sz: uint, align: uint) -> bool;
fn visit_rec_field(&self, i: uint, name: &str,
mtbl: uint, inner: *TyDesc) -> bool;
fn visit_leave_rec(&self, n_fields: uint,
sz: uint, align: uint) -> bool;
fn visit_enter_class(&self, n_fields: uint,
sz: uint, align: uint) -> bool;
fn visit_class_field(&self, i: uint, name: &str,
mtbl: uint, inner: *TyDesc) -> bool;
fn visit_leave_class(&self, n_fields: uint,
sz: uint, align: uint) -> bool;
fn visit_enter_tup(&self, n_fields: uint,
sz: uint, align: uint) -> bool;
fn visit_tup_field(&self, i: uint, inner: *TyDesc) -> bool;
fn visit_leave_tup(&self, n_fields: uint,
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,
n_fields: uint,
name: &str) -> 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,
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,
n_inputs: uint, retstyle: uint) -> bool;
fn visit_fn_input(&self, i: uint, mode: uint, inner: *TyDesc) -> bool;
fn visit_fn_output(&self, retstyle: uint, inner: *TyDesc) -> bool;
fn visit_leave_fn(&self, purity: uint, proto: uint,
n_inputs: uint, retstyle: uint) -> bool;
fn visit_trait(&self) -> bool;
fn visit_var(&self) -> bool;
fn visit_var_integral(&self) -> bool;
fn visit_param(&self, i: uint) -> bool;
fn visit_self(&self) -> bool;
fn visit_type(&self) -> bool;
fn visit_opaque_box(&self) -> bool;
fn visit_constr(&self, inner: *TyDesc) -> bool;
fn visit_closure_ptr(&self, ck: uint) -> bool;
}
pub mod rusti {
use super::{TyDesc, TyVisitor};
#[abi = "rust-intrinsic"]
pub extern "rust-intrinsic" {
pub fn get_tydesc<T>() -> *();
pub fn visit_tydesc(td: *TyDesc, tv: @TyVisitor);
}
}
}

View file

@ -1,47 +0,0 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use core::prelude::*;
use core::vec;
use driver::session::Session;
use syntax::parse;
use syntax::ast;
use syntax::codemap::spanned;
pub fn inject_intrinsic(sess: Session, crate: @ast::crate) -> @ast::crate {
let intrinsic_module = include_str!("intrinsic.rs").to_managed();
let item = parse::parse_item_from_source_str(@"<intrinsic>",
intrinsic_module,
/*bad*/copy sess.opts.cfg,
~[],
sess.parse_sess);
let item =
match item {
Some(i) => i,
None => {
sess.fatal("no item found in intrinsic module");
}
};
let items = vec::append(~[item], crate.node.module.items);
@spanned {
node: ast::crate_ {
module: ast::_mod {
items: items,
.. /*bad*/copy crate.node.module
},
.. /*bad*/copy crate.node
},
.. /*bad*/copy *crate
}
}

View file

@ -76,16 +76,20 @@ pub enum LangItem {
UnrecordBorrowFnLangItem, // 36
StartFnLangItem, // 37
TyDescStructLangItem, // 38
TyVisitorTraitLangItem, // 39
OpaqueStructLangItem, // 40
}
pub struct LanguageItems {
items: [Option<def_id>, ..38]
items: [Option<def_id>, ..41]
}
impl LanguageItems {
pub fn new() -> LanguageItems {
LanguageItems {
items: [ None, ..38 ]
items: [ None, ..41 ]
}
}
@ -138,6 +142,10 @@ impl LanguageItems {
37 => "start",
38 => "ty_desc",
39 => "ty_visitor",
40 => "opaque",
_ => "???"
}
}
@ -262,6 +270,15 @@ impl LanguageItems {
pub fn start_fn(&const self) -> def_id {
self.items[StartFnLangItem as uint].get()
}
pub fn ty_desc(&const self) -> def_id {
self.items[TyDescStructLangItem as uint].get()
}
pub fn ty_visitor(&const self) -> def_id {
self.items[TyVisitorTraitLangItem as uint].get()
}
pub fn opaque(&const self) -> def_id {
self.items[OpaqueStructLangItem as uint].get()
}
}
fn LanguageItemCollector(crate: @crate,
@ -313,6 +330,9 @@ fn LanguageItemCollector(crate: @crate,
item_refs.insert(@"record_borrow", RecordBorrowFnLangItem as uint);
item_refs.insert(@"unrecord_borrow", UnrecordBorrowFnLangItem as uint);
item_refs.insert(@"start", StartFnLangItem as uint);
item_refs.insert(@"ty_desc", TyDescStructLangItem as uint);
item_refs.insert(@"ty_visitor", TyVisitorTraitLangItem as uint);
item_refs.insert(@"opaque", OpaqueStructLangItem as uint);
LanguageItemCollector {
crate: crate,

View file

@ -681,9 +681,12 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
let static_ti = get_tydesc(ccx, tp_ty);
glue::lazily_emit_all_tydesc_glue(ccx, static_ti);
// FIXME (#3727): change this to ccx.tydesc_ty.ptr_to() when the
// core::sys copy of the get_tydesc interface dies off.
let td = PointerCast(bcx, static_ti.tydesc, Type::nil().ptr_to());
// FIXME (#3730): ideally this shouldn't need a cast,
// but there's a circularity between translating rust types to llvm
// types and having a tydesc type available. So I can't directly access
// the llvm type of intrinsic::TyDesc struct.
let userland_tydesc_ty = type_of::type_of(ccx, output_type);
let td = PointerCast(bcx, static_ti.tydesc, userland_tydesc_ty);
Store(bcx, td, fcx.llretptr.get());
}
"init" => {

View file

@ -232,7 +232,7 @@ pub fn lazily_emit_tydesc_glue(ccx: @mut CrateContext,
field: uint,
ti: @mut tydesc_info) {
let _icx = push_ctxt("lazily_emit_tydesc_glue");
let llfnty = type_of_glue_fn(ccx);
let llfnty = Type::glue_fn();
if lazily_emit_simplified_tydesc_glue(ccx, field, ti) {
return;
@ -338,9 +338,7 @@ pub fn call_tydesc_glue_full(bcx: block,
}
};
Call(bcx, llfn, [C_null(Type::nil().ptr_to()),
C_null(bcx.ccx().tydesc_type.ptr_to().ptr_to()),
llrawptr]);
Call(bcx, llfn, [C_null(Type::nil().ptr_to()), llrawptr]);
}
// See [Note-arg-mode]
@ -680,7 +678,7 @@ pub fn make_generic_glue_inner(ccx: @mut CrateContext,
let bcx = top_scope_block(fcx, None);
let lltop = bcx.llbb;
let rawptr0_arg = fcx.arg_pos(1u);
let rawptr0_arg = fcx.arg_pos(0u);
let llrawptr0 = unsafe { llvm::LLVMGetParam(llfn, rawptr0_arg as c_uint) };
let llty = type_of(ccx, t);
let llrawptr0 = PointerCast(bcx, llrawptr0, llty.ptr_to());
@ -715,7 +713,7 @@ pub fn emit_tydescs(ccx: &mut CrateContext) {
let _icx = push_ctxt("emit_tydescs");
// As of this point, allow no more tydescs to be created.
ccx.finished_tydescs = true;
let glue_fn_ty = Type::generic_glue_fn(ccx);
let glue_fn_ty = Type::generic_glue_fn(ccx).ptr_to();
let tyds = &mut ccx.tydescs;
for tyds.each_value |&val| {
let ti = val;
@ -765,19 +763,13 @@ pub fn emit_tydescs(ccx: &mut CrateContext) {
}
};
let shape = C_null(Type::i8p());
let shape_tables = C_null(Type::i8p());
let tydesc = C_named_struct(ccx.tydesc_type,
[ti.size, // size
ti.align, // align
take_glue, // take_glue
drop_glue, // drop_glue
free_glue, // free_glue
visit_glue, // visit_glue
shape, // shape
shape_tables]); // shape_tables
[ti.size, // size
ti.align, // align
take_glue, // take_glue
drop_glue, // drop_glue
free_glue, // free_glue
visit_glue]); // visit_glue
unsafe {
let gvar = ti.tydesc;
@ -788,8 +780,3 @@ pub fn emit_tydescs(ccx: &mut CrateContext) {
}
};
}
fn type_of_glue_fn(ccx: &CrateContext) -> Type {
let tydescpp = ccx.tydesc_type.ptr_to().ptr_to();
Type::func([ Type::nil().ptr_to(), tydescpp, Type::i8p() ], &Type::void())
}

View file

@ -274,9 +274,7 @@ impl Reflector {
let repr = adt::represent_type(bcx.ccx(), t);
let variants = ty::substd_enum_variants(ccx.tcx, did, substs);
let llptrty = type_of(ccx, t).ptr_to();
let (_, opaquety) =
ccx.tcx.intrinsic_defs.find_copy(&ccx.sess.ident_of("Opaque"))
.expect("Failed to resolve intrinsic::Opaque");
let opaquety = ty::get_opaque_ty(ccx.tcx);
let opaqueptrty = ty::mk_ptr(ccx.tcx, ty::mt { ty: opaquety, mutbl: ast::m_imm });
let make_get_disr = || {
@ -373,10 +371,8 @@ pub fn emit_calls_to_trait_visit_ty(bcx: block,
visitor_val: ValueRef,
visitor_trait_id: def_id)
-> block {
use syntax::parse::token::special_idents::tydesc;
let final = sub_block(bcx, "final");
assert!(bcx.ccx().tcx.intrinsic_defs.contains_key(&tydesc));
let (_, tydesc_ty) = bcx.ccx().tcx.intrinsic_defs.get_copy(&tydesc);
let tydesc_ty = ty::get_tydesc_ty(bcx.ccx().tcx);
let tydesc_ty = type_of(bcx.ccx(), tydesc_ty);
let mut r = Reflector {
visitor_val: visitor_val,

View file

@ -20,7 +20,6 @@ use middle::trans::base;
use syntax::ast;
use syntax::abi::{Architecture, X86, X86_64, Arm, Mips};
use back::abi;
use core::vec;
use core::cast;
@ -189,25 +188,26 @@ impl Type {
None => ()
}
let ty = cx.tydesc_type.get_field(abi::tydesc_field_drop_glue);
let ty = Type::glue_fn();
cx.tn.associate_type("glue_fn", &ty);
return ty;
}
pub fn glue_fn() -> Type {
Type::func([ Type::nil().ptr_to(), Type::i8p() ],
&Type::void())
}
pub fn tydesc(arch: Architecture) -> Type {
let mut tydesc = Type::named_struct("tydesc");
let tydescpp = tydesc.ptr_to().ptr_to();
let pvoid = Type::i8p();
let glue_fn_ty = Type::func([ Type::nil().ptr_to(), tydescpp, pvoid ],
&Type::void()).ptr_to();
let glue_fn_ty = Type::glue_fn().ptr_to();
let int_ty = Type::int(arch);
let elems = [
int_ty, int_ty,
glue_fn_ty, glue_fn_ty, glue_fn_ty, glue_fn_ty,
pvoid, pvoid
glue_fn_ty, glue_fn_ty, glue_fn_ty, glue_fn_ty
];
tydesc.set_struct_body(elems, false);
@ -265,10 +265,6 @@ impl Type {
cx.int_type
}
pub fn captured_tydescs(ctx: &CrateContext, num: uint) -> Type {
Type::struct_(vec::from_elem(num, ctx.tydesc_type.ptr_to()), false)
}
pub fn opaque_trait(ctx: &CrateContext, store: ty::TraitStore) -> Type {
let tydesc_ptr = ctx.tydesc_type.ptr_to();
match store {

View file

@ -44,7 +44,6 @@ use syntax::attr;
use syntax::codemap::span;
use syntax::codemap;
use syntax::parse::token;
use syntax::parse::token::special_idents;
use syntax::{ast, ast_map};
use syntax::opt_vec::OptVec;
use syntax::opt_vec;
@ -276,8 +275,7 @@ struct ctxt_ {
trait_defs: @mut HashMap<def_id, @TraitDef>,
items: ast_map::map,
intrinsic_defs: @mut HashMap<ast::ident, (ast::def_id, t)>,
intrinsic_traits: @mut HashMap<ast::ident, @TraitRef>,
intrinsic_defs: @mut HashMap<ast::def_id, t>,
freevars: freevars::freevar_map,
tcache: type_cache,
rcache: creader_cache,
@ -954,7 +952,6 @@ pub fn mk_ctxt(s: session::Session,
node_type_substs: @mut HashMap::new(),
trait_refs: @mut HashMap::new(),
trait_defs: @mut HashMap::new(),
intrinsic_traits: @mut HashMap::new(),
items: amap,
intrinsic_defs: @mut HashMap::new(),
freevars: freevars,
@ -4469,10 +4466,26 @@ pub fn get_impl_id(tcx: ctxt, trait_id: def_id, self_ty: t) -> def_id {
}
}
pub fn get_tydesc_ty(tcx: ctxt) -> t {
let tydesc_lang_item = tcx.lang_items.ty_desc();
tcx.intrinsic_defs.find_copy(&tydesc_lang_item)
.expect("Failed to resolve TyDesc")
}
pub fn get_opaque_ty(tcx: ctxt) -> t {
let opaque_lang_item = tcx.lang_items.opaque();
tcx.intrinsic_defs.find_copy(&opaque_lang_item)
.expect("Failed to resolve Opaque")
}
pub fn visitor_object_ty(tcx: ctxt) -> (@TraitRef, t) {
let ty_visitor_name = special_idents::ty_visitor;
assert!(tcx.intrinsic_traits.contains_key(&ty_visitor_name));
let trait_ref = tcx.intrinsic_traits.get_copy(&ty_visitor_name);
let substs = substs {
self_r: None,
self_ty: None,
tps: ~[]
};
let trait_lang_item = tcx.lang_items.ty_visitor();
let trait_ref = @TraitRef { def_id: trait_lang_item, substs: substs };
(trait_ref,
mk_trait(tcx, trait_ref.def_id, copy trait_ref.substs,
BoxTraitStore, ast::m_imm, EmptyBuiltinBounds()))

View file

@ -3506,13 +3506,15 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) {
}
"get_tydesc" => {
// FIXME (#3730): return *intrinsic::tydesc, not *()
(1u, ~[], ty::mk_nil_ptr(ccx.tcx))
let tydesc_ty = ty::get_tydesc_ty(ccx.tcx);
let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {
ty: tydesc_ty,
mutbl: ast::m_imm
});
(1u, ~[], td_ptr)
}
"visit_tydesc" => {
let tydesc_name = special_idents::tydesc;
assert!(tcx.intrinsic_defs.contains_key(&tydesc_name));
let (_, tydesc_ty) = tcx.intrinsic_defs.get_copy(&tydesc_name);
let tydesc_ty = ty::get_tydesc_ty(ccx.tcx);
let (_, visitor_object_ty) = ty::visitor_object_ty(tcx);
let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {
ty: tydesc_ty,

View file

@ -62,55 +62,16 @@ use syntax::opt_vec::OptVec;
use syntax::opt_vec;
pub fn collect_item_types(ccx: @mut CrateCtxt, crate: @ast::crate) {
// FIXME (#2592): hooking into the "intrinsic" root module is crude.
// There ought to be a better approach. Attributes?
for crate.node.module.items.iter().advance |crate_item| {
if crate_item.ident
== ::syntax::parse::token::special_idents::intrinsic {
match crate_item.node {
ast::item_mod(ref m) => {
for m.items.iter().advance |intrinsic_item| {
let def_id = ast::def_id { crate: ast::local_crate,
node: intrinsic_item.id };
let substs = substs {
self_r: None,
self_ty: None,
tps: ~[]
};
match intrinsic_item.node {
ast::item_trait(*) => {
let tref = @ty::TraitRef {def_id: def_id,
substs: substs};
ccx.tcx.intrinsic_traits.insert
(intrinsic_item.ident, tref);
}
ast::item_enum(*) => {
let ty = ty::mk_enum(ccx.tcx, def_id, substs);
ccx.tcx.intrinsic_defs.insert
(intrinsic_item.ident, (def_id, ty));
}
ast::item_struct(*) => {
let ty = ty::mk_struct(ccx.tcx, def_id, substs);
ccx.tcx.intrinsic_defs.insert
(intrinsic_item.ident, (def_id, ty));
}
_ => {}
}
}
}
_ => { }
}
break;
}
fn collect_intrinsic_type(ccx: @mut CrateCtxt,
lang_item: ast::def_id) {
let ty::ty_param_bounds_and_ty { ty: ty, _ } =
ccx.get_item_ty(lang_item);
ccx.tcx.intrinsic_defs.insert(lang_item, ty);
}
collect_intrinsic_type(ccx, ccx.tcx.lang_items.ty_desc());
collect_intrinsic_type(ccx, ccx.tcx.lang_items.opaque());
visit::visit_crate(
crate, ((),
visit::mk_simple_visitor(@visit::SimpleVisitor {

View file

@ -86,7 +86,6 @@ pub mod front {
pub mod config;
pub mod test;
pub mod std_inject;
pub mod intrinsic_inject;
}
pub mod back {