about summary refs log tree commit diff
diff options
context:
space:
mode:
authorFolkert <folkert@folkertdev.nl>2024-07-18 14:32:10 +0200
committerFolkert <folkert@folkertdev.nl>2024-07-18 14:32:10 +0200
commitc2894a4297fd1e824e071fd21a92bfe475c0169a (patch)
treea9c5c4c52d9f3d478858d0caedefeec2c354c908
parent6b6b8422bafe310b911832119cbcf4d93f46871e (diff)
downloadrust-c2894a4297fd1e824e071fd21a92bfe475c0169a.tar.gz
rust-c2894a4297fd1e824e071fd21a92bfe475c0169a.zip
improve error reporting
-rw-r--r--compiler/rustc_hir_analysis/messages.ftl8
-rw-r--r--compiler/rustc_hir_analysis/src/errors.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs50
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs2
-rw-r--r--tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.stderr8
-rw-r--r--tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-via-stack.rs10
-rw-r--r--tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-via-stack.stderr20
-rw-r--r--tests/ui/cmse-nonsecure/cmse-nonsecure-call/return-via-stack.stderr9
8 files changed, 65 insertions, 46 deletions
diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index 83618041133..9e5fa37de32 100644
--- a/compiler/rustc_hir_analysis/messages.ftl
+++ b/compiler/rustc_hir_analysis/messages.ftl
@@ -63,13 +63,17 @@ hir_analysis_cmse_call_generic =
 
 hir_analysis_cmse_call_inputs_stack_spill =
     arguments for `"C-cmse-nonsecure-call"` function too large to pass via registers
-    .label = these arguments don't fit in the available registers
+    .label = {$plural ->
+        [false] this argument doesn't
+        *[true] these arguments don't
+    } fit in the available registers
     .note = functions with the `"C-cmse-nonsecure-call"` ABI must pass all their arguments via the 4 32-bit available argument registers
 
 hir_analysis_cmse_call_output_stack_spill =
     return value of `"C-cmse-nonsecure-call"` function too large to pass via registers
     .label = this type doesn't fit in the available registers
-    .note = functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers
+    .note1 = functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers
+    .note2 = the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
 
 hir_analysis_coerce_unsized_may = the trait `{$trait_name}` may only be implemented for a coercion between structures
 
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index f6783364f16..a77f967a5ca 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -1690,11 +1690,13 @@ pub struct CmseCallInputsStackSpill {
     #[primary_span]
     #[label]
     pub span: Span,
+    pub plural: bool,
 }
 
 #[derive(Diagnostic)]
 #[diag(hir_analysis_cmse_call_output_stack_spill, code = E0798)]
-#[note]
+#[note(hir_analysis_note1)]
+#[note(hir_analysis_note2)]
 pub struct CmseCallOutputStackSpill {
     #[primary_span]
     #[label]
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs
index 8980173f738..e99717ce00f 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs
@@ -13,7 +13,7 @@ use crate::errors;
 /// conditions, but by checking them here rustc can emit nicer error messages.
 pub fn validate_cmse_abi<'tcx>(
     tcx: TyCtxt<'tcx>,
-    dcx: &DiagCtxtHandle<'_>,
+    dcx: DiagCtxtHandle<'_>,
     hir_id: HirId,
     abi: abi::Abi,
     fn_sig: ty::PolyFnSig<'tcx>,
@@ -30,25 +30,20 @@ pub fn validate_cmse_abi<'tcx>(
             return;
         };
 
-        // fn(u32, u32, u32, u16, u16) -> u32,
-        //    ^^^^^^^^^^^^^^^^^^^^^^^     ^^^
-        let output_span = bare_fn_ty.decl.output.span();
-        let inputs_span = match (
-            bare_fn_ty.param_names.first(),
-            bare_fn_ty.decl.inputs.first(),
-            bare_fn_ty.decl.inputs.last(),
-        ) {
-            (Some(ident), Some(ty1), Some(ty2)) => ident.span.to(ty1.span).to(ty2.span),
-            _ => *bare_fn_span,
-        };
-
         match is_valid_cmse_inputs(tcx, fn_sig) {
-            Ok(true) => {}
-            Ok(false) => {
-                dcx.emit_err(errors::CmseCallInputsStackSpill { span: inputs_span });
+            Ok(Ok(())) => {}
+            Ok(Err(index)) => {
+                // fn(x: u32, u32, u32, u16, y: u16) -> u32,
+                //                           ^^^^^^
+                let span = bare_fn_ty.param_names[index]
+                    .span
+                    .to(bare_fn_ty.decl.inputs[index].span)
+                    .to(bare_fn_ty.decl.inputs.last().unwrap().span);
+                let plural = bare_fn_ty.param_names.len() - index != 1;
+                dcx.emit_err(errors::CmseCallInputsStackSpill { span, plural });
             }
             Err(layout_err) => {
-                if let Some(err) = cmse_layout_err(layout_err, inputs_span) {
+                if let Some(err) = cmse_layout_err(layout_err, *bare_fn_span) {
                     dcx.emit_err(err);
                 }
             }
@@ -57,10 +52,11 @@ pub fn validate_cmse_abi<'tcx>(
         match is_valid_cmse_output(tcx, fn_sig) {
             Ok(true) => {}
             Ok(false) => {
-                dcx.emit_err(errors::CmseCallOutputStackSpill { span: output_span });
+                let span = bare_fn_ty.decl.output.span();
+                dcx.emit_err(errors::CmseCallOutputStackSpill { span });
             }
             Err(layout_err) => {
-                if let Some(err) = cmse_layout_err(layout_err, output_span) {
+                if let Some(err) = cmse_layout_err(layout_err, *bare_fn_span) {
                     dcx.emit_err(err);
                 }
             }
@@ -72,10 +68,11 @@ pub fn validate_cmse_abi<'tcx>(
 fn is_valid_cmse_inputs<'tcx>(
     tcx: TyCtxt<'tcx>,
     fn_sig: ty::PolyFnSig<'tcx>,
-) -> Result<bool, &'tcx LayoutError<'tcx>> {
+) -> Result<Result<(), usize>, &'tcx LayoutError<'tcx>> {
+    let mut span = None;
     let mut accum = 0u64;
 
-    for arg_def in fn_sig.inputs().iter() {
+    for (index, arg_def) in fn_sig.inputs().iter().enumerate() {
         let layout = tcx.layout_of(ParamEnv::reveal_all().and(*arg_def.skip_binder()))?;
 
         let align = layout.layout.align().abi.bytes();
@@ -83,10 +80,17 @@ fn is_valid_cmse_inputs<'tcx>(
 
         accum += size;
         accum = accum.next_multiple_of(Ord::max(4, align));
+
+        // i.e. exceeds 4 32-bit registers
+        if accum > 16 {
+            span = span.or(Some(index));
+        }
     }
 
-    // i.e. 4 32-bit registers
-    Ok(accum <= 16)
+    match span {
+        None => Ok(Ok(())),
+        Some(span) => Ok(Err(span)),
+    }
 }
 
 /// Returns whether the output will fit into the available registers
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
index c118181780a..a632619aef2 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -2326,7 +2326,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         let bare_fn_ty = ty::Binder::bind_with_vars(fn_ty, bound_vars);
 
         // reject function types that violate cmse ABI requirements
-        cmse::validate_cmse_abi(self.tcx(), &self.dcx(), hir_id, abi, bare_fn_ty);
+        cmse::validate_cmse_abi(self.tcx(), self.dcx(), hir_id, abi, bare_fn_ty);
 
         // Find any late-bound regions declared in return type that do
         // not appear in the arguments. These are not well-formed.
diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.stderr
index b255d261938..fa68d95218c 100644
--- a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.stderr
+++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.stderr
@@ -30,16 +30,16 @@ LL |     f2: extern "C-cmse-nonsecure-call" fn(impl Copy, u32, u32, u32) -> u64,
    = note: `impl Trait` is only allowed in arguments and return types of functions and methods
 
 error[E0798]: function pointers with the `"C-cmse-nonsecure-call"` ABI cannot contain generics in their type
-  --> $DIR/generics.rs:19:43
+  --> $DIR/generics.rs:19:9
    |
 LL |     f3: extern "C-cmse-nonsecure-call" fn(T, u32, u32, u32) -> u64,
-   |                                           ^^^^^^^^^^^^^^^^
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0798]: function pointers with the `"C-cmse-nonsecure-call"` ABI cannot contain generics in their type
-  --> $DIR/generics.rs:20:43
+  --> $DIR/generics.rs:20:9
    |
 LL |     f4: extern "C-cmse-nonsecure-call" fn(Wrapper<T>, u32, u32, u32) -> u64,
-   |                                           ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 5 previous errors
 
diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-via-stack.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-via-stack.rs
index f8ef4419921..083a563bd7b 100644
--- a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-via-stack.rs
+++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-via-stack.rs
@@ -14,10 +14,10 @@ pub struct AlignRelevant(u32);
 
 #[no_mangle]
 pub fn test(
-    f1: extern "C-cmse-nonsecure-call" fn(u32, u32, u32, u32, u32), //~ ERROR [E0798]
-    f2: extern "C-cmse-nonsecure-call" fn(u32, u32, u32, u16, u16), //~ ERROR [E0798]
-    f3: extern "C-cmse-nonsecure-call" fn(u32, u64, u32),           //~ ERROR [E0798]
-    f4: extern "C-cmse-nonsecure-call" fn(AlignRelevant, u32),      //~ ERROR [E0798]
-    f5: extern "C-cmse-nonsecure-call" fn([u32; 5]),                //~ ERROR [E0798]
+    f1: extern "C-cmse-nonsecure-call" fn(u32, u32, u32, u32, x: u32, y: u32), //~ ERROR [E0798]
+    f2: extern "C-cmse-nonsecure-call" fn(u32, u32, u32, u16, u16),            //~ ERROR [E0798]
+    f3: extern "C-cmse-nonsecure-call" fn(u32, u64, u32),                      //~ ERROR [E0798]
+    f4: extern "C-cmse-nonsecure-call" fn(AlignRelevant, u32),                 //~ ERROR [E0798]
+    f5: extern "C-cmse-nonsecure-call" fn([u32; 5]),                           //~ ERROR [E0798]
 ) {
 }
diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-via-stack.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-via-stack.stderr
index 499122ab2c5..a5f5e1c3151 100644
--- a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-via-stack.stderr
+++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-via-stack.stderr
@@ -1,32 +1,32 @@
 error[E0798]: arguments for `"C-cmse-nonsecure-call"` function too large to pass via registers
-  --> $DIR/params-via-stack.rs:17:43
+  --> $DIR/params-via-stack.rs:17:63
    |
-LL |     f1: extern "C-cmse-nonsecure-call" fn(u32, u32, u32, u32, u32),
-   |                                           ^^^^^^^^^^^^^^^^^^^^^^^ these arguments don't fit in the available registers
+LL |     f1: extern "C-cmse-nonsecure-call" fn(u32, u32, u32, u32, x: u32, y: u32),
+   |                                                               ^^^^^^^^^^^^^^ these arguments don't fit in the available registers
    |
    = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass all their arguments via the 4 32-bit available argument registers
 
 error[E0798]: arguments for `"C-cmse-nonsecure-call"` function too large to pass via registers
-  --> $DIR/params-via-stack.rs:18:43
+  --> $DIR/params-via-stack.rs:18:63
    |
 LL |     f2: extern "C-cmse-nonsecure-call" fn(u32, u32, u32, u16, u16),
-   |                                           ^^^^^^^^^^^^^^^^^^^^^^^ these arguments don't fit in the available registers
+   |                                                               ^^^ this argument doesn't fit in the available registers
    |
    = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass all their arguments via the 4 32-bit available argument registers
 
 error[E0798]: arguments for `"C-cmse-nonsecure-call"` function too large to pass via registers
-  --> $DIR/params-via-stack.rs:19:43
+  --> $DIR/params-via-stack.rs:19:53
    |
 LL |     f3: extern "C-cmse-nonsecure-call" fn(u32, u64, u32),
-   |                                           ^^^^^^^^^^^^^ these arguments don't fit in the available registers
+   |                                                     ^^^ this argument doesn't fit in the available registers
    |
    = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass all their arguments via the 4 32-bit available argument registers
 
 error[E0798]: arguments for `"C-cmse-nonsecure-call"` function too large to pass via registers
-  --> $DIR/params-via-stack.rs:20:43
+  --> $DIR/params-via-stack.rs:20:58
    |
 LL |     f4: extern "C-cmse-nonsecure-call" fn(AlignRelevant, u32),
-   |                                           ^^^^^^^^^^^^^^^^^^ these arguments don't fit in the available registers
+   |                                                          ^^^ this argument doesn't fit in the available registers
    |
    = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass all their arguments via the 4 32-bit available argument registers
 
@@ -34,7 +34,7 @@ error[E0798]: arguments for `"C-cmse-nonsecure-call"` function too large to pass
   --> $DIR/params-via-stack.rs:21:43
    |
 LL |     f5: extern "C-cmse-nonsecure-call" fn([u32; 5]),
-   |                                           ^^^^^^^^ these arguments don't fit in the available registers
+   |                                           ^^^^^^^^ this argument doesn't fit in the available registers
    |
    = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass all their arguments via the 4 32-bit available argument registers
 
diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/return-via-stack.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/return-via-stack.stderr
index c8984e3c0d9..89f7f159d6e 100644
--- a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/return-via-stack.stderr
+++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/return-via-stack.stderr
@@ -5,6 +5,7 @@ LL |     u128: extern "C-cmse-nonsecure-call" fn() -> u128,
    |                                                  ^^^^ this type doesn't fit in the available registers
    |
    = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers
+   = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
 
 error[E0798]: return value of `"C-cmse-nonsecure-call"` function too large to pass via registers
   --> $DIR/return-via-stack.rs:36:50
@@ -13,6 +14,7 @@ LL |     i128: extern "C-cmse-nonsecure-call" fn() -> i128,
    |                                                  ^^^^ this type doesn't fit in the available registers
    |
    = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers
+   = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
 
 error[E0798]: return value of `"C-cmse-nonsecure-call"` function too large to pass via registers
   --> $DIR/return-via-stack.rs:25:48
@@ -21,6 +23,7 @@ LL |     f1: extern "C-cmse-nonsecure-call" fn() -> ReprCU64,
    |                                                ^^^^^^^^ this type doesn't fit in the available registers
    |
    = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers
+   = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
 
 error[E0798]: return value of `"C-cmse-nonsecure-call"` function too large to pass via registers
   --> $DIR/return-via-stack.rs:26:48
@@ -29,6 +32,7 @@ LL |     f2: extern "C-cmse-nonsecure-call" fn() -> ReprCBytes,
    |                                                ^^^^^^^^^^ this type doesn't fit in the available registers
    |
    = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers
+   = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
 
 error[E0798]: return value of `"C-cmse-nonsecure-call"` function too large to pass via registers
   --> $DIR/return-via-stack.rs:27:48
@@ -37,6 +41,7 @@ LL |     f3: extern "C-cmse-nonsecure-call" fn() -> U64Compound,
    |                                                ^^^^^^^^^^^ this type doesn't fit in the available registers
    |
    = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers
+   = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
 
 error[E0798]: return value of `"C-cmse-nonsecure-call"` function too large to pass via registers
   --> $DIR/return-via-stack.rs:28:48
@@ -45,6 +50,7 @@ LL |     f4: extern "C-cmse-nonsecure-call" fn() -> ReprCAlign16,
    |                                                ^^^^^^^^^^^^ this type doesn't fit in the available registers
    |
    = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers
+   = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
 
 error[E0798]: return value of `"C-cmse-nonsecure-call"` function too large to pass via registers
   --> $DIR/return-via-stack.rs:29:48
@@ -53,6 +59,7 @@ LL |     f5: extern "C-cmse-nonsecure-call" fn() -> [u8; 5],
    |                                                ^^^^^^^ this type doesn't fit in the available registers
    |
    = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers
+   = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
 
 error[E0798]: return value of `"C-cmse-nonsecure-call"` function too large to pass via registers
   --> $DIR/return-via-stack.rs:51:48
@@ -61,6 +68,7 @@ LL |     f1: extern "C-cmse-nonsecure-call" fn() -> ReprRustUnionU64,
    |                                                ^^^^^^^^^^^^^^^^ this type doesn't fit in the available registers
    |
    = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers
+   = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
 
 error[E0798]: return value of `"C-cmse-nonsecure-call"` function too large to pass via registers
   --> $DIR/return-via-stack.rs:52:48
@@ -69,6 +77,7 @@ LL |     f2: extern "C-cmse-nonsecure-call" fn() -> ReprCUnionU64,
    |                                                ^^^^^^^^^^^^^ this type doesn't fit in the available registers
    |
    = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers
+   = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
 
 error: aborting due to 9 previous errors