Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit fe72062

Browse filesBrowse files
committed
add FCW to warn about wasm ABI transition
1 parent 10bcdad commit fe72062
Copy full SHA for fe72062

File tree

Expand file treeCollapse file tree

7 files changed

+255
-13
lines changed
Filter options
Expand file treeCollapse file tree

7 files changed

+255
-13
lines changed

‎compiler/rustc_lint_defs/src/builtin.rs

Copy file name to clipboardExpand all lines: compiler/rustc_lint_defs/src/builtin.rs
+46Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ declare_lint_pass! {
143143
UNUSED_VARIABLES,
144144
USELESS_DEPRECATED,
145145
WARNINGS,
146+
WASM_C_ABI,
146147
// tidy-alphabetical-end
147148
]
148149
}
@@ -5082,6 +5083,8 @@ declare_lint! {
50825083
/// }
50835084
/// ```
50845085
///
5086+
/// This will produce:
5087+
///
50855088
/// ```text
50865089
/// warning: ABI error: this function call uses a avx vector type, which is not enabled in the caller
50875090
/// --> lint_example.rs:18:12
@@ -5125,3 +5128,46 @@ declare_lint! {
51255128
reference: "issue #116558 <https://github.com/rust-lang/rust/issues/116558>",
51265129
};
51275130
}
5131+
5132+
declare_lint! {
5133+
/// The `wasm_c_abi` lint detects usage of the `extern "C"` ABI of wasm that is affected
5134+
/// by a planned ABI change that has the goal of aligning Rust with the standard C ABI
5135+
/// of this target.
5136+
///
5137+
/// ### Example
5138+
///
5139+
/// ```rust,ignore (needs wasm32-unknown-unknown)
5140+
/// #[repr(C)]
5141+
/// struct MyType(i32, i32);
5142+
///
5143+
/// extern "C" my_fun(x: MyType) {}
5144+
/// ```
5145+
///
5146+
/// This will produce:
5147+
///
5148+
/// ```text
5149+
/// error: this function function definition is affected by the wasm ABI transition: it passes an argument of non-scalar type `MyType`
5150+
/// --> $DIR/wasm_c_abi_transition.rs:17:1
5151+
/// |
5152+
/// | pub extern "C" fn my_fun(_x: MyType) {}
5153+
/// | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5154+
/// |
5155+
/// = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
5156+
/// = note: for more information, see issue #122532 <https://github.com/rust-lang/rust/issues/122532>
5157+
/// = help: the "C" ABI Rust uses on wasm32-unknown-unknown will change to align with the standard "C" ABI for this target
5158+
/// ```
5159+
///
5160+
/// ### Explanation
5161+
///
5162+
/// Rust has historically implemented a non-spec-compliant C ABI on wasm32-unknown-unknown. This
5163+
/// has caused incompatibilities with other compilers and Wasm targets. In a future version
5164+
/// of Rust, this will be fixed, and therefore code relying on the non-spec-compliant C ABI will
5165+
/// stop functioning.
5166+
pub WASM_C_ABI,
5167+
Warn,
5168+
"detects code relying on rustc's non-spec-compliant wasm C ABI",
5169+
@future_incompatible = FutureIncompatibleInfo {
5170+
reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps,
5171+
reference: "issue #122532 <https://github.com/rust-lang/rust/issues/122532>",
5172+
};
5173+
}

‎compiler/rustc_monomorphize/messages.ftl

Copy file name to clipboardExpand all lines: compiler/rustc_monomorphize/messages.ftl
+7Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,4 +63,11 @@ monomorphize_symbol_already_defined = symbol `{$symbol}` is already defined
6363
monomorphize_unknown_cgu_collection_mode =
6464
unknown codegen-item collection mode '{$mode}', falling back to 'lazy' mode
6565
66+
monomorphize_wasm_c_abi_transition =
67+
this function {$is_call ->
68+
[true] call
69+
*[false] definition
70+
} involves an argument of type `{$ty}` which is affected by the wasm ABI transition
71+
.help = the "C" ABI Rust uses on wasm32-unknown-unknown will change to align with the standard "C" ABI for this target
72+
6673
monomorphize_written_to_path = the full type name has been written to '{$path}'

‎compiler/rustc_monomorphize/src/errors.rs

Copy file name to clipboardExpand all lines: compiler/rustc_monomorphize/src/errors.rs
+9Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,3 +103,12 @@ pub(crate) struct AbiRequiredTargetFeature<'a> {
103103
/// Whether this is a problem at a call site or at a declaration.
104104
pub is_call: bool,
105105
}
106+
107+
#[derive(LintDiagnostic)]
108+
#[diag(monomorphize_wasm_c_abi_transition)]
109+
#[help]
110+
pub(crate) struct WasmCAbiTransition<'a> {
111+
pub ty: Ty<'a>,
112+
/// Whether this is a problem at a call site or at a declaration.
113+
pub is_call: bool,
114+
}

‎compiler/rustc_monomorphize/src/mono_checks/abi_check.rs

Copy file name to clipboardExpand all lines: compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
+67-12Lines changed: 67 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@
33
use rustc_abi::{BackendRepr, RegKind};
44
use rustc_hir::CRATE_HIR_ID;
55
use rustc_middle::mir::{self, traversal};
6-
use rustc_middle::ty::{self, Instance, InstanceKind, Ty, TyCtxt};
7-
use rustc_session::lint::builtin::ABI_UNSUPPORTED_VECTOR_TYPES;
6+
use rustc_middle::ty::layout::LayoutCx;
7+
use rustc_middle::ty::{self, Instance, InstanceKind, Ty, TyCtxt, TypingEnv};
8+
use rustc_session::lint::builtin::{ABI_UNSUPPORTED_VECTOR_TYPES, WASM_C_ABI};
89
use rustc_span::def_id::DefId;
910
use rustc_span::{DUMMY_SP, Span, Symbol, sym};
10-
use rustc_target::callconv::{Conv, FnAbi, PassMode};
11+
use rustc_target::callconv::{ArgAbi, Conv, FnAbi, PassMode};
12+
use rustc_target::spec::{HasWasmCAbiOpt, WasmCAbi};
1113

1214
use crate::errors;
1315

@@ -26,13 +28,15 @@ fn uses_vector_registers(mode: &PassMode, repr: &BackendRepr) -> bool {
2628
/// for a certain function.
2729
/// `is_call` indicates whether this is a call-site check or a definition-site check;
2830
/// this is only relevant for the wording in the emitted error.
29-
fn do_check_abi<'tcx>(
31+
fn do_check_simd_vector_abi<'tcx>(
3032
tcx: TyCtxt<'tcx>,
3133
abi: &FnAbi<'tcx, Ty<'tcx>>,
3234
def_id: DefId,
3335
is_call: bool,
3436
span: impl Fn() -> Span,
3537
) {
38+
// We check this on all functions, including those using the "Rust" ABI.
39+
// For the "Rust" ABI it would be a bug if the lint ever triggered, but better safe than sorry.
3640
let feature_def = tcx.sess.target.features_for_correct_vector_abi();
3741
let codegen_attrs = tcx.codegen_fn_attrs(def_id);
3842
let have_feature = |feat: Symbol| {
@@ -88,6 +92,59 @@ fn do_check_abi<'tcx>(
8892
}
8993
}
9094

95+
fn wasm_abi_safe<'tcx>(tcx: TyCtxt<'tcx>, arg: &ArgAbi<'tcx, Ty<'tcx>>) -> bool {
96+
if matches!(arg.layout.backend_repr, BackendRepr::Scalar(_)) {
97+
return true;
98+
}
99+
100+
// This matches `unwrap_trivial_aggregate` in the wasm ABI logic.`
101+
if arg.layout.is_aggregate() {
102+
let cx = LayoutCx::new(tcx, TypingEnv::fully_monomorphized());
103+
if let Some(unit) = arg.layout.homogeneous_aggregate(&cx).ok().and_then(|ha| ha.unit()) {
104+
let size = arg.layout.size;
105+
if unit.size == size {
106+
return true;
107+
}
108+
}
109+
}
110+
111+
false
112+
}
113+
114+
/// Warns against usage of `extern "C"` on wasm32-unknown-unknown that is affected by the
115+
/// ABI transition.
116+
fn do_check_wasm_abi<'tcx>(
117+
tcx: TyCtxt<'tcx>,
118+
abi: &FnAbi<'tcx, Ty<'tcx>>,
119+
is_call: bool,
120+
span: impl Fn() -> Span,
121+
) {
122+
// Only proceed for `extern "C" fn`` on wasm32-unknown-unknown (same check as what `adjust_for_foreign_abi` uses to call `compute_wasm_abi_info`).
123+
if !(tcx.sess.target.arch == "wasm32"
124+
&& tcx.sess.target.os == "unknown"
125+
&& tcx.wasm_c_abi_opt() == WasmCAbi::Legacy
126+
&& abi.conv == Conv::C)
127+
{
128+
return;
129+
}
130+
// Warn against all types whose ABI will change. That's all arguments except for things passed as scalars.
131+
// Return values are not affected by this change.
132+
for arg_abi in abi.args.iter() {
133+
if wasm_abi_safe(tcx, arg_abi) {
134+
continue;
135+
}
136+
let span = span();
137+
tcx.emit_node_span_lint(
138+
WASM_C_ABI,
139+
CRATE_HIR_ID,
140+
span,
141+
errors::WasmCAbiTransition { ty: arg_abi.layout.ty, is_call },
142+
);
143+
// Let's only warn once per function.
144+
break;
145+
}
146+
}
147+
91148
/// Checks that the ABI of a given instance of a function does not contain vector-passed arguments
92149
/// or return values for which the corresponding target feature is not enabled.
93150
fn check_instance_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) {
@@ -98,13 +155,10 @@ fn check_instance_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) {
98155
// function.
99156
return;
100157
};
101-
do_check_abi(
102-
tcx,
103-
abi,
104-
instance.def_id(),
105-
/*is_call*/ false,
106-
|| tcx.def_span(instance.def_id()),
107-
)
158+
do_check_simd_vector_abi(tcx, abi, instance.def_id(), /*is_call*/ false, || {
159+
tcx.def_span(instance.def_id())
160+
});
161+
do_check_wasm_abi(tcx, abi, /*is_call*/ false, || tcx.def_span(instance.def_id()));
108162
}
109163

110164
/// Checks that a call expression does not try to pass a vector-passed argument which requires a
@@ -141,7 +195,8 @@ fn check_call_site_abi<'tcx>(
141195
// ABI failed to compute; this will not get through codegen.
142196
return;
143197
};
144-
do_check_abi(tcx, callee_abi, caller.def_id(), /*is_call*/ true, || span);
198+
do_check_simd_vector_abi(tcx, callee_abi, caller.def_id(), /*is_call*/ true, || span);
199+
do_check_wasm_abi(tcx, callee_abi, /*is_call*/ true, || span);
145200
}
146201

147202
fn check_callees_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>, body: &mir::Body<'tcx>) {

‎tests/ui/abi/compatibility.rs

Copy file name to clipboardExpand all lines: tests/ui/abi/compatibility.rs
-1Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@
6262
//@[nvptx64] needs-llvm-components: nvptx
6363
#![feature(no_core, rustc_attrs, lang_items)]
6464
#![feature(unsized_fn_params, transparent_unions)]
65-
#![no_std]
6665
#![no_core]
6766
#![allow(unused, improper_ctypes_definitions, internal_features)]
6867

+41Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
//@ compile-flags: --target wasm32-unknown-unknown
2+
//@ needs-llvm-components: webassembly
3+
//@ add-core-stubs
4+
//@ build-fail
5+
6+
#![feature(no_core)]
7+
#![no_core]
8+
#![crate_type = "lib"]
9+
#![deny(wasm_c_abi)]
10+
11+
extern crate minicore;
12+
use minicore::*;
13+
14+
pub extern "C" fn my_fun_trivial(_x: i32, _y: f32) {}
15+
16+
#[repr(C)]
17+
pub struct MyType(i32, i32);
18+
pub extern "C" fn my_fun(_x: MyType) {} //~ERROR: wasm ABI transition
19+
//~^WARN: previously accepted
20+
21+
// This one is ABI-safe as it only wraps a single field,
22+
// and the return type can be anything.
23+
#[repr(C)]
24+
pub struct MySafeType(i32);
25+
pub extern "C" fn my_fun_safe(_x: MySafeType) -> MyType { loop {} }
26+
27+
// This one not ABI-safe due to the alignment.
28+
#[repr(C, align(16))]
29+
pub struct MyAlignedType(i32);
30+
pub extern "C" fn my_fun_aligned(_x: MyAlignedType) {} //~ERROR: wasm ABI transition
31+
//~^WARN: previously accepted
32+
33+
// Check call-site warning
34+
extern "C" {
35+
fn other_fun(x: MyType);
36+
}
37+
38+
pub fn call_other_fun(x: MyType) {
39+
unsafe { other_fun(x) } //~ERROR: wasm ABI transition
40+
//~^WARN: previously accepted
41+
}
+85Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
error: this function definition involves an argument of type `MyType` which is affected by the wasm ABI transition
2+
--> $DIR/wasm_c_abi_transition.rs:18:1
3+
|
4+
LL | pub extern "C" fn my_fun(_x: MyType) {}
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
8+
= note: for more information, see issue #122532 <https://github.com/rust-lang/rust/issues/122532>
9+
= help: the "C" ABI Rust uses on wasm32-unknown-unknown will change to align with the standard "C" ABI for this target
10+
note: the lint level is defined here
11+
--> $DIR/wasm_c_abi_transition.rs:9:9
12+
|
13+
LL | #![deny(wasm_c_abi)]
14+
| ^^^^^^^^^^
15+
16+
error: this function definition involves an argument of type `MyAlignedType` which is affected by the wasm ABI transition
17+
--> $DIR/wasm_c_abi_transition.rs:30:1
18+
|
19+
LL | pub extern "C" fn my_fun_aligned(_x: MyAlignedType) {}
20+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
21+
|
22+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
23+
= note: for more information, see issue #122532 <https://github.com/rust-lang/rust/issues/122532>
24+
= help: the "C" ABI Rust uses on wasm32-unknown-unknown will change to align with the standard "C" ABI for this target
25+
26+
error: this function call involves an argument of type `MyType` which is affected by the wasm ABI transition
27+
--> $DIR/wasm_c_abi_transition.rs:39:14
28+
|
29+
LL | unsafe { other_fun(x) }
30+
| ^^^^^^^^^^^^
31+
|
32+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
33+
= note: for more information, see issue #122532 <https://github.com/rust-lang/rust/issues/122532>
34+
= help: the "C" ABI Rust uses on wasm32-unknown-unknown will change to align with the standard "C" ABI for this target
35+
36+
error: aborting due to 3 previous errors
37+
38+
Future incompatibility report: Future breakage diagnostic:
39+
error: this function definition involves an argument of type `MyType` which is affected by the wasm ABI transition
40+
--> $DIR/wasm_c_abi_transition.rs:18:1
41+
|
42+
LL | pub extern "C" fn my_fun(_x: MyType) {}
43+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
44+
|
45+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
46+
= note: for more information, see issue #122532 <https://github.com/rust-lang/rust/issues/122532>
47+
= help: the "C" ABI Rust uses on wasm32-unknown-unknown will change to align with the standard "C" ABI for this target
48+
note: the lint level is defined here
49+
--> $DIR/wasm_c_abi_transition.rs:9:9
50+
|
51+
LL | #![deny(wasm_c_abi)]
52+
| ^^^^^^^^^^
53+
54+
Future breakage diagnostic:
55+
error: this function definition involves an argument of type `MyAlignedType` which is affected by the wasm ABI transition
56+
--> $DIR/wasm_c_abi_transition.rs:30:1
57+
|
58+
LL | pub extern "C" fn my_fun_aligned(_x: MyAlignedType) {}
59+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
60+
|
61+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
62+
= note: for more information, see issue #122532 <https://github.com/rust-lang/rust/issues/122532>
63+
= help: the "C" ABI Rust uses on wasm32-unknown-unknown will change to align with the standard "C" ABI for this target
64+
note: the lint level is defined here
65+
--> $DIR/wasm_c_abi_transition.rs:9:9
66+
|
67+
LL | #![deny(wasm_c_abi)]
68+
| ^^^^^^^^^^
69+
70+
Future breakage diagnostic:
71+
error: this function call involves an argument of type `MyType` which is affected by the wasm ABI transition
72+
--> $DIR/wasm_c_abi_transition.rs:39:14
73+
|
74+
LL | unsafe { other_fun(x) }
75+
| ^^^^^^^^^^^^
76+
|
77+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
78+
= note: for more information, see issue #122532 <https://github.com/rust-lang/rust/issues/122532>
79+
= help: the "C" ABI Rust uses on wasm32-unknown-unknown will change to align with the standard "C" ABI for this target
80+
note: the lint level is defined here
81+
--> $DIR/wasm_c_abi_transition.rs:9:9
82+
|
83+
LL | #![deny(wasm_c_abi)]
84+
| ^^^^^^^^^^
85+

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.