1
1
use rustc_errors:: { DiagCtxtHandle , E0781 , struct_span_code_err} ;
2
2
use rustc_hir:: { self as hir, HirId } ;
3
+ use rustc_middle:: bug;
3
4
use rustc_middle:: ty:: layout:: LayoutError ;
4
5
use rustc_middle:: ty:: { self , ParamEnv , TyCtxt } ;
5
- use rustc_span:: Span ;
6
6
use rustc_target:: spec:: abi;
7
7
8
8
use crate :: errors;
@@ -17,61 +17,104 @@ pub(crate) fn validate_cmse_abi<'tcx>(
17
17
abi : abi:: Abi ,
18
18
fn_sig : ty:: PolyFnSig < ' tcx > ,
19
19
) {
20
- if let abi:: Abi :: CCmseNonSecureCall = abi {
21
- let hir_node = tcx. hir_node ( hir_id) ;
22
- let hir:: Node :: Ty ( hir:: Ty {
23
- span : bare_fn_span,
24
- kind : hir:: TyKind :: BareFn ( bare_fn_ty) ,
25
- ..
26
- } ) = hir_node
27
- else {
28
- let span = match tcx. parent_hir_node ( hir_id) {
29
- hir:: Node :: Item ( hir:: Item {
30
- kind : hir:: ItemKind :: ForeignMod { .. } , span, ..
31
- } ) => * span,
32
- _ => tcx. hir ( ) . span ( hir_id) ,
20
+ let abi_name = abi. name ( ) ;
21
+
22
+ match abi {
23
+ abi:: Abi :: CCmseNonSecureCall => {
24
+ let hir_node = tcx. hir_node ( hir_id) ;
25
+ let hir:: Node :: Ty ( hir:: Ty {
26
+ span : bare_fn_span,
27
+ kind : hir:: TyKind :: BareFn ( bare_fn_ty) ,
28
+ ..
29
+ } ) = hir_node
30
+ else {
31
+ let span = match tcx. parent_hir_node ( hir_id) {
32
+ hir:: Node :: Item ( hir:: Item {
33
+ kind : hir:: ItemKind :: ForeignMod { .. } ,
34
+ span,
35
+ ..
36
+ } ) => * span,
37
+ _ => tcx. hir ( ) . span ( hir_id) ,
38
+ } ;
39
+ struct_span_code_err ! (
40
+ tcx. dcx( ) ,
41
+ span,
42
+ E0781 ,
43
+ "the `\" C-cmse-nonsecure-call\" ` ABI is only allowed on function pointers"
44
+ )
45
+ . emit ( ) ;
46
+ return ;
33
47
} ;
34
- struct_span_code_err ! (
35
- tcx. dcx( ) ,
36
- span,
37
- E0781 ,
38
- "the `\" C-cmse-nonsecure-call\" ` ABI is only allowed on function pointers"
39
- )
40
- . emit ( ) ;
41
- return ;
42
- } ;
43
48
44
- match is_valid_cmse_inputs ( tcx, fn_sig) {
45
- Ok ( Ok ( ( ) ) ) => { }
46
- Ok ( Err ( index) ) => {
47
- // fn(x: u32, u32, u32, u16, y: u16) -> u32,
48
- // ^^^^^^
49
- let span = bare_fn_ty. param_names [ index]
50
- . span
51
- . to ( bare_fn_ty. decl . inputs [ index] . span )
52
- . to ( bare_fn_ty. decl . inputs . last ( ) . unwrap ( ) . span ) ;
53
- let plural = bare_fn_ty. param_names . len ( ) - index != 1 ;
54
- dcx. emit_err ( errors:: CmseCallInputsStackSpill { span, plural } ) ;
55
- }
56
- Err ( layout_err) => {
57
- if let Some ( err) = cmse_layout_err ( layout_err, * bare_fn_span) {
58
- dcx. emit_err ( err) ;
49
+ match is_valid_cmse_inputs ( tcx, fn_sig) {
50
+ Ok ( Ok ( ( ) ) ) => { }
51
+ Ok ( Err ( index) ) => {
52
+ // fn(x: u32, u32, u32, u16, y: u16) -> u32,
53
+ // ^^^^^^
54
+ let span = bare_fn_ty. param_names [ index]
55
+ . span
56
+ . to ( bare_fn_ty. decl . inputs [ index] . span )
57
+ . to ( bare_fn_ty. decl . inputs . last ( ) . unwrap ( ) . span ) ;
58
+ let plural = bare_fn_ty. param_names . len ( ) - index != 1 ;
59
+ dcx. emit_err ( errors:: CmseInputsStackSpill { span, plural, abi_name } ) ;
60
+ }
61
+ Err ( layout_err) => {
62
+ if should_emit_generic_error ( abi, layout_err) {
63
+ dcx. emit_err ( errors:: CmseCallGeneric { span : * bare_fn_span } ) ;
64
+ }
59
65
}
60
66
}
67
+
68
+ match is_valid_cmse_output ( tcx, fn_sig) {
69
+ Ok ( true ) => { }
70
+ Ok ( false ) => {
71
+ let span = bare_fn_ty. decl . output . span ( ) ;
72
+ dcx. emit_err ( errors:: CmseOutputStackSpill { span, abi_name } ) ;
73
+ }
74
+ Err ( layout_err) => {
75
+ if should_emit_generic_error ( abi, layout_err) {
76
+ dcx. emit_err ( errors:: CmseCallGeneric { span : * bare_fn_span } ) ;
77
+ }
78
+ }
79
+ } ;
61
80
}
81
+ abi:: Abi :: CCmseNonSecureEntry => {
82
+ let hir_node = tcx. hir_node ( hir_id) ;
83
+ let Some ( hir:: FnSig { decl, span : fn_sig_span, .. } ) = hir_node. fn_sig ( ) else {
84
+ // might happen when this ABI is used incorrectly. That will be handled elsewhere
85
+ return ;
86
+ } ;
62
87
63
- match is_valid_cmse_output ( tcx, fn_sig) {
64
- Ok ( true ) => { }
65
- Ok ( false ) => {
66
- let span = bare_fn_ty. decl . output . span ( ) ;
67
- dcx. emit_err ( errors:: CmseCallOutputStackSpill { span } ) ;
68
- }
69
- Err ( layout_err) => {
70
- if let Some ( err) = cmse_layout_err ( layout_err, * bare_fn_span) {
71
- dcx. emit_err ( err) ;
88
+ match is_valid_cmse_inputs ( tcx, fn_sig) {
89
+ Ok ( Ok ( ( ) ) ) => { }
90
+ Ok ( Err ( index) ) => {
91
+ // fn f(x: u32, y: u32, z: u32, w: u16, q: u16) -> u32,
92
+ // ^^^^^^
93
+ let span = decl. inputs [ index] . span . to ( decl. inputs . last ( ) . unwrap ( ) . span ) ;
94
+ let plural = decl. inputs . len ( ) - index != 1 ;
95
+ dcx. emit_err ( errors:: CmseInputsStackSpill { span, plural, abi_name } ) ;
96
+ }
97
+ Err ( layout_err) => {
98
+ if should_emit_generic_error ( abi, layout_err) {
99
+ dcx. emit_err ( errors:: CmseEntryGeneric { span : * fn_sig_span } ) ;
100
+ }
72
101
}
73
102
}
74
- } ;
103
+
104
+ match is_valid_cmse_output ( tcx, fn_sig) {
105
+ Ok ( true ) => { }
106
+ Ok ( false ) => {
107
+ let span = decl. output . span ( ) ;
108
+ dcx. emit_err ( errors:: CmseOutputStackSpill { span, abi_name } ) ;
109
+ }
110
+ Err ( layout_err) => {
111
+ if should_emit_generic_error ( abi, layout_err) {
112
+ dcx. emit_err ( errors:: CmseEntryGeneric { span : * fn_sig_span } ) ;
113
+ }
114
+ }
115
+ } ;
116
+ }
117
+ _ => ( ) ,
75
118
}
76
119
}
77
120
@@ -152,22 +195,22 @@ fn is_valid_cmse_output<'tcx>(
152
195
Ok ( ret_ty == tcx. types . i64 || ret_ty == tcx. types . u64 || ret_ty == tcx. types . f64 )
153
196
}
154
197
155
- fn cmse_layout_err < ' tcx > (
156
- layout_err : & ' tcx LayoutError < ' tcx > ,
157
- span : Span ,
158
- ) -> Option < crate :: errors:: CmseCallGeneric > {
198
+ fn should_emit_generic_error < ' tcx > ( abi : abi:: Abi , layout_err : & ' tcx LayoutError < ' tcx > ) -> bool {
159
199
use LayoutError :: * ;
160
200
161
201
match layout_err {
162
202
Unknown ( ty) => {
163
- if ty. is_impl_trait ( ) {
164
- None // prevent double reporting of this error
165
- } else {
166
- Some ( errors:: CmseCallGeneric { span } )
203
+ match abi {
204
+ abi:: Abi :: CCmseNonSecureCall => {
205
+ // prevent double reporting of this error
206
+ !ty. is_impl_trait ( )
207
+ }
208
+ abi:: Abi :: CCmseNonSecureEntry => true ,
209
+ _ => bug ! ( "invalid ABI: {abi}" ) ,
167
210
}
168
211
}
169
212
SizeOverflow ( ..) | NormalizationFailure ( ..) | ReferencesError ( ..) | Cycle ( ..) => {
170
- None // not our job to report these
213
+ false // not our job to report these
171
214
}
172
215
}
173
216
}
0 commit comments