1+ use crate :: attributes;
12use crate :: builder:: Builder ;
23use crate :: context:: CodegenCx ;
3- use crate :: llvm:: { self , AttributePlace } ;
4+ use crate :: llvm:: { self , Attribute , AttributePlace } ;
45use crate :: type_:: Type ;
56use crate :: type_of:: LayoutLlvmExt ;
67use crate :: value:: Value ;
@@ -20,6 +21,7 @@ use rustc_target::abi::{self, HasDataLayout, Int};
2021pub use rustc_target:: spec:: abi:: Abi ;
2122
2223use libc:: c_uint;
24+ use smallvec:: SmallVec ;
2325
2426pub trait ArgAttributesExt {
2527 fn apply_attrs_to_llfn ( & self , idx : AttributePlace , cx : & CodegenCx < ' _ , ' _ > , llfn : & Value ) ;
@@ -38,57 +40,65 @@ fn should_use_mutable_noalias(cx: &CodegenCx<'_, '_>) -> bool {
3840 cx. tcx . sess . opts . debugging_opts . mutable_noalias . unwrap_or ( true )
3941}
4042
41- const ABI_AFFECTING_ATTRIBUTES : [ ( ArgAttribute , llvm:: Attribute ) ; 1 ] =
42- [ ( ArgAttribute :: InReg , llvm:: Attribute :: InReg ) ] ;
43+ const ABI_AFFECTING_ATTRIBUTES : [ ( ArgAttribute , llvm:: AttributeKind ) ; 1 ] =
44+ [ ( ArgAttribute :: InReg , llvm:: AttributeKind :: InReg ) ] ;
4345
44- const OPTIMIZATION_ATTRIBUTES : [ ( ArgAttribute , llvm:: Attribute ) ; 5 ] = [
45- ( ArgAttribute :: NoAlias , llvm:: Attribute :: NoAlias ) ,
46- ( ArgAttribute :: NoCapture , llvm:: Attribute :: NoCapture ) ,
47- ( ArgAttribute :: NonNull , llvm:: Attribute :: NonNull ) ,
48- ( ArgAttribute :: ReadOnly , llvm:: Attribute :: ReadOnly ) ,
49- ( ArgAttribute :: NoUndef , llvm:: Attribute :: NoUndef ) ,
46+ const OPTIMIZATION_ATTRIBUTES : [ ( ArgAttribute , llvm:: AttributeKind ) ; 5 ] = [
47+ ( ArgAttribute :: NoAlias , llvm:: AttributeKind :: NoAlias ) ,
48+ ( ArgAttribute :: NoCapture , llvm:: AttributeKind :: NoCapture ) ,
49+ ( ArgAttribute :: NonNull , llvm:: AttributeKind :: NonNull ) ,
50+ ( ArgAttribute :: ReadOnly , llvm:: AttributeKind :: ReadOnly ) ,
51+ ( ArgAttribute :: NoUndef , llvm:: AttributeKind :: NoUndef ) ,
5052] ;
5153
52- impl ArgAttributesExt for ArgAttributes {
53- fn apply_attrs_to_llfn ( & self , idx : AttributePlace , cx : & CodegenCx < ' _ , ' _ > , llfn : & Value ) {
54- let mut regular = self . regular ;
55- unsafe {
56- // ABI-affecting attributes must always be applied
57- for ( attr, llattr) in ABI_AFFECTING_ATTRIBUTES {
58- if regular. contains ( attr) {
59- llattr. apply_llfn ( idx, llfn) ;
60- }
61- }
62- if let Some ( align) = self . pointee_align {
63- llvm:: LLVMRustAddAlignmentAttr ( llfn, idx. as_uint ( ) , align. bytes ( ) as u32 ) ;
64- }
65- match self . arg_ext {
66- ArgExtension :: None => { }
67- ArgExtension :: Zext => llvm:: Attribute :: ZExt . apply_llfn ( idx, llfn) ,
68- ArgExtension :: Sext => llvm:: Attribute :: SExt . apply_llfn ( idx, llfn) ,
69- }
70- // Only apply remaining attributes when optimizing
71- if cx. sess ( ) . opts . optimize == config:: OptLevel :: No {
72- return ;
73- }
74- let deref = self . pointee_size . bytes ( ) ;
75- if deref != 0 {
76- if regular. contains ( ArgAttribute :: NonNull ) {
77- llvm:: LLVMRustAddDereferenceableAttr ( llfn, idx. as_uint ( ) , deref) ;
78- } else {
79- llvm:: LLVMRustAddDereferenceableOrNullAttr ( llfn, idx. as_uint ( ) , deref) ;
80- }
81- regular -= ArgAttribute :: NonNull ;
82- }
83- for ( attr, llattr) in OPTIMIZATION_ATTRIBUTES {
84- if regular. contains ( attr) {
85- llattr. apply_llfn ( idx, llfn) ;
86- }
54+ fn get_attrs < ' ll > ( this : & ArgAttributes , cx : & CodegenCx < ' ll , ' _ > ) -> SmallVec < [ & ' ll Attribute ; 8 ] > {
55+ let mut regular = this. regular ;
56+
57+ let mut attrs = SmallVec :: new ( ) ;
58+
59+ // ABI-affecting attributes must always be applied
60+ for ( attr, llattr) in ABI_AFFECTING_ATTRIBUTES {
61+ if regular. contains ( attr) {
62+ attrs. push ( llattr. create_attr ( cx. llcx ) ) ;
63+ }
64+ }
65+ if let Some ( align) = this. pointee_align {
66+ attrs. push ( llvm:: CreateAlignmentAttr ( cx. llcx , align. bytes ( ) ) ) ;
67+ }
68+ match this. arg_ext {
69+ ArgExtension :: None => { }
70+ ArgExtension :: Zext => attrs. push ( llvm:: AttributeKind :: ZExt . create_attr ( cx. llcx ) ) ,
71+ ArgExtension :: Sext => attrs. push ( llvm:: AttributeKind :: SExt . create_attr ( cx. llcx ) ) ,
72+ }
73+
74+ // Only apply remaining attributes when optimizing
75+ if cx. sess ( ) . opts . optimize != config:: OptLevel :: No {
76+ let deref = this. pointee_size . bytes ( ) ;
77+ if deref != 0 {
78+ if regular. contains ( ArgAttribute :: NonNull ) {
79+ attrs. push ( llvm:: CreateDereferenceableAttr ( cx. llcx , deref) ) ;
80+ } else {
81+ attrs. push ( llvm:: CreateDereferenceableOrNullAttr ( cx. llcx , deref) ) ;
8782 }
88- if regular. contains ( ArgAttribute :: NoAliasMutRef ) && should_use_mutable_noalias ( cx) {
89- llvm:: Attribute :: NoAlias . apply_llfn ( idx, llfn) ;
83+ regular -= ArgAttribute :: NonNull ;
84+ }
85+ for ( attr, llattr) in OPTIMIZATION_ATTRIBUTES {
86+ if regular. contains ( attr) {
87+ attrs. push ( llattr. create_attr ( cx. llcx ) ) ;
9088 }
9189 }
90+ if regular. contains ( ArgAttribute :: NoAliasMutRef ) && should_use_mutable_noalias ( cx) {
91+ attrs. push ( llvm:: AttributeKind :: NoAlias . create_attr ( cx. llcx ) ) ;
92+ }
93+ }
94+
95+ attrs
96+ }
97+
98+ impl ArgAttributesExt for ArgAttributes {
99+ fn apply_attrs_to_llfn ( & self , idx : AttributePlace , cx : & CodegenCx < ' _ , ' _ > , llfn : & Value ) {
100+ let attrs = get_attrs ( self , cx) ;
101+ attributes:: apply_to_llfn ( llfn, idx, & attrs) ;
92102 }
93103
94104 fn apply_attrs_to_callsite (
@@ -97,52 +107,8 @@ impl ArgAttributesExt for ArgAttributes {
97107 cx : & CodegenCx < ' _ , ' _ > ,
98108 callsite : & Value ,
99109 ) {
100- let mut regular = self . regular ;
101- unsafe {
102- // ABI-affecting attributes must always be applied
103- for ( attr, llattr) in ABI_AFFECTING_ATTRIBUTES {
104- if regular. contains ( attr) {
105- llattr. apply_callsite ( idx, callsite) ;
106- }
107- }
108- if let Some ( align) = self . pointee_align {
109- llvm:: LLVMRustAddAlignmentCallSiteAttr (
110- callsite,
111- idx. as_uint ( ) ,
112- align. bytes ( ) as u32 ,
113- ) ;
114- }
115- match self . arg_ext {
116- ArgExtension :: None => { }
117- ArgExtension :: Zext => llvm:: Attribute :: ZExt . apply_callsite ( idx, callsite) ,
118- ArgExtension :: Sext => llvm:: Attribute :: SExt . apply_callsite ( idx, callsite) ,
119- }
120- // Only apply remaining attributes when optimizing
121- if cx. sess ( ) . opts . optimize == config:: OptLevel :: No {
122- return ;
123- }
124- let deref = self . pointee_size . bytes ( ) ;
125- if deref != 0 {
126- if regular. contains ( ArgAttribute :: NonNull ) {
127- llvm:: LLVMRustAddDereferenceableCallSiteAttr ( callsite, idx. as_uint ( ) , deref) ;
128- } else {
129- llvm:: LLVMRustAddDereferenceableOrNullCallSiteAttr (
130- callsite,
131- idx. as_uint ( ) ,
132- deref,
133- ) ;
134- }
135- regular -= ArgAttribute :: NonNull ;
136- }
137- for ( attr, llattr) in OPTIMIZATION_ATTRIBUTES {
138- if regular. contains ( attr) {
139- llattr. apply_callsite ( idx, callsite) ;
140- }
141- }
142- if regular. contains ( ArgAttribute :: NoAliasMutRef ) && should_use_mutable_noalias ( cx) {
143- llvm:: Attribute :: NoAlias . apply_callsite ( idx, callsite) ;
144- }
145- }
110+ let attrs = get_attrs ( self , cx) ;
111+ attributes:: apply_to_callsite ( callsite, idx, & attrs) ;
146112 }
147113}
148114
@@ -444,15 +410,14 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
444410 }
445411
446412 fn apply_attrs_llfn ( & self , cx : & CodegenCx < ' ll , ' tcx > , llfn : & ' ll Value ) {
447- // FIXME(eddyb) can this also be applied to callsites?
413+ let mut func_attrs = SmallVec :: < [ _ ; 2 ] > :: new ( ) ;
448414 if self . ret . layout . abi . is_uninhabited ( ) {
449- llvm:: Attribute :: NoReturn . apply_llfn ( llvm :: AttributePlace :: Function , llfn ) ;
415+ func_attrs . push ( llvm:: AttributeKind :: NoReturn . create_attr ( cx . llcx ) ) ;
450416 }
451-
452- // FIXME(eddyb, wesleywiser): apply this to callsites as well?
453417 if !self . can_unwind {
454- llvm:: Attribute :: NoUnwind . apply_llfn ( llvm :: AttributePlace :: Function , llfn ) ;
418+ func_attrs . push ( llvm:: AttributeKind :: NoUnwind . create_attr ( cx . llcx ) ) ;
455419 }
420+ attributes:: apply_to_llfn ( llfn, llvm:: AttributePlace :: Function , & { func_attrs } ) ;
456421
457422 let mut i = 0 ;
458423 let mut apply = |attrs : & ArgAttributes | {
@@ -467,13 +432,8 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
467432 PassMode :: Indirect { ref attrs, extra_attrs : _, on_stack } => {
468433 assert ! ( !on_stack) ;
469434 let i = apply ( attrs) ;
470- unsafe {
471- llvm:: LLVMRustAddStructRetAttr (
472- llfn,
473- llvm:: AttributePlace :: Argument ( i) . as_uint ( ) ,
474- self . ret . layout . llvm_type ( cx) ,
475- ) ;
476- }
435+ let sret = llvm:: CreateStructRetAttr ( cx. llcx , self . ret . layout . llvm_type ( cx) ) ;
436+ attributes:: apply_to_llfn ( llfn, llvm:: AttributePlace :: Argument ( i) , & [ sret] ) ;
477437 }
478438 PassMode :: Cast ( cast) => {
479439 cast. attrs . apply_attrs_to_llfn ( llvm:: AttributePlace :: ReturnValue , cx, llfn) ;
@@ -488,13 +448,8 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
488448 PassMode :: Ignore => { }
489449 PassMode :: Indirect { ref attrs, extra_attrs : None , on_stack : true } => {
490450 let i = apply ( attrs) ;
491- unsafe {
492- llvm:: LLVMRustAddByValAttr (
493- llfn,
494- llvm:: AttributePlace :: Argument ( i) . as_uint ( ) ,
495- arg. layout . llvm_type ( cx) ,
496- ) ;
497- }
451+ let byval = llvm:: CreateByValAttr ( cx. llcx , arg. layout . llvm_type ( cx) ) ;
452+ attributes:: apply_to_llfn ( llfn, llvm:: AttributePlace :: Argument ( i) , & [ byval] ) ;
498453 }
499454 PassMode :: Direct ( ref attrs)
500455 | PassMode :: Indirect { ref attrs, extra_attrs : None , on_stack : false } => {
@@ -517,12 +472,14 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
517472 }
518473
519474 fn apply_attrs_callsite ( & self , bx : & mut Builder < ' _ , ' ll , ' tcx > , callsite : & ' ll Value ) {
475+ let mut func_attrs = SmallVec :: < [ _ ; 2 ] > :: new ( ) ;
520476 if self . ret . layout . abi . is_uninhabited ( ) {
521- llvm:: Attribute :: NoReturn . apply_callsite ( llvm :: AttributePlace :: Function , callsite ) ;
477+ func_attrs . push ( llvm:: AttributeKind :: NoReturn . create_attr ( bx . cx . llcx ) ) ;
522478 }
523479 if !self . can_unwind {
524- llvm:: Attribute :: NoUnwind . apply_callsite ( llvm :: AttributePlace :: Function , callsite ) ;
480+ func_attrs . push ( llvm:: AttributeKind :: NoUnwind . create_attr ( bx . cx . llcx ) ) ;
525481 }
482+ attributes:: apply_to_callsite ( callsite, llvm:: AttributePlace :: Function , & { func_attrs } ) ;
526483
527484 let mut i = 0 ;
528485 let mut apply = |cx : & CodegenCx < ' _ , ' _ > , attrs : & ArgAttributes | {
@@ -537,13 +494,8 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
537494 PassMode :: Indirect { ref attrs, extra_attrs : _, on_stack } => {
538495 assert ! ( !on_stack) ;
539496 let i = apply ( bx. cx , attrs) ;
540- unsafe {
541- llvm:: LLVMRustAddStructRetCallSiteAttr (
542- callsite,
543- llvm:: AttributePlace :: Argument ( i) . as_uint ( ) ,
544- self . ret . layout . llvm_type ( bx) ,
545- ) ;
546- }
497+ let sret = llvm:: CreateStructRetAttr ( bx. cx . llcx , self . ret . layout . llvm_type ( bx) ) ;
498+ attributes:: apply_to_callsite ( callsite, llvm:: AttributePlace :: Argument ( i) , & [ sret] ) ;
547499 }
548500 PassMode :: Cast ( cast) => {
549501 cast. attrs . apply_attrs_to_callsite (
@@ -572,13 +524,12 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
572524 PassMode :: Ignore => { }
573525 PassMode :: Indirect { ref attrs, extra_attrs : None , on_stack : true } => {
574526 let i = apply ( bx. cx , attrs) ;
575- unsafe {
576- llvm:: LLVMRustAddByValCallSiteAttr (
577- callsite,
578- llvm:: AttributePlace :: Argument ( i) . as_uint ( ) ,
579- arg. layout . llvm_type ( bx) ,
580- ) ;
581- }
527+ let byval = llvm:: CreateByValAttr ( bx. cx . llcx , arg. layout . llvm_type ( bx) ) ;
528+ attributes:: apply_to_callsite (
529+ callsite,
530+ llvm:: AttributePlace :: Argument ( i) ,
531+ & [ byval] ,
532+ ) ;
582533 }
583534 PassMode :: Direct ( ref attrs)
584535 | PassMode :: Indirect { ref attrs, extra_attrs : None , on_stack : false } => {
@@ -610,10 +561,12 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
610561 if self . conv == Conv :: CCmseNonSecureCall {
611562 // This will probably get ignored on all targets but those supporting the TrustZone-M
612563 // extension (thumbv8m targets).
613- llvm:: AddCallSiteAttrString (
564+ let cmse_nonsecure_call =
565+ llvm:: CreateAttrString ( bx. cx . llcx , cstr:: cstr!( "cmse_nonsecure_call" ) ) ;
566+ attributes:: apply_to_callsite (
614567 callsite,
615568 llvm:: AttributePlace :: Function ,
616- cstr :: cstr! ( " cmse_nonsecure_call" ) ,
569+ & [ cmse_nonsecure_call] ,
617570 ) ;
618571 }
619572 }
0 commit comments