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,68 @@ 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 > (
55+ this : & ArgAttributes ,
56+ cx : & CodegenCx < ' ll , ' _ > ,
57+ ) -> SmallVec < impl smallvec:: Array < Item = & ' ll Attribute > > {
58+ let mut regular = this. regular ;
59+
60+ let mut attrs = SmallVec :: < [ _ ; 8 ] > :: new ( ) ;
61+
62+ // ABI-affecting attributes must always be applied
63+ for ( attr, llattr) in ABI_AFFECTING_ATTRIBUTES {
64+ if regular. contains ( attr) {
65+ attrs. push ( llattr. create_attr ( cx. llcx ) ) ;
66+ }
67+ }
68+ if let Some ( align) = this. pointee_align {
69+ attrs. push ( llvm:: CreateAlignmentAttr ( cx. llcx , align. bytes ( ) ) ) ;
70+ }
71+ match this. arg_ext {
72+ ArgExtension :: None => { }
73+ ArgExtension :: Zext => attrs. push ( llvm:: AttributeKind :: ZExt . create_attr ( cx. llcx ) ) ,
74+ ArgExtension :: Sext => attrs. push ( llvm:: AttributeKind :: SExt . create_attr ( cx. llcx ) ) ,
75+ }
76+
77+ // Only apply remaining attributes when optimizing
78+ if cx. sess ( ) . opts . optimize != config:: OptLevel :: No {
79+ let deref = this. pointee_size . bytes ( ) ;
80+ if deref != 0 {
81+ if regular. contains ( ArgAttribute :: NonNull ) {
82+ attrs. push ( llvm:: CreateDereferenceableAttr ( cx. llcx , deref) ) ;
83+ } else {
84+ attrs. push ( llvm:: CreateDereferenceableOrNullAttr ( cx. llcx , deref) ) ;
8785 }
88- if regular. contains ( ArgAttribute :: NoAliasMutRef ) && should_use_mutable_noalias ( cx) {
89- llvm:: Attribute :: NoAlias . apply_llfn ( idx, llfn) ;
86+ regular -= ArgAttribute :: NonNull ;
87+ }
88+ for ( attr, llattr) in OPTIMIZATION_ATTRIBUTES {
89+ if regular. contains ( attr) {
90+ attrs. push ( llattr. create_attr ( cx. llcx ) ) ;
9091 }
9192 }
93+ if regular. contains ( ArgAttribute :: NoAliasMutRef ) && should_use_mutable_noalias ( cx) {
94+ attrs. push ( llvm:: AttributeKind :: NoAlias . create_attr ( cx. llcx ) ) ;
95+ }
96+ }
97+
98+ attrs
99+ }
100+
101+ impl ArgAttributesExt for ArgAttributes {
102+ fn apply_attrs_to_llfn ( & self , idx : AttributePlace , cx : & CodegenCx < ' _ , ' _ > , llfn : & Value ) {
103+ let attrs = get_attrs ( self , cx) ;
104+ attributes:: apply_to_llfn ( llfn, idx, & attrs) ;
92105 }
93106
94107 fn apply_attrs_to_callsite (
@@ -97,52 +110,8 @@ impl ArgAttributesExt for ArgAttributes {
97110 cx : & CodegenCx < ' _ , ' _ > ,
98111 callsite : & Value ,
99112 ) {
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- }
113+ let attrs = get_attrs ( self , cx) ;
114+ attributes:: apply_to_callsite ( callsite, idx, & attrs) ;
146115 }
147116}
148117
@@ -444,15 +413,14 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
444413 }
445414
446415 fn apply_attrs_llfn ( & self , cx : & CodegenCx < ' ll , ' tcx > , llfn : & ' ll Value ) {
447- // FIXME(eddyb) can this also be applied to callsites?
416+ let mut func_attrs = SmallVec :: < [ _ ; 2 ] > :: new ( ) ;
448417 if self . ret . layout . abi . is_uninhabited ( ) {
449- llvm:: Attribute :: NoReturn . apply_llfn ( llvm :: AttributePlace :: Function , llfn ) ;
418+ func_attrs . push ( llvm:: AttributeKind :: NoReturn . create_attr ( cx . llcx ) ) ;
450419 }
451-
452- // FIXME(eddyb, wesleywiser): apply this to callsites as well?
453420 if !self . can_unwind {
454- llvm:: Attribute :: NoUnwind . apply_llfn ( llvm :: AttributePlace :: Function , llfn ) ;
421+ func_attrs . push ( llvm:: AttributeKind :: NoUnwind . create_attr ( cx . llcx ) ) ;
455422 }
423+ attributes:: apply_to_llfn ( llfn, llvm:: AttributePlace :: Function , & { func_attrs } ) ;
456424
457425 let mut i = 0 ;
458426 let mut apply = |attrs : & ArgAttributes | {
@@ -467,13 +435,8 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
467435 PassMode :: Indirect { ref attrs, extra_attrs : _, on_stack } => {
468436 assert ! ( !on_stack) ;
469437 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- }
438+ let sret = llvm:: CreateStructRetAttr ( cx. llcx , self . ret . layout . llvm_type ( cx) ) ;
439+ attributes:: apply_to_llfn ( llfn, llvm:: AttributePlace :: Argument ( i) , & [ sret] ) ;
477440 }
478441 PassMode :: Cast ( cast) => {
479442 cast. attrs . apply_attrs_to_llfn ( llvm:: AttributePlace :: ReturnValue , cx, llfn) ;
@@ -488,13 +451,8 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
488451 PassMode :: Ignore => { }
489452 PassMode :: Indirect { ref attrs, extra_attrs : None , on_stack : true } => {
490453 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- }
454+ let byval = llvm:: CreateByValAttr ( cx. llcx , arg. layout . llvm_type ( cx) ) ;
455+ attributes:: apply_to_llfn ( llfn, llvm:: AttributePlace :: Argument ( i) , & [ byval] ) ;
498456 }
499457 PassMode :: Direct ( ref attrs)
500458 | PassMode :: Indirect { ref attrs, extra_attrs : None , on_stack : false } => {
@@ -517,12 +475,14 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
517475 }
518476
519477 fn apply_attrs_callsite ( & self , bx : & mut Builder < ' _ , ' ll , ' tcx > , callsite : & ' ll Value ) {
478+ let mut func_attrs = SmallVec :: < [ _ ; 2 ] > :: new ( ) ;
520479 if self . ret . layout . abi . is_uninhabited ( ) {
521- llvm:: Attribute :: NoReturn . apply_callsite ( llvm :: AttributePlace :: Function , callsite ) ;
480+ func_attrs . push ( llvm:: AttributeKind :: NoReturn . create_attr ( bx . cx . llcx ) ) ;
522481 }
523482 if !self . can_unwind {
524- llvm:: Attribute :: NoUnwind . apply_callsite ( llvm :: AttributePlace :: Function , callsite ) ;
483+ func_attrs . push ( llvm:: AttributeKind :: NoUnwind . create_attr ( bx . cx . llcx ) ) ;
525484 }
485+ attributes:: apply_to_callsite ( callsite, llvm:: AttributePlace :: Function , & { func_attrs } ) ;
526486
527487 let mut i = 0 ;
528488 let mut apply = |cx : & CodegenCx < ' _ , ' _ > , attrs : & ArgAttributes | {
@@ -537,13 +497,8 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
537497 PassMode :: Indirect { ref attrs, extra_attrs : _, on_stack } => {
538498 assert ! ( !on_stack) ;
539499 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- }
500+ let sret = llvm:: CreateStructRetAttr ( bx. cx . llcx , self . ret . layout . llvm_type ( bx) ) ;
501+ attributes:: apply_to_callsite ( callsite, llvm:: AttributePlace :: Argument ( i) , & [ sret] ) ;
547502 }
548503 PassMode :: Cast ( cast) => {
549504 cast. attrs . apply_attrs_to_callsite (
@@ -572,13 +527,12 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
572527 PassMode :: Ignore => { }
573528 PassMode :: Indirect { ref attrs, extra_attrs : None , on_stack : true } => {
574529 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- }
530+ let byval = llvm:: CreateByValAttr ( bx. cx . llcx , arg. layout . llvm_type ( bx) ) ;
531+ attributes:: apply_to_callsite (
532+ callsite,
533+ llvm:: AttributePlace :: Argument ( i) ,
534+ & [ byval] ,
535+ ) ;
582536 }
583537 PassMode :: Direct ( ref attrs)
584538 | PassMode :: Indirect { ref attrs, extra_attrs : None , on_stack : false } => {
@@ -610,10 +564,12 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
610564 if self . conv == Conv :: CCmseNonSecureCall {
611565 // This will probably get ignored on all targets but those supporting the TrustZone-M
612566 // extension (thumbv8m targets).
613- llvm:: AddCallSiteAttrString (
567+ let cmse_nonsecure_call =
568+ llvm:: CreateAttrString ( bx. cx . llcx , cstr:: cstr!( "cmse_nonsecure_call" ) ) ;
569+ attributes:: apply_to_callsite (
614570 callsite,
615571 llvm:: AttributePlace :: Function ,
616- cstr :: cstr! ( " cmse_nonsecure_call" ) ,
572+ & [ cmse_nonsecure_call] ,
617573 ) ;
618574 }
619575 }
0 commit comments