19
19
use arena:: TypedArena ;
20
20
use back:: abi;
21
21
use back:: link;
22
- use driver:: session;
23
22
use lib:: llvm:: ValueRef ;
24
23
use lib:: llvm:: llvm;
25
24
use metadata:: csearch;
@@ -40,6 +39,7 @@ use middle::trans::expr;
40
39
use middle:: trans:: glue;
41
40
use middle:: trans:: inline;
42
41
use middle:: trans:: foreign;
42
+ use middle:: trans:: intrinsic;
43
43
use middle:: trans:: meth;
44
44
use middle:: trans:: monomorphize;
45
45
use middle:: trans:: type_:: Type ;
@@ -53,7 +53,6 @@ use util::ppaux::Repr;
53
53
use std:: gc:: Gc ;
54
54
use syntax:: ast;
55
55
use synabi = syntax:: abi;
56
- use syntax:: ast_map;
57
56
58
57
pub struct MethodData {
59
58
pub llfn : ValueRef ,
@@ -68,6 +67,8 @@ pub enum CalleeData {
68
67
// value (which is a pair).
69
68
Fn ( /* llfn */ ValueRef ) ,
70
69
70
+ Intrinsic ( ast:: NodeId , subst:: Substs ) ,
71
+
71
72
TraitMethod ( MethodData )
72
73
}
73
74
@@ -119,7 +120,21 @@ fn trans<'a>(bcx: &'a Block<'a>, expr: &ast::Expr) -> Callee<'a> {
119
120
120
121
fn trans_def < ' a > ( bcx : & ' a Block < ' a > , def : def:: Def , ref_expr : & ast:: Expr )
121
122
-> 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 ) ;
122
125
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
+ }
123
138
def:: DefFn ( did, _) |
124
139
def:: DefStaticMethod ( did, def:: FromImpl ( _) , _) => {
125
140
fn_callee ( bcx, trans_fn_ref ( bcx, did, ExprId ( ref_expr. id ) ) )
@@ -460,27 +475,8 @@ pub fn trans_fn_ref_with_vtables(
460
475
}
461
476
} ;
462
477
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;
484
480
485
481
// Create a monomorphic version of generic functions
486
482
if must_monomorphise {
@@ -662,6 +658,12 @@ pub fn trans_call_inner<'a>(
662
658
let callee = get_callee ( bcx, cleanup:: CustomScope ( arg_cleanup_scope) ) ;
663
659
let mut bcx = callee. bcx ;
664
660
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
+
665
667
let ( llfn, llenv, llself) = match callee. data {
666
668
Fn ( llfn) => {
667
669
( llfn, None , None )
@@ -679,14 +681,19 @@ pub fn trans_call_inner<'a>(
679
681
let llenv = Load ( bcx, llenv) ;
680
682
( llfn, Some ( llenv) , None )
681
683
}
682
- } ;
684
+ Intrinsic ( node, substs) => {
685
+ assert ! ( abi == synabi:: RustIntrinsic ) ;
686
+ assert ! ( dest. is_some( ) ) ;
683
687
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
+ }
688
692
} ;
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 ) ;
690
697
691
698
// Generate a location to store the result. If the user does
692
699
// not care about the result, just make a stack slot.
@@ -716,7 +723,7 @@ pub fn trans_call_inner<'a>(
716
723
// and done, either the return value of the function will have been
717
724
// written in opt_llretslot (if it is Some) or `llresult` will be
718
725
// set appropriately (otherwise).
719
- if is_rust_fn {
726
+ if abi == synabi :: Rust {
720
727
let mut llargs = Vec :: new ( ) ;
721
728
722
729
// Push the out-pointer if we use an out-pointer for this
@@ -816,13 +823,13 @@ pub enum CallArgs<'a> {
816
823
ArgOverloadedOp ( Datum < Expr > , Option < ( Datum < Expr > , ast:: NodeId ) > ) ,
817
824
}
818
825
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 > {
826
833
let _icx = push_ctxt ( "trans_args" ) ;
827
834
let arg_tys = ty:: ty_fn_args ( fn_ty) ;
828
835
let variadic = ty:: fn_is_variadic ( fn_ty) ;
0 commit comments