From 95d54f9d68a588467ddc65574ea1599e5a7a15b1 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon, 17 Aug 2026 17:15:59 +0200 Subject: [PATCH 1/5] Remove emit_almost_fatal A fatal error that doesn't actually abort is indistinguishable from a regular error. And the only places where emit_almost_fatal is called, the produced FatalError is ignored. --- example/mini_core.rs | 1 + src/abi/pass_mode.rs | 4 +- src/base.rs | 1 + src/cast.rs | 4 - src/codegen_f16_f128.rs | 4 - src/driver/aot.rs | 1 + src/driver/jit.rs | 4 +- src/global_asm.rs | 1 + src/inline_asm.rs | 7 +- src/intrinsics/mod.rs | 167 ++++++++++++++++++++++------------------ 10 files changed, 105 insertions(+), 89 deletions(-) diff --git a/example/mini_core.rs b/example/mini_core.rs index 40ce0bf30d..08adec96a0 100644 --- a/example/mini_core.rs +++ b/example/mini_core.rs @@ -6,6 +6,7 @@ extern_types, decl_macro, rustc_attrs, + rustc_private, transparent_unions, pattern_types, auto_traits, diff --git a/src/abi/pass_mode.rs b/src/abi/pass_mode.rs index c4d4ddcf6b..1c552ca1a9 100644 --- a/src/abi/pass_mode.rs +++ b/src/abi/pass_mode.rs @@ -122,8 +122,8 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> { } _ => unreachable!("{:?}", self.layout.backend_repr), }, - PassMode::Cast { ref cast, pad_i32 } => { - assert!(!pad_i32, "padding support not yet implemented"); + PassMode::Cast { ref cast, pad_i32_count } => { + assert_eq!(pad_i32_count, 0, "padding support not yet implemented"); cast_target_to_abi_params(cast).into_iter().map(|(_, param)| param).collect() } PassMode::Indirect { attrs, meta_attrs: None, on_stack } => { diff --git a/src/base.rs b/src/base.rs index 2f6bb30df8..506037c151 100644 --- a/src/base.rs +++ b/src/base.rs @@ -997,6 +997,7 @@ pub(crate) fn codegen_place<'tcx>( PlaceElem::Deref => { cplace = cplace.place_deref(fx); } + PlaceElem::PhantomDeref => bug!("encountered PhantomDeref in codegen"), PlaceElem::OpaqueCast(ty) => bug!("encountered OpaqueCast({ty}) in codegen"), PlaceElem::UnwrapUnsafeBinder(ty) => { cplace = cplace.place_transmute_type(fx, fx.monomorphize(ty)); diff --git a/src/cast.rs b/src/cast.rs index f124739d1e..abf4326f91 100644 --- a/src/cast.rs +++ b/src/cast.rs @@ -148,10 +148,6 @@ pub(crate) fn clif_int_or_float_cast( fx.bcx.ins().fcvt_to_uint_sat(to_ty, from) }; - if let Some(false) = fx.tcx.sess.opts.unstable_opts.saturating_float_casts { - return val; - } - let is_not_nan = fx.bcx.ins().fcmp(FloatCC::Equal, from, from); let zero = type_zero_value(&mut fx.bcx, to_ty); fx.bcx.ins().select(is_not_nan, val, zero) diff --git a/src/codegen_f16_f128.rs b/src/codegen_f16_f128.rs index 3dbd59c2fc..09762f1a45 100644 --- a/src/codegen_f16_f128.rs +++ b/src/codegen_f16_f128.rs @@ -265,10 +265,6 @@ pub(crate) fn codegen_cast( fx.bcx.ins().ireduce(to_ty, val) }; - if let Some(false) = fx.tcx.sess.opts.unstable_opts.saturating_float_casts { - return val; - } - let is_not_nan = fcmp(fx, FloatCC::Equal, from, from); let zero = type_zero_value(&mut fx.bcx, to_ty); fx.bcx.ins().select(is_not_nan, val, zero) diff --git a/src/driver/aot.rs b/src/driver/aot.rs index d6c25cf524..e065490902 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -284,6 +284,7 @@ impl ExtraBackendMethods for AotDriver { &self, tcx: TyCtxt<'_>, cgu_name: Symbol, + _bitcode_needed: bool, ) -> (ModuleCodegen, u64) { let start_time = Instant::now(); diff --git a/src/driver/jit.rs b/src/driver/jit.rs index 32f6061584..8bf1cd9bf8 100644 --- a/src/driver/jit.rs +++ b/src/driver/jit.rs @@ -37,7 +37,7 @@ fn create_jit_module( } pub(crate) fn run_jit(tcx: TyCtxt<'_>, target_cpu: String, jit_args: Vec) -> ! { - if !tcx.crate_types().contains(&rustc_session::config::CrateType::Executable) { + if !tcx.crate_types().contains(&rustc_structures::CrateType::Executable) { tcx.dcx().fatal("can't jit non-executable crate"); } @@ -180,7 +180,7 @@ fn dep_symbol_lookup_fn( let mut dylib_paths = Vec::new(); - let data = &crate_info.dependency_formats[&rustc_session::config::CrateType::Executable]; + let data = &crate_info.dependency_formats[&rustc_structures::CrateType::Executable]; // `used_crates` is in reverse postorder in terms of dependencies. Reverse the order here to // get a postorder which ensures that all dependencies of a dylib are loaded before the dylib // itself. This helps the dynamic linker to find dylibs not in the regular dynamic library diff --git a/src/global_asm.rs b/src/global_asm.rs index 9763b0c0fa..c5b164b8e9 100644 --- a/src/global_asm.rs +++ b/src/global_asm.rs @@ -30,6 +30,7 @@ impl<'tcx> AsmCodegenMethods<'tcx> for GlobalAsmContext<'_, 'tcx> { operands: &[GlobalAsmOperandRef<'tcx>], options: InlineAsmOptions, _line_spans: &[Span], + _extra_rust_target_features: &[String], ) { codegen_global_asm_inner(self.tcx, self.global_asm, template, operands, options); } diff --git a/src/inline_asm.rs b/src/inline_asm.rs index d4d64cb3fb..cd2b06cc1d 100644 --- a/src/inline_asm.rs +++ b/src/inline_asm.rs @@ -443,11 +443,12 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> { .supported_types(self.arch, true) .iter() .map(|(ty, _)| ty.size()) + .filter_map(InlineAsmSize::fixed_size_bytes) .max() - .unwrap(); - let align = rustc_abi::Align::from_bytes(reg_size.bytes()).unwrap(); + .expect("expected fixed-size type"); + let align = rustc_abi::Align::from_bytes(reg_size).unwrap(); let offset = slot_size.align_to(align); - *slot_size = offset + reg_size; + *slot_size = offset + rustc_abi::Size::from_bytes(reg_size); offset }; let mut new_slot = |x| new_slot_fn(&mut slot_size, x); diff --git a/src/intrinsics/mod.rs b/src/intrinsics/mod.rs index 4a779e2287..cf1c1f027e 100644 --- a/src/intrinsics/mod.rs +++ b/src/intrinsics/mod.rs @@ -322,16 +322,6 @@ fn codegen_float_intrinsic_call<'tcx>( ret: CPlace<'tcx>, ) -> bool { let (name, arg_count, ty, clif_ty) = match intrinsic { - sym::expf16 => return false, // has a fallback via f32 - sym::expf32 => ("expf", 1, fx.tcx.types.f32, types::F32), - sym::expf64 => ("exp", 1, fx.tcx.types.f64, types::F64), - sym::expf128 => ("expf128", 1, fx.tcx.types.f128, types::F128), - - sym::exp2f16 => return false, // has a fallback via f32 - sym::exp2f32 => ("exp2f", 1, fx.tcx.types.f32, types::F32), - sym::exp2f64 => ("exp2", 1, fx.tcx.types.f64, types::F64), - sym::exp2f128 => ("exp2f128", 1, fx.tcx.types.f128, types::F128), - sym::sqrtf16 => return false, // has a fallback via f32 sym::sqrtf32 => ("sqrtf", 1, fx.tcx.types.f32, types::F32), sym::sqrtf64 => ("sqrt", 1, fx.tcx.types.f64, types::F64), @@ -347,22 +337,7 @@ fn codegen_float_intrinsic_call<'tcx>( sym::powf64 => ("pow", 2, fx.tcx.types.f64, types::F64), sym::powf128 => ("powf128", 2, fx.tcx.types.f128, types::F128), - sym::logf16 => return false, // has a fallback via f32 - sym::logf32 => ("logf", 1, fx.tcx.types.f32, types::F32), - sym::logf64 => ("log", 1, fx.tcx.types.f64, types::F64), - sym::logf128 => ("logf128", 1, fx.tcx.types.f128, types::F128), - - sym::log2f16 => return false, // has a fallback via f32 - sym::log2f32 => ("log2f", 1, fx.tcx.types.f32, types::F32), - sym::log2f64 => ("log2", 1, fx.tcx.types.f64, types::F64), - sym::log2f128 => ("log2f128", 1, fx.tcx.types.f128, types::F128), - - sym::log10f16 => return false, // has a fallback via f32 - sym::log10f32 => ("log10f", 1, fx.tcx.types.f32, types::F32), - sym::log10f64 => ("log10", 1, fx.tcx.types.f64, types::F64), - sym::log10f128 => ("log10f128", 1, fx.tcx.types.f128, types::F128), - - sym::fmaf16 => return false, // has a fallback via f32 + sym::fmaf16 => return false, // has a fallback via f64 sym::fmaf32 => ("fmaf", 3, fx.tcx.types.f32, types::F32), sym::fmaf64 => ("fma", 3, fx.tcx.types.f64, types::F64), sym::fmaf128 => ("fmaf128", 3, fx.tcx.types.f128, types::F128), @@ -404,16 +379,6 @@ fn codegen_float_intrinsic_call<'tcx>( sym::roundf64 => ("round", 1, fx.tcx.types.f64, types::F64), sym::roundf128 => ("roundf128", 1, fx.tcx.types.f128, types::F128), - sym::sinf16 => return false, // has a fallback via f32 - sym::sinf32 => ("sinf", 1, fx.tcx.types.f32, types::F32), - sym::sinf64 => ("sin", 1, fx.tcx.types.f64, types::F64), - sym::sinf128 => ("sinf128", 1, fx.tcx.types.f128, types::F128), - - sym::cosf16 => return false, // has a fallback via f32 - sym::cosf32 => ("cosf", 1, fx.tcx.types.f32, types::F32), - sym::cosf64 => ("cos", 1, fx.tcx.types.f64, types::F64), - sym::cosf128 => ("cosf128", 1, fx.tcx.types.f128, types::F128), - _ => return false, }; @@ -448,36 +413,16 @@ fn codegen_float_intrinsic_call<'tcx>( let layout = fx.layout_of(ty); // FIXME(bytecodealliance/wasmtime#8312): Use native Cranelift operations // for `f16` and `f128` once the lowerings have been implemented in Cranelift. - let res = match intrinsic { + let val = match intrinsic { sym::fmaf32 | sym::fmaf64 | sym::fmuladdf32 | sym::fmuladdf64 => { - CValue::by_val(fx.bcx.ins().fma(args[0], args[1], args[2]), layout) - } - sym::copysignf32 | sym::copysignf64 => { - CValue::by_val(fx.bcx.ins().fcopysign(args[0], args[1]), layout) - } - sym::floorf32 - | sym::floorf64 - | sym::ceilf32 - | sym::ceilf64 - | sym::truncf32 - | sym::truncf64 - | sym::round_ties_even_f32 - | sym::round_ties_even_f64 - | sym::sqrtf32 - | sym::sqrtf64 => { - let val = match intrinsic { - sym::floorf32 | sym::floorf64 => fx.bcx.ins().floor(args[0]), - sym::ceilf32 | sym::ceilf64 => fx.bcx.ins().ceil(args[0]), - sym::truncf32 | sym::truncf64 => fx.bcx.ins().trunc(args[0]), - sym::round_ties_even_f32 | sym::round_ties_even_f64 => { - fx.bcx.ins().nearest(args[0]) - } - sym::sqrtf32 | sym::sqrtf64 => fx.bcx.ins().sqrt(args[0]), - _ => unreachable!(), - }; - - CValue::by_val(val, layout) + fx.bcx.ins().fma(args[0], args[1], args[2]) } + sym::copysignf32 | sym::copysignf64 => fx.bcx.ins().fcopysign(args[0], args[1]), + sym::floorf32 | sym::floorf64 => fx.bcx.ins().floor(args[0]), + sym::ceilf32 | sym::ceilf64 => fx.bcx.ins().ceil(args[0]), + sym::truncf32 | sym::truncf64 => fx.bcx.ins().trunc(args[0]), + sym::round_ties_even_f32 | sym::round_ties_even_f64 => fx.bcx.ins().nearest(args[0]), + sym::sqrtf32 | sym::sqrtf64 => fx.bcx.ins().sqrt(args[0]), // These intrinsics aren't supported natively by Cranelift. // Lower them to a libcall. @@ -492,20 +437,19 @@ fn codegen_float_intrinsic_call<'tcx>( let input_tys: Vec<_> = vec![AbiParam::new(clif_ty), lib_call_arg_param(fx.tcx, types::I32, true)]; let ret_val = fx.lib_call(name, input_tys, vec![AbiParam::new(clif_ty)], args)[0]; - let ret_val = if intrinsic == sym::powif16 { + if intrinsic == sym::powif16 { codegen_f16_f128::f32_to_f16(fx, ret_val) } else { ret_val - }; - CValue::by_val(ret_val, fx.layout_of(ty)) + } } _ => { let input_tys: Vec<_> = args.iter().map(|_| AbiParam::new(clif_ty)).collect(); - let ret_val = fx.lib_call(name, input_tys, vec![AbiParam::new(clif_ty)], args)[0]; - CValue::by_val(ret_val, fx.layout_of(ty)) + fx.lib_call(name, input_tys, vec![AbiParam::new(clif_ty)], args)[0] } }; + let res = CValue::by_val(val, layout); ret.write_cvalue(fx, res); true @@ -630,6 +574,26 @@ fn codegen_regular_intrinsic_call<'tcx>( let res = crate::num::codegen_int_binop(fx, BinOp::Div, x, y); ret.write_cvalue(fx, res); } + // FIXME: remove the guard here once `umin.i128` and friends are supported + // cc https://github.com/bytecodealliance/wasmtime/issues/13790 + sym::integer_max | sym::integer_min if ret.layout().size <= Size::from_bits(64) => { + intrinsic_args!(fx, args => (lhs, rhs); intrinsic); + + assert_eq!(lhs.layout().ty, rhs.layout().ty); + let signed = type_sign(lhs.layout().ty); + let lhs = lhs.load_scalar(fx); + let rhs = rhs.load_scalar(fx); + let res = match (intrinsic, signed) { + (sym::integer_max, false) => fx.bcx.ins().umax(lhs, rhs), + (sym::integer_max, true) => fx.bcx.ins().smax(lhs, rhs), + (sym::integer_min, false) => fx.bcx.ins().umin(lhs, rhs), + (sym::integer_min, true) => fx.bcx.ins().smin(lhs, rhs), + _ => unreachable!(), + }; + + let res = CValue::by_val(res, ret.layout()); + ret.write_cvalue(fx, res); + } sym::saturating_add | sym::saturating_sub => { intrinsic_args!(fx, args => (lhs, rhs); intrinsic); @@ -1199,7 +1163,14 @@ fn codegen_regular_intrinsic_call<'tcx>( ret.write_cvalue(fx, old); } - sym::fabs => { + sym::fabs + | sym::exp + | sym::exp2 + | sym::log + | sym::log2 + | sym::log10 + | sym::sin + | sym::cos => { intrinsic_args!(fx, args => (arg); intrinsic); let layout = arg.layout(); let ty::Float(float_ty) = layout.ty.kind() else { @@ -1209,13 +1180,61 @@ fn codegen_regular_intrinsic_call<'tcx>( layout.ty ); }; + enum IntrinsicFallback { + Fallback(&'static str), + Codegen(Value), + } + use FloatTy::*; + use IntrinsicFallback::*; let x = arg.load_scalar(fx); - let val = match float_ty { - FloatTy::F32 | FloatTy::F64 => fx.bcx.ins().fabs(x), + let res = match (intrinsic, float_ty) { + (sym::fabs, F32 | F64) => Codegen(fx.bcx.ins().fabs(x)), // FIXME(bytecodealliance/wasmtime#8312): Use `fabsf16` once Cranelift // backend lowerings are implemented. - FloatTy::F16 => codegen_f16_f128::abs_f16(fx, x), - FloatTy::F128 => codegen_f16_f128::abs_f128(fx, x), + (sym::fabs, F16) => Codegen(codegen_f16_f128::abs_f16(fx, x)), + (sym::fabs, F128) => Codegen(codegen_f16_f128::abs_f128(fx, x)), + + (sym::exp, F32) => Fallback("expf"), + (sym::exp, F64) => Fallback("exp"), + (sym::exp, F128) => Fallback("expf128"), + + (sym::exp2, F32) => Fallback("exp2f"), + (sym::exp2, F64) => Fallback("exp2"), + (sym::exp2, F128) => Fallback("exp2f128"), + + (sym::log, F32) => Fallback("logf"), + (sym::log, F64) => Fallback("log"), + (sym::log, F128) => Fallback("logf128"), + + (sym::log2, F32) => Fallback("log2f"), + (sym::log2, F64) => Fallback("log2"), + (sym::log2, F128) => Fallback("log2f128"), + + (sym::log10, F32) => Fallback("log10f"), + (sym::log10, F64) => Fallback("log10"), + (sym::log10, F128) => Fallback("log10f128"), + + (sym::sin, F32) => Fallback("sinf"), + (sym::sin, F64) => Fallback("sin"), + (sym::sin, F128) => Fallback("sinf128"), + + (sym::cos, F32) => Fallback("cosf"), + (sym::cos, F64) => Fallback("cos"), + (sym::cos, F128) => Fallback("cosf128"), + + (_, F16) => { + // We implement fallbacks for other f16 intrinsics via f32 + return Err(Instance::new_raw(instance.def_id(), instance.args)); + } + + _ => unreachable!(), + }; + let val = match res { + Codegen(val) => val, + Fallback(name) => { + let ty = fx.clif_type(layout.ty).unwrap(); + fx.lib_call(name, vec![AbiParam::new(ty)], vec![AbiParam::new(ty)], &[x])[0] + } }; let val = CValue::by_val(val, layout); ret.write_cvalue(fx, val); From fd9224830c21ae00bf62388770424dff343505ce Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon, 31 Aug 2026 12:56:40 +0200 Subject: [PATCH 2/5] Don't rely on codegen emitting fn_abi_of_* errors in abi checks This avoids a delayed bug if compilation is aborted between checking function ABIs and codegening all functions. --- src/common.rs | 21 +++------------------ 1 file changed, 3 insertions(+), 18 deletions(-) diff --git a/src/common.rs b/src/common.rs index 1bdb3efefa..d31c8fc810 100644 --- a/src/common.rs +++ b/src/common.rs @@ -5,8 +5,9 @@ use rustc_index::IndexVec; use rustc_middle::ty::TypeFoldable; use rustc_middle::ty::layout::{ self, FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOfHelpers, + codegen_handle_fn_abi_err, }; -use rustc_span::{Spanned, Symbol}; +use rustc_span::Symbol; use rustc_target::callconv::FnAbi; use rustc_target::spec::{Arch, HasTargetSpec, Target}; @@ -453,23 +454,7 @@ impl<'tcx> FnAbiOfHelpers<'tcx> for FullyMonomorphizedLayoutCx<'tcx> { span: Span, fn_abi_request: FnAbiRequest<'tcx>, ) -> ! { - if let FnAbiError::Layout(LayoutError::SizeOverflow(_) | LayoutError::InvalidSimd { .. }) = - err - { - self.0.sess.dcx().emit_fatal(Spanned { span, node: err }) - } else { - match fn_abi_request { - FnAbiRequest::OfFnPtr { sig, extra_args } => { - span_bug!(span, "`fn_abi_of_fn_ptr({sig}, {extra_args:?})` failed: {err:?}"); - } - FnAbiRequest::OfInstance { instance, extra_args } => { - span_bug!( - span, - "`fn_abi_of_instance({instance}, {extra_args:?})` failed: {err:?}" - ); - } - } - } + codegen_handle_fn_abi_err(self.0, err, span, fn_abi_request).raise_fatal() } } From 106755942c461b6d63ed4aa7f734b59e97546541 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Fri, 11 Sep 2026 15:17:07 +0200 Subject: [PATCH 3/5] Initial josh-sync configuration --- josh-sync.toml | 3 +++ rust-version | 0 2 files changed, 3 insertions(+) create mode 100644 josh-sync.toml create mode 100644 rust-version diff --git a/josh-sync.toml b/josh-sync.toml new file mode 100644 index 0000000000..2de9f9489c --- /dev/null +++ b/josh-sync.toml @@ -0,0 +1,3 @@ +repo = "rustc_codegen_cranelift" +filter = ":~(history=\"keep-trivial-merges,no-splice\")[:rev(<=5e120485964f4857f1ad70f7d661fd244d087668:prefix=compiler/rustc_codegen_cranelift,<=7bd21608dfab11ea536f7be8936cc7dfac5864fb:SQUASH)]:/compiler/rustc_codegen_cranelift" +filter-version = 2 diff --git a/rust-version b/rust-version new file mode 100644 index 0000000000..e69de29bb2 From 4967f3320d167b65ad50c9c6ef081801ac8aea61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Fri, 11 Sep 2026 15:17:10 +0200 Subject: [PATCH 4/5] Prepare for merging from rust-lang/rust This updates the rust-version file to ca0a6473ffde01deb7fce24cc04864cf723e14a0. --- rust-version | 1 + 1 file changed, 1 insertion(+) diff --git a/rust-version b/rust-version index e69de29bb2..4dce583659 100644 --- a/rust-version +++ b/rust-version @@ -0,0 +1 @@ +ca0a6473ffde01deb7fce24cc04864cf723e14a0 From e2c67be98fae648e67a5ed211b9c0c90bb5aeed3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Fri, 11 Sep 2026 17:09:03 +0200 Subject: [PATCH 5/5] Update nightly version --- rust-toolchain.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain.toml b/rust-toolchain.toml index b83354ee49..d7e313a7a3 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2026-09-10" +channel = "nightly-2026-09-11" components = ["rust-src", "rustc-dev", "llvm-tools", "rustfmt"] profile = "minimal"