@@ -20,7 +20,7 @@ use std::slice;
20
20
21
21
use back:: abi;
22
22
use driver:: session;
23
- use lib:: llvm:: { ValueRef , NoAliasAttribute , StructRetAttribute } ;
23
+ use lib:: llvm:: { ValueRef , NoAliasAttribute , StructRetAttribute , NoCaptureAttribute } ;
24
24
use lib:: llvm:: llvm;
25
25
use metadata:: csearch;
26
26
use middle:: trans:: base;
@@ -661,9 +661,15 @@ pub fn trans_call_inner<'a>(
661
661
llargs. push ( opt_llretslot. unwrap ( ) ) ;
662
662
}
663
663
664
+ // start at 1, because index 0 is the return value of the llvm func
665
+ let mut first_arg_offset = 1 ;
666
+
664
667
// Push the environment (or a trait object's self).
665
668
match ( llenv, llself) {
666
- ( Some ( llenv) , None ) => llargs. push ( llenv) ,
669
+ ( Some ( llenv) , None ) => {
670
+ first_arg_offset += 1 ;
671
+ llargs. push ( llenv)
672
+ } ,
667
673
( None , Some ( llself) ) => llargs. push ( llself) ,
668
674
_ => { }
669
675
}
@@ -682,6 +688,11 @@ pub fn trans_call_inner<'a>(
682
688
let mut attrs = Vec :: new ( ) ;
683
689
if type_of:: return_uses_outptr ( ccx, ret_ty) {
684
690
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 ;
685
696
}
686
697
687
698
// The `noalias` attribute on the return value is useful to a
@@ -695,6 +706,30 @@ pub fn trans_call_inner<'a>(
695
706
_ => { }
696
707
}
697
708
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
+
698
733
// Invoke the actual rust fn and update bcx/llresult.
699
734
let ( llret, b) = base:: invoke ( bcx,
700
735
llfn,
0 commit comments