Skip to content

Commit c2894a4

Browse files
committed
improve error reporting
1 parent 6b6b842 commit c2894a4

File tree

8 files changed

+65
-46
lines changed

8 files changed

+65
-46
lines changed

compiler/rustc_hir_analysis/messages.ftl

+6-2
Original file line numberDiff line numberDiff line change
@@ -63,13 +63,17 @@ hir_analysis_cmse_call_generic =
6363
6464
hir_analysis_cmse_call_inputs_stack_spill =
6565
arguments for `"C-cmse-nonsecure-call"` function too large to pass via registers
66-
.label = these arguments don't fit in the available registers
66+
.label = {$plural ->
67+
[false] this argument doesn't
68+
*[true] these arguments don't
69+
} fit in the available registers
6770
.note = functions with the `"C-cmse-nonsecure-call"` ABI must pass all their arguments via the 4 32-bit available argument registers
6871
6972
hir_analysis_cmse_call_output_stack_spill =
7073
return value of `"C-cmse-nonsecure-call"` function too large to pass via registers
7174
.label = this type doesn't fit in the available registers
72-
.note = functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers
75+
.note1 = functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers
76+
.note2 = the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
7377
7478
hir_analysis_coerce_unsized_may = the trait `{$trait_name}` may only be implemented for a coercion between structures
7579

compiler/rustc_hir_analysis/src/errors.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -1690,11 +1690,13 @@ pub struct CmseCallInputsStackSpill {
16901690
#[primary_span]
16911691
#[label]
16921692
pub span: Span,
1693+
pub plural: bool,
16931694
}
16941695

16951696
#[derive(Diagnostic)]
16961697
#[diag(hir_analysis_cmse_call_output_stack_spill, code = E0798)]
1697-
#[note]
1698+
#[note(hir_analysis_note1)]
1699+
#[note(hir_analysis_note2)]
16981700
pub struct CmseCallOutputStackSpill {
16991701
#[primary_span]
17001702
#[label]

compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs

+27-23
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use crate::errors;
1313
/// conditions, but by checking them here rustc can emit nicer error messages.
1414
pub fn validate_cmse_abi<'tcx>(
1515
tcx: TyCtxt<'tcx>,
16-
dcx: &DiagCtxtHandle<'_>,
16+
dcx: DiagCtxtHandle<'_>,
1717
hir_id: HirId,
1818
abi: abi::Abi,
1919
fn_sig: ty::PolyFnSig<'tcx>,
@@ -30,25 +30,20 @@ pub fn validate_cmse_abi<'tcx>(
3030
return;
3131
};
3232

33-
// fn(u32, u32, u32, u16, u16) -> u32,
34-
// ^^^^^^^^^^^^^^^^^^^^^^^ ^^^
35-
let output_span = bare_fn_ty.decl.output.span();
36-
let inputs_span = match (
37-
bare_fn_ty.param_names.first(),
38-
bare_fn_ty.decl.inputs.first(),
39-
bare_fn_ty.decl.inputs.last(),
40-
) {
41-
(Some(ident), Some(ty1), Some(ty2)) => ident.span.to(ty1.span).to(ty2.span),
42-
_ => *bare_fn_span,
43-
};
44-
4533
match is_valid_cmse_inputs(tcx, fn_sig) {
46-
Ok(true) => {}
47-
Ok(false) => {
48-
dcx.emit_err(errors::CmseCallInputsStackSpill { span: inputs_span });
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 });
4944
}
5045
Err(layout_err) => {
51-
if let Some(err) = cmse_layout_err(layout_err, inputs_span) {
46+
if let Some(err) = cmse_layout_err(layout_err, *bare_fn_span) {
5247
dcx.emit_err(err);
5348
}
5449
}
@@ -57,10 +52,11 @@ pub fn validate_cmse_abi<'tcx>(
5752
match is_valid_cmse_output(tcx, fn_sig) {
5853
Ok(true) => {}
5954
Ok(false) => {
60-
dcx.emit_err(errors::CmseCallOutputStackSpill { span: output_span });
55+
let span = bare_fn_ty.decl.output.span();
56+
dcx.emit_err(errors::CmseCallOutputStackSpill { span });
6157
}
6258
Err(layout_err) => {
63-
if let Some(err) = cmse_layout_err(layout_err, output_span) {
59+
if let Some(err) = cmse_layout_err(layout_err, *bare_fn_span) {
6460
dcx.emit_err(err);
6561
}
6662
}
@@ -72,21 +68,29 @@ pub fn validate_cmse_abi<'tcx>(
7268
fn is_valid_cmse_inputs<'tcx>(
7369
tcx: TyCtxt<'tcx>,
7470
fn_sig: ty::PolyFnSig<'tcx>,
75-
) -> Result<bool, &'tcx LayoutError<'tcx>> {
71+
) -> Result<Result<(), usize>, &'tcx LayoutError<'tcx>> {
72+
let mut span = None;
7673
let mut accum = 0u64;
7774

78-
for arg_def in fn_sig.inputs().iter() {
75+
for (index, arg_def) in fn_sig.inputs().iter().enumerate() {
7976
let layout = tcx.layout_of(ParamEnv::reveal_all().and(*arg_def.skip_binder()))?;
8077

8178
let align = layout.layout.align().abi.bytes();
8279
let size = layout.layout.size().bytes();
8380

8481
accum += size;
8582
accum = accum.next_multiple_of(Ord::max(4, align));
83+
84+
// i.e. exceeds 4 32-bit registers
85+
if accum > 16 {
86+
span = span.or(Some(index));
87+
}
8688
}
8789

88-
// i.e. 4 32-bit registers
89-
Ok(accum <= 16)
90+
match span {
91+
None => Ok(Ok(())),
92+
Some(span) => Ok(Err(span)),
93+
}
9094
}
9195

9296
/// Returns whether the output will fit into the available registers

compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2326,7 +2326,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
23262326
let bare_fn_ty = ty::Binder::bind_with_vars(fn_ty, bound_vars);
23272327

23282328
// reject function types that violate cmse ABI requirements
2329-
cmse::validate_cmse_abi(self.tcx(), &self.dcx(), hir_id, abi, bare_fn_ty);
2329+
cmse::validate_cmse_abi(self.tcx(), self.dcx(), hir_id, abi, bare_fn_ty);
23302330

23312331
// Find any late-bound regions declared in return type that do
23322332
// not appear in the arguments. These are not well-formed.

tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,16 @@ LL | f2: extern "C-cmse-nonsecure-call" fn(impl Copy, u32, u32, u32) -> u64,
3030
= note: `impl Trait` is only allowed in arguments and return types of functions and methods
3131

3232
error[E0798]: function pointers with the `"C-cmse-nonsecure-call"` ABI cannot contain generics in their type
33-
--> $DIR/generics.rs:19:43
33+
--> $DIR/generics.rs:19:9
3434
|
3535
LL | f3: extern "C-cmse-nonsecure-call" fn(T, u32, u32, u32) -> u64,
36-
| ^^^^^^^^^^^^^^^^
36+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3737

3838
error[E0798]: function pointers with the `"C-cmse-nonsecure-call"` ABI cannot contain generics in their type
39-
--> $DIR/generics.rs:20:43
39+
--> $DIR/generics.rs:20:9
4040
|
4141
LL | f4: extern "C-cmse-nonsecure-call" fn(Wrapper<T>, u32, u32, u32) -> u64,
42-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
42+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4343

4444
error: aborting due to 5 previous errors
4545

tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-via-stack.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ pub struct AlignRelevant(u32);
1414

1515
#[no_mangle]
1616
pub fn test(
17-
f1: extern "C-cmse-nonsecure-call" fn(u32, u32, u32, u32, u32), //~ ERROR [E0798]
18-
f2: extern "C-cmse-nonsecure-call" fn(u32, u32, u32, u16, u16), //~ ERROR [E0798]
19-
f3: extern "C-cmse-nonsecure-call" fn(u32, u64, u32), //~ ERROR [E0798]
20-
f4: extern "C-cmse-nonsecure-call" fn(AlignRelevant, u32), //~ ERROR [E0798]
21-
f5: extern "C-cmse-nonsecure-call" fn([u32; 5]), //~ ERROR [E0798]
17+
f1: extern "C-cmse-nonsecure-call" fn(u32, u32, u32, u32, x: u32, y: u32), //~ ERROR [E0798]
18+
f2: extern "C-cmse-nonsecure-call" fn(u32, u32, u32, u16, u16), //~ ERROR [E0798]
19+
f3: extern "C-cmse-nonsecure-call" fn(u32, u64, u32), //~ ERROR [E0798]
20+
f4: extern "C-cmse-nonsecure-call" fn(AlignRelevant, u32), //~ ERROR [E0798]
21+
f5: extern "C-cmse-nonsecure-call" fn([u32; 5]), //~ ERROR [E0798]
2222
) {
2323
}

tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-via-stack.stderr

+10-10
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,40 @@
11
error[E0798]: arguments for `"C-cmse-nonsecure-call"` function too large to pass via registers
2-
--> $DIR/params-via-stack.rs:17:43
2+
--> $DIR/params-via-stack.rs:17:63
33
|
4-
LL | f1: extern "C-cmse-nonsecure-call" fn(u32, u32, u32, u32, u32),
5-
| ^^^^^^^^^^^^^^^^^^^^^^^ these arguments don't fit in the available registers
4+
LL | f1: extern "C-cmse-nonsecure-call" fn(u32, u32, u32, u32, x: u32, y: u32),
5+
| ^^^^^^^^^^^^^^ these arguments don't fit in the available registers
66
|
77
= note: functions with the `"C-cmse-nonsecure-call"` ABI must pass all their arguments via the 4 32-bit available argument registers
88

99
error[E0798]: arguments for `"C-cmse-nonsecure-call"` function too large to pass via registers
10-
--> $DIR/params-via-stack.rs:18:43
10+
--> $DIR/params-via-stack.rs:18:63
1111
|
1212
LL | f2: extern "C-cmse-nonsecure-call" fn(u32, u32, u32, u16, u16),
13-
| ^^^^^^^^^^^^^^^^^^^^^^^ these arguments don't fit in the available registers
13+
| ^^^ this argument doesn't fit in the available registers
1414
|
1515
= note: functions with the `"C-cmse-nonsecure-call"` ABI must pass all their arguments via the 4 32-bit available argument registers
1616

1717
error[E0798]: arguments for `"C-cmse-nonsecure-call"` function too large to pass via registers
18-
--> $DIR/params-via-stack.rs:19:43
18+
--> $DIR/params-via-stack.rs:19:53
1919
|
2020
LL | f3: extern "C-cmse-nonsecure-call" fn(u32, u64, u32),
21-
| ^^^^^^^^^^^^^ these arguments don't fit in the available registers
21+
| ^^^ this argument doesn't fit in the available registers
2222
|
2323
= note: functions with the `"C-cmse-nonsecure-call"` ABI must pass all their arguments via the 4 32-bit available argument registers
2424

2525
error[E0798]: arguments for `"C-cmse-nonsecure-call"` function too large to pass via registers
26-
--> $DIR/params-via-stack.rs:20:43
26+
--> $DIR/params-via-stack.rs:20:58
2727
|
2828
LL | f4: extern "C-cmse-nonsecure-call" fn(AlignRelevant, u32),
29-
| ^^^^^^^^^^^^^^^^^^ these arguments don't fit in the available registers
29+
| ^^^ this argument doesn't fit in the available registers
3030
|
3131
= note: functions with the `"C-cmse-nonsecure-call"` ABI must pass all their arguments via the 4 32-bit available argument registers
3232

3333
error[E0798]: arguments for `"C-cmse-nonsecure-call"` function too large to pass via registers
3434
--> $DIR/params-via-stack.rs:21:43
3535
|
3636
LL | f5: extern "C-cmse-nonsecure-call" fn([u32; 5]),
37-
| ^^^^^^^^ these arguments don't fit in the available registers
37+
| ^^^^^^^^ this argument doesn't fit in the available registers
3838
|
3939
= note: functions with the `"C-cmse-nonsecure-call"` ABI must pass all their arguments via the 4 32-bit available argument registers
4040

tests/ui/cmse-nonsecure/cmse-nonsecure-call/return-via-stack.stderr

+9
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ LL | u128: extern "C-cmse-nonsecure-call" fn() -> u128,
55
| ^^^^ this type doesn't fit in the available registers
66
|
77
= note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers
8+
= note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
89

910
error[E0798]: return value of `"C-cmse-nonsecure-call"` function too large to pass via registers
1011
--> $DIR/return-via-stack.rs:36:50
@@ -13,6 +14,7 @@ LL | i128: extern "C-cmse-nonsecure-call" fn() -> i128,
1314
| ^^^^ this type doesn't fit in the available registers
1415
|
1516
= note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers
17+
= note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
1618

1719
error[E0798]: return value of `"C-cmse-nonsecure-call"` function too large to pass via registers
1820
--> $DIR/return-via-stack.rs:25:48
@@ -21,6 +23,7 @@ LL | f1: extern "C-cmse-nonsecure-call" fn() -> ReprCU64,
2123
| ^^^^^^^^ this type doesn't fit in the available registers
2224
|
2325
= note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers
26+
= note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
2427

2528
error[E0798]: return value of `"C-cmse-nonsecure-call"` function too large to pass via registers
2629
--> $DIR/return-via-stack.rs:26:48
@@ -29,6 +32,7 @@ LL | f2: extern "C-cmse-nonsecure-call" fn() -> ReprCBytes,
2932
| ^^^^^^^^^^ this type doesn't fit in the available registers
3033
|
3134
= note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers
35+
= note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
3236

3337
error[E0798]: return value of `"C-cmse-nonsecure-call"` function too large to pass via registers
3438
--> $DIR/return-via-stack.rs:27:48
@@ -37,6 +41,7 @@ LL | f3: extern "C-cmse-nonsecure-call" fn() -> U64Compound,
3741
| ^^^^^^^^^^^ this type doesn't fit in the available registers
3842
|
3943
= note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers
44+
= note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
4045

4146
error[E0798]: return value of `"C-cmse-nonsecure-call"` function too large to pass via registers
4247
--> $DIR/return-via-stack.rs:28:48
@@ -45,6 +50,7 @@ LL | f4: extern "C-cmse-nonsecure-call" fn() -> ReprCAlign16,
4550
| ^^^^^^^^^^^^ this type doesn't fit in the available registers
4651
|
4752
= note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers
53+
= note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
4854

4955
error[E0798]: return value of `"C-cmse-nonsecure-call"` function too large to pass via registers
5056
--> $DIR/return-via-stack.rs:29:48
@@ -53,6 +59,7 @@ LL | f5: extern "C-cmse-nonsecure-call" fn() -> [u8; 5],
5359
| ^^^^^^^ this type doesn't fit in the available registers
5460
|
5561
= note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers
62+
= note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
5663

5764
error[E0798]: return value of `"C-cmse-nonsecure-call"` function too large to pass via registers
5865
--> $DIR/return-via-stack.rs:51:48
@@ -61,6 +68,7 @@ LL | f1: extern "C-cmse-nonsecure-call" fn() -> ReprRustUnionU64,
6168
| ^^^^^^^^^^^^^^^^ this type doesn't fit in the available registers
6269
|
6370
= note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers
71+
= note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
6472

6573
error[E0798]: return value of `"C-cmse-nonsecure-call"` function too large to pass via registers
6674
--> $DIR/return-via-stack.rs:52:48
@@ -69,6 +77,7 @@ LL | f2: extern "C-cmse-nonsecure-call" fn() -> ReprCUnionU64,
6977
| ^^^^^^^^^^^^^ this type doesn't fit in the available registers
7078
|
7179
= note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers
80+
= note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
7281

7382
error: aborting due to 9 previous errors
7483

0 commit comments

Comments
 (0)