@@ -20,7 +20,7 @@ use std::slice;
2020
2121use back:: abi;
2222use driver:: session;
23- use lib:: llvm:: { ValueRef , NoAliasAttribute , StructRetAttribute } ;
23+ use lib:: llvm:: { ValueRef , NoAliasAttribute , StructRetAttribute , NoCaptureAttribute } ;
2424use lib:: llvm:: llvm;
2525use metadata:: csearch;
2626use middle:: trans:: base;
@@ -661,9 +661,15 @@ pub fn trans_call_inner<'a>(
661661 llargs. push ( opt_llretslot. unwrap ( ) ) ;
662662 }
663663
664+ // start at 1, because index 0 is the return value of the llvm func
665+ let mut first_arg_offset = 1 ;
666+
664667 // Push the environment (or a trait object's self).
665668 match ( llenv, llself) {
666- ( Some ( llenv) , None ) => llargs. push ( llenv) ,
669+ ( Some ( llenv) , None ) => {
670+ first_arg_offset += 1 ;
671+ llargs. push ( llenv)
672+ } ,
667673 ( None , Some ( llself) ) => llargs. push ( llself) ,
668674 _ => { }
669675 }
@@ -682,6 +688,11 @@ pub fn trans_call_inner<'a>(
682688 let mut attrs = Vec :: new ( ) ;
683689 if type_of:: return_uses_outptr ( ccx, ret_ty) {
684690 attrs. push ( ( 1 , StructRetAttribute ) ) ;
691+ // The outptr can be noalias and nocapture because it's entirely
692+ // invisible to the program.
693+ attrs. push ( ( 1 , NoAliasAttribute ) ) ;
694+ attrs. push ( ( 1 , NoCaptureAttribute ) ) ;
695+ first_arg_offset += 1 ;
685696 }
686697
687698 // The `noalias` attribute on the return value is useful to a
@@ -695,6 +706,30 @@ pub fn trans_call_inner<'a>(
695706 _ => { }
696707 }
697708
709+ debug ! ( "trans_callee_inner: first_arg_offset={}" , first_arg_offset) ;
710+
711+ for ( idx, & t) in ty:: ty_fn_args ( callee_ty) . iter ( ) . enumerate ( )
712+ . map ( |( i, v) | ( i+first_arg_offset, v) ) {
713+ use middle:: ty:: { BrAnon , ReLateBound } ;
714+ if !type_is_immediate ( ccx, t) {
715+ // if it's not immediate, we have a program-invisible pointer,
716+ // which it can't possibly capture
717+ attrs. push ( ( idx, NoCaptureAttribute ) ) ;
718+ debug ! ( "trans_callee_inner: argument {} nocapture because it's non-immediate" , idx) ;
719+ continue ;
720+ }
721+
722+ let t_ = ty:: get ( t) ;
723+ match t_. sty {
724+ ty:: ty_rptr( ReLateBound ( _, BrAnon ( _) ) , _) => {
725+ debug ! ( "trans_callee_inner: argument {} nocapture because \
726+ of anonymous lifetime", idx) ;
727+ attrs. push ( ( idx, NoCaptureAttribute ) ) ;
728+ } ,
729+ _ => { }
730+ }
731+ }
732+
698733 // Invoke the actual rust fn and update bcx/llresult.
699734 let ( llret, b) = base:: invoke ( bcx,
700735 llfn,
0 commit comments