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,65 @@ 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 > ( 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) ) ;
87
82
}
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 ) ) ;
90
88
}
91
89
}
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) ;
92
102
}
93
103
94
104
fn apply_attrs_to_callsite (
@@ -97,52 +107,8 @@ impl ArgAttributesExt for ArgAttributes {
97
107
cx : & CodegenCx < ' _ , ' _ > ,
98
108
callsite : & Value ,
99
109
) {
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) ;
146
112
}
147
113
}
148
114
@@ -444,15 +410,14 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
444
410
}
445
411
446
412
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 ( ) ;
448
414
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 ) ) ;
450
416
}
451
-
452
- // FIXME(eddyb, wesleywiser): apply this to callsites as well?
453
417
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 ) ) ;
455
419
}
420
+ attributes:: apply_to_llfn ( llfn, llvm:: AttributePlace :: Function , & { func_attrs } ) ;
456
421
457
422
let mut i = 0 ;
458
423
let mut apply = |attrs : & ArgAttributes | {
@@ -467,13 +432,8 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
467
432
PassMode :: Indirect { ref attrs, extra_attrs : _, on_stack } => {
468
433
assert ! ( !on_stack) ;
469
434
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] ) ;
477
437
}
478
438
PassMode :: Cast ( cast) => {
479
439
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>> {
488
448
PassMode :: Ignore => { }
489
449
PassMode :: Indirect { ref attrs, extra_attrs : None , on_stack : true } => {
490
450
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] ) ;
498
453
}
499
454
PassMode :: Direct ( ref attrs)
500
455
| 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>> {
517
472
}
518
473
519
474
fn apply_attrs_callsite ( & self , bx : & mut Builder < ' _ , ' ll , ' tcx > , callsite : & ' ll Value ) {
475
+ let mut func_attrs = SmallVec :: < [ _ ; 2 ] > :: new ( ) ;
520
476
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 ) ) ;
522
478
}
523
479
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 ) ) ;
525
481
}
482
+ attributes:: apply_to_callsite ( callsite, llvm:: AttributePlace :: Function , & { func_attrs } ) ;
526
483
527
484
let mut i = 0 ;
528
485
let mut apply = |cx : & CodegenCx < ' _ , ' _ > , attrs : & ArgAttributes | {
@@ -537,13 +494,8 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
537
494
PassMode :: Indirect { ref attrs, extra_attrs : _, on_stack } => {
538
495
assert ! ( !on_stack) ;
539
496
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] ) ;
547
499
}
548
500
PassMode :: Cast ( cast) => {
549
501
cast. attrs . apply_attrs_to_callsite (
@@ -572,13 +524,12 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
572
524
PassMode :: Ignore => { }
573
525
PassMode :: Indirect { ref attrs, extra_attrs : None , on_stack : true } => {
574
526
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
+ ) ;
582
533
}
583
534
PassMode :: Direct ( ref attrs)
584
535
| 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>> {
610
561
if self . conv == Conv :: CCmseNonSecureCall {
611
562
// This will probably get ignored on all targets but those supporting the TrustZone-M
612
563
// 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 (
614
567
callsite,
615
568
llvm:: AttributePlace :: Function ,
616
- cstr :: cstr! ( " cmse_nonsecure_call" ) ,
569
+ & [ cmse_nonsecure_call] ,
617
570
) ;
618
571
}
619
572
}
0 commit comments