1919use arena:: TypedArena ;
2020use back:: abi;
2121use back:: link;
22- use driver:: session;
2322use lib:: llvm:: ValueRef ;
2423use lib:: llvm:: llvm;
2524use metadata:: csearch;
@@ -40,6 +39,7 @@ use middle::trans::expr;
4039use middle:: trans:: glue;
4140use middle:: trans:: inline;
4241use middle:: trans:: foreign;
42+ use middle:: trans:: intrinsic;
4343use middle:: trans:: meth;
4444use middle:: trans:: monomorphize;
4545use middle:: trans:: type_:: Type ;
@@ -53,7 +53,6 @@ use util::ppaux::Repr;
5353use std:: gc:: Gc ;
5454use syntax:: ast;
5555use synabi = syntax:: abi;
56- use syntax:: ast_map;
5756
5857pub struct MethodData {
5958 pub llfn : ValueRef ,
@@ -68,6 +67,8 @@ pub enum CalleeData {
6867 // value (which is a pair).
6968 Fn ( /* llfn */ ValueRef ) ,
7069
70+ Intrinsic ( ast:: NodeId , subst:: Substs ) ,
71+
7172 TraitMethod ( MethodData )
7273}
7374
@@ -119,7 +120,21 @@ fn trans<'a>(bcx: &'a Block<'a>, expr: &ast::Expr) -> Callee<'a> {
119120
120121 fn trans_def < ' a > ( bcx : & ' a Block < ' a > , def : def:: Def , ref_expr : & ast:: Expr )
121122 -> Callee < ' a > {
123+ debug ! ( "trans_def(def={}, ref_expr={})" , def. repr( bcx. tcx( ) ) , ref_expr. repr( bcx. tcx( ) ) ) ;
124+ let expr_ty = node_id_type ( bcx, ref_expr. id ) ;
122125 match def {
126+ def:: DefFn ( did, _) if match ty:: get ( expr_ty) . sty {
127+ ty:: ty_bare_fn( ref f) => f. abi == synabi:: RustIntrinsic ,
128+ _ => false
129+ } => {
130+ let substs = node_id_substs ( bcx, ExprId ( ref_expr. id ) ) ;
131+ let def_id = if did. krate != ast:: LOCAL_CRATE {
132+ inline:: maybe_instantiate_inline ( bcx. ccx ( ) , did)
133+ } else {
134+ did
135+ } ;
136+ Callee { bcx : bcx, data : Intrinsic ( def_id. node , substs) }
137+ }
123138 def:: DefFn ( did, _) |
124139 def:: DefStaticMethod ( did, def:: FromImpl ( _) , _) => {
125140 fn_callee ( bcx, trans_fn_ref ( bcx, did, ExprId ( ref_expr. id ) ) )
@@ -460,27 +475,8 @@ pub fn trans_fn_ref_with_vtables(
460475 }
461476 } ;
462477
463- // We must monomorphise if the fn has type parameters, is a rust
464- // intrinsic, or is a default method. In particular, if we see an
465- // intrinsic that is inlined from a different crate, we want to reemit the
466- // intrinsic instead of trying to call it in the other crate.
467- let must_monomorphise = if !substs. types . is_empty ( ) || is_default {
468- true
469- } else if def_id. krate == ast:: LOCAL_CRATE {
470- let map_node = session:: expect (
471- ccx. sess ( ) ,
472- tcx. map . find ( def_id. node ) ,
473- || "local item should be in ast map" . to_string ( ) ) ;
474-
475- match map_node {
476- ast_map:: NodeForeignItem ( _) => {
477- tcx. map . get_foreign_abi ( def_id. node ) == synabi:: RustIntrinsic
478- }
479- _ => false
480- }
481- } else {
482- false
483- } ;
478+ // We must monomorphise if the fn has type parameters or is a default method.
479+ let must_monomorphise = !substs. types . is_empty ( ) || is_default;
484480
485481 // Create a monomorphic version of generic functions
486482 if must_monomorphise {
@@ -662,6 +658,12 @@ pub fn trans_call_inner<'a>(
662658 let callee = get_callee ( bcx, cleanup:: CustomScope ( arg_cleanup_scope) ) ;
663659 let mut bcx = callee. bcx ;
664660
661+ let ( abi, ret_ty) = match ty:: get ( callee_ty) . sty {
662+ ty:: ty_bare_fn( ref f) => ( f. abi , f. sig . output ) ,
663+ ty:: ty_closure( ref f) => ( synabi:: Rust , f. sig . output ) ,
664+ _ => fail ! ( "expected bare rust fn or closure in trans_call_inner" )
665+ } ;
666+
665667 let ( llfn, llenv, llself) = match callee. data {
666668 Fn ( llfn) => {
667669 ( llfn, None , None )
@@ -679,14 +681,19 @@ pub fn trans_call_inner<'a>(
679681 let llenv = Load ( bcx, llenv) ;
680682 ( llfn, Some ( llenv) , None )
681683 }
682- } ;
684+ Intrinsic ( node, substs) => {
685+ assert ! ( abi == synabi:: RustIntrinsic ) ;
686+ assert ! ( dest. is_some( ) ) ;
683687
684- let ( abi , ret_ty ) = match ty :: get ( callee_ty ) . sty {
685- ty :: ty_bare_fn ( ref f ) => ( f . abi , f . sig . output ) ,
686- ty :: ty_closure ( ref f ) => ( synabi :: Rust , f . sig . output ) ,
687- _ => fail ! ( "expected bare rust fn or closure in trans_call_inner" )
688+ return intrinsic :: trans_intrinsic_call ( bcx , node , callee_ty ,
689+ arg_cleanup_scope , args ,
690+ dest . unwrap ( ) , substs ) ;
691+ }
688692 } ;
689- let is_rust_fn = abi == synabi:: Rust || abi == synabi:: RustIntrinsic ;
693+
694+ // Intrinsics should not become actual functions.
695+ // We trans them in place in `trans_intrinsic_call`
696+ assert ! ( abi != synabi:: RustIntrinsic ) ;
690697
691698 // Generate a location to store the result. If the user does
692699 // not care about the result, just make a stack slot.
@@ -716,7 +723,7 @@ pub fn trans_call_inner<'a>(
716723 // and done, either the return value of the function will have been
717724 // written in opt_llretslot (if it is Some) or `llresult` will be
718725 // set appropriately (otherwise).
719- if is_rust_fn {
726+ if abi == synabi :: Rust {
720727 let mut llargs = Vec :: new ( ) ;
721728
722729 // Push the out-pointer if we use an out-pointer for this
@@ -816,13 +823,13 @@ pub enum CallArgs<'a> {
816823 ArgOverloadedOp ( Datum < Expr > , Option < ( Datum < Expr > , ast:: NodeId ) > ) ,
817824}
818825
819- fn trans_args < ' a > ( cx : & ' a Block < ' a > ,
820- args : CallArgs ,
821- fn_ty : ty:: t ,
822- llargs : & mut Vec < ValueRef > ,
823- arg_cleanup_scope : cleanup:: ScopeId ,
824- ignore_self : bool )
825- -> & ' a Block < ' a > {
826+ pub fn trans_args < ' a > ( cx : & ' a Block < ' a > ,
827+ args : CallArgs ,
828+ fn_ty : ty:: t ,
829+ llargs : & mut Vec < ValueRef > ,
830+ arg_cleanup_scope : cleanup:: ScopeId ,
831+ ignore_self : bool )
832+ -> & ' a Block < ' a > {
826833 let _icx = push_ctxt ( "trans_args" ) ;
827834 let arg_tys = ty:: ty_fn_args ( fn_ty) ;
828835 let variadic = ty:: fn_is_variadic ( fn_ty) ;
0 commit comments