1
+ use crate :: attributes;
1
2
use crate :: builder:: Builder ;
2
3
use crate :: context:: CodegenCx ;
3
- use crate :: llvm:: { self , AttributePlace } ;
4
+ use crate :: llvm:: { self , Attribute , AttributePlace } ;
4
5
use crate :: type_:: Type ;
5
6
use crate :: type_of:: LayoutLlvmExt ;
6
7
use crate :: value:: Value ;
@@ -20,6 +21,7 @@ use rustc_target::abi::{self, HasDataLayout, Int};
20
21
pub use rustc_target:: spec:: abi:: Abi ;
21
22
22
23
use libc:: c_uint;
24
+ use smallvec:: SmallVec ;
23
25
24
26
pub trait ArgAttributesExt {
25
27
fn apply_attrs_to_llfn ( & self , idx : AttributePlace , cx : & CodegenCx < ' _ , ' _ > , llfn : & Value ) ;
@@ -38,57 +40,68 @@ fn should_use_mutable_noalias(cx: &CodegenCx<'_, '_>) -> bool {
38
40
cx. tcx . sess . opts . debugging_opts . mutable_noalias . unwrap_or ( true )
39
41
}
40
42
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 ) ] ;
43
45
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 ) ,
50
52
] ;
51
53
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) ) ;
87
85
}
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 ) ) ;
90
91
}
91
92
}
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) ;
92
105
}
93
106
94
107
fn apply_attrs_to_callsite (
@@ -97,52 +110,8 @@ impl ArgAttributesExt for ArgAttributes {
97
110
cx : & CodegenCx < ' _ , ' _ > ,
98
111
callsite : & Value ,
99
112
) {
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) ;
146
115
}
147
116
}
148
117
@@ -444,15 +413,14 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
444
413
}
445
414
446
415
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 ( ) ;
448
417
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 ) ) ;
450
419
}
451
-
452
- // FIXME(eddyb, wesleywiser): apply this to callsites as well?
453
420
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 ) ) ;
455
422
}
423
+ attributes:: apply_to_llfn ( llfn, llvm:: AttributePlace :: Function , & { func_attrs } ) ;
456
424
457
425
let mut i = 0 ;
458
426
let mut apply = |attrs : & ArgAttributes | {
@@ -467,13 +435,8 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
467
435
PassMode :: Indirect { ref attrs, extra_attrs : _, on_stack } => {
468
436
assert ! ( !on_stack) ;
469
437
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] ) ;
477
440
}
478
441
PassMode :: Cast ( cast) => {
479
442
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>> {
488
451
PassMode :: Ignore => { }
489
452
PassMode :: Indirect { ref attrs, extra_attrs : None , on_stack : true } => {
490
453
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] ) ;
498
456
}
499
457
PassMode :: Direct ( ref attrs)
500
458
| 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>> {
517
475
}
518
476
519
477
fn apply_attrs_callsite ( & self , bx : & mut Builder < ' _ , ' ll , ' tcx > , callsite : & ' ll Value ) {
478
+ let mut func_attrs = SmallVec :: < [ _ ; 2 ] > :: new ( ) ;
520
479
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 ) ) ;
522
481
}
523
482
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 ) ) ;
525
484
}
485
+ attributes:: apply_to_callsite ( callsite, llvm:: AttributePlace :: Function , & { func_attrs } ) ;
526
486
527
487
let mut i = 0 ;
528
488
let mut apply = |cx : & CodegenCx < ' _ , ' _ > , attrs : & ArgAttributes | {
@@ -537,13 +497,8 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
537
497
PassMode :: Indirect { ref attrs, extra_attrs : _, on_stack } => {
538
498
assert ! ( !on_stack) ;
539
499
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] ) ;
547
502
}
548
503
PassMode :: Cast ( cast) => {
549
504
cast. attrs . apply_attrs_to_callsite (
@@ -572,13 +527,12 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
572
527
PassMode :: Ignore => { }
573
528
PassMode :: Indirect { ref attrs, extra_attrs : None , on_stack : true } => {
574
529
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
+ ) ;
582
536
}
583
537
PassMode :: Direct ( ref attrs)
584
538
| 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>> {
610
564
if self . conv == Conv :: CCmseNonSecureCall {
611
565
// This will probably get ignored on all targets but those supporting the TrustZone-M
612
566
// 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 (
614
570
callsite,
615
571
llvm:: AttributePlace :: Function ,
616
- cstr :: cstr! ( " cmse_nonsecure_call" ) ,
572
+ & [ cmse_nonsecure_call] ,
617
573
) ;
618
574
}
619
575
}
0 commit comments