@@ -27,7 +27,14 @@ use smallvec::SmallVec;
27
27
use std:: cmp;
28
28
29
29
pub trait ArgAttributesExt {
30
- fn apply_attrs_to_llfn ( & self , idx : AttributePlace , cx : & CodegenCx < ' _ , ' _ > , llfn : & Value ) ;
30
+ fn apply_attrs_to_llfn (
31
+ & self ,
32
+ idx : AttributePlace ,
33
+ cx : & CodegenCx < ' _ , ' _ > ,
34
+ llfn : & Value ,
35
+ is_foreign_fn : bool ,
36
+ force_set_align : bool ,
37
+ ) ;
31
38
fn apply_attrs_to_callsite (
32
39
& self ,
33
40
idx : AttributePlace ,
@@ -47,7 +54,16 @@ const OPTIMIZATION_ATTRIBUTES: [(ArgAttribute, llvm::AttributeKind); 5] = [
47
54
( ArgAttribute :: NoUndef , llvm:: AttributeKind :: NoUndef ) ,
48
55
] ;
49
56
50
- fn get_attrs < ' ll > ( this : & ArgAttributes , cx : & CodegenCx < ' ll , ' _ > ) -> SmallVec < [ & ' ll Attribute ; 8 ] > {
57
+ /// `is_foreign_fn_decl` indicates whether the attributes should be computed for a foreign function declaration,
58
+ /// where we emit non-essential attributes.
59
+ /// See <https://github.com/rust-lang/rust/issues/46188> for background and discussion.
60
+ /// `force_set_align` indicates whether the alignment is ABI-relevant.
61
+ fn get_attrs < ' ll > (
62
+ this : & ArgAttributes ,
63
+ cx : & CodegenCx < ' ll , ' _ > ,
64
+ is_foreign_fn_decl : bool ,
65
+ force_set_align : bool ,
66
+ ) -> SmallVec < [ & ' ll Attribute ; 8 ] > {
51
67
let mut regular = this. regular ;
52
68
53
69
let mut attrs = SmallVec :: new ( ) ;
@@ -58,15 +74,31 @@ fn get_attrs<'ll>(this: &ArgAttributes, cx: &CodegenCx<'ll, '_>) -> SmallVec<[&'
58
74
attrs. push ( llattr. create_attr ( cx. llcx ) ) ;
59
75
}
60
76
}
61
- if let Some ( align) = this. pointee_align {
62
- attrs. push ( llvm:: CreateAlignmentAttr ( cx. llcx , align. bytes ( ) ) ) ;
77
+ if force_set_align {
78
+ if let Some ( align) = this. pointee_align {
79
+ attrs. push ( llvm:: CreateAlignmentAttr ( cx. llcx , align. bytes ( ) ) ) ;
80
+ }
63
81
}
64
82
match this. arg_ext {
65
83
ArgExtension :: None => { }
66
84
ArgExtension :: Zext => attrs. push ( llvm:: AttributeKind :: ZExt . create_attr ( cx. llcx ) ) ,
67
85
ArgExtension :: Sext => attrs. push ( llvm:: AttributeKind :: SExt . create_attr ( cx. llcx ) ) ,
68
86
}
69
87
88
+ // For foreign function declarations, this is it.
89
+ if is_foreign_fn_decl {
90
+ return attrs;
91
+ }
92
+
93
+ // If we didn't add alignment yet, do it now.
94
+ // HACK: this should really be inside the "only if optimizations" below,
95
+ // but to avoid tedious codegen test changes, we have it here.
96
+ if !force_set_align {
97
+ if let Some ( align) = this. pointee_align {
98
+ attrs. push ( llvm:: CreateAlignmentAttr ( cx. llcx , align. bytes ( ) ) ) ;
99
+ }
100
+ }
101
+
70
102
// Only apply remaining attributes when optimizing
71
103
if cx. sess ( ) . opts . optimize != config:: OptLevel :: No {
72
104
let deref = this. pointee_size . bytes ( ) ;
@@ -96,8 +128,15 @@ fn get_attrs<'ll>(this: &ArgAttributes, cx: &CodegenCx<'ll, '_>) -> SmallVec<[&'
96
128
}
97
129
98
130
impl ArgAttributesExt for ArgAttributes {
99
- fn apply_attrs_to_llfn ( & self , idx : AttributePlace , cx : & CodegenCx < ' _ , ' _ > , llfn : & Value ) {
100
- let attrs = get_attrs ( self , cx) ;
131
+ fn apply_attrs_to_llfn (
132
+ & self ,
133
+ idx : AttributePlace ,
134
+ cx : & CodegenCx < ' _ , ' _ > ,
135
+ llfn : & Value ,
136
+ is_foreign_fn : bool ,
137
+ force_set_align : bool ,
138
+ ) {
139
+ let attrs = get_attrs ( self , cx, is_foreign_fn, force_set_align) ;
101
140
attributes:: apply_to_llfn ( llfn, idx, & attrs) ;
102
141
}
103
142
@@ -107,7 +146,10 @@ impl ArgAttributesExt for ArgAttributes {
107
146
cx : & CodegenCx < ' _ , ' _ > ,
108
147
callsite : & Value ,
109
148
) {
110
- let attrs = get_attrs ( self , cx) ;
149
+ // It's not a declaration at all, so in particular not a foreign function declaration.
150
+ // We also don't need to force setting the alignment.
151
+ let attrs =
152
+ get_attrs ( self , cx, /*is_foreign_fn_decl*/ false , /*force_set_align*/ false ) ;
111
153
attributes:: apply_to_callsite ( callsite, idx, & attrs) ;
112
154
}
113
155
}
@@ -310,7 +352,7 @@ pub trait FnAbiLlvmExt<'ll, 'tcx> {
310
352
fn llvm_type ( & self , cx : & CodegenCx < ' ll , ' tcx > ) -> & ' ll Type ;
311
353
fn ptr_to_llvm_type ( & self , cx : & CodegenCx < ' ll , ' tcx > ) -> & ' ll Type ;
312
354
fn llvm_cconv ( & self ) -> llvm:: CallConv ;
313
- fn apply_attrs_llfn ( & self , cx : & CodegenCx < ' ll , ' tcx > , llfn : & ' ll Value ) ;
355
+ fn apply_attrs_llfn ( & self , cx : & CodegenCx < ' ll , ' tcx > , llfn : & ' ll Value , is_foreign_fn : bool ) ;
314
356
fn apply_attrs_callsite ( & self , bx : & mut Builder < ' _ , ' ll , ' tcx > , callsite : & ' ll Value ) ;
315
357
}
316
358
@@ -396,32 +438,46 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
396
438
self . conv . into ( )
397
439
}
398
440
399
- fn apply_attrs_llfn ( & self , cx : & CodegenCx < ' ll , ' tcx > , llfn : & ' ll Value ) {
441
+ fn apply_attrs_llfn ( & self , cx : & CodegenCx < ' ll , ' tcx > , llfn : & ' ll Value , is_foreign_fn : bool ) {
400
442
let mut func_attrs = SmallVec :: < [ _ ; 3 ] > :: new ( ) ;
401
- if self . ret . layout . abi . is_uninhabited ( ) {
402
- func_attrs. push ( llvm:: AttributeKind :: NoReturn . create_attr ( cx. llcx ) ) ;
403
- }
404
- if !self . can_unwind {
405
- func_attrs. push ( llvm:: AttributeKind :: NoUnwind . create_attr ( cx. llcx ) ) ;
443
+ if !is_foreign_fn {
444
+ if self . ret . layout . abi . is_uninhabited ( ) {
445
+ func_attrs. push ( llvm:: AttributeKind :: NoReturn . create_attr ( cx. llcx ) ) ;
446
+ }
447
+ if !self . can_unwind {
448
+ func_attrs. push ( llvm:: AttributeKind :: NoUnwind . create_attr ( cx. llcx ) ) ;
449
+ }
406
450
}
407
451
if let Conv :: RiscvInterrupt { kind } = self . conv {
408
452
func_attrs. push ( llvm:: CreateAttrStringValue ( cx. llcx , "interrupt" , kind. as_str ( ) ) ) ;
409
453
}
410
454
attributes:: apply_to_llfn ( llfn, llvm:: AttributePlace :: Function , & { func_attrs } ) ;
411
455
412
456
let mut i = 0 ;
413
- let mut apply = |attrs : & ArgAttributes | {
414
- attrs. apply_attrs_to_llfn ( llvm:: AttributePlace :: Argument ( i) , cx, llfn) ;
457
+ let mut apply_next_arg = |attrs : & ArgAttributes , force_set_align : bool | {
458
+ attrs. apply_attrs_to_llfn (
459
+ llvm:: AttributePlace :: Argument ( i) ,
460
+ cx,
461
+ llfn,
462
+ is_foreign_fn,
463
+ force_set_align,
464
+ ) ;
415
465
i += 1 ;
416
466
i - 1
417
467
} ;
418
468
match & self . ret . mode {
419
469
PassMode :: Direct ( attrs) => {
420
- attrs. apply_attrs_to_llfn ( llvm:: AttributePlace :: ReturnValue , cx, llfn) ;
470
+ attrs. apply_attrs_to_llfn (
471
+ llvm:: AttributePlace :: ReturnValue ,
472
+ cx,
473
+ llfn,
474
+ is_foreign_fn,
475
+ /*force_set_align*/ false ,
476
+ ) ;
421
477
}
422
478
PassMode :: Indirect { attrs, meta_attrs : _, on_stack } => {
423
479
assert ! ( !on_stack) ;
424
- let i = apply ( attrs) ;
480
+ let i = apply_next_arg ( attrs, /*force_set_align*/ false ) ;
425
481
let sret = llvm:: CreateStructRetAttr (
426
482
cx. llcx ,
427
483
cx. type_array ( cx. type_i8 ( ) , self . ret . layout . size . bytes ( ) ) ,
@@ -441,15 +497,21 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
441
497
}
442
498
}
443
499
PassMode :: Cast { cast, pad_i32 : _ } => {
444
- cast. attrs . apply_attrs_to_llfn ( llvm:: AttributePlace :: ReturnValue , cx, llfn) ;
500
+ cast. attrs . apply_attrs_to_llfn (
501
+ llvm:: AttributePlace :: ReturnValue ,
502
+ cx,
503
+ llfn,
504
+ is_foreign_fn,
505
+ /*force_set_align*/ false ,
506
+ ) ;
445
507
}
446
508
_ => { }
447
509
}
448
510
for arg in self . args . iter ( ) {
449
511
match & arg. mode {
450
512
PassMode :: Ignore => { }
451
513
PassMode :: Indirect { attrs, meta_attrs : None , on_stack : true } => {
452
- let i = apply ( attrs) ;
514
+ let i = apply_next_arg ( attrs, /*force_set_align*/ true ) ;
453
515
let byval = llvm:: CreateByValAttr (
454
516
cx. llcx ,
455
517
cx. type_array ( cx. type_i8 ( ) , arg. layout . size . bytes ( ) ) ,
@@ -458,22 +520,22 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
458
520
}
459
521
PassMode :: Direct ( attrs)
460
522
| PassMode :: Indirect { attrs, meta_attrs : None , on_stack : false } => {
461
- apply ( attrs) ;
523
+ apply_next_arg ( attrs, /*force_set_align*/ false ) ;
462
524
}
463
525
PassMode :: Indirect { attrs, meta_attrs : Some ( meta_attrs) , on_stack } => {
464
526
assert ! ( !on_stack) ;
465
- apply ( attrs) ;
466
- apply ( meta_attrs) ;
527
+ apply_next_arg ( attrs, /*force_set_align*/ false ) ;
528
+ apply_next_arg ( meta_attrs, /*force_set_align*/ false ) ;
467
529
}
468
530
PassMode :: Pair ( a, b) => {
469
- apply ( a ) ;
470
- apply ( b ) ;
531
+ apply_next_arg ( a , /*force_set_align*/ false ) ;
532
+ apply_next_arg ( b , /*force_set_align*/ false ) ;
471
533
}
472
534
PassMode :: Cast { cast, pad_i32 } => {
473
535
if * pad_i32 {
474
- apply ( & ArgAttributes :: new ( ) ) ;
536
+ apply_next_arg ( & ArgAttributes :: new ( ) , /*force_set_align*/ false ) ;
475
537
}
476
- apply ( & cast. attrs ) ;
538
+ apply_next_arg ( & cast. attrs , /*force_set_align*/ false ) ;
477
539
}
478
540
}
479
541
}
0 commit comments