about summary refs log tree commit diff
path: root/src/rustc
diff options
context:
space:
mode:
authorMarijn Haverbeke <marijnh@gmail.com>2012-03-09 13:35:20 +0100
committerMarijn Haverbeke <marijnh@gmail.com>2012-03-15 10:22:46 +0100
commitb6ad34bef4f0b3613d51557cd327055a2c5311fd (patch)
tree9d94307570687aedc031e0e8b8b16a6b8cd4f9fc /src/rustc
parente4cbd43c430ef0d5f63ca7cb86a65a618521e175 (diff)
downloadrust-b6ad34bef4f0b3613d51557cd327055a2c5311fd.tar.gz
rust-b6ad34bef4f0b3613d51557cd327055a2c5311fd.zip
Properly recognize external intrinsics
Diffstat (limited to 'src/rustc')
-rw-r--r--src/rustc/metadata/common.rs1
-rw-r--r--src/rustc/metadata/csearch.rs6
-rw-r--r--src/rustc/metadata/decoder.rs8
-rw-r--r--src/rustc/metadata/encoder.rs24
-rw-r--r--src/rustc/middle/trans/base.rs93
-rw-r--r--src/rustc/middle/trans/impl.rs22
6 files changed, 89 insertions, 65 deletions
diff --git a/src/rustc/metadata/common.rs b/src/rustc/metadata/common.rs
index db3dc4078ed..88800e17aff 100644
--- a/src/rustc/metadata/common.rs
+++ b/src/rustc/metadata/common.rs
@@ -68,6 +68,7 @@ const tag_mod_impl: uint = 0x30u;
 
 const tag_item_method: uint = 0x31u;
 const tag_impl_iface: uint = 0x32u;
+const tag_item_is_intrinsic: uint = 0x33u;
 
 // discriminator value for variants
 const tag_disr_val: uint = 0x34u;
diff --git a/src/rustc/metadata/csearch.rs b/src/rustc/metadata/csearch.rs
index 6be4124d5e6..08836703836 100644
--- a/src/rustc/metadata/csearch.rs
+++ b/src/rustc/metadata/csearch.rs
@@ -19,6 +19,7 @@ export get_type;
 export get_impl_iface;
 export get_impl_method;
 export get_item_path;
+export item_is_intrinsic;
 export maybe_get_item_ast, found_ast, found, found_parent, not_found;
 
 fn get_symbol(cstore: cstore::cstore, def: ast::def_id) -> str {
@@ -134,6 +135,11 @@ fn get_impl_method(cstore: cstore::cstore, def: ast::def_id, mname: str)
     decoder::get_impl_method(cdata, def.node, mname)
 }
 
+fn item_is_intrinsic(cstore: cstore::cstore, def: ast::def_id) -> bool {
+    let cdata = cstore::get_crate_data(cstore, def.crate);
+    decoder::item_is_intrinsic(cdata, def.node)
+}
+
 // Local Variables:
 // mode: rust
 // fill-column: 78;
diff --git a/src/rustc/metadata/decoder.rs b/src/rustc/metadata/decoder.rs
index ac6e32f292d..70c771b85c1 100644
--- a/src/rustc/metadata/decoder.rs
+++ b/src/rustc/metadata/decoder.rs
@@ -34,6 +34,7 @@ export get_iface_methods;
 export get_crate_module_paths;
 export get_item_path;
 export maybe_get_item_ast;
+export item_is_intrinsic;
 
 // Used internally by astencode:
 export translate_def_id;
@@ -272,6 +273,13 @@ fn get_impl_method(cdata: cmd, id: ast::node_id, name: str) -> ast::def_id {
     option::get(found)
 }
 
+fn item_is_intrinsic(cdata: cmd, id: ast::node_id) -> bool {
+    let intrinsic = false;
+    ebml::tagged_docs(lookup_item(id, cdata.data), tag_item_is_intrinsic,
+                      {|_i| intrinsic = true;});
+    intrinsic
+}
+
 fn get_symbol(data: @[u8], id: ast::node_id) -> str {
     ret item_symbol(lookup_item(id, data));
 }
diff --git a/src/rustc/metadata/encoder.rs b/src/rustc/metadata/encoder.rs
index 57813f1791b..fee50a927e6 100644
--- a/src/rustc/metadata/encoder.rs
+++ b/src/rustc/metadata/encoder.rs
@@ -502,7 +502,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
 fn encode_info_for_native_item(ecx: @encode_ctxt, ebml_w: ebml::writer,
                                nitem: @native_item,
                                index: @mutable [entry<int>],
-                               path: ast_map::path) {
+                               path: ast_map::path, abi: native_abi) {
     if !ecx.reachable.contains_key(nitem.id) { ret; }
     *index += [{val: nitem.id, pos: ebml_w.writer.tell()}];
 
@@ -512,6 +512,10 @@ fn encode_info_for_native_item(ecx: @encode_ctxt, ebml_w: ebml::writer,
         encode_def_id(ebml_w, local_def(nitem.id));
         encode_family(ebml_w, purity_fn_family(fn_decl.purity));
         encode_type_param_bounds(ebml_w, ecx, tps);
+        if abi == native_abi_rust_intrinsic {
+            ebml_w.start_tag(tag_item_is_intrinsic);
+            ebml_w.end_tag();
+        }
         encode_type(ecx, ebml_w, node_id_to_type(ecx.ccx.tcx, nitem.id));
         encode_symbol(ecx, ebml_w, nitem.id);
         encode_path(ebml_w, path, ast_map::path_name(nitem.ident));
@@ -531,17 +535,19 @@ fn encode_info_for_items(ecx: @encode_ctxt, ebml_w: ebml::writer,
         visit_expr: {|_e, _cx, _v|},
         visit_item: {|i, cx, v|
             visit::visit_item(i, cx, v);
-            let path = alt check ecx.ccx.tcx.items.get(i.id) {
-              ast_map::node_item(_, pt) { pt }
-            };
-            encode_info_for_item(ecx, ebml_w, i, index, *path);
+            alt check ecx.ccx.tcx.items.get(i.id) {
+              ast_map::node_item(_, pt) {
+                encode_info_for_item(ecx, ebml_w, i, index, *pt);
+              }
+            }
         },
         visit_native_item: {|ni, cx, v|
             visit::visit_native_item(ni, cx, v);
-            let path = alt check ecx.ccx.tcx.items.get(ni.id) {
-              ast_map::node_native_item(_, _, pt) { pt }
-            };
-            encode_info_for_native_item(ecx, ebml_w, ni, index, *path);
+            alt check ecx.ccx.tcx.items.get(ni.id) {
+              ast_map::node_native_item(_, abi, pt) {
+                encode_info_for_native_item(ecx, ebml_w, ni, index, *pt, abi);
+              }
+            }
         }
         with *visit::default_visitor()
     }));
diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs
index 0ea5408c8ed..f81c24d811e 100644
--- a/src/rustc/middle/trans/base.rs
+++ b/src/rustc/middle/trans/base.rs
@@ -2136,21 +2136,44 @@ fn maybe_instantiate_inline(ccx: @crate_ctxt, fn_id: ast::def_id)
     }
 }
 
-fn add_tydesc_params(ccx: crate_ctxt, llfty: TypeRef, n: uint) -> TypeRef {
-    let out_ty = llvm::LLVMGetReturnType(llfty);
-    let n_args = llvm::LLVMCountParamTypes(llfty);
-    let args = vec::init_elt(n_args as uint, 0 as TypeRef);
-    unsafe { llvm::LLVMGetParamTypes(llfty, vec::unsafe::to_ptr(args)); }
-    T_fn(vec::slice(args, 0u, first_real_arg) +
-         vec::init_elt(n, T_ptr(ccx.tydesc_type)) +
-         vec::tail_n(args, first_real_arg), out_ty)
-}
-
-fn lval_static_fn(bcx: block, fn_id: ast::def_id, id: ast::node_id,
-                  substs: option<([ty::t], typeck::vtable_res)>)
+fn lval_intrinsic_fn(bcx: block, val: ValueRef, tys: [ty::t],
+                     id: ast::node_id) -> lval_maybe_callee {
+    fn add_tydesc_params(ccx: @crate_ctxt, llfty: TypeRef, n: uint)
+        -> TypeRef {
+        let out_ty = llvm::LLVMGetReturnType(llfty);
+        let n_args = llvm::LLVMCountParamTypes(llfty);
+        let args = vec::from_elem(n_args as uint, 0 as TypeRef);
+        unsafe { llvm::LLVMGetParamTypes(llfty, vec::unsafe::to_ptr(args)); }
+        T_fn(vec::slice(args, 0u, first_real_arg) +
+             vec::from_elem(n, T_ptr(ccx.tydesc_type)) +
+             vec::tailn(args, first_real_arg), out_ty)
+    }
+
+    let bcx = bcx, ccx = bcx.ccx();
+    let tds = vec::map(tys, {|t|
+        let ti = none, td_res = get_tydesc(bcx, t, ti);
+        bcx = td_res.bcx;
+        lazily_emit_all_tydesc_glue(ccx, ti);
+        td_res.val
+    });
+    let llfty = type_of_fn_from_ty(ccx, node_id_type(bcx, id));
+    let val = PointerCast(bcx, val, T_ptr(add_tydesc_params(
+        ccx, llfty, tys.len())));
+    {bcx: bcx, val: val, kind: owned, env: null_env, tds: some(tds)}
+}
+
+fn lval_static_fn(bcx: block, fn_id: ast::def_id, id: ast::node_id)
+    -> lval_maybe_callee {
+    let vts = option::map(bcx.ccx().maps.vtable_map.find(id), {|vts|
+        impl::resolve_vtables_in_fn_ctxt(bcx.fcx, vts)
+    });
+    lval_static_fn_inner(bcx, fn_id, id, node_id_type_params(bcx, id), vts)
+}
+
+fn lval_static_fn_inner(bcx: block, fn_id: ast::def_id, id: ast::node_id,
+                        tys: [ty::t], vtables: option<typeck::vtable_res>)
     -> lval_maybe_callee {
-    let bcx = bcx, ccx = bcx.ccx(), tcx = ccx.tcx;
-    let tys = node_id_type_params(bcx, id);
+    let ccx = bcx.ccx(), tcx = ccx.tcx;
     let tpt = ty::lookup_item_type(tcx, fn_id);
 
     // Check whether this fn has an inlined copy and, if so, redirect fn_id to
@@ -2159,32 +2182,15 @@ fn lval_static_fn(bcx: block, fn_id: ast::def_id, id: ast::node_id,
         maybe_instantiate_inline(ccx, fn_id)
     } else { fn_id };
 
-    if fn_id.crate == ast::local_crate {
-        let (tys, vtables) = alt substs {
-          some((tys, vts)) { (tys, some(vts)) }
-          none { (tys, option::map(ccx.maps.vtable_map.find(id), {|vts|
-                           impl::resolve_vtables_in_fn_ctxt(bcx.fcx, vts)})) }
-        };
-        if tys.len() > 0u {
-            let {val, must_cast, intrinsic} = monomorphic_fn(ccx, fn_id, tys,
-                                                             vtables);
-            let tds = none;
-            if intrinsic {
-                tds = some(vec::map(tys, {|t|
-                    let ti = none, td_res = get_tydesc(bcx, t, ti);
-                    bcx = td_res.bcx;
-                    lazily_emit_all_tydesc_glue(ccx, ti);
-                    td_res.val
-                }));
-                let llfty = type_of_fn_from_ty(ccx, node_id_type(bcx, id));
-                val = PointerCast(bcx, val, T_ptr(add_tydesc_params(
-                    ccx, llfty, tys.len())));
-            } else if must_cast {
-                val = PointerCast(bcx, val, T_ptr(type_of_fn_from_ty(
-                    ccx, node_id_type(bcx, id))));
-            }
-            ret {bcx: bcx, val: val, kind: owned, env: null_env, tds: tds};
+    if fn_id.crate == ast::local_crate && tys.len() > 0u {
+        let {val, must_cast, intrinsic} = monomorphic_fn(ccx, fn_id, tys,
+                                                         vtables);
+        if intrinsic { ret lval_intrinsic_fn(bcx, val, tys, id); }
+        if must_cast {
+            val = PointerCast(bcx, val, T_ptr(type_of_fn_from_ty(
+                ccx, node_id_type(bcx, id))));
         }
+        ret {bcx: bcx, val: val, kind: owned, env: null_env, tds: none};
     }
 
     let val = if fn_id.crate == ast::local_crate {
@@ -2197,6 +2203,9 @@ fn lval_static_fn(bcx: block, fn_id: ast::def_id, id: ast::node_id,
     if tys.len() > 0u {
         // This is supposed to be an external native function.
         // Unfortunately, I found no easy/cheap way to assert that.
+        if csearch::item_is_intrinsic(ccx.sess.cstore, fn_id) {
+            ret lval_intrinsic_fn(bcx, val, tys, id);
+        }
         val = PointerCast(bcx, val, T_ptr(type_of_fn_from_ty(
             ccx, node_id_type(bcx, id))));
     }
@@ -2287,12 +2296,12 @@ fn trans_var(cx: block, def: ast::def, id: ast::node_id, path: @ast::path)
     let ccx = cx.ccx();
     alt def {
       ast::def_fn(did, _) {
-        ret lval_static_fn(cx, did, id, none);
+        ret lval_static_fn(cx, did, id);
       }
       ast::def_variant(tid, vid) {
         if ty::enum_variant_with_id(ccx.tcx, tid, vid).args.len() > 0u {
             // N-ary variant.
-            ret lval_static_fn(cx, vid, id, none);
+            ret lval_static_fn(cx, vid, id);
         } else {
             // Nullary variant.
             let enum_ty = node_id_type(cx, id);
@@ -2766,7 +2775,7 @@ fn trans_call_inner(in_cx: block, fn_expr_ty: ty::t,
         let llargs = args_res.args;
         option::may(f_res.tds) {|vals|
             llargs = vec::slice(llargs, 0u, first_real_arg) + vals +
-                vec::tail_n(llargs, first_real_arg);
+                vec::tailn(llargs, first_real_arg);
         }
 
         let llretslot = args_res.retslot;
diff --git a/src/rustc/middle/trans/impl.rs b/src/rustc/middle/trans/impl.rs
index 00782c0a11b..3486de0dc90 100644
--- a/src/rustc/middle/trans/impl.rs
+++ b/src/rustc/middle/trans/impl.rs
@@ -48,7 +48,9 @@ fn trans_method_callee(bcx: block, callee_id: ast::node_id,
     -> lval_maybe_callee {
     alt origin {
       typeck::method_static(did) {
-        trans_static_callee(bcx, callee_id, self, did, none)
+        let {bcx, val} = trans_self_arg(bcx, self);
+        {env: self_env(val, node_id_type(bcx, self.id))
+         with lval_static_fn(bcx, did, callee_id)}
       }
       typeck::method_param(iid, off, p, b) {
         alt check bcx.fcx.param_substs {
@@ -64,16 +66,6 @@ fn trans_method_callee(bcx: block, callee_id: ast::node_id,
     }
 }
 
-// Method callee where the method is statically known
-fn trans_static_callee(bcx: block, callee_id: ast::node_id,
-                       base: @ast::expr, did: ast::def_id,
-                       substs: option<([ty::t], typeck::vtable_res)>)
-    -> lval_maybe_callee {
-    let {bcx, val} = trans_self_arg(bcx, base);
-    {env: self_env(val, node_id_type(bcx, base.id))
-     with lval_static_fn(bcx, did, callee_id, substs)}
-}
-
 fn trans_vtable_callee(bcx: block, env: callee_env, vtable: ValueRef,
                        callee_id: ast::node_id, n_method: uint)
     -> lval_maybe_callee {
@@ -122,11 +114,13 @@ fn trans_monomorphized_callee(bcx: block, callee_id: ast::node_id,
         let node_substs = node_id_type_params(bcx, callee_id);
         let ty_substs = impl_substs +
             vec::tailn(node_substs, node_substs.len() - n_m_tps);
-        ret trans_static_callee(bcx, callee_id, base, mth_id,
-                                some((ty_substs, sub_origins)));
+        let {bcx, val} = trans_self_arg(bcx, base);
+        {env: self_env(val, node_id_type(bcx, base.id))
+         with lval_static_fn_inner(bcx, mth_id, callee_id, ty_substs,
+                                   some(sub_origins))}
       }
       typeck::vtable_iface(iid, tps) {
-        ret trans_iface_callee(bcx, base, callee_id, n_method);
+        trans_iface_callee(bcx, base, callee_id, n_method)
       }
       typeck::vtable_param(n_param, n_bound) {
         fail "vtable_param left in monomorphized function's vtable substs";