9
9
// except according to those terms.
10
10
11
11
use llvm:: { self , ValueRef } ;
12
- use trans:: common:: { return_type_is_void , type_is_fat_ptr } ;
12
+ use trans:: common:: { type_is_fat_ptr , Block } ;
13
13
use trans:: context:: CrateContext ;
14
14
use trans:: cabi_x86;
15
15
use trans:: cabi_x86_64;
@@ -20,7 +20,7 @@ use trans::cabi_powerpc;
20
20
use trans:: cabi_powerpc64;
21
21
use trans:: cabi_mips;
22
22
use trans:: cabi_asmjs;
23
- use trans:: machine:: { llsize_of_alloc , llsize_of_real} ;
23
+ use trans:: machine:: { llalign_of_min , llsize_of , llsize_of_real} ;
24
24
use trans:: type_:: Type ;
25
25
use trans:: type_of;
26
26
@@ -97,6 +97,8 @@ impl ArgType {
97
97
}
98
98
99
99
pub fn make_indirect ( & mut self , ccx : & CrateContext ) {
100
+ assert_eq ! ( self . kind, ArgKind :: Direct ) ;
101
+
100
102
// Wipe old attributes, likely not valid through indirection.
101
103
self . attrs = llvm:: Attributes :: default ( ) ;
102
104
@@ -113,6 +115,7 @@ impl ArgType {
113
115
}
114
116
115
117
pub fn ignore ( & mut self ) {
118
+ assert_eq ! ( self . kind, ArgKind :: Direct ) ;
116
119
self . kind = ArgKind :: Ignore ;
117
120
}
118
121
@@ -200,39 +203,40 @@ impl FnType {
200
203
arg. attrs . set ( llvm:: Attribute :: ZExt ) ;
201
204
arg
202
205
} else {
203
- ArgType :: new ( type_of:: type_of ( ccx, ty) ,
204
- type_of:: sizing_type_of ( ccx, ty) )
206
+ let mut arg = ArgType :: new ( type_of:: type_of ( ccx, ty) ,
207
+ type_of:: sizing_type_of ( ccx, ty) ) ;
208
+ if llsize_of_real ( ccx, arg. ty ) == 0 {
209
+ arg. ignore ( ) ;
210
+ }
211
+ arg
205
212
}
206
213
} ;
207
214
208
- let mut ret = match sig. output {
209
- ty:: FnConverging ( ret_ty) if !return_type_is_void ( ccx, ret_ty) => {
210
- arg_of ( ret_ty)
211
- }
212
- _ => ArgType :: new ( Type :: void ( ccx) , Type :: void ( ccx) )
215
+ let ret_ty = match sig. output {
216
+ ty:: FnConverging ( ret_ty) => ret_ty,
217
+ ty:: FnDiverging => ccx. tcx ( ) . mk_nil ( )
213
218
} ;
219
+ let mut ret = arg_of ( ret_ty) ;
220
+
221
+ if !type_is_fat_ptr ( ccx. tcx ( ) , ret_ty) {
222
+ // The `noalias` attribute on the return value is useful to a
223
+ // function ptr caller.
224
+ if let ty:: TyBox ( _) = ret_ty. sty {
225
+ // `Box` pointer return values never alias because ownership
226
+ // is transferred
227
+ ret. attrs . set ( llvm:: Attribute :: NoAlias ) ;
228
+ }
214
229
215
- if let ty:: FnConverging ( ret_ty) = sig. output {
216
- if !type_is_fat_ptr ( ccx. tcx ( ) , ret_ty) {
217
- // The `noalias` attribute on the return value is useful to a
218
- // function ptr caller.
219
- if let ty:: TyBox ( _) = ret_ty. sty {
220
- // `Box` pointer return values never alias because ownership
221
- // is transferred
222
- ret. attrs . set ( llvm:: Attribute :: NoAlias ) ;
223
- }
224
-
225
- // We can also mark the return value as `dereferenceable` in certain cases
226
- match ret_ty. sty {
227
- // These are not really pointers but pairs, (pointer, len)
228
- ty:: TyRef ( _, ty:: TypeAndMut { ty, .. } ) |
229
- ty:: TyBox ( ty) => {
230
- let llty = type_of:: sizing_type_of ( ccx, ty) ;
231
- let llsz = llsize_of_real ( ccx, llty) ;
232
- ret. attrs . set_dereferenceable ( llsz) ;
233
- }
234
- _ => { }
230
+ // We can also mark the return value as `dereferenceable` in certain cases
231
+ match ret_ty. sty {
232
+ // These are not really pointers but pairs, (pointer, len)
233
+ ty:: TyRef ( _, ty:: TypeAndMut { ty, .. } ) |
234
+ ty:: TyBox ( ty) => {
235
+ let llty = type_of:: sizing_type_of ( ccx, ty) ;
236
+ let llsz = llsize_of_real ( ccx, llty) ;
237
+ ret. attrs . set_dereferenceable ( llsz) ;
235
238
}
239
+ _ => { }
236
240
}
237
241
}
238
242
@@ -318,8 +322,8 @@ impl FnType {
318
322
// Scalars and vectors, always immediate.
319
323
return ;
320
324
}
321
- let size = llsize_of_alloc ( ccx, arg. ty ) ;
322
- if size > llsize_of_alloc ( ccx, ccx. int_type ( ) ) {
325
+ let size = llsize_of_real ( ccx, arg. ty ) ;
326
+ if size > llsize_of_real ( ccx, ccx. int_type ( ) ) {
323
327
arg. make_indirect ( ccx) ;
324
328
} else if size > 0 {
325
329
// We want to pass small aggregates as immediates, but using
@@ -376,7 +380,9 @@ impl FnType {
376
380
pub fn llvm_type ( & self , ccx : & CrateContext ) -> Type {
377
381
let mut llargument_tys = Vec :: new ( ) ;
378
382
379
- let llreturn_ty = if self . ret . is_indirect ( ) {
383
+ let llreturn_ty = if self . ret . is_ignore ( ) {
384
+ Type :: void ( ccx)
385
+ } else if self . ret . is_indirect ( ) {
380
386
llargument_tys. push ( self . ret . original_ty . ptr_to ( ) ) ;
381
387
Type :: void ( ccx)
382
388
} else {
@@ -410,7 +416,9 @@ impl FnType {
410
416
411
417
pub fn apply_attrs_llfn ( & self , llfn : ValueRef ) {
412
418
let mut i = if self . ret . is_indirect ( ) { 1 } else { 0 } ;
413
- self . ret . attrs . apply_llfn ( i, llfn) ;
419
+ if !self . ret . is_ignore ( ) {
420
+ self . ret . attrs . apply_llfn ( i, llfn) ;
421
+ }
414
422
i += 1 ;
415
423
for arg in & self . args {
416
424
if !arg. is_ignore ( ) {
@@ -423,7 +431,9 @@ impl FnType {
423
431
424
432
pub fn apply_attrs_callsite ( & self , callsite : ValueRef ) {
425
433
let mut i = if self . ret . is_indirect ( ) { 1 } else { 0 } ;
426
- self . ret . attrs . apply_callsite ( i, callsite) ;
434
+ if !self . ret . is_ignore ( ) {
435
+ self . ret . attrs . apply_callsite ( i, callsite) ;
436
+ }
427
437
i += 1 ;
428
438
for arg in & self . args {
429
439
if !arg. is_ignore ( ) {
0 commit comments