10
10
11
11
pub use self :: ArgKind :: * ;
12
12
13
- use llvm:: { self , AttrHelper , ValueRef } ;
14
- use trans:: attributes;
13
+ use llvm;
15
14
use trans:: common:: { return_type_is_void, type_is_fat_ptr} ;
16
15
use trans:: context:: CrateContext ;
17
16
use trans:: cabi_x86;
@@ -23,7 +22,7 @@ use trans::cabi_powerpc;
23
22
use trans:: cabi_powerpc64;
24
23
use trans:: cabi_mips;
25
24
use trans:: cabi_asmjs;
26
- use trans:: machine:: llsize_of_alloc;
25
+ use trans:: machine:: { llsize_of_alloc, llsize_of_real } ;
27
26
use trans:: type_:: Type ;
28
27
use trans:: type_of;
29
28
@@ -191,6 +190,13 @@ impl FnType {
191
190
cconv : cconv
192
191
} ;
193
192
193
+ // Add ZExt attributes to i1 arguments and returns.
194
+ for arg in Some ( & mut fty. ret ) . into_iter ( ) . chain ( & mut fty. args ) {
195
+ if arg. ty == Type :: i1 ( ccx) {
196
+ arg. attr = Some ( llvm:: Attribute :: ZExt ) ;
197
+ }
198
+ }
199
+
194
200
if abi == Rust || abi == RustCall {
195
201
let fixup = |arg : & mut ArgType | {
196
202
if !arg. ty . is_aggregate ( ) {
@@ -246,7 +252,7 @@ impl FnType {
246
252
fty
247
253
}
248
254
249
- pub fn to_llvm ( & self , ccx : & CrateContext ) -> Type {
255
+ pub fn llvm_type ( & self , ccx : & CrateContext ) -> Type {
250
256
let mut llargument_tys = Vec :: new ( ) ;
251
257
252
258
let llreturn_ty = if self . ret . is_indirect ( ) {
@@ -281,19 +287,29 @@ impl FnType {
281
287
}
282
288
}
283
289
284
- pub fn add_attributes ( & self , llfn : ValueRef ) {
285
- let mut i = if self . ret . is_indirect ( ) {
286
- 1
287
- } else {
288
- 0
290
+ pub fn llvm_attrs ( & self , ccx : & CrateContext ) -> llvm:: AttrBuilder {
291
+ let mut attrs = llvm:: AttrBuilder :: new ( ) ;
292
+ let mut i = if self . ret . is_indirect ( ) { 1 } else { 0 } ;
293
+
294
+ // Add attributes that are always applicable, independent of the concrete foreign ABI
295
+ if self . ret . is_indirect ( ) {
296
+ let llret_sz = llsize_of_real ( ccx, self . ret . ty ) ;
297
+
298
+ // The outptr can be noalias and nocapture because it's entirely
299
+ // invisible to the program. We also know it's nonnull as well
300
+ // as how many bytes we can dereference
301
+ attrs. arg ( i, llvm:: Attribute :: StructRet )
302
+ . arg ( i, llvm:: Attribute :: NoAlias )
303
+ . arg ( i, llvm:: Attribute :: NoCapture )
304
+ . arg ( i, llvm:: DereferenceableAttribute ( llret_sz) ) ;
289
305
} ;
290
306
307
+ // Add attributes that depend on the concrete foreign ABI
291
308
if let Some ( attr) = self . ret . attr {
292
- attr . apply_llfn ( i, llfn ) ;
309
+ attrs . arg ( i, attr ) ;
293
310
}
294
311
295
312
i += 1 ;
296
-
297
313
for arg in & self . args {
298
314
if arg. is_ignore ( ) {
299
315
continue ;
@@ -302,12 +318,12 @@ impl FnType {
302
318
if arg. pad . is_some ( ) { i += 1 ; }
303
319
304
320
if let Some ( attr) = arg. attr {
305
- attr . apply_llfn ( i, llfn ) ;
321
+ attrs . arg ( i, attr ) ;
306
322
}
307
323
308
324
i += 1 ;
309
325
}
310
326
311
- attributes :: unwind ( llfn , false ) ;
327
+ attrs
312
328
}
313
329
}
0 commit comments