@@ -27,7 +27,14 @@ use smallvec::SmallVec;
2727use std:: cmp;
2828
2929pub 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+ ) ;
3138 fn apply_attrs_to_callsite (
3239 & self ,
3340 idx : AttributePlace ,
@@ -47,7 +54,16 @@ const OPTIMIZATION_ATTRIBUTES: [(ArgAttribute, llvm::AttributeKind); 5] = [
4754 ( ArgAttribute :: NoUndef , llvm:: AttributeKind :: NoUndef ) ,
4855] ;
4956
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 ] > {
5167 let mut regular = this. regular ;
5268
5369 let mut attrs = SmallVec :: new ( ) ;
@@ -58,15 +74,31 @@ fn get_attrs<'ll>(this: &ArgAttributes, cx: &CodegenCx<'ll, '_>) -> SmallVec<[&'
5874 attrs. push ( llattr. create_attr ( cx. llcx ) ) ;
5975 }
6076 }
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+ }
6381 }
6482 match this. arg_ext {
6583 ArgExtension :: None => { }
6684 ArgExtension :: Zext => attrs. push ( llvm:: AttributeKind :: ZExt . create_attr ( cx. llcx ) ) ,
6785 ArgExtension :: Sext => attrs. push ( llvm:: AttributeKind :: SExt . create_attr ( cx. llcx ) ) ,
6886 }
6987
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+
70102 // Only apply remaining attributes when optimizing
71103 if cx. sess ( ) . opts . optimize != config:: OptLevel :: No {
72104 let deref = this. pointee_size . bytes ( ) ;
@@ -96,8 +128,15 @@ fn get_attrs<'ll>(this: &ArgAttributes, cx: &CodegenCx<'ll, '_>) -> SmallVec<[&'
96128}
97129
98130impl 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) ;
101140 attributes:: apply_to_llfn ( llfn, idx, & attrs) ;
102141 }
103142
@@ -107,7 +146,10 @@ impl ArgAttributesExt for ArgAttributes {
107146 cx : & CodegenCx < ' _ , ' _ > ,
108147 callsite : & Value ,
109148 ) {
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 ) ;
111153 attributes:: apply_to_callsite ( callsite, idx, & attrs) ;
112154 }
113155}
@@ -310,7 +352,7 @@ pub trait FnAbiLlvmExt<'ll, 'tcx> {
310352 fn llvm_type ( & self , cx : & CodegenCx < ' ll , ' tcx > ) -> & ' ll Type ;
311353 fn ptr_to_llvm_type ( & self , cx : & CodegenCx < ' ll , ' tcx > ) -> & ' ll Type ;
312354 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 ) ;
314356 fn apply_attrs_callsite ( & self , bx : & mut Builder < ' _ , ' ll , ' tcx > , callsite : & ' ll Value ) ;
315357}
316358
@@ -396,32 +438,46 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
396438 self . conv . into ( )
397439 }
398440
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 ) {
400442 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+ }
406450 }
407451 if let Conv :: RiscvInterrupt { kind } = self . conv {
408452 func_attrs. push ( llvm:: CreateAttrStringValue ( cx. llcx , "interrupt" , kind. as_str ( ) ) ) ;
409453 }
410454 attributes:: apply_to_llfn ( llfn, llvm:: AttributePlace :: Function , & { func_attrs } ) ;
411455
412456 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+ ) ;
415465 i += 1 ;
416466 i - 1
417467 } ;
418468 match & self . ret . mode {
419469 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+ ) ;
421477 }
422478 PassMode :: Indirect { attrs, meta_attrs : _, on_stack } => {
423479 assert ! ( !on_stack) ;
424- let i = apply ( attrs) ;
480+ let i = apply_next_arg ( attrs, /*force_set_align*/ false ) ;
425481 let sret = llvm:: CreateStructRetAttr (
426482 cx. llcx ,
427483 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>> {
441497 }
442498 }
443499 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+ ) ;
445507 }
446508 _ => { }
447509 }
448510 for arg in self . args . iter ( ) {
449511 match & arg. mode {
450512 PassMode :: Ignore => { }
451513 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 ) ;
453515 let byval = llvm:: CreateByValAttr (
454516 cx. llcx ,
455517 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>> {
458520 }
459521 PassMode :: Direct ( attrs)
460522 | PassMode :: Indirect { attrs, meta_attrs : None , on_stack : false } => {
461- apply ( attrs) ;
523+ apply_next_arg ( attrs, /*force_set_align*/ false ) ;
462524 }
463525 PassMode :: Indirect { attrs, meta_attrs : Some ( meta_attrs) , on_stack } => {
464526 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 ) ;
467529 }
468530 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 ) ;
471533 }
472534 PassMode :: Cast { cast, pad_i32 } => {
473535 if * pad_i32 {
474- apply ( & ArgAttributes :: new ( ) ) ;
536+ apply_next_arg ( & ArgAttributes :: new ( ) , /*force_set_align*/ false ) ;
475537 }
476- apply ( & cast. attrs ) ;
538+ apply_next_arg ( & cast. attrs , /*force_set_align*/ false ) ;
477539 }
478540 }
479541 }
0 commit comments