Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit ab162c6

Browse files
committedMar 22, 2025
Auto merge of #138827 - tgross35:rollup-agm26cd, r=tgross35
Rollup of 10 pull requests Successful merges: - #137736 (Don't attempt to export compiler-builtins symbols from rust dylibs) - #138236 (uefi: Add OwnedEvent abstraction) - #138321 ([bootstrap] Distribute split debuginfo if present) - #138410 (Couple mir building cleanups) - #138490 (Forward `stream_position` in `Arc<File>` as well) - #138535 (Cleanup `LangString::parse`) - #138536 (stable_mir: Add `MutMirVisitor`) - #138580 (resolve: Avoid some unstable iteration 2) - #138601 (add FCW to warn about wasm ABI transition) - #138631 (Update test for SGX now implementing `read_buf`) r? `@ghost` `@rustbot` modify labels: rollup
2 parents db68788 + 2799f83 commit ab162c6

File tree

39 files changed

+1181
-591
lines changed

39 files changed

+1181
-591
lines changed
 

‎compiler/rustc_codegen_ssa/src/back/linker.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -1782,7 +1782,10 @@ fn exported_symbols_for_non_proc_macro(tcx: TyCtxt<'_>, crate_type: CrateType) -
17821782
let mut symbols = Vec::new();
17831783
let export_threshold = symbol_export::crates_export_threshold(&[crate_type]);
17841784
for_each_exported_symbols_include_dep(tcx, crate_type, |symbol, info, cnum| {
1785-
if info.level.is_below_threshold(export_threshold) {
1785+
// Do not export mangled symbols from cdylibs and don't attempt to export compiler-builtins
1786+
// from any cdylib. The latter doesn't work anyway as we use hidden visibility for
1787+
// compiler-builtins. Most linkers silently ignore it, but ld64 gives a warning.
1788+
if info.level.is_below_threshold(export_threshold) && !tcx.is_compiler_builtins(cnum) {
17861789
symbols.push(symbol_export::exporting_symbol_name_for_instance_in_crate(
17871790
tcx, symbol, cnum,
17881791
));
@@ -1821,7 +1824,9 @@ pub(crate) fn linked_symbols(
18211824

18221825
let export_threshold = symbol_export::crates_export_threshold(&[crate_type]);
18231826
for_each_exported_symbols_include_dep(tcx, crate_type, |symbol, info, cnum| {
1824-
if info.level.is_below_threshold(export_threshold) || info.used {
1827+
if info.level.is_below_threshold(export_threshold) && !tcx.is_compiler_builtins(cnum)
1828+
|| info.used
1829+
{
18251830
symbols.push((
18261831
symbol_export::linking_symbol_name_for_instance_in_crate(tcx, symbol, cnum),
18271832
info.kind,

‎compiler/rustc_codegen_ssa/src/mir/naked_asm.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,7 @@ fn wasm_functype<'tcx>(tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, def_id
332332
// please also add `wasm32-unknown-unknown` back in `tests/assembly/wasm32-naked-fn.rs`
333333
// basically the commit introducing this comment should be reverted
334334
if let PassMode::Pair { .. } = fn_abi.ret.mode {
335-
let _ = WasmCAbi::Legacy;
335+
let _ = WasmCAbi::Legacy { with_lint: true };
336336
span_bug!(
337337
tcx.def_span(def_id),
338338
"cannot return a pair (the wasm32-unknown-unknown ABI is broken, see https://github.com/rust-lang/rust/issues/115666"
@@ -384,7 +384,7 @@ fn wasm_type<'tcx>(
384384
BackendRepr::SimdVector { .. } => "v128",
385385
BackendRepr::Memory { .. } => {
386386
// FIXME: remove this branch once the wasm32-unknown-unknown ABI is fixed
387-
let _ = WasmCAbi::Legacy;
387+
let _ = WasmCAbi::Legacy { with_lint: true };
388388
span_bug!(
389389
tcx.def_span(def_id),
390390
"cannot use memory args (the wasm32-unknown-unknown ABI is broken, see https://github.com/rust-lang/rust/issues/115666"

‎compiler/rustc_lint_defs/src/builtin.rs

+46
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 #138762 <https://github.com/rust-lang/rust/issues/138762>
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 #138762 <https://github.com/rust-lang/rust/issues/138762>",
5172+
};
5173+
}

‎compiler/rustc_mir_build/src/builder/expr/as_constant.rs

+11-16
Original file line numberDiff line numberDiff line change
@@ -105,23 +105,19 @@ fn lit_to_mir_constant<'tcx>(tcx: TyCtxt<'tcx>, lit_input: LitToConstInput<'tcx>
105105
return Const::Ty(Ty::new_error(tcx, guar), ty::Const::new_error(tcx, guar));
106106
}
107107

108-
let trunc = |n, width: ty::UintTy| {
109-
let width = width
110-
.normalize(tcx.data_layout.pointer_size.bits().try_into().unwrap())
111-
.bit_width()
112-
.unwrap();
113-
let width = Size::from_bits(width);
108+
let lit_ty = match *ty.kind() {
109+
ty::Pat(base, _) => base,
110+
_ => ty,
111+
};
112+
113+
let trunc = |n| {
114+
let width = lit_ty.primitive_size(tcx);
114115
trace!("trunc {} with size {} and shift {}", n, width.bits(), 128 - width.bits());
115116
let result = width.truncate(n);
116117
trace!("trunc result: {}", result);
117118
ConstValue::Scalar(Scalar::from_uint(result, width))
118119
};
119120

120-
let lit_ty = match *ty.kind() {
121-
ty::Pat(base, _) => base,
122-
_ => ty,
123-
};
124-
125121
let value = match (lit, lit_ty.kind()) {
126122
(ast::LitKind::Str(s, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_str() => {
127123
let s = s.as_str();
@@ -149,11 +145,10 @@ fn lit_to_mir_constant<'tcx>(tcx: TyCtxt<'tcx>, lit_input: LitToConstInput<'tcx>
149145
(ast::LitKind::Byte(n), ty::Uint(ty::UintTy::U8)) => {
150146
ConstValue::Scalar(Scalar::from_uint(*n, Size::from_bytes(1)))
151147
}
152-
(ast::LitKind::Int(n, _), ty::Uint(ui)) if !neg => trunc(n.get(), *ui),
153-
(ast::LitKind::Int(n, _), ty::Int(i)) => trunc(
154-
if neg { (n.get() as i128).overflowing_neg().0 as u128 } else { n.get() },
155-
i.to_unsigned(),
156-
),
148+
(ast::LitKind::Int(n, _), ty::Uint(_)) if !neg => trunc(n.get()),
149+
(ast::LitKind::Int(n, _), ty::Int(_)) => {
150+
trunc(if neg { (n.get() as i128).overflowing_neg().0 as u128 } else { n.get() })
151+
}
157152
(ast::LitKind::Float(n, _), ty::Float(fty)) => {
158153
parse_float_into_constval(*n, *fty, neg).unwrap()
159154
}

‎compiler/rustc_mir_build/src/builder/scope.rs

+17-20
Original file line numberDiff line numberDiff line change
@@ -305,27 +305,25 @@ impl DropTree {
305305
}
306306

307307
/// Builds the MIR for a given drop tree.
308-
///
309-
/// `blocks` should have the same length as `self.drops`, and may have its
310-
/// first value set to some already existing block.
311308
fn build_mir<'tcx, T: DropTreeBuilder<'tcx>>(
312309
&mut self,
313310
cfg: &mut CFG<'tcx>,
314-
blocks: &mut IndexVec<DropIdx, Option<BasicBlock>>,
315-
) {
311+
root_node: Option<BasicBlock>,
312+
) -> IndexVec<DropIdx, Option<BasicBlock>> {
316313
debug!("DropTree::build_mir(drops = {:#?})", self);
317-
assert_eq!(blocks.len(), self.drops.len());
318314

319-
self.assign_blocks::<T>(cfg, blocks);
320-
self.link_blocks(cfg, blocks)
315+
let mut blocks = self.assign_blocks::<T>(cfg, root_node);
316+
self.link_blocks(cfg, &mut blocks);
317+
318+
blocks
321319
}
322320

323321
/// Assign blocks for all of the drops in the drop tree that need them.
324322
fn assign_blocks<'tcx, T: DropTreeBuilder<'tcx>>(
325323
&mut self,
326324
cfg: &mut CFG<'tcx>,
327-
blocks: &mut IndexVec<DropIdx, Option<BasicBlock>>,
328-
) {
325+
root_node: Option<BasicBlock>,
326+
) -> IndexVec<DropIdx, Option<BasicBlock>> {
329327
// StorageDead statements can share blocks with each other and also with
330328
// a Drop terminator. We iterate through the drops to find which drops
331329
// need their own block.
@@ -342,8 +340,11 @@ impl DropTree {
342340
Own,
343341
}
344342

343+
let mut blocks = IndexVec::from_elem(None, &self.drops);
344+
blocks[ROOT_NODE] = root_node;
345+
345346
let mut needs_block = IndexVec::from_elem(Block::None, &self.drops);
346-
if blocks[ROOT_NODE].is_some() {
347+
if root_node.is_some() {
347348
// In some cases (such as drops for `continue`) the root node
348349
// already has a block. In this case, make sure that we don't
349350
// override it.
@@ -385,6 +386,8 @@ impl DropTree {
385386

386387
debug!("assign_blocks: blocks = {:#?}", blocks);
387388
assert!(entry_points.is_empty());
389+
390+
blocks
388391
}
389392

390393
fn link_blocks<'tcx>(
@@ -1574,10 +1577,7 @@ impl<'a, 'tcx: 'a> Builder<'a, 'tcx> {
15741577
span: Span,
15751578
continue_block: Option<BasicBlock>,
15761579
) -> Option<BlockAnd<()>> {
1577-
let mut blocks = IndexVec::from_elem(None, &drops.drops);
1578-
blocks[ROOT_NODE] = continue_block;
1579-
1580-
drops.build_mir::<ExitScopes>(&mut self.cfg, &mut blocks);
1580+
let blocks = drops.build_mir::<ExitScopes>(&mut self.cfg, continue_block);
15811581
let is_coroutine = self.coroutine.is_some();
15821582

15831583
// Link the exit drop tree to unwind drop tree.
@@ -1633,8 +1633,7 @@ impl<'a, 'tcx: 'a> Builder<'a, 'tcx> {
16331633
let drops = &mut self.scopes.coroutine_drops;
16341634
let cfg = &mut self.cfg;
16351635
let fn_span = self.fn_span;
1636-
let mut blocks = IndexVec::from_elem(None, &drops.drops);
1637-
drops.build_mir::<CoroutineDrop>(cfg, &mut blocks);
1636+
let blocks = drops.build_mir::<CoroutineDrop>(cfg, None);
16381637
if let Some(root_block) = blocks[ROOT_NODE] {
16391638
cfg.terminate(
16401639
root_block,
@@ -1670,9 +1669,7 @@ impl<'a, 'tcx: 'a> Builder<'a, 'tcx> {
16701669
fn_span: Span,
16711670
resume_block: &mut Option<BasicBlock>,
16721671
) {
1673-
let mut blocks = IndexVec::from_elem(None, &drops.drops);
1674-
blocks[ROOT_NODE] = *resume_block;
1675-
drops.build_mir::<Unwind>(cfg, &mut blocks);
1672+
let blocks = drops.build_mir::<Unwind>(cfg, *resume_block);
16761673
if let (None, Some(resume)) = (*resume_block, blocks[ROOT_NODE]) {
16771674
cfg.terminate(resume, SourceInfo::outermost(fn_span), TerminatorKind::UnwindResume);
16781675

‎compiler/rustc_monomorphize/messages.ftl

+7
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

+9
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

+69-12
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,61 @@ fn do_check_abi<'tcx>(
8892
}
8993
}
9094

95+
/// Determines whether the given argument is passed the same way on the old and new wasm ABIs.
96+
fn wasm_abi_safe<'tcx>(tcx: TyCtxt<'tcx>, arg: &ArgAbi<'tcx, Ty<'tcx>>) -> bool {
97+
if matches!(arg.layout.backend_repr, BackendRepr::Scalar(_)) {
98+
return true;
99+
}
100+
101+
// This matches `unwrap_trivial_aggregate` in the wasm ABI logic.
102+
if arg.layout.is_aggregate() {
103+
let cx = LayoutCx::new(tcx, TypingEnv::fully_monomorphized());
104+
if let Some(unit) = arg.layout.homogeneous_aggregate(&cx).ok().and_then(|ha| ha.unit()) {
105+
let size = arg.layout.size;
106+
// Ensure there's just a single `unit` element in `arg`.
107+
if unit.size == size {
108+
return true;
109+
}
110+
}
111+
}
112+
113+
false
114+
}
115+
116+
/// Warns against usage of `extern "C"` on wasm32-unknown-unknown that is affected by the
117+
/// ABI transition.
118+
fn do_check_wasm_abi<'tcx>(
119+
tcx: TyCtxt<'tcx>,
120+
abi: &FnAbi<'tcx, Ty<'tcx>>,
121+
is_call: bool,
122+
span: impl Fn() -> Span,
123+
) {
124+
// 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`),
125+
// and only proceed if `wasm_c_abi_opt` indicates we should emit the lint.
126+
if !(tcx.sess.target.arch == "wasm32"
127+
&& tcx.sess.target.os == "unknown"
128+
&& tcx.wasm_c_abi_opt() == WasmCAbi::Legacy { with_lint: true }
129+
&& abi.conv == Conv::C)
130+
{
131+
return;
132+
}
133+
// Warn against all types whose ABI will change. Return values are not affected by this change.
134+
for arg_abi in abi.args.iter() {
135+
if wasm_abi_safe(tcx, arg_abi) {
136+
continue;
137+
}
138+
let span = span();
139+
tcx.emit_node_span_lint(
140+
WASM_C_ABI,
141+
CRATE_HIR_ID,
142+
span,
143+
errors::WasmCAbiTransition { ty: arg_abi.layout.ty, is_call },
144+
);
145+
// Let's only warn once per function.
146+
break;
147+
}
148+
}
149+
91150
/// Checks that the ABI of a given instance of a function does not contain vector-passed arguments
92151
/// or return values for which the corresponding target feature is not enabled.
93152
fn check_instance_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) {
@@ -98,13 +157,10 @@ fn check_instance_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) {
98157
// function.
99158
return;
100159
};
101-
do_check_abi(
102-
tcx,
103-
abi,
104-
instance.def_id(),
105-
/*is_call*/ false,
106-
|| tcx.def_span(instance.def_id()),
107-
)
160+
do_check_simd_vector_abi(tcx, abi, instance.def_id(), /*is_call*/ false, || {
161+
tcx.def_span(instance.def_id())
162+
});
163+
do_check_wasm_abi(tcx, abi, /*is_call*/ false, || tcx.def_span(instance.def_id()));
108164
}
109165

110166
/// Checks that a call expression does not try to pass a vector-passed argument which requires a
@@ -141,7 +197,8 @@ fn check_call_site_abi<'tcx>(
141197
// ABI failed to compute; this will not get through codegen.
142198
return;
143199
};
144-
do_check_abi(tcx, callee_abi, caller.def_id(), /*is_call*/ true, || span);
200+
do_check_simd_vector_abi(tcx, callee_abi, caller.def_id(), /*is_call*/ true, || span);
201+
do_check_wasm_abi(tcx, callee_abi, /*is_call*/ true, || span);
145202
}
146203

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

‎compiler/rustc_resolve/src/build_reduced_graph.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1115,7 +1115,6 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
11151115
}
11161116
});
11171117
} else {
1118-
#[allow(rustc::potential_query_instability)] // FIXME
11191118
for ident in single_imports.iter().cloned() {
11201119
let result = self.r.maybe_resolve_ident_in_module(
11211120
ModuleOrUniformRoot::Module(module),
There was a problem loading the remainder of the diff.

0 commit comments

Comments
 (0)
Failed to load comments.