@@ -174,6 +174,7 @@ impl<'self> Drop for StatRecorder<'self> {
174
174
}
175
175
}
176
176
177
+ // only use this for foreign function ABIs and glue, use `decl_rust_fn` for Rust functions
177
178
pub fn decl_fn ( llmod : ModuleRef , name : & str , cc : lib:: llvm:: CallConv , ty : Type ) -> ValueRef {
178
179
let llfn: ValueRef = do name. with_c_str |buf| {
179
180
unsafe {
@@ -185,18 +186,12 @@ pub fn decl_fn(llmod: ModuleRef, name: &str, cc: lib::llvm::CallConv, ty: Type)
185
186
return llfn;
186
187
}
187
188
189
+ // only use this for foreign function ABIs and glue, use `decl_rust_fn` for Rust functions
188
190
pub fn decl_cdecl_fn ( llmod : ModuleRef , name : & str , ty : Type ) -> ValueRef {
189
191
return decl_fn ( llmod, name, lib:: llvm:: CCallConv , ty) ;
190
192
}
191
193
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
200
195
pub fn get_extern_fn ( externs : & mut ExternMap , llmod : ModuleRef , name : & str ,
201
196
cc : lib:: llvm:: CallConv , ty : Type ) -> ValueRef {
202
197
match externs. find_equiv ( & name) {
@@ -205,7 +200,73 @@ pub fn get_extern_fn(externs: &mut ExternMap, llmod: ModuleRef, name: &str,
205
200
}
206
201
let f = decl_fn ( llmod, name, cc, ty) ;
207
202
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
209
270
}
210
271
211
272
pub fn get_extern_const ( externs : & mut ExternMap , llmod : ModuleRef ,
@@ -809,33 +870,30 @@ pub fn null_env_ptr(ccx: &CrateContext) -> ValueRef {
809
870
C_null(Type::opaque_box(ccx).ptr_to())
810
871
}
811
872
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 {
814
874
let name = csearch::get_symbol(ccx.sess.cstore, did);
815
875
match ty::get(t).sty {
816
876
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
+ }
821
881
Some(*) | None => {
822
882
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)
824
886
}
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
+ }
828
888
}
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)
833
891
}
834
892
_ => {
835
893
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)
837
895
}
838
- };
896
+ }
839
897
}
840
898
841
899
pub fn invoke(bcx: @mut Block, llfn: ValueRef, llargs: ~[ValueRef],
@@ -868,7 +926,8 @@ pub fn invoke(bcx: @mut Block, llfn: ValueRef, llargs: ~[ValueRef],
868
926
llfn,
869
927
llargs,
870
928
normal_bcx. llbb ,
871
- get_landing_pad ( bcx) ) ;
929
+ get_landing_pad ( bcx) ,
930
+ attributes) ;
872
931
return ( llresult, normal_bcx) ;
873
932
} else {
874
933
unsafe {
@@ -1707,8 +1766,7 @@ pub fn new_fn_ctxt(ccx: @mut CrateContext,
1707
1766
// field of the fn_ctxt with
1708
1767
pub fn create_llargs_for_fn_args ( cx : @mut FunctionContext ,
1709
1768
self_arg : self_arg ,
1710
- args : & [ ast:: arg ] ,
1711
- arg_tys : & [ ty:: t ] )
1769
+ args : & [ ast:: arg ] )
1712
1770
-> ~[ ValueRef ] {
1713
1771
let _icx = push_ctxt ( "create_llargs_for_fn_args" ) ;
1714
1772
@@ -1726,23 +1784,7 @@ pub fn create_llargs_for_fn_args(cx: @mut FunctionContext,
1726
1784
// Return an array containing the ValueRefs that we get from
1727
1785
// llvm::LLVMGetParam for each argument.
1728
1786
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 ) }
1746
1788
}
1747
1789
}
1748
1790
@@ -1896,8 +1938,7 @@ pub fn trans_closure(ccx: @mut CrateContext,
1896
1938
1897
1939
// Set up arguments to the function.
1898
1940
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 ) ;
1901
1942
1902
1943
// Set the fixed stack segment flag if necessary.
1903
1944
if attr:: contains_name ( attributes, "fixed_stack_segment" ) {
@@ -1961,18 +2002,6 @@ pub fn trans_fn(ccx: @mut CrateContext,
1961
2002
param_substs. repr( ccx. tcx) ) ;
1962
2003
let _icx = push_ctxt ( "trans_fn" ) ;
1963
2004
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
-
1976
2005
trans_closure ( ccx,
1977
2006
path. clone ( ) ,
1978
2007
decl,
@@ -2120,7 +2149,7 @@ pub fn trans_enum_variant_or_tuple_like_struct<A:IdAndTy>(
2120
2149
2121
2150
let arg_tys = ty:: ty_fn_args ( ctor_ty) ;
2122
2151
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) ;
2124
2153
2125
2154
let bcx = fcx. entry_bcx . unwrap ( ) ;
2126
2155
@@ -2298,10 +2327,28 @@ pub fn register_fn(ccx: @mut CrateContext,
2298
2327
node_id : ast:: NodeId ,
2299
2328
node_type : ty:: t )
2300
2329
-> 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
2303
2349
}
2304
2350
2351
+ // only use this for foreign function ABIs and glue, use `register_fn` for Rust functions
2305
2352
pub fn register_fn_llvmty ( ccx : @mut CrateContext ,
2306
2353
sp : Span ,
2307
2354
sym : ~str ,
0 commit comments