11use rustc_errors:: DiagCtxtHandle ;
22use rustc_hir as hir;
33use rustc_hir:: HirId ;
4+ use rustc_middle:: bug;
45use rustc_middle:: ty:: layout:: LayoutError ;
56use rustc_middle:: ty:: { self , ParamEnv , TyCtxt } ;
6- use rustc_span:: Span ;
77use rustc_target:: spec:: abi;
88
99use crate :: errors;
@@ -18,49 +18,90 @@ pub fn validate_cmse_abi<'tcx>(
1818 abi : abi:: Abi ,
1919 fn_sig : ty:: PolyFnSig < ' tcx > ,
2020) {
21- if let abi:: Abi :: CCmseNonSecureCall = abi {
22- let hir_node = tcx. hir_node ( hir_id) ;
23- let hir:: Node :: Ty ( hir:: Ty {
24- span : bare_fn_span,
25- kind : hir:: TyKind :: BareFn ( bare_fn_ty) ,
26- ..
27- } ) = hir_node
28- else {
29- // might happen when this ABI is used incorrectly. That will be handled elsewhere
30- return ;
31- } ;
32-
33- match is_valid_cmse_inputs ( tcx, fn_sig) {
34- Ok ( Ok ( ( ) ) ) => { }
35- Ok ( Err ( index) ) => {
36- // fn(x: u32, u32, u32, u16, y: u16) -> u32,
37- // ^^^^^^
38- let span = bare_fn_ty. param_names [ index]
39- . span
40- . to ( bare_fn_ty. decl . inputs [ index] . span )
41- . to ( bare_fn_ty. decl . inputs . last ( ) . unwrap ( ) . span ) ;
42- let plural = bare_fn_ty. param_names . len ( ) - index != 1 ;
43- dcx. emit_err ( errors:: CmseCallInputsStackSpill { span, plural } ) ;
44- }
45- Err ( layout_err) => {
46- if let Some ( err) = cmse_layout_err ( layout_err, * bare_fn_span) {
47- dcx. emit_err ( err) ;
21+ let abi_name = abi. name ( ) ;
22+
23+ match abi {
24+ abi:: Abi :: CCmseNonSecureCall => {
25+ let hir_node = tcx. hir_node ( hir_id) ;
26+ let hir:: Node :: Ty ( hir:: Ty {
27+ span : bare_fn_span,
28+ kind : hir:: TyKind :: BareFn ( bare_fn_ty) ,
29+ ..
30+ } ) = hir_node
31+ else {
32+ // might happen when this ABI is used incorrectly. That will be handled elsewhere
33+ return ;
34+ } ;
35+
36+ match is_valid_cmse_inputs ( tcx, fn_sig) {
37+ Ok ( Ok ( ( ) ) ) => { }
38+ Ok ( Err ( index) ) => {
39+ // fn(x: u32, u32, u32, u16, y: u16) -> u32,
40+ // ^^^^^^
41+ let span = bare_fn_ty. param_names [ index]
42+ . span
43+ . to ( bare_fn_ty. decl . inputs [ index] . span )
44+ . to ( bare_fn_ty. decl . inputs . last ( ) . unwrap ( ) . span ) ;
45+ let plural = bare_fn_ty. param_names . len ( ) - index != 1 ;
46+ dcx. emit_err ( errors:: CmseInputsStackSpill { span, plural, abi_name } ) ;
47+ }
48+ Err ( layout_err) => {
49+ if should_emit_generic_error ( abi, layout_err) {
50+ dcx. emit_err ( errors:: CmseCallGeneric { span : * bare_fn_span } ) ;
51+ }
4852 }
4953 }
50- }
5154
52- match is_valid_cmse_output ( tcx, fn_sig) {
53- Ok ( true ) => { }
54- Ok ( false ) => {
55- let span = bare_fn_ty. decl . output . span ( ) ;
56- dcx. emit_err ( errors:: CmseCallOutputStackSpill { span } ) ;
57- }
58- Err ( layout_err) => {
59- if let Some ( err) = cmse_layout_err ( layout_err, * bare_fn_span) {
60- dcx. emit_err ( err) ;
55+ match is_valid_cmse_output ( tcx, fn_sig) {
56+ Ok ( true ) => { }
57+ Ok ( false ) => {
58+ let span = bare_fn_ty. decl . output . span ( ) ;
59+ dcx. emit_err ( errors:: CmseOutputStackSpill { span, 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+ }
65+ }
66+ } ;
67+ }
68+ abi:: Abi :: CCmseNonSecureEntry => {
69+ let hir_node = tcx. hir_node ( hir_id) ;
70+ let Some ( hir:: FnSig { decl, span : fn_sig_span, .. } ) = hir_node. fn_sig ( ) else {
71+ // might happen when this ABI is used incorrectly. That will be handled elsewhere
72+ return ;
73+ } ;
74+
75+ match is_valid_cmse_inputs ( tcx, fn_sig) {
76+ Ok ( Ok ( ( ) ) ) => { }
77+ Ok ( Err ( index) ) => {
78+ // fn f(x: u32, y: u32, z: u32, w: u16, q: u16) -> u32,
79+ // ^^^^^^
80+ let span = decl. inputs [ index] . span . to ( decl. inputs . last ( ) . unwrap ( ) . span ) ;
81+ let plural = decl. inputs . len ( ) - index != 1 ;
82+ dcx. emit_err ( errors:: CmseInputsStackSpill { span, plural, abi_name } ) ;
83+ }
84+ Err ( layout_err) => {
85+ if should_emit_generic_error ( abi, layout_err) {
86+ dcx. emit_err ( errors:: CmseEntryGeneric { span : * fn_sig_span } ) ;
87+ }
6188 }
6289 }
63- } ;
90+
91+ match is_valid_cmse_output ( tcx, fn_sig) {
92+ Ok ( true ) => { }
93+ Ok ( false ) => {
94+ let span = decl. output . span ( ) ;
95+ dcx. emit_err ( errors:: CmseOutputStackSpill { span, 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+ }
101+ }
102+ } ;
103+ }
104+ _ => ( ) ,
64105 }
65106}
66107
@@ -135,22 +176,22 @@ fn is_valid_cmse_output<'tcx>(
135176 Ok ( ret_ty == tcx. types . i64 || ret_ty == tcx. types . u64 || ret_ty == tcx. types . f64 )
136177}
137178
138- fn cmse_layout_err < ' tcx > (
139- layout_err : & ' tcx LayoutError < ' tcx > ,
140- span : Span ,
141- ) -> Option < crate :: errors:: CmseCallGeneric > {
179+ fn should_emit_generic_error < ' tcx > ( abi : abi:: Abi , layout_err : & ' tcx LayoutError < ' tcx > ) -> bool {
142180 use LayoutError :: * ;
143181
144182 match layout_err {
145183 Unknown ( ty) => {
146- if ty. is_impl_trait ( ) {
147- None // prevent double reporting of this error
148- } else {
149- Some ( errors:: CmseCallGeneric { span } )
184+ match abi {
185+ abi:: Abi :: CCmseNonSecureCall => {
186+ // prevent double reporting of this error
187+ !ty. is_impl_trait ( )
188+ }
189+ abi:: Abi :: CCmseNonSecureEntry => true ,
190+ _ => bug ! ( "invalid ABI: {abi}" ) ,
150191 }
151192 }
152193 SizeOverflow ( ..) | NormalizationFailure ( ..) | ReferencesError ( ..) | Cycle ( ..) => {
153- None // not our job to report these
194+ false // not our job to report these
154195 }
155196 }
156197}
0 commit comments