@@ -174,6 +174,7 @@ impl<'self> Drop for StatRecorder<'self> {
174174 }
175175}
176176
177+ // only use this for foreign function ABIs and glue, use `decl_rust_fn` for Rust functions
177178pub fn decl_fn ( llmod : ModuleRef , name : & str , cc : lib:: llvm:: CallConv , ty : Type ) -> ValueRef {
178179 let llfn: ValueRef = do name. with_c_str |buf| {
179180 unsafe {
@@ -185,18 +186,12 @@ pub fn decl_fn(llmod: ModuleRef, name: &str, cc: lib::llvm::CallConv, ty: Type)
185186 return llfn;
186187}
187188
189+ // only use this for foreign function ABIs and glue, use `decl_rust_fn` for Rust functions
188190pub fn decl_cdecl_fn ( llmod : ModuleRef , name : & str , ty : Type ) -> ValueRef {
189191 return decl_fn ( llmod, name, lib:: llvm:: CCallConv , ty) ;
190192}
191193
192- // Only use this if you are going to actually define the function. It's
193- // not valid to simply declare a function as internal.
194- pub fn decl_internal_cdecl_fn ( llmod : ModuleRef , name : & str , ty : Type ) -> ValueRef {
195- let llfn = decl_cdecl_fn ( llmod, name, ty) ;
196- lib:: llvm:: SetLinkage ( llfn, lib:: llvm:: InternalLinkage ) ;
197- return llfn;
198- }
199-
194+ // only use this for foreign function ABIs and glue, use `get_extern_rust_fn` for Rust functions
200195pub fn get_extern_fn ( externs : & mut ExternMap , llmod : ModuleRef , name : & str ,
201196 cc : lib:: llvm:: CallConv , ty : Type ) -> ValueRef {
202197 match externs. find_equiv ( & name) {
@@ -205,7 +200,73 @@ pub fn get_extern_fn(externs: &mut ExternMap, llmod: ModuleRef, name: &str,
205200 }
206201 let f = decl_fn ( llmod, name, cc, ty) ;
207202 externs. insert ( name. to_owned ( ) , f) ;
208- return f;
203+ f
204+ }
205+
206+ pub fn get_extern_rust_fn ( ccx : & mut CrateContext , inputs : & [ ty:: t ] , output : ty:: t ,
207+ name : & str ) -> ValueRef {
208+ match ccx. externs . find_equiv ( & name) {
209+ Some ( n) => return * n,
210+ None => ( )
211+ }
212+ let f = decl_rust_fn ( ccx, inputs, output, name) ;
213+ ccx. externs . insert ( name. to_owned ( ) , f) ;
214+ f
215+ }
216+
217+ pub fn decl_rust_fn ( ccx : & mut CrateContext , inputs : & [ ty:: t ] , output : ty:: t ,
218+ name : & str ) -> ValueRef {
219+ let llfty = type_of_rust_fn ( ccx, inputs, output) ;
220+ let llfn = decl_cdecl_fn ( ccx. llmod , name, llfty) ;
221+
222+ match ty:: get ( output) . sty {
223+ // `~` pointer return values never alias because ownership is transferred
224+ ty:: ty_uniq( * ) |
225+ ty:: ty_evec( _, ty:: vstore_uniq) => {
226+ unsafe {
227+ llvm:: LLVMAddReturnAttribute ( llfn, lib:: llvm:: NoAliasAttribute as c_uint ) ;
228+ }
229+ }
230+ _ => ( )
231+ }
232+
233+ let uses_outptr = type_of:: return_uses_outptr ( ccx. tcx , output) ;
234+ let offset = if uses_outptr { 2 } else { 1 } ;
235+
236+ for ( i, & arg_ty) in inputs. iter ( ) . enumerate ( ) {
237+ let llarg = unsafe { llvm:: LLVMGetParam ( llfn, ( offset + i) as c_uint ) } ;
238+ match ty:: get ( arg_ty) . sty {
239+ // `~` pointer parameters never alias because ownership is transferred
240+ ty:: ty_uniq( * ) |
241+ ty:: ty_evec( _, ty:: vstore_uniq) |
242+ ty:: ty_closure( ty:: ClosureTy { sigil : ast:: OwnedSigil , _} ) => {
243+ unsafe {
244+ llvm:: LLVMAddAttribute ( llarg, lib:: llvm:: NoAliasAttribute as c_uint ) ;
245+ }
246+ }
247+ _ => ( )
248+ }
249+ }
250+
251+ // The out pointer will never alias with any other pointers, as the object only exists at a
252+ // language level after the call. It can also be tagged with SRet to indicate that it is
253+ // guaranteed to point to a usable block of memory for the type.
254+ if uses_outptr {
255+ unsafe {
256+ let outptr = llvm:: LLVMGetParam ( llfn, 0 ) ;
257+ llvm:: LLVMAddAttribute ( outptr, lib:: llvm:: StructRetAttribute as c_uint ) ;
258+ llvm:: LLVMAddAttribute ( outptr, lib:: llvm:: NoAliasAttribute as c_uint ) ;
259+ }
260+ }
261+
262+ llfn
263+ }
264+
265+ pub fn decl_internal_rust_fn ( ccx : & mut CrateContext , inputs : & [ ty:: t ] , output : ty:: t ,
266+ name : & str ) -> ValueRef {
267+ let llfn = decl_rust_fn ( ccx, inputs, output, name) ;
268+ lib:: llvm:: SetLinkage ( llfn, lib:: llvm:: InternalLinkage ) ;
269+ llfn
209270}
210271
211272pub fn get_extern_const ( externs : & mut ExternMap , llmod : ModuleRef ,
@@ -809,33 +870,30 @@ pub fn null_env_ptr(ccx: &CrateContext) -> ValueRef {
809870 C_null(Type::opaque_box(ccx).ptr_to())
810871}
811872
812- pub fn trans_external_path(ccx: &mut CrateContext, did: ast::DefId, t: ty::t)
813- -> ValueRef {
873+ pub fn trans_external_path(ccx: &mut CrateContext, did: ast::DefId, t: ty::t) -> ValueRef {
814874 let name = csearch::get_symbol(ccx.sess.cstore, did);
815875 match ty::get(t).sty {
816876 ty::ty_bare_fn(ref fn_ty) => {
817- // Currently llvm_calling_convention triggers unimpl/bug on
818- // Rust/RustIntrinsic, so those two are handled specially here.
819- let cconv = match fn_ty.abis.for_arch (ccx.sess.targ_cfg.arch) {
820- Some(Rust) | Some(RustIntrinsic) => lib::llvm::CCallConv,
877+ match fn_ty.abis.for_arch(ccx.sess.targ_cfg.arch) {
878+ Some(Rust) | Some(RustIntrinsic) => {
879+ get_extern_rust_fn (ccx, fn_ty.sig.inputs, fn_ty.sig.output, name)
880+ }
821881 Some(*) | None => {
822882 let c = foreign::llvm_calling_convention(ccx, fn_ty.abis);
823- c.unwrap_or(lib::llvm::CCallConv)
883+ let cconv = c.unwrap_or(lib::llvm::CCallConv);
884+ let llty = type_of_fn_from_ty(ccx, t);
885+ get_extern_fn(&mut ccx.externs, ccx.llmod, name, cconv, llty)
824886 }
825- };
826- let llty = type_of_fn_from_ty(ccx, t);
827- return get_extern_fn(&mut ccx.externs, ccx.llmod, name, cconv, llty);
887+ }
828888 }
829- ty::ty_closure(_) => {
830- let llty = type_of_fn_from_ty(ccx, t);
831- return get_extern_fn(&mut ccx.externs, ccx.llmod, name,
832- lib::llvm::CCallConv, llty);
889+ ty::ty_closure(ref f) => {
890+ get_extern_rust_fn(ccx, f.sig.inputs, f.sig.output, name)
833891 }
834892 _ => {
835893 let llty = type_of(ccx, t);
836- return get_extern_const(&mut ccx.externs, ccx.llmod, name, llty);
894+ get_extern_const(&mut ccx.externs, ccx.llmod, name, llty)
837895 }
838- };
896+ }
839897}
840898
841899pub fn invoke(bcx: @mut Block, llfn: ValueRef, llargs: ~[ValueRef],
@@ -868,7 +926,8 @@ pub fn invoke(bcx: @mut Block, llfn: ValueRef, llargs: ~[ValueRef],
868926 llfn,
869927 llargs,
870928 normal_bcx. llbb ,
871- get_landing_pad ( bcx) ) ;
929+ get_landing_pad ( bcx) ,
930+ attributes) ;
872931 return ( llresult, normal_bcx) ;
873932 } else {
874933 unsafe {
@@ -1707,8 +1766,7 @@ pub fn new_fn_ctxt(ccx: @mut CrateContext,
17071766// field of the fn_ctxt with
17081767pub fn create_llargs_for_fn_args ( cx : @mut FunctionContext ,
17091768 self_arg : self_arg ,
1710- args : & [ ast:: arg ] ,
1711- arg_tys : & [ ty:: t ] )
1769+ args : & [ ast:: arg ] )
17121770 -> ~[ ValueRef ] {
17131771 let _icx = push_ctxt ( "create_llargs_for_fn_args" ) ;
17141772
@@ -1726,23 +1784,7 @@ pub fn create_llargs_for_fn_args(cx: @mut FunctionContext,
17261784 // Return an array containing the ValueRefs that we get from
17271785 // llvm::LLVMGetParam for each argument.
17281786 do vec:: from_fn ( args. len ( ) ) |i| {
1729- let arg_n = cx. arg_pos ( i) ;
1730- let arg_ty = arg_tys[ i] ;
1731- let llarg = unsafe { llvm:: LLVMGetParam ( cx. llfn , arg_n as c_uint ) } ;
1732-
1733- match ty:: get ( arg_ty) . sty {
1734- // `~` pointer parameters never alias because ownership is transferred
1735- ty:: ty_uniq( * ) |
1736- ty:: ty_evec( _, ty:: vstore_uniq) |
1737- ty:: ty_closure( ty:: ClosureTy { sigil : ast:: OwnedSigil , _} ) => {
1738- unsafe {
1739- llvm:: LLVMAddAttribute ( llarg, lib:: llvm:: NoAliasAttribute as c_uint ) ;
1740- }
1741- }
1742- _ => ( )
1743- }
1744-
1745- llarg
1787+ unsafe { llvm:: LLVMGetParam ( cx. llfn , cx. arg_pos ( i) as c_uint ) }
17461788 }
17471789}
17481790
@@ -1896,8 +1938,7 @@ pub fn trans_closure(ccx: @mut CrateContext,
18961938
18971939 // Set up arguments to the function.
18981940 let arg_tys = ty:: ty_fn_args ( node_id_type ( bcx, id) ) ;
1899- let raw_llargs = create_llargs_for_fn_args ( fcx, self_arg,
1900- decl. inputs , arg_tys) ;
1941+ let raw_llargs = create_llargs_for_fn_args ( fcx, self_arg, decl. inputs ) ;
19011942
19021943 // Set the fixed stack segment flag if necessary.
19031944 if attr:: contains_name ( attributes, "fixed_stack_segment" ) {
@@ -1961,18 +2002,6 @@ pub fn trans_fn(ccx: @mut CrateContext,
19612002 param_substs. repr( ccx. tcx) ) ;
19622003 let _icx = push_ctxt ( "trans_fn" ) ;
19632004 let output_type = ty:: ty_fn_ret ( ty:: node_id_to_type ( ccx. tcx , id) ) ;
1964-
1965- match ty:: get ( output_type) . sty {
1966- // `~` pointer return values never alias because ownership is transferred
1967- ty:: ty_uniq( * ) |
1968- ty:: ty_evec( _, ty:: vstore_uniq) => {
1969- unsafe {
1970- llvm:: LLVMAddReturnAttribute ( llfndecl, lib:: llvm:: NoAliasAttribute as c_uint ) ;
1971- }
1972- }
1973- _ => ( )
1974- }
1975-
19762005 trans_closure ( ccx,
19772006 path. clone ( ) ,
19782007 decl,
@@ -2120,7 +2149,7 @@ pub fn trans_enum_variant_or_tuple_like_struct<A:IdAndTy>(
21202149
21212150 let arg_tys = ty:: ty_fn_args ( ctor_ty) ;
21222151
2123- let raw_llargs = create_llargs_for_fn_args ( fcx, no_self, fn_args, arg_tys ) ;
2152+ let raw_llargs = create_llargs_for_fn_args ( fcx, no_self, fn_args) ;
21242153
21252154 let bcx = fcx. entry_bcx . unwrap ( ) ;
21262155
@@ -2298,10 +2327,28 @@ pub fn register_fn(ccx: @mut CrateContext,
22982327 node_id : ast:: NodeId ,
22992328 node_type : ty:: t )
23002329 -> ValueRef {
2301- let llfty = type_of_fn_from_ty ( ccx, node_type) ;
2302- register_fn_llvmty ( ccx, sp, sym, node_id, lib:: llvm:: CCallConv , llfty)
2330+ let f = match ty:: get ( node_type) . sty {
2331+ ty:: ty_bare_fn( ref f) => {
2332+ assert ! ( f. abis. is_rust( ) || f. abis. is_intrinsic( ) ) ;
2333+ f
2334+ }
2335+ _ => fail ! ( "expected bare rust fn or an intrinsic" )
2336+ } ;
2337+
2338+ let llfn = decl_rust_fn ( ccx, f. sig . inputs , f. sig . output , sym) ;
2339+ ccx. item_symbols . insert ( node_id, sym) ;
2340+
2341+ // FIXME #4404 android JNI hacks
2342+ let is_entry = is_entry_fn ( & ccx. sess , node_id) && ( !* ccx. sess . building_library ||
2343+ ( * ccx. sess . building_library &&
2344+ ccx. sess . targ_cfg . os == session:: OsAndroid ) ) ;
2345+ if is_entry {
2346+ create_entry_wrapper ( ccx, sp, llfn) ;
2347+ }
2348+ llfn
23032349}
23042350
2351+ // only use this for foreign function ABIs and glue, use `register_fn` for Rust functions
23052352pub fn register_fn_llvmty ( ccx : @mut CrateContext ,
23062353 sp : Span ,
23072354 sym : ~str ,
0 commit comments