diff --git a/Cargo.lock b/Cargo.lock index 45020437fd903..e27b49ca29046 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1217,9 +1217,9 @@ dependencies = [ [[package]] name = "dispatch2" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec" +checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" dependencies = [ "bitflags", "block2", diff --git a/compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs b/compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs index a60e2d1f0ab09..18a95e810bee4 100644 --- a/compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs +++ b/compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs @@ -3,11 +3,12 @@ use std::ffi::CString; use bitflags::Flags; use llvm::Linkage::*; use rustc_abi::Align; +use rustc_codegen_ssa::MemFlags; use rustc_codegen_ssa::common::TypeKind; use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue}; use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, BuilderMethods}; use rustc_middle::bug; -use rustc_middle::ty::offload_meta::{MappingFlags, OffloadMetadata}; +use rustc_middle::ty::offload_meta::{MappingFlags, OffloadMetadata, OffloadSize}; use crate::builder::Builder; use crate::common::CodegenCx; @@ -450,7 +451,15 @@ pub(crate) fn gen_define_handling<'ll>( // FIXME(offload): add `OMP_MAP_TARGET_PARAM = 0x20` only if necessary let transfer_kernel = vec![MappingFlags::TARGET_PARAM.bits(); transfer_to.len()]; - let offload_sizes = add_priv_unnamed_arr(&cx, &format!(".offload_sizes.{symbol}"), &sizes); + let actual_sizes = sizes + .iter() + .map(|s| match s { + OffloadSize::Static(sz) => *sz, + OffloadSize::Dynamic => 0, + }) + .collect::>(); + let offload_sizes = + add_priv_unnamed_arr(&cx, &format!(".offload_sizes.{symbol}"), &actual_sizes); let memtransfer_begin = add_priv_unnamed_arr(&cx, &format!(".offload_maptypes.{symbol}.begin"), &transfer_to); let memtransfer_kernel = @@ -499,9 +508,6 @@ pub(crate) fn gen_define_handling<'ll>( region_id, }; - // FIXME(Sa4dUs): use this global for constant offload sizes - cx.add_compiler_used_global(result.offload_sizes); - cx.offload_kernel_cache.borrow_mut().insert(symbol, result); result @@ -535,6 +541,15 @@ pub(crate) fn scalar_width<'ll>(cx: &'ll SimpleCx<'_>, ty: &'ll Type) -> u64 { } } +fn get_runtime_size<'ll, 'tcx>( + _cx: &CodegenCx<'ll, 'tcx>, + _val: &'ll Value, + _meta: &OffloadMetadata, +) -> &'ll Value { + // FIXME(Sa4dUs): handle dynamic-size data (e.g. slices) + bug!("offload does not support dynamic sizes yet"); +} + // For each kernel *call*, we now use some of our previous declared globals to move data to and from // the gpu. For now, we only handle the data transfer part of it. // If two consecutive kernels use the same memory, we still move it to the host and back to the gpu. @@ -564,15 +579,17 @@ pub(crate) fn gen_call_handling<'ll, 'tcx>( ) { let cx = builder.cx; let OffloadKernelGlobals { + offload_sizes, memtransfer_begin, memtransfer_kernel, memtransfer_end, region_id, - .. } = offload_data; let OffloadKernelDims { num_workgroups, threads_per_block, workgroup_dims, thread_dims } = offload_dims; + let has_dynamic = metadata.iter().any(|m| matches!(m.payload_size, OffloadSize::Dynamic)); + let tgt_decl = offload_globals.launcher_fn; let tgt_target_kernel_ty = offload_globals.launcher_ty; @@ -596,7 +613,24 @@ pub(crate) fn gen_call_handling<'ll, 'tcx>( let a2 = builder.direct_alloca(ty, Align::EIGHT, ".offload_ptrs"); // These represent the sizes in bytes, e.g. the entry for `&[f64; 16]` will be 8*16. let ty2 = cx.type_array(cx.type_i64(), num_args); - let a4 = builder.direct_alloca(ty2, Align::EIGHT, ".offload_sizes"); + + let a4 = if has_dynamic { + let alloc = builder.direct_alloca(ty2, Align::EIGHT, ".offload_sizes"); + + builder.memcpy( + alloc, + Align::EIGHT, + offload_sizes, + Align::EIGHT, + cx.get_const_i64(8 * args.len() as u64), + MemFlags::empty(), + None, + ); + + alloc + } else { + offload_sizes + }; //%kernel_args = alloca %struct.__tgt_kernel_arguments, align 8 let a5 = builder.direct_alloca(tgt_kernel_decl, Align::EIGHT, "kernel_args"); @@ -648,9 +682,12 @@ pub(crate) fn gen_call_handling<'ll, 'tcx>( builder.store(vals[i as usize], gep1, Align::EIGHT); let gep2 = builder.inbounds_gep(ty, a2, &[i32_0, idx]); builder.store(geps[i as usize], gep2, Align::EIGHT); - let gep3 = builder.inbounds_gep(ty2, a4, &[i32_0, idx]); - // FIXME(offload): write an offload frontend and handle arbitrary types. - builder.store(cx.get_const_i64(metadata[i as usize].payload_size), gep3, Align::EIGHT); + + if matches!(metadata[i as usize].payload_size, OffloadSize::Dynamic) { + let gep3 = builder.inbounds_gep(ty2, a4, &[i32_0, idx]); + let size_val = get_runtime_size(cx, args[i as usize], &metadata[i as usize]); + builder.store(size_val, gep3, Align::EIGHT); + } } // For now we have a very simplistic indexing scheme into our @@ -662,13 +699,14 @@ pub(crate) fn gen_call_handling<'ll, 'tcx>( a1: &'ll Value, a2: &'ll Value, a4: &'ll Value, + is_dynamic: bool, ) -> [&'ll Value; 3] { let cx = builder.cx; let i32_0 = cx.get_const_i32(0); let gep1 = builder.inbounds_gep(ty, a1, &[i32_0, i32_0]); let gep2 = builder.inbounds_gep(ty, a2, &[i32_0, i32_0]); - let gep3 = builder.inbounds_gep(ty2, a4, &[i32_0, i32_0]); + let gep3 = if is_dynamic { builder.inbounds_gep(ty2, a4, &[i32_0, i32_0]) } else { a4 }; [gep1, gep2, gep3] } @@ -692,7 +730,7 @@ pub(crate) fn gen_call_handling<'ll, 'tcx>( // Step 2) let s_ident_t = offload_globals.ident_t_global; - let geps = get_geps(builder, ty, ty2, a1, a2, a4); + let geps = get_geps(builder, ty, ty2, a1, a2, a4, has_dynamic); generate_mapper_call( builder, geps, @@ -725,7 +763,7 @@ pub(crate) fn gen_call_handling<'ll, 'tcx>( // %41 = call i32 @__tgt_target_kernel(ptr @1, i64 -1, i32 2097152, i32 256, ptr @.kernel_1.region_id, ptr %kernel_args) // Step 4) - let geps = get_geps(builder, ty, ty2, a1, a2, a4); + let geps = get_geps(builder, ty, ty2, a1, a2, a4, has_dynamic); generate_mapper_call( builder, geps, diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 0d42ccc1a73c9..cf643931717be 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -1256,55 +1256,37 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } CallKind::Tail => { - match fn_abi.args[i].mode { - PassMode::Indirect { on_stack: false, .. } => { - let Some(tmp) = tail_call_temporaries[i].take() else { - span_bug!( - fn_span, - "missing temporary for indirect tail call argument #{i}" - ) - }; - - let local = self.mir.args_iter().nth(i).unwrap(); - - match &self.locals[local] { - LocalRef::Place(arg) => { - bx.typed_place_copy(arg.val, tmp.val, fn_abi.args[i].layout); - op.val = Ref(arg.val); - } - LocalRef::Operand(arg) => { - let Ref(place_value) = arg.val else { - bug!("only `Ref` should use `PassMode::Indirect`"); - }; - bx.typed_place_copy( - place_value, - tmp.val, - fn_abi.args[i].layout, - ); - op.val = arg.val; - } - LocalRef::UnsizedPlace(_) => { - span_bug!(fn_span, "unsized types are not supported") - } - LocalRef::PendingOperand => { - span_bug!(fn_span, "argument local should not be pending") - } - }; - - bx.lifetime_end(tmp.val.llval, tmp.layout.size); - } - PassMode::Indirect { on_stack: true, .. } => { - // FIXME: some LLVM backends (notably x86) do not correctly pass byval - // arguments to tail calls (as of LLVM 21). See also: - // - // - https://github.com/rust-lang/rust/pull/144232#discussion_r2218543841 - // - https://github.com/rust-lang/rust/issues/144855 + if let PassMode::Indirect { on_stack: false, .. } = fn_abi.args[i].mode { + let Some(tmp) = tail_call_temporaries[i].take() else { span_bug!( fn_span, - "arguments using PassMode::Indirect {{ on_stack: true, .. }} are currently not supported for tail calls" + "missing temporary for indirect tail call argument #{i}" ) - } - _ => (), + }; + + let local = self.mir.args_iter().nth(i).unwrap(); + + match &self.locals[local] { + LocalRef::Place(arg) => { + bx.typed_place_copy(arg.val, tmp.val, fn_abi.args[i].layout); + op.val = Ref(arg.val); + } + LocalRef::Operand(arg) => { + let Ref(place_value) = arg.val else { + bug!("only `Ref` should use `PassMode::Indirect`"); + }; + bx.typed_place_copy(place_value, tmp.val, fn_abi.args[i].layout); + op.val = arg.val; + } + LocalRef::UnsizedPlace(_) => { + span_bug!(fn_span, "unsized types are not supported") + } + LocalRef::PendingOperand => { + span_bug!(fn_span, "argument local should not be pending") + } + }; + + bx.lifetime_end(tmp.val.llval, tmp.layout.size); } } } diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs index 9d3da6ef49302..dc6e3b1f358dc 100644 --- a/compiler/rustc_lexer/src/lib.rs +++ b/compiler/rustc_lexer/src/lib.rs @@ -367,7 +367,8 @@ pub fn is_whitespace(c: char) -> bool { /// True if `c` is considered horizontal whitespace according to Rust language definition. pub fn is_horizontal_whitespace(c: char) -> bool { - // This is Pattern_White_Space. + // This is the horizontal space subset of `Pattern_White_Space` as + // categorized by UAX #31, Section 4.1. // // Note that this set is stable (ie, it doesn't change with different // Unicode versions), so it's ok to just hard-code the values. diff --git a/compiler/rustc_llvm/build.rs b/compiler/rustc_llvm/build.rs index 7a1c95da29ea1..45d5bbd020f43 100644 --- a/compiler/rustc_llvm/build.rs +++ b/compiler/rustc_llvm/build.rs @@ -476,7 +476,7 @@ fn main() { // C++ runtime library if !target.contains("msvc") { if let Some(s) = llvm_static_stdcpp { - assert!(cxxflags_iter.all(|flag| flag != "stdlib=libc++")); + assert!(cxxflags_iter.all(|flag| flag != "-stdlib=libc++")); let path = PathBuf::from(s); println!("cargo:rustc-link-search=native={}", path.parent().unwrap().display()); if target.contains("windows") { @@ -484,7 +484,7 @@ fn main() { } else { println!("cargo:rustc-link-lib=static={stdcppname}"); } - } else if cxxflags_iter.any(|flag| flag == "stdlib=libc++") { + } else if cxxflags_iter.any(|flag| flag == "-stdlib=libc++") { println!("cargo:rustc-link-lib=c++"); } else { println!("cargo:rustc-link-lib={stdcppname}"); diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index ae348c668fb50..e1e69a9d0b262 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -11,7 +11,7 @@ use rustc_macros::HashStable; use rustc_span::{ErrorGuaranteed, Span}; pub use sealed::IntoQueryParam; -use crate::dep_graph::{DepKind, DepNode, DepNodeIndex, SerializedDepNodeIndex}; +use crate::dep_graph::{DepKind, DepNodeIndex, SerializedDepNodeIndex}; use crate::ich::StableHashingContext; use crate::queries::{ExternProviders, Providers, QueryArenas, QueryVTables}; use crate::query::on_disk_cache::OnDiskCache; @@ -113,7 +113,6 @@ pub struct QueryVTable<'tcx, C: QueryCache> { pub cycle_error_handling: CycleErrorHandling, pub state: QueryState<'tcx, C::Key>, pub cache: C, - pub will_cache_on_disk_for_key_fn: Option, key: &C::Key) -> bool>, /// Function pointer that calls `tcx.$query(key)` for this query and /// discards the returned value. @@ -129,17 +128,17 @@ pub struct QueryVTable<'tcx, C: QueryCache> { /// This should be the only code that calls the provider function. pub invoke_provider_fn: fn(tcx: TyCtxt<'tcx>, key: C::Key) -> C::Value, - pub try_load_from_disk_fn: Option< - fn( - tcx: TyCtxt<'tcx>, - key: &C::Key, - prev_index: SerializedDepNodeIndex, - index: DepNodeIndex, - ) -> Option, - >, + pub will_cache_on_disk_for_key_fn: fn(tcx: TyCtxt<'tcx>, key: &C::Key) -> bool, + + pub try_load_from_disk_fn: fn( + tcx: TyCtxt<'tcx>, + key: &C::Key, + prev_index: SerializedDepNodeIndex, + index: DepNodeIndex, + ) -> Option, pub is_loadable_from_disk_fn: - Option, key: &C::Key, index: SerializedDepNodeIndex) -> bool>, + fn(tcx: TyCtxt<'tcx>, key: &C::Key, index: SerializedDepNodeIndex) -> bool, /// Function pointer that hashes this query's result values. /// @@ -180,49 +179,6 @@ impl<'tcx, C: QueryCache> fmt::Debug for QueryVTable<'tcx, C> { } } -impl<'tcx, C: QueryCache> QueryVTable<'tcx, C> { - #[inline(always)] - pub fn will_cache_on_disk_for_key(&self, tcx: TyCtxt<'tcx>, key: &C::Key) -> bool { - self.will_cache_on_disk_for_key_fn.map_or(false, |f| f(tcx, key)) - } - - #[inline(always)] - pub fn try_load_from_disk( - &self, - tcx: TyCtxt<'tcx>, - key: &C::Key, - prev_index: SerializedDepNodeIndex, - index: DepNodeIndex, - ) -> Option { - // `?` will return None immediately for queries that never cache to disk. - self.try_load_from_disk_fn?(tcx, key, prev_index, index) - } - - #[inline] - pub fn is_loadable_from_disk( - &self, - tcx: TyCtxt<'tcx>, - key: &C::Key, - index: SerializedDepNodeIndex, - ) -> bool { - self.is_loadable_from_disk_fn.map_or(false, |f| f(tcx, key, index)) - } - - /// Synthesize an error value to let compilation continue after a cycle. - pub fn value_from_cycle_error( - &self, - tcx: TyCtxt<'tcx>, - cycle_error: CycleError, - guar: ErrorGuaranteed, - ) -> C::Value { - (self.value_from_cycle_error)(tcx, cycle_error, guar) - } - - pub fn construct_dep_node(&self, tcx: TyCtxt<'tcx>, key: &C::Key) -> DepNode { - DepNode::construct(tcx, self.dep_kind, key) - } -} - pub struct QuerySystem<'tcx> { pub arenas: WorkerLocal>, pub query_vtables: QueryVTables<'tcx>, diff --git a/compiler/rustc_middle/src/ty/offload_meta.rs b/compiler/rustc_middle/src/ty/offload_meta.rs index 67c00765ed57b..849670d76d464 100644 --- a/compiler/rustc_middle/src/ty/offload_meta.rs +++ b/compiler/rustc_middle/src/ty/offload_meta.rs @@ -3,10 +3,16 @@ use bitflags::bitflags; use crate::ty::{self, PseudoCanonicalInput, Ty, TyCtxt, TypingEnv}; pub struct OffloadMetadata { - pub payload_size: u64, + pub payload_size: OffloadSize, pub mode: MappingFlags, } +#[derive(Debug, Copy, Clone)] +pub enum OffloadSize { + Dynamic, + Static(u64), +} + bitflags! { /// Mirrors `OpenMPOffloadMappingFlags` from Clang/OpenMP. #[derive(Debug, Copy, Clone)] @@ -59,17 +65,18 @@ impl OffloadMetadata { } // FIXME(Sa4dUs): implement a solid logic to determine the payload size -fn get_payload_size<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> u64 { +fn get_payload_size<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> OffloadSize { match ty.kind() { ty::RawPtr(inner, _) | ty::Ref(_, inner, _) => get_payload_size(tcx, *inner), - _ => tcx - .layout_of(PseudoCanonicalInput { + _ => OffloadSize::Static( + tcx.layout_of(PseudoCanonicalInput { typing_env: TypingEnv::fully_monomorphized(), value: ty, }) .unwrap() .size .bytes(), + ), } } diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 8e6e9af5a4867..02deff6474080 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -645,6 +645,7 @@ impl<'tcx> ThirBuildCx<'tcx> { base, hir::StructTailExpr::None | hir::StructTailExpr::DefaultFields(_) + | hir::StructTailExpr::NoneWithError(_) )); let index = adt.variant_index_with_id(variant_id); diff --git a/compiler/rustc_query_impl/src/execution.rs b/compiler/rustc_query_impl/src/execution.rs index 34be511ad3121..27b6214ed2887 100644 --- a/compiler/rustc_query_impl/src/execution.rs +++ b/compiler/rustc_query_impl/src/execution.rs @@ -129,11 +129,11 @@ fn mk_cycle<'tcx, C: QueryCache>( match query.cycle_error_handling { CycleErrorHandling::Error => { let guar = error.emit(); - query.value_from_cycle_error(tcx, cycle_error, guar) + (query.value_from_cycle_error)(tcx, cycle_error, guar) } CycleErrorHandling::DelayBug => { let guar = error.delay_as_bug(); - query.value_from_cycle_error(tcx, cycle_error, guar) + (query.value_from_cycle_error)(tcx, cycle_error, guar) } CycleErrorHandling::Stash => { let guar = if let Some(root) = cycle_error.cycle.first() @@ -143,7 +143,7 @@ fn mk_cycle<'tcx, C: QueryCache>( } else { error.emit() }; - query.value_from_cycle_error(tcx, cycle_error, guar) + (query.value_from_cycle_error)(tcx, cycle_error, guar) } } } @@ -449,7 +449,8 @@ fn execute_job_incr<'tcx, C: QueryCache>( if !query.anon && !query.eval_always { // `to_dep_node` is expensive for some `DepKind`s. - let dep_node = dep_node_opt.get_or_insert_with(|| query.construct_dep_node(tcx, &key)); + let dep_node = + dep_node_opt.get_or_insert_with(|| DepNode::construct(tcx, query.dep_kind, &key)); // The diagnostics for this query will be promoted to the current session during // `try_mark_green()`, so we can ignore them here. @@ -481,7 +482,8 @@ fn execute_job_incr<'tcx, C: QueryCache>( } // `to_dep_node` is expensive for some `DepKind`s. - let dep_node = dep_node_opt.unwrap_or_else(|| query.construct_dep_node(tcx, &key)); + let dep_node = + dep_node_opt.unwrap_or_else(|| DepNode::construct(tcx, query.dep_kind, &key)); // Call the query provider. dep_graph_data.with_task( @@ -518,7 +520,7 @@ fn load_from_disk_or_invoke_provider_green<'tcx, C: QueryCache>( // First we try to load the result from the on-disk cache. // Some things are never cached on disk. - if let Some(value) = query.try_load_from_disk(tcx, key, prev_index, dep_node_index) { + if let Some(value) = (query.try_load_from_disk_fn)(tcx, key, prev_index, dep_node_index) { if std::intrinsics::unlikely(tcx.sess.opts.unstable_opts.query_dep_graph) { dep_graph_data.mark_debug_loaded_from_disk(*dep_node) } @@ -551,7 +553,7 @@ fn load_from_disk_or_invoke_provider_green<'tcx, C: QueryCache>( // We always expect to find a cached result for things that // can be forced from `DepNode`. debug_assert!( - !query.will_cache_on_disk_for_key(tcx, key) + !(query.will_cache_on_disk_for_key_fn)(tcx, key) || !tcx.key_fingerprint_style(dep_node.kind).is_maybe_recoverable(), "missing on-disk cache entry for {dep_node:?}" ); @@ -559,7 +561,7 @@ fn load_from_disk_or_invoke_provider_green<'tcx, C: QueryCache>( // Sanity check for the logic in `ensure`: if the node is green and the result loadable, // we should actually be able to load it. debug_assert!( - !query.is_loadable_from_disk(tcx, key, prev_index), + !(query.is_loadable_from_disk_fn)(tcx, key, prev_index), "missing on-disk cache entry for loadable {dep_node:?}" ); @@ -625,7 +627,7 @@ fn check_if_ensure_can_skip_execution<'tcx, C: QueryCache>( // Ensuring an anonymous query makes no sense assert!(!query.anon); - let dep_node = query.construct_dep_node(tcx, key); + let dep_node = DepNode::construct(tcx, query.dep_kind, key); let dep_graph = &tcx.dep_graph; let serialized_dep_node_index = match dep_graph.try_mark_green(tcx, &dep_node) { @@ -656,7 +658,7 @@ fn check_if_ensure_can_skip_execution<'tcx, C: QueryCache>( // In ensure-done mode, we can only skip execution for this key if // there's a disk-cached value available to load later if needed, // which guarantees the query provider will never run for this key. - let is_loadable = query.is_loadable_from_disk(tcx, key, serialized_dep_node_index); + let is_loadable = (query.is_loadable_from_disk_fn)(tcx, key, serialized_dep_node_index); EnsureCanSkip { skip_execution: is_loadable, dep_node: Some(dep_node) } } } diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 425ca28910073..36335a3ef9ef4 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -168,7 +168,7 @@ pub(crate) fn encode_query_results<'a, 'tcx, C, V>( assert!(all_inactive(&query.state)); query.cache.iter(&mut |key, value, dep_node| { - if query.will_cache_on_disk_for_key(tcx, key) { + if (query.will_cache_on_disk_for_key_fn)(tcx, key) { let dep_node = SerializedDepNodeIndex::new(dep_node.index()); // Record position of the cache entry. @@ -221,7 +221,7 @@ pub(crate) fn promote_from_disk_inner<'tcx, Q: GetQueryVTable<'tcx>>( dep_node.key_fingerprint ) }); - if query.will_cache_on_disk_for_key(tcx, &key) { + if (query.will_cache_on_disk_for_key_fn)(tcx, &key) { // Call `tcx.$query(key)` for its side-effect of loading the disk-cached // value into memory. (query.call_query_method_fn)(tcx, key); @@ -427,12 +427,6 @@ macro_rules! define_queries { state: Default::default(), cache: Default::default(), - #[cfg($cache_on_disk)] - will_cache_on_disk_for_key_fn: - Some(rustc_middle::queries::_cache_on_disk_if_fns::$name), - #[cfg(not($cache_on_disk))] - will_cache_on_disk_for_key_fn: None, - call_query_method_fn: |tcx, key| { // Call the query method for its side-effect of loading a value // from disk-cache; the caller doesn't need the value. @@ -441,7 +435,13 @@ macro_rules! define_queries { invoke_provider_fn: self::invoke_provider_fn::__rust_begin_short_backtrace, #[cfg($cache_on_disk)] - try_load_from_disk_fn: Some(|tcx, key, prev_index, index| { + will_cache_on_disk_for_key_fn: + rustc_middle::queries::_cache_on_disk_if_fns::$name, + #[cfg(not($cache_on_disk))] + will_cache_on_disk_for_key_fn: |_, _| false, + + #[cfg($cache_on_disk)] + try_load_from_disk_fn: |tcx, key, prev_index, index| { // Check the `cache_on_disk_if` condition for this key. if !rustc_middle::queries::_cache_on_disk_if_fns::$name(tcx, key) { return None; @@ -452,17 +452,17 @@ macro_rules! define_queries { // Arena-alloc the value if appropriate, and erase it. Some(queries::$name::provided_to_erased(tcx, value)) - }), + }, #[cfg(not($cache_on_disk))] - try_load_from_disk_fn: None, + try_load_from_disk_fn: |_tcx, _key, _prev_index, _index| None, #[cfg($cache_on_disk)] - is_loadable_from_disk_fn: Some(|tcx, key, index| -> bool { + is_loadable_from_disk_fn: |tcx, key, index| -> bool { rustc_middle::queries::_cache_on_disk_if_fns::$name(tcx, key) && $crate::plumbing::loadable_from_disk(tcx, index) - }), + }, #[cfg(not($cache_on_disk))] - is_loadable_from_disk_fn: None, + is_loadable_from_disk_fn: |_tcx, _key, _index| false, value_from_cycle_error: |tcx, cycle, guar| { let result: queries::$name::Value<'tcx> = diff --git a/library/test/build.rs b/library/test/build.rs index 8e31adbf2ca74..3f7a5c16e5b1e 100644 --- a/library/test/build.rs +++ b/library/test/build.rs @@ -2,11 +2,16 @@ fn main() { println!("cargo:rerun-if-changed=build.rs"); println!("cargo:rustc-check-cfg=cfg(enable_unstable_features)"); - let rustc = std::env::var("RUSTC").unwrap_or_else(|_| "rustc".into()); - let version = std::process::Command::new(rustc).arg("-vV").output().unwrap(); - let stdout = String::from_utf8(version.stdout).unwrap(); + // Miri testing uses unstable features, so always enable that for its sysroot. + // Otherwise, only enable unstable if rustc looks like a nightly or dev build. + let enable_unstable_features = std::env::var("MIRI_CALLED_FROM_SETUP").is_ok() || { + let rustc = std::env::var("RUSTC").unwrap_or_else(|_| "rustc".into()); + let version = std::process::Command::new(rustc).arg("-vV").output().unwrap(); + let stdout = String::from_utf8(version.stdout).unwrap(); + stdout.contains("nightly") || stdout.contains("dev") + }; - if stdout.contains("nightly") || stdout.contains("dev") { + if enable_unstable_features { println!("cargo:rustc-cfg=enable_unstable_features"); } } diff --git a/tests/codegen-llvm/gpu_offload/control_flow.rs b/tests/codegen-llvm/gpu_offload/control_flow.rs index fb483db667b2a..503e9e4221cdc 100644 --- a/tests/codegen-llvm/gpu_offload/control_flow.rs +++ b/tests/codegen-llvm/gpu_offload/control_flow.rs @@ -14,14 +14,13 @@ // CHECK-NOT: define // CHECK: %.offload_baseptrs = alloca [1 x ptr], align 8 // CHECK-NEXT: %.offload_ptrs = alloca [1 x ptr], align 8 -// CHECK-NEXT: %.offload_sizes = alloca [1 x i64], align 8 // CHECK-NEXT: %kernel_args = alloca %struct.__tgt_kernel_arguments, align 8 // CHECK: br label %bb3 // CHECK-NOT define // CHECK: bb3 -// CHECK: call void @__tgt_target_data_begin_mapper(ptr nonnull @anon.{{.*}}.1, i64 -1, i32 1, ptr nonnull %.offload_baseptrs, ptr nonnull %.offload_ptrs, ptr nonnull %.offload_sizes, ptr nonnull @.offload_maptypes.foo.begin, ptr null, ptr null) +// CHECK: call void @__tgt_target_data_begin_mapper(ptr nonnull @anon.{{.*}}.1, i64 -1, i32 1, ptr nonnull %.offload_baseptrs, ptr nonnull %.offload_ptrs, ptr nonnull @.offload_sizes.foo, ptr nonnull @.offload_maptypes.foo.begin, ptr null, ptr null) // CHECK: %10 = call i32 @__tgt_target_kernel(ptr nonnull @anon.{{.*}}.1, i64 -1, i32 256, i32 32, ptr nonnull @.foo.region_id, ptr nonnull %kernel_args) -// CHECK-NEXT: call void @__tgt_target_data_end_mapper(ptr nonnull @anon.{{.*}}.1, i64 -1, i32 1, ptr nonnull %.offload_baseptrs, ptr nonnull %.offload_ptrs, ptr nonnull %.offload_sizes, ptr nonnull @.offload_maptypes.foo.end, ptr null, ptr null) +// CHECK-NEXT: call void @__tgt_target_data_end_mapper(ptr nonnull @anon.{{.*}}.1, i64 -1, i32 1, ptr nonnull %.offload_baseptrs, ptr nonnull %.offload_ptrs, ptr nonnull @.offload_sizes.foo, ptr nonnull @.offload_maptypes.foo.end, ptr null, ptr null) #[unsafe(no_mangle)] unsafe fn main() { let A = [1.0, 1.0, 1.0, 1.0, 1.0, 1.0]; diff --git a/tests/codegen-llvm/gpu_offload/gpu_host.rs b/tests/codegen-llvm/gpu_offload/gpu_host.rs index f25ba679abbdf..8179d868da95f 100644 --- a/tests/codegen-llvm/gpu_offload/gpu_host.rs +++ b/tests/codegen-llvm/gpu_offload/gpu_host.rs @@ -58,18 +58,14 @@ pub fn _kernel_1(x: &mut [f32; 256], y: &[f32; 256]) { // CHECK-NEXT: %x = alloca [1024 x i8], align 16 // CHECK-NEXT: %.offload_baseptrs = alloca [2 x ptr], align 8 // CHECK-NEXT: %.offload_ptrs = alloca [2 x ptr], align 8 -// CHECK-NEXT: %.offload_sizes = alloca [2 x i64], align 8 // CHECK-NEXT: %kernel_args = alloca %struct.__tgt_kernel_arguments, align 8 // CHECK: store ptr %x, ptr %.offload_baseptrs, align 8 // CHECK-NEXT: store ptr %x, ptr %.offload_ptrs, align 8 -// CHECK-NEXT: store i64 1024, ptr %.offload_sizes, align 8 // CHECK-NEXT: [[BPTRS_1:%.*]] = getelementptr inbounds nuw i8, ptr %.offload_baseptrs, i64 8 // CHECK-NEXT: store ptr %y, ptr [[BPTRS_1]], align 8 // CHECK-NEXT: [[PTRS_1:%.*]] = getelementptr inbounds nuw i8, ptr %.offload_ptrs, i64 8 // CHECK-NEXT: store ptr %y, ptr [[PTRS_1]], align 8 -// CHECK-NEXT: [[SIZES_1:%.*]] = getelementptr inbounds nuw i8, ptr %.offload_sizes, i64 8 -// CHECK-NEXT: store i64 1024, ptr [[SIZES_1]], align 8 -// CHECK-NEXT: call void @__tgt_target_data_begin_mapper(ptr nonnull @anon.{{.*}}.1, i64 -1, i32 2, ptr nonnull %.offload_baseptrs, ptr nonnull %.offload_ptrs, ptr nonnull %.offload_sizes, ptr nonnull @.offload_maptypes.[[K]].begin, ptr null, ptr null) +// CHECK-NEXT: call void @__tgt_target_data_begin_mapper(ptr nonnull @anon.{{.*}}.1, i64 -1, i32 2, ptr nonnull %.offload_baseptrs, ptr nonnull %.offload_ptrs, ptr nonnull @.offload_sizes.[[K]], ptr nonnull @.offload_maptypes.[[K]].begin, ptr null, ptr null) // CHECK-NEXT: store i32 3, ptr %kernel_args, align 8 // CHECK-NEXT: [[P4:%[^ ]+]] = getelementptr inbounds nuw i8, ptr %kernel_args, i64 4 // CHECK-NEXT: store i32 2, ptr [[P4]], align 4 @@ -78,7 +74,7 @@ pub fn _kernel_1(x: &mut [f32; 256], y: &[f32; 256]) { // CHECK-NEXT: [[P16:%[^ ]+]] = getelementptr inbounds nuw i8, ptr %kernel_args, i64 16 // CHECK-NEXT: store ptr %.offload_ptrs, ptr [[P16]], align 8 // CHECK-NEXT: [[P24:%[^ ]+]] = getelementptr inbounds nuw i8, ptr %kernel_args, i64 24 -// CHECK-NEXT: store ptr %.offload_sizes, ptr [[P24]], align 8 +// CHECK-NEXT: store ptr @.offload_sizes.[[K]], ptr [[P24]], align 8 // CHECK-NEXT: [[P32:%[^ ]+]] = getelementptr inbounds nuw i8, ptr %kernel_args, i64 32 // CHECK-NEXT: store ptr @.offload_maptypes.[[K]].kernel, ptr [[P32]], align 8 // CHECK-NEXT: [[P40:%[^ ]+]] = getelementptr inbounds nuw i8, ptr %kernel_args, i64 40 @@ -92,7 +88,7 @@ pub fn _kernel_1(x: &mut [f32; 256], y: &[f32; 256]) { // CHECK-NEXT: [[P96:%[^ ]+]] = getelementptr inbounds nuw i8, ptr %kernel_args, i64 96 // CHECK-NEXT: store i32 0, ptr [[P96]], align 8 // CHECK-NEXT: [[TGT_RET:%.*]] = call i32 @__tgt_target_kernel(ptr nonnull @anon.{{.*}}.1, i64 -1, i32 256, i32 32, ptr nonnull @.[[K]].region_id, ptr nonnull %kernel_args) -// CHECK-NEXT: call void @__tgt_target_data_end_mapper(ptr nonnull @anon.{{.*}}.1, i64 -1, i32 2, ptr nonnull %.offload_baseptrs, ptr nonnull %.offload_ptrs, ptr nonnull %.offload_sizes, ptr nonnull @.offload_maptypes.[[K]].end, ptr null, ptr null) +// CHECK-NEXT: call void @__tgt_target_data_end_mapper(ptr nonnull @anon.{{.*}}.1, i64 -1, i32 2, ptr nonnull %.offload_baseptrs, ptr nonnull %.offload_ptrs, ptr nonnull @.offload_sizes.[[K]], ptr nonnull @.offload_maptypes.[[K]].end, ptr null, ptr null) // CHECK: ret void // CHECK-NEXT: } diff --git a/tests/codegen-llvm/gpu_offload/scalar_host.rs b/tests/codegen-llvm/gpu_offload/scalar_host.rs index 8c7dcd4dd5817..d5b40fb0a26db 100644 --- a/tests/codegen-llvm/gpu_offload/scalar_host.rs +++ b/tests/codegen-llvm/gpu_offload/scalar_host.rs @@ -20,8 +20,6 @@ // CHECK-NEXT: store double %_0.i, ptr %1, align 8 // CHECK-NEXT: %2 = getelementptr inbounds nuw i8, ptr %.offload_ptrs, i64 8 // CHECK-NEXT: store ptr %addr, ptr %2, align 8 -// CHECK-NEXT: %3 = getelementptr inbounds nuw i8, ptr %.offload_sizes, i64 8 -// CHECK-NEXT: store i64 4, ptr %3, align 8 // CHECK-NEXT: call void @__tgt_target_data_begin_mapper #[unsafe(no_mangle)] diff --git a/tests/ui/explicit-tail-calls/support/basic.rs b/tests/ui/explicit-tail-calls/support/basic.rs new file mode 100644 index 0000000000000..d46dd726c0bd1 --- /dev/null +++ b/tests/ui/explicit-tail-calls/support/basic.rs @@ -0,0 +1,97 @@ +//@ build-pass +//@ ignore-backends: gcc +//@ add-minicore +//@ min-llvm-version: 22 +// +//@ revisions: i686 +//@[i686] compile-flags: --target i686-unknown-linux-gnu +//@[i686] needs-llvm-components: x86 +//@ revisions: x86-64 +//@[x86-64] compile-flags: --target x86_64-unknown-linux-gnu +//@[x86-64] needs-llvm-components: x86 +//@ revisions: x86-64-win +//@[x86-64-win] compile-flags: --target x86_64-pc-windows-msvc +//@[x86-64-win] needs-llvm-components: x86 +//@ revisions: arm +//@[arm] compile-flags: --target arm-unknown-linux-gnueabi +//@[arm] needs-llvm-components: arm +//@ revisions: thumb +//@[thumb] compile-flags: --target thumbv8m.main-none-eabi +//@[thumb] needs-llvm-components: arm +//@ revisions: aarch64 +//@[aarch64] compile-flags: --target aarch64-unknown-linux-gnu +//@[aarch64] needs-llvm-components: aarch64 +//@ revisions: s390x +//@[s390x] compile-flags: --target s390x-unknown-linux-gnu +//@[s390x] needs-llvm-components: systemz +//@ revisions: sparc +//@[sparc] compile-flags: --target sparc-unknown-linux-gnu +//@[sparc] needs-llvm-components: sparc +//@ revisions: sparc64 +//@[sparc64] compile-flags: --target sparc64-unknown-linux-gnu +//@[sparc64] needs-llvm-components: sparc +//@ revisions: powerpc64 +//@[powerpc64] compile-flags: --target powerpc64-unknown-linux-gnu +//@[powerpc64] needs-llvm-components: powerpc +//@ revisions: riscv +//@[riscv] compile-flags: --target riscv64gc-unknown-linux-gnu +//@[riscv] needs-llvm-components: riscv +//@ revisions: loongarch32 +//@[loongarch32] compile-flags: --target loongarch32-unknown-none +//@[loongarch32] needs-llvm-components: loongarch +//@ revisions: loongarch64 +//@[loongarch64] compile-flags: --target loongarch64-unknown-linux-gnu +//@[loongarch64] needs-llvm-components: loongarch +//@ revisions: bpf +//@[bpf] compile-flags: --target bpfeb-unknown-none +//@[bpf] needs-llvm-components: bpf +//@ revisions: m68k +//@[m68k] compile-flags: --target m68k-unknown-linux-gnu +//@[m68k] needs-llvm-components: m68k +//@ revisions: nvptx64 +//@[nvptx64] compile-flags: --target nvptx64-nvidia-cuda +//@[nvptx64] needs-llvm-components: nvptx +// +// Wasm needs a special target feature. +// +//@ revisions: wasm +//@[wasm] compile-flags: --target wasm32-unknown-unknown -Ctarget-feature=+tail-call +//@[wasm] needs-llvm-components: webassembly +//@ revisions: wasip1 +//@[wasip1] compile-flags: --target wasm32-wasip1 -Ctarget-feature=+tail-call +//@[wasip1] needs-llvm-components: webassembly +// +// Failing cases (just zero support) +// +// //@ revisions: powerpc +// //@[powerpc] compile-flags: --target powerpc-unknown-linux-gnu +// //@[powerpc] needs-llvm-components: powerpc +// //@ revisions: aix +// //@[aix] compile-flags: --target powerpc64-ibm-aix +// //@[aix] needs-llvm-components: powerpc +// //@ revisions: csky +// //@[csky] compile-flags: --target csky-unknown-linux-gnuabiv2 +// //@[csky] needs-llvm-components: csky +// //@ revisions: mips +// //@[mips] compile-flags: --target mips-unknown-linux-gnu +// //@[mips] needs-llvm-components: mips +// //@ revisions: mips64 +// //@[mips64] compile-flags: --target mips64-unknown-linux-gnuabi64 +// //@[mips64] needs-llvm-components: mips +#![feature(no_core, explicit_tail_calls)] +#![expect(incomplete_features)] +#![no_core] +#![crate_type = "lib"] + +extern crate minicore; +use minicore::*; + +#[inline(never)] +fn simple1(x: u64) -> u64 { + x +} + +#[unsafe(no_mangle)] +fn simple2(x: u64) -> u64 { + become simple1(x); +} diff --git a/tests/ui/explicit-tail-calls/support/bystack.rs b/tests/ui/explicit-tail-calls/support/bystack.rs new file mode 100644 index 0000000000000..ad1e0827f9f05 --- /dev/null +++ b/tests/ui/explicit-tail-calls/support/bystack.rs @@ -0,0 +1,108 @@ +//@ build-pass +//@ ignore-backends: gcc +//@ add-minicore +//@ min-llvm-version: 22 +// +//@ revisions: i686 +//@[i686] compile-flags: --target i686-unknown-linux-gnu +//@[i686] needs-llvm-components: x86 +//@ revisions: x86-64 +//@[x86-64] compile-flags: --target x86_64-unknown-linux-gnu +//@[x86-64] needs-llvm-components: x86 +//@ revisions: x86-64-win +//@[x86-64-win] compile-flags: --target x86_64-pc-windows-msvc +//@[x86-64-win] needs-llvm-components: x86 +//@ revisions: arm +//@[arm] compile-flags: --target arm-unknown-linux-gnueabi +//@[arm] needs-llvm-components: arm +//@ revisions: thumb +//@[thumb] compile-flags: --target thumbv8m.main-none-eabi +//@[thumb] needs-llvm-components: arm +//@ revisions: aarch64 +//@[aarch64] compile-flags: --target aarch64-unknown-linux-gnu +//@[aarch64] needs-llvm-components: aarch64 +//@ revisions: s390x +//@[s390x] compile-flags: --target s390x-unknown-linux-gnu +//@[s390x] needs-llvm-components: systemz +//@ revisions: sparc +//@[sparc] compile-flags: --target sparc-unknown-linux-gnu +//@[sparc] needs-llvm-components: sparc +//@ revisions: sparc64 +//@[sparc64] compile-flags: --target sparc64-unknown-linux-gnu +//@[sparc64] needs-llvm-components: sparc +//@ revisions: powerpc64 +//@[powerpc64] compile-flags: --target powerpc64-unknown-linux-gnu +//@[powerpc64] needs-llvm-components: powerpc +//@ revisions: loongarch32 +//@[loongarch32] compile-flags: --target loongarch32-unknown-none +//@[loongarch32] needs-llvm-components: loongarch +//@ revisions: loongarch64 +//@[loongarch64] compile-flags: --target loongarch64-unknown-linux-gnu +//@[loongarch64] needs-llvm-components: loongarch +//@ revisions: bpf +//@[bpf] compile-flags: --target bpfeb-unknown-none +//@[bpf] needs-llvm-components: bpf +//@ revisions: m68k +//@[m68k] compile-flags: --target m68k-unknown-linux-gnu +//@[m68k] needs-llvm-components: m68k +//@ revisions: nvptx64 +//@[nvptx64] compile-flags: --target nvptx64-nvidia-cuda +//@[nvptx64] needs-llvm-components: nvptx +// +// Riscv does not support byval in LLVM 22 (but wil in LLVM 23) +// +// //@ revisions: riscv +// //@[riscv] compile-flags: --target riscv64gc-unknown-linux-gnu +// //@[riscv] needs-llvm-components: riscv +// +// Wasm needs a special target feature. +// +//@ revisions: wasm +//@[wasm] compile-flags: --target wasm32-unknown-unknown -Ctarget-feature=+tail-call +//@[wasm] needs-llvm-components: webassembly +//@ revisions: wasip1 +//@[wasip1] compile-flags: --target wasm32-wasip1 -Ctarget-feature=+tail-call +//@[wasip1] needs-llvm-components: webassembly +// +// Failing cases (just zero support) +// +// //@ revisions: powerpc +// //@[powerpc] compile-flags: --target powerpc-unknown-linux-gnu +// //@[powerpc] needs-llvm-components: powerpc +// //@ revisions: aix +// //@[aix] compile-flags: --target powerpc64-ibm-aix +// //@[aix] needs-llvm-components: powerpc +// //@ revisions: csky +// //@[csky] compile-flags: --target csky-unknown-linux-gnuabiv2 +// //@[csky] needs-llvm-components: csky +// //@ revisions: mips +// //@[mips] compile-flags: --target mips-unknown-linux-gnu +// //@[mips] needs-llvm-components: mips +// //@ revisions: mips64 +// //@[mips64] compile-flags: --target mips64-unknown-linux-gnuabi64 +// //@[mips64] needs-llvm-components: mips +#![feature(no_core, explicit_tail_calls)] +#![expect(incomplete_features)] +#![no_core] +#![crate_type = "lib"] + +extern crate minicore; +use minicore::*; + +#[repr(C)] +struct PassedByVal { + a: u64, + b: u64, + c: u64, + d: u64, +} + +#[inline(never)] +extern "C" fn callee(x: PassedByVal) -> PassedByVal { + x +} + +#[unsafe(no_mangle)] +extern "C" fn byval(x: PassedByVal) -> PassedByVal { + become callee(x); +} diff --git a/tests/ui/explicit-tail-calls/support/byval.rs b/tests/ui/explicit-tail-calls/support/byval.rs new file mode 100644 index 0000000000000..965c63c8688a8 --- /dev/null +++ b/tests/ui/explicit-tail-calls/support/byval.rs @@ -0,0 +1,108 @@ +//@ build-pass +//@ ignore-backends: gcc +//@ add-minicore +//@ min-llvm-version: 22 +// +//@ revisions: i686 +//@[i686] compile-flags: --target i686-unknown-linux-gnu +//@[i686] needs-llvm-components: x86 +//@ revisions: x86-64 +//@[x86-64] compile-flags: --target x86_64-unknown-linux-gnu +//@[x86-64] needs-llvm-components: x86 +//@ revisions: x86-64-win +//@[x86-64-win] compile-flags: --target x86_64-pc-windows-msvc +//@[x86-64-win] needs-llvm-components: x86 +//@ revisions: arm +//@[arm] compile-flags: --target arm-unknown-linux-gnueabi +//@[arm] needs-llvm-components: arm +//@ revisions: thumb +//@[thumb] compile-flags: --target thumbv8m.main-none-eabi +//@[thumb] needs-llvm-components: arm +//@ revisions: aarch64 +//@[aarch64] compile-flags: --target aarch64-unknown-linux-gnu +//@[aarch64] needs-llvm-components: aarch64 +//@ revisions: s390x +//@[s390x] compile-flags: --target s390x-unknown-linux-gnu +//@[s390x] needs-llvm-components: systemz +//@ revisions: sparc +//@[sparc] compile-flags: --target sparc-unknown-linux-gnu +//@[sparc] needs-llvm-components: sparc +//@ revisions: sparc64 +//@[sparc64] compile-flags: --target sparc64-unknown-linux-gnu +//@[sparc64] needs-llvm-components: sparc +//@ revisions: powerpc64 +//@[powerpc64] compile-flags: --target powerpc64-unknown-linux-gnu +//@[powerpc64] needs-llvm-components: powerpc +//@ revisions: loongarch32 +//@[loongarch32] compile-flags: --target loongarch32-unknown-none +//@[loongarch32] needs-llvm-components: loongarch +//@ revisions: loongarch64 +//@[loongarch64] compile-flags: --target loongarch64-unknown-linux-gnu +//@[loongarch64] needs-llvm-components: loongarch +//@ revisions: bpf +//@[bpf] compile-flags: --target bpfeb-unknown-none +//@[bpf] needs-llvm-components: bpf +//@ revisions: m68k +//@[m68k] compile-flags: --target m68k-unknown-linux-gnu +//@[m68k] needs-llvm-components: m68k +//@ revisions: nvptx64 +//@[nvptx64] compile-flags: --target nvptx64-nvidia-cuda +//@[nvptx64] needs-llvm-components: nvptx +// +// Riscv does not support byval in LLVM 22 (but wil in LLVM 23) +// +// //@ revisions: riscv +// //@[riscv] compile-flags: --target riscv64gc-unknown-linux-gnu +// //@[riscv] needs-llvm-components: riscv +// +// Wasm needs a special target feature. +// +//@ revisions: wasm +//@[wasm] compile-flags: --target wasm32-unknown-unknown -Ctarget-feature=+tail-call +//@[wasm] needs-llvm-components: webassembly +//@ revisions: wasip1 +//@[wasip1] compile-flags: --target wasm32-wasip1 -Ctarget-feature=+tail-call +//@[wasip1] needs-llvm-components: webassembly +// +// Failing cases (just zero support) +// +// //@ revisions: powerpc +// //@[powerpc] compile-flags: --target powerpc-unknown-linux-gnu +// //@[powerpc] needs-llvm-components: powerpc +// //@ revisions: aix +// //@[aix] compile-flags: --target powerpc64-ibm-aix +// //@[aix] needs-llvm-components: powerpc +// //@ revisions: csky +// //@[csky] compile-flags: --target csky-unknown-linux-gnuabiv2 +// //@[csky] needs-llvm-components: csky +// //@ revisions: mips +// //@[mips] compile-flags: --target mips-unknown-linux-gnu +// //@[mips] needs-llvm-components: mips +// //@ revisions: mips64 +// //@[mips64] compile-flags: --target mips64-unknown-linux-gnuabi64 +// //@[mips64] needs-llvm-components: mips +#![feature(no_core, explicit_tail_calls)] +#![expect(incomplete_features)] +#![no_core] +#![crate_type = "lib"] + +extern crate minicore; +use minicore::*; + +// The rust calling convention will pass this by-value. +struct PassedByVal { + a: u64, + b: u64, + c: u64, + d: u64, +} + +#[inline(never)] +fn callee(x: PassedByVal) -> PassedByVal { + x +} + +#[unsafe(no_mangle)] +fn byval(x: PassedByVal) -> PassedByVal { + become callee(x); +} diff --git a/tests/ui/structs/syntax-error-not-missing-field.rs b/tests/ui/structs/syntax-error-not-missing-field.rs index f1080d3908cf4..0988e12584216 100644 --- a/tests/ui/structs/syntax-error-not-missing-field.rs +++ b/tests/ui/structs/syntax-error-not-missing-field.rs @@ -6,6 +6,10 @@ struct Foo { a: isize, b: isize } +enum Bar { + Baz { a: isize, b: isize }, +} + fn make_a() -> isize { 1234 } fn expr_wrong_separator() { @@ -35,4 +39,12 @@ fn pat_missing_separator(Foo { a b }: Foo) { //~ ERROR expected `,` fn pat_rest_trailing_comma(Foo { a, .., }: Foo) { //~ ERROR expected `}`, found `,` } +fn enum_expr_wrong_separator() { + let e = Bar::Baz { a: make_a(); b: 2 }; //~ ERROR found `;` +} + +fn enum_expr_missing_separator() { + let e = Bar::Baz { a: make_a() b: 2 }; //~ ERROR found `b` +} + fn main() {} diff --git a/tests/ui/structs/syntax-error-not-missing-field.stderr b/tests/ui/structs/syntax-error-not-missing-field.stderr index d781a41300f36..eec2bb19d1153 100644 --- a/tests/ui/structs/syntax-error-not-missing-field.stderr +++ b/tests/ui/structs/syntax-error-not-missing-field.stderr @@ -1,5 +1,5 @@ error: expected one of `,`, `.`, `?`, `}`, or an operator, found `;` - --> $DIR/syntax-error-not-missing-field.rs:12:30 + --> $DIR/syntax-error-not-missing-field.rs:16:30 | LL | let f = Foo { a: make_a(); b: 2 }; | --- ^ @@ -9,7 +9,7 @@ LL | let f = Foo { a: make_a(); b: 2 }; | while parsing this struct error: expected one of `,`, `.`, `?`, `}`, or an operator, found `b` - --> $DIR/syntax-error-not-missing-field.rs:16:31 + --> $DIR/syntax-error-not-missing-field.rs:20:31 | LL | let f = Foo { a: make_a() b: 2 }; | --- -^ expected one of `,`, `.`, `?`, `}`, or an operator @@ -18,7 +18,7 @@ LL | let f = Foo { a: make_a() b: 2 }; | while parsing this struct error: cannot use a comma after the base struct - --> $DIR/syntax-error-not-missing-field.rs:20:32 + --> $DIR/syntax-error-not-missing-field.rs:24:32 | LL | let f = Foo { a: make_a(), ..todo!(), }; | ^^^^^^^^^ @@ -31,7 +31,7 @@ LL + let f = Foo { a: make_a(), ..todo!() }; | error: expected one of `,`, `:`, or `}`, found `(` - --> $DIR/syntax-error-not-missing-field.rs:24:25 + --> $DIR/syntax-error-not-missing-field.rs:28:25 | LL | let f = Foo { make_a(), b: 2, }; | --- ------^ expected one of `,`, `:`, or `}` @@ -45,7 +45,7 @@ LL | let f = Foo { make_a: make_a(), b: 2, }; | +++++++ error: expected `,` - --> $DIR/syntax-error-not-missing-field.rs:27:31 + --> $DIR/syntax-error-not-missing-field.rs:31:31 | LL | fn pat_wrong_separator(Foo { a; b }: Foo) { | --- ^ @@ -53,7 +53,7 @@ LL | fn pat_wrong_separator(Foo { a; b }: Foo) { | while parsing the fields for this pattern error: expected `,` - --> $DIR/syntax-error-not-missing-field.rs:31:34 + --> $DIR/syntax-error-not-missing-field.rs:35:34 | LL | fn pat_missing_separator(Foo { a b }: Foo) { | --- ^ @@ -61,7 +61,7 @@ LL | fn pat_missing_separator(Foo { a b }: Foo) { | while parsing the fields for this pattern error: expected `}`, found `,` - --> $DIR/syntax-error-not-missing-field.rs:35:39 + --> $DIR/syntax-error-not-missing-field.rs:39:39 | LL | fn pat_rest_trailing_comma(Foo { a, .., }: Foo) { | --^ @@ -70,5 +70,24 @@ LL | fn pat_rest_trailing_comma(Foo { a, .., }: Foo) { | | help: remove this comma | `..` must be at the end and cannot have a trailing comma -error: aborting due to 7 previous errors +error: expected one of `,`, `.`, `?`, `}`, or an operator, found `;` + --> $DIR/syntax-error-not-missing-field.rs:43:35 + | +LL | let e = Bar::Baz { a: make_a(); b: 2 }; + | -------- ^ + | | | + | | expected one of `,`, `.`, `?`, `}`, or an operator + | | help: try adding a comma: `,` + | while parsing this struct + +error: expected one of `,`, `.`, `?`, `}`, or an operator, found `b` + --> $DIR/syntax-error-not-missing-field.rs:47:36 + | +LL | let e = Bar::Baz { a: make_a() b: 2 }; + | -------- -^ expected one of `,`, `.`, `?`, `}`, or an operator + | | | + | | help: try adding a comma: `,` + | while parsing this struct + +error: aborting due to 9 previous errors