diff --git a/.cargo/config.toml b/.cargo/config.toml index 22dcbe588c..9c99fc9e3b 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -3,6 +3,8 @@ compiletest = "run --release -p compiletests --" [target.'cfg(all())'] rustflags = [ + # FIXME(eddyb) update/review these lints. + # # BEGIN - Embark standard lints v6 for Rust 1.55+ # do not change or add/remove here, but one can add exceptions after this section # for more info see: @@ -47,7 +49,6 @@ rustflags = [ "-Wclippy::match_wild_err_arm", "-Wclippy::match_wildcard_for_single_variants", "-Wclippy::mem_forget", - "-Wclippy::mismatched_target_os", "-Wclippy::missing_enforced_import_renames", "-Wclippy::mut_mut", "-Wclippy::mutex_integer", diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 680d35e957..c08d392c72 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -76,13 +76,18 @@ jobs: - name: build example shaders if: ${{ matrix.target != 'aarch64-linux-android' }} env: - OUT_DIR: "target/tmp" + PROFILE: release + OUT_DIR: "target/release/ci/out" run: cargo run -p example-runner-wgpu-builder --release --no-default-features --features "use-installed-tools" - - name: build example shaders dev - if: ${{ matrix.target != 'aarch64-linux-android' && matrix.target != 'x86_64-apple-darwin' }} + - name: build example shaders (dev aka "debug mode") + if: ${{ matrix.target != 'aarch64-linux-android' }} env: - OUT_DIR: "target/tmp" + # HACK(eddyb) see `[profile.dev]` in `Cargo.toml` for more on why + # `-Zshare-generics=off` is useful (and why it had to be moved here). + RUSTFLAGS: -Zshare-generics=off + PROFILE: debug + OUT_DIR: "target/debug/ci/out" run: cargo run -p example-runner-wgpu-builder --no-default-features --features "use-installed-tools" - name: Build WGPU Example for Android @@ -155,4 +160,4 @@ jobs: runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 - - uses: EmbarkStudios/cargo-deny-action@v1 + - uses: EmbarkStudios/cargo-deny-action@v2 diff --git a/.github/workflows/lint.sh b/.github/workflows/lint.sh index f64abd0fd0..31941a5084 100755 --- a/.github/workflows/lint.sh +++ b/.github/workflows/lint.sh @@ -87,3 +87,16 @@ function version_test() { # FIXME(eddyb) try to get this working for `spirv-builder`, which has a larger # dependency graph, with too much imprecision in upstream `Cargo.toml` files. version_test crates/spirv-std + +# 3. Ensure `rustc_codegen_spirv` still compiles with `rustc_codegen_ssa`. + +# HACK(eddyb) see `crates/rustc_codegen_spirv/build.rs` for more on `pqp_cg_ssa` +# (a patched copy of `rustc_codegen_ssa`). +echo ::group::rustc_codegen_spirv_disable_pqp_cg_ssa +cargo clippy \ + --manifest-path "crates/rustc_codegen_spirv/Cargo.toml" \ + --no-default-features \ + --features "$FEAT" \ + --all-targets \ + -- -D warnings --cfg rustc_codegen_spirv_disable_pqp_cg_ssa +echo ::endgroup:: diff --git a/Cargo.lock b/Cargo.lock index a7f49b5c68..32b040975b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -18,6 +18,12 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c71b1793ee61086797f5c80b6efa2b8ffa6d5dd703f118545808a7f2e27f7046" +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + [[package]] name = "ahash" version = "0.7.8" @@ -637,6 +643,15 @@ dependencies = [ "libc", ] +[[package]] +name = "crc32fast" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +dependencies = [ + "cfg-if", +] + [[package]] name = "crossbeam-channel" version = "0.5.13" @@ -891,6 +906,12 @@ dependencies = [ "spirv-builder", ] +[[package]] +name = "fallible-iterator" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" + [[package]] name = "fastrand" version = "2.3.0" @@ -915,6 +936,22 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" +[[package]] +name = "flate2" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "foldhash" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f81ec6369c545a7d40e4589b5597581fa1c441fe1cce96dd1de43159910a36a2" + [[package]] name = "foreign-types" version = "0.5.0" @@ -1070,6 +1107,17 @@ dependencies = [ "wasi", ] +[[package]] +name = "gimli" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2e1d97fbe9722ba9bbd0c97051c2956e726562b61f86a25a4360398a40edfc9" +dependencies = [ + "fallible-iterator", + "indexmap", + "stable_deref_trait", +] + [[package]] name = "gl_generator" version = "0.14.0" @@ -1188,6 +1236,9 @@ name = "hashbrown" version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" +dependencies = [ + "foldhash", +] [[package]] name = "hassle-rs" @@ -1555,6 +1606,15 @@ dependencies = [ "x11-dl", ] +[[package]] +name = "miniz_oxide" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +dependencies = [ + "adler2", +] + [[package]] name = "mio" version = "0.8.11" @@ -1752,6 +1812,21 @@ version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d079845b37af429bfe5dfa76e6d087d788031045b25cfc6fd898486fd9847666" +[[package]] +name = "object" +version = "0.36.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" +dependencies = [ + "crc32fast", + "flate2", + "hashbrown 0.15.2", + "indexmap", + "memchr", + "ruzstd", + "wasmparser", +] + [[package]] name = "once_cell" version = "1.20.2" @@ -2122,6 +2197,7 @@ dependencies = [ "lazy_static", "libc", "num-traits", + "object", "once_cell", "pipe", "pretty_assertions", @@ -2133,7 +2209,7 @@ dependencies = [ "smallvec", "spirt", "spirv-tools", - "tempfile", + "thorin-dwp", ] [[package]] @@ -2185,6 +2261,15 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" +[[package]] +name = "ruzstd" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fad02996bfc73da3e301efe90b1837be9ed8f4a462b6ed410aa35d00381de89f" +dependencies = [ + "twox-hash", +] + [[package]] name = "ryu" version = "1.0.18" @@ -2610,6 +2695,18 @@ dependencies = [ "syn 2.0.90", ] +[[package]] +name = "thorin-dwp" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "813ba76597db32dc4f6992fd8bf8f394715b88d352fd97401da67dab6283b4c6" +dependencies = [ + "gimli", + "hashbrown 0.14.5", + "object", + "tracing", +] + [[package]] name = "time" version = "0.3.37" @@ -2690,14 +2787,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ "pin-project-lite", + "tracing-attributes", "tracing-core", ] +[[package]] +name = "tracing-attributes" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + [[package]] name = "tracing-core" version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" +dependencies = [ + "once_cell", +] [[package]] name = "ttf-parser" @@ -2705,6 +2817,16 @@ version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31" +[[package]] +name = "twox-hash" +version = "1.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" +dependencies = [ + "cfg-if", + "static_assertions", +] + [[package]] name = "unicode-ident" version = "1.0.14" @@ -2830,6 +2952,15 @@ version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6" +[[package]] +name = "wasmparser" +version = "0.218.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b09e46c7fceceaa72b2dd1a8a137ea7fd8f93dfaa69806010a709918e496c5dc" +dependencies = [ + "bitflags 2.6.0", +] + [[package]] name = "wayland-backend" version = "0.3.7" diff --git a/Cargo.toml b/Cargo.toml index 5502ffd038..4fe02da511 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,3 +1,8 @@ +# HACK(eddyb) meant for `[profile.dev]` `rustflags` overrides below, but sadly +# not configurable w/o breaking `Cargo.toml` parsing from non-nightly Cargo. +# +# cargo-features = ["profile-rustflags"] + [workspace] resolver = "2" members = [ @@ -60,3 +65,15 @@ codegen-units = 256 opt-level = 3 incremental = true codegen-units = 256 + +# HACK(eddyb) reduce the number of linker exports and/or imports, by avoiding +# inter-CGU linkage, to stay under the 64Ki MSVC limit for `rustc_codegen_spirv` +# when building it in "debug mode" (only relevant to CI for now, realistically), +# i.e. working around this issue: https://github.com/rust-lang/rust/issues/53014. +[profile.dev] +# HACK(eddyb) fewer inter-crate exports/imports (not just inter-CGU), but sadly +# not configurable w/o breaking `Cargo.toml` parsing from non-nightly Cargo +# (moved to `.github/workflows/ci.yaml` as `RUSTFLAGS: -Zshare-generics=off`). +# +# rustflags = ["-Zshare-generics=off"] +codegen-units = 1 diff --git a/crates/rustc_codegen_spirv/Cargo.toml b/crates/rustc_codegen_spirv/Cargo.toml index acb621679a..5c42e1077b 100644 --- a/crates/rustc_codegen_spirv/Cargo.toml +++ b/crates/rustc_codegen_spirv/Cargo.toml @@ -39,6 +39,11 @@ num-traits = { workspace = true, default-features = true } once_cell = "1" regex = { version = "1", features = ["perf"] } +# HACK(eddyb) deps of `rustc_codegen_ssa`, for `pqp_cg_ssa` (see `build.rs`), +# that cannot be handled with just `extern crate` pulling out of the sysroot. +object = { version = "0.36.2", default-features = false, features = ["read_core", "elf", "macho", "pe", "xcoff", "unaligned", "archive", "write", "wasm"] } +thorin-dwp = "0.8" + # Normal dependencies. ar = "0.9.0" either = "1.8.0" @@ -56,7 +61,10 @@ itertools = "0.10.5" [dev-dependencies] pipe = "0.4" pretty_assertions = "1.0" -tempfile = "3.4" + +# HACK(eddyb) can't re-introduce deps of `rustc_codegen_ssa`, for `pqp_cg_ssa` +# (see `build.rs`). +# tempfile = "3.4" # Note that in order to use RA and have access to `rustc_*` crates, you also # need to set `"rust-analyzer.rustcSource": "discover"` in e.g. VSCode. diff --git a/crates/rustc_codegen_spirv/build.rs b/crates/rustc_codegen_spirv/build.rs index b0cd95db81..b82a0e31c6 100644 --- a/crates/rustc_codegen_spirv/build.rs +++ b/crates/rustc_codegen_spirv/build.rs @@ -1,26 +1,37 @@ -//! This custom build script merely checks whether we're compiling with the appropriate Rust toolchain +//! This custom build script checks whether we're compiling with the appropriate +//! Rust toolchain, and also handles patching `rustc_codegen_ssa` to work around +//! pre-`qptr`-transition limitations (search `pqp_cg_ssa` for affected places). #![allow(clippy::string_add)] +use std::collections::VecDeque; use std::error::Error; +use std::path::{Path, PathBuf}; use std::process::{Command, ExitCode}; +use std::{env, fs, mem}; /// Current `rust-toolchain.toml` file /// Unfortunately, directly including the actual workspace `rust-toolchain.toml` doesn't work together with /// `cargo publish`. We need to figure out a way to do this properly, but let's hardcode it for now :/ //const REQUIRED_RUST_TOOLCHAIN: &str = include_str!("../../rust-toolchain.toml"); const REQUIRED_RUST_TOOLCHAIN: &str = r#"[toolchain] -channel = "nightly-2024-04-24" +channel = "nightly-2024-11-22" components = ["rust-src", "rustc-dev", "llvm-tools"] -# commit_hash = 244da22fabd9fa677bbd0ac601a88e5ca6917526"#; +# commit_hash = b19329a37cedf2027517ae22c87cf201f93d776e"#; + +fn rustc_output(arg: &str) -> Result> { + let rustc = env::var("RUSTC").unwrap_or_else(|_| "rustc".into()); + Ok(String::from_utf8( + Command::new(rustc).arg(arg).output()?.stdout, + )?) +} fn get_rustc_commit_hash() -> Result> { - let rustc = std::env::var("RUSTC").unwrap_or_else(|_| String::from("rustc")); - String::from_utf8(Command::new(rustc).arg("-vV").output()?.stdout)? + rustc_output("-vV")? .lines() .find_map(|l| l.strip_prefix("commit-hash: ")) .map(|s| s.to_string()) - .ok_or_else(|| Box::::from("`commit-hash` not found in `rustc -vV` output")) + .ok_or_else(|| "`commit-hash` not found in `rustc -vV` output".into()) } fn get_required_commit_hash() -> Result> { @@ -28,7 +39,7 @@ fn get_required_commit_hash() -> Result> { .lines() .find_map(|l| l.strip_prefix("# commit_hash = ")) .map(|s| s.to_string()) - .ok_or_else(|| Box::::from("`commit_hash` not found in `rust-toolchain.toml`")) + .ok_or_else(|| "`commit_hash` not found in `rust-toolchain.toml`".into()) } fn check_toolchain_version() -> Result<(), Box> { @@ -36,21 +47,20 @@ fn check_toolchain_version() -> Result<(), Box> { println!("cargo:rerun-if-env-changed=RUSTGPU_SKIP_TOOLCHAIN_CHECK"); // if we're building from local source, check if REQUIRED_RUST_TOOLCHAIN matches ../../rust-toolchain.toml - if std::env::current_dir()?.ends_with("crates/rustc_codegen_spirv") { + if env::current_dir()?.ends_with("crates/rustc_codegen_spirv") { let current_toolchain = std::fs::read_to_string("../../rust-toolchain.toml")?; if !current_toolchain.contains(REQUIRED_RUST_TOOLCHAIN) { - return Err(Box::::from(format!( + return Err(format!( "error: building from local source while `REQUIRED_RUST_TOOLCHAIN` (defined in `{}`) doesn't match `{}`", file!(), - std::path::Path::new("../../rust-toolchain.toml") + Path::new("../../rust-toolchain.toml") .canonicalize()? .display() - ))); + ).into()); } } - if !cfg!(feature = "skip-toolchain-check") - && std::env::var("RUSTGPU_SKIP_TOOLCHAIN_CHECK").is_err() + if !cfg!(feature = "skip-toolchain-check") && env::var("RUSTGPU_SKIP_TOOLCHAIN_CHECK").is_err() { // check if our current rustc's commit hash matches with what we expect it to be let current_hash = get_rustc_commit_hash()?; @@ -63,21 +73,211 @@ fn check_toolchain_version() -> Result<(), Box> { .reduce(|a, b| a + "\n" + &b) .unwrap_or_default(); - return Err(Box::::from(format!( + return Err(format!( r#"error: wrong toolchain detected (found commit hash `{current_hash}`, expected `{required_hash}`). Make sure your `rust-toolchain.toml` file contains the following: ------------- {stripped_toolchain} -------------"# - ))); + ).into()); + } + } + + Ok(()) +} + +/// Copy `rustc_codegen_ssa` (from the `rustc-dev` component) and patch it to +/// produce a "pqp" ("pre-`qptr`-patched") version that maintains compatibility +/// with "legacy" Rust-GPU pointer handling (mainly typed `alloca`s). +// +// FIXME(eddyb) get rid of this as soon as it's not needed anymore. +fn generate_pqp_cg_ssa() -> Result<(), Box> { + let sysroot = rustc_output("--print=sysroot")?; + let sysroot = Path::new(sysroot.trim()); + let cg_ssa_dir = sysroot.join("lib/rustlib/rustc-src/rust/compiler/rustc_codegen_ssa"); + if !cg_ssa_dir.is_dir() { + return Err(format!( + "missing `rustc-dev` component from toolchain `{}` (at {})", + env::var("RUSTUP_TOOLCHAIN").unwrap_or_else(|_| "".into()), + sysroot.display(), + ) + .into()); + } + + let mut cg_ssa_lib_rc_attrs = String::new(); + let mut cg_ssa_lib_rs_extern_crates = String::new(); + let writeln = |s: &mut String, line: &str| { + *s += line; + s.push('\n'); + }; + + let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap()); + let out_pqp_cg_ssa_dir = out_dir.join("pqp_cg_ssa"); + let _ = fs::remove_dir_all(&out_pqp_cg_ssa_dir); + + let mut queue = VecDeque::new(); + queue.push_back(PathBuf::new()); + while let Some(suffix) = queue.pop_front() { + let in_dir = cg_ssa_dir.join(&suffix); + let out_dir = out_pqp_cg_ssa_dir.join(&suffix); + fs::create_dir_all(&out_dir)?; + + for entry in in_dir.read_dir()? { + let entry = entry?; + let relative_path = suffix.join(entry.file_name()); + if entry.file_type()?.is_dir() { + queue.push_back(relative_path); + continue; + } + + let in_path = entry.path(); + let out_path = out_dir.join(entry.file_name()); + + let mut src = fs::read_to_string(in_path)?; + + // FIXME(eddyb) `regex` crate might be more efficient here. + src = src.replace("crate::", "crate::maybe_pqp_cg_ssa::"); + // HACK(eddyb) needed for `fluent` diagnostic identifiers. + src = src.replace("codegen_ssa_", "codegen_spirv_"); + + if relative_path == Path::new("src/lib.rs") { + // HACK(eddyb) rewrite line-by-line to comment (and copy) some lines. + for line in mem::take(&mut src).lines() { + if line.starts_with("#!") { + src += "// "; + if !line.starts_with("#![doc(") && line != "#![warn(unreachable_pub)]" { + writeln(&mut cg_ssa_lib_rc_attrs, line); + } + } else if line == "#[macro_use]" || line.starts_with("extern crate ") { + src += "// "; + writeln(&mut cg_ssa_lib_rs_extern_crates, line); + } + writeln(&mut src, line); + } + } + + // HACK(eddyb) remove `windows` dependency (from MSVC linker output + // parsing, which `rustc_codegen_spirv` will never invoke anyway). + if relative_path == Path::new("src/back/link.rs") { + src = src.replace( + "#[cfg(not(windows))] +fn escape_linker_output(", + "fn escape_linker_output(", + ); + src = src.replace( + "#[cfg(windows)] +fn escape_linker_output(", + "#[cfg(any())] +fn escape_linker_output(", + ); + src = src.replace( + "#[cfg(windows)] +mod win {", + "#[cfg(any())] +mod win {", + ); + } + + // HACK(eddyb) "typed alloca" patches. + if relative_path == Path::new("src/traits/builder.rs") { + src = src.replace( + " + fn alloca(", + " + fn typed_alloca(&mut self, ty: Self::Type, align: Align) -> Self::Value; + fn alloca(", + ); + } else if relative_path == Path::new("src/mir/place.rs") { + src = src.replace( + "Self::alloca_size(bx, layout.size, layout)", + "PlaceValue::new_sized(bx.typed_alloca(bx.cx().backend_type(layout), layout.align.abi), layout.align.abi).with_type(layout)", + ); + } else if relative_path == Path::new("src/mir/operand.rs") { + src = src.replace("alloca(field.size,", "typed_alloca(llfield_ty,"); + + // HACK(eddyb) non-array `#[repr(simd)]` workaround (see `src/abi.rs`). + src = src.replace("if constant_ty.is_simd() {", "if false {"); + } + + fs::write(out_path, src)?; + } + } + + // HACK(eddyb) very basic extraction of deps from original `Cargo.toml`. + let mut all_extern_crates = cg_ssa_lib_rs_extern_crates; + let cg_ssa_cargo_toml = fs::read_to_string(out_pqp_cg_ssa_dir.join("Cargo.toml"))?; + let mut toml_directive = None; + for line in cg_ssa_cargo_toml.lines() { + let line = line.trim(); + if line.starts_with('#') || line.is_empty() { + continue; } + if line.starts_with('[') { + toml_directive = Some(line); + } else if toml_directive == Some("[dependencies]") { + if let Some((name, _)) = line.split_once(" = ") { + // HACK(eddyb) ignore a weird edge case. + if name == "thorin-dwp" { + continue; + } + let extern_crate = format!("extern crate {};", name.replace('-', "_")); + if !all_extern_crates.contains(&extern_crate) { + writeln(&mut all_extern_crates, "#[allow(unused_extern_crates)]"); + writeln(&mut all_extern_crates, &extern_crate); + } + } + } + } + + // HACK(eddyb) warn if `rustc_codegen_spirv`'s `lib.rs` lacks crate attrs. + let expected_lib_rs_header = format!( + "\ +// HACK(eddyb) start of `rustc_codegen_ssa` crate-level attributes (see `build.rs`). +{cg_ssa_lib_rc_attrs}\ +// HACK(eddyb) end of `rustc_codegen_ssa` crate-level attributes (see `build.rs`). +" + ); + let lib_rs_path = Path::canonicalize(Path::new("src/lib.rs"))?; + let lib_rs_src = fs::read_to_string(&lib_rs_path)?; + let lib_rs_has_header = lib_rs_src.starts_with(&expected_lib_rs_header); + if !lib_rs_has_header { + println!( + "cargo::warning={} pqp_cg_ssa header in {}", + if lib_rs_src.starts_with(expected_lib_rs_header.lines().next().unwrap()) { + "outdated" + } else { + "missing" + }, + lib_rs_path.display(), + ); + println!("cargo::warning=(compilation may fail if these attributes don't match)"); + println!("cargo::warning="); + for line in expected_lib_rs_header.lines() { + println!("cargo::warning={line}"); + } + println!("cargo::warning="); } + // HACK(eddyb) write a file that can be `include!`d from `lib.rs`. + let pqp_cg_ssa_top_level = all_extern_crates + + r#" + +// HACK(eddyb) reexporting macro output for further macro use (can't patch macro). +use maybe_pqp_cg_ssa::fluent_generated; + +#[allow(unused, clippy::all, clippy::pedantic, clippy::restriction)] +#[path = "pqp_cg_ssa/src/lib.rs"] +mod maybe_pqp_cg_ssa; +"#; + fs::write(out_dir.join("pqp_cg_ssa.rs"), pqp_cg_ssa_top_level)?; + + println!("cargo::rustc-check-cfg=cfg(rustc_codegen_spirv_disable_pqp_cg_ssa)"); + Ok(()) } fn main() -> ExitCode { - match check_toolchain_version() { + match check_toolchain_version().and_then(|()| generate_pqp_cg_ssa()) { Ok(_) => ExitCode::SUCCESS, Err(e) => { eprint!("{e}"); diff --git a/crates/rustc_codegen_spirv/src/abi.rs b/crates/rustc_codegen_spirv/src/abi.rs index 44188bfc5c..04d1bf9860 100644 --- a/crates/rustc_codegen_spirv/src/abi.rs +++ b/crates/rustc_codegen_spirv/src/abi.rs @@ -4,31 +4,32 @@ use crate::attr::{AggregatedSpirvAttributes, IntrinsicType}; use crate::codegen_cx::CodegenCx; use crate::spirv_type::SpirvType; +use itertools::Itertools; use rspirv::spirv::{Dim, ImageFormat, StorageClass, Word}; use rustc_data_structures::fx::FxHashMap; use rustc_errors::ErrorGuaranteed; use rustc_index::Idx; use rustc_middle::query::Providers; use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, TyAndLayout}; -use rustc_middle::ty::GenericArgsRef; use rustc_middle::ty::{ - self, Const, CoroutineArgs, FloatTy, IntTy, ParamEnv, PolyFnSig, Ty, TyCtxt, TyKind, UintTy, + self, Const, CoroutineArgs, CoroutineArgsExt as _, FloatTy, IntTy, PolyFnSig, Ty, TyCtxt, + TyKind, UintTy, }; +use rustc_middle::ty::{GenericArgsRef, ScalarInt}; use rustc_middle::{bug, span_bug}; -use rustc_span::def_id::DefId; use rustc_span::DUMMY_SP; +use rustc_span::def_id::DefId; use rustc_span::{Span, Symbol}; use rustc_target::abi::call::{ArgAbi, ArgAttributes, FnAbi, PassMode}; use rustc_target::abi::{ - Abi, Align, FieldsShape, LayoutS, Primitive, Scalar, Size, TagEncoding, VariantIdx, Variants, + Align, BackendRepr, FieldsShape, LayoutData, Primitive, ReprFlags, ReprOptions, Scalar, Size, + TagEncoding, VariantIdx, Variants, }; -use rustc_target::spec::abi::Abi as SpecAbi; +use rustc_target::spec::abi::Abi; use std::cell::RefCell; use std::collections::hash_map::Entry; use std::fmt; -use num_traits::cast::FromPrimitive; - pub(crate) fn provide(providers: &mut Providers) { // This is a lil weird: so, we obviously don't support C ABIs at all. However, libcore does declare some extern // C functions: @@ -45,8 +46,8 @@ pub(crate) fn provide(providers: &mut Providers) { let result = (rustc_interface::DEFAULT_QUERY_PROVIDERS.fn_sig)(tcx, def_id); result.map_bound(|outer| { outer.map_bound(|mut inner| { - if let SpecAbi::C { .. } = inner.abi { - inner.abi = SpecAbi::Unadjusted; + if let Abi::C { .. } = inner.abi { + inner.abi = Abi::Unadjusted; } inner }) @@ -96,22 +97,21 @@ pub(crate) fn provide(providers: &mut Providers) { Ok(readjust_fn_abi(tcx, result?)) }; - // FIXME(eddyb) remove this by deriving `Clone` for `LayoutS` upstream. - // FIXME(eddyb) the `S` suffix is a naming antipattern, rename upstream. + // FIXME(eddyb) remove this by deriving `Clone` for `LayoutData` upstream. fn clone_layout( - layout: &LayoutS, - ) -> LayoutS { - let LayoutS { + layout: &LayoutData, + ) -> LayoutData { + let LayoutData { ref fields, ref variants, - abi, + backend_repr, largest_niche, align, size, max_repr_align, unadjusted_abi_align, } = *layout; - LayoutS { + LayoutData { fields: match *fields { FieldsShape::Primitive => FieldsShape::Primitive, FieldsShape::Union(count) => FieldsShape::Union(count), @@ -149,7 +149,7 @@ pub(crate) fn provide(providers: &mut Providers) { variants: variants.clone(), }, }, - abi, + backend_repr, largest_niche, align, size, @@ -157,6 +157,7 @@ pub(crate) fn provide(providers: &mut Providers) { unadjusted_abi_align, } } + providers.layout_of = |tcx, key| { let TyAndLayout { ty, mut layout } = (rustc_interface::DEFAULT_QUERY_PROVIDERS.layout_of)(tcx, key)?; @@ -168,7 +169,7 @@ pub(crate) fn provide(providers: &mut Providers) { }; if hide_niche { - layout = tcx.mk_layout(LayoutS { + layout = tcx.mk_layout(LayoutData { largest_niche: None, ..clone_layout(layout.0.0) }); @@ -176,6 +177,102 @@ pub(crate) fn provide(providers: &mut Providers) { Ok(TyAndLayout { ty, layout }) }; + + // HACK(eddyb) work around https://github.com/rust-lang/rust/pull/129403 + // banning "struct-style" `#[repr(simd)]` (in favor of "array-newtype-style"), + // by simply bypassing "type definition WF checks" for affected types, which: + // - can only really be sound for types with trivial field types, that are + // either completely non-generic (covering most `#[repr(simd)]` `struct`s), + // or *at most* one generic type parameter with no bounds/where clause + // - relies on upstream `layout_of` not having had the non-array logic removed + // + // FIXME(eddyb) remove this once migrating beyond `#[repr(simd)]` becomes + // an option (may require Rust-GPU distinguishing between "SPIR-V interface" + // and "Rust-facing" types, which is even worse when the `OpTypeVector`s + // may be e.g. nested in `struct`s/arrays/etc. - at least buffers are easy). + // + // FIXME(eddyb) maybe using `#[spirv(vector)]` and `BackendRepr::Memory`, + // no claims at `rustc`-understood SIMD whatsoever, would be enough? + // (i.e. only SPIR-V caring about such a type vs a struct/array) + providers.check_well_formed = |tcx, def_id| { + let trivial_struct = match tcx.hir_node_by_def_id(def_id) { + rustc_hir::Node::Item(item) => match item.kind { + rustc_hir::ItemKind::Struct( + _, + &rustc_hir::Generics { + params: + &[] + | &[ + rustc_hir::GenericParam { + kind: + rustc_hir::GenericParamKind::Type { + default: None, + synthetic: false, + }, + .. + }, + ], + predicates: &[], + has_where_clause_predicates: false, + where_clause_span: _, + span: _, + }, + ) => Some(tcx.adt_def(def_id)), + _ => None, + }, + _ => None, + }; + let valid_non_array_simd_struct = trivial_struct.is_some_and(|adt_def| { + let ReprOptions { + int: None, + align: None, + pack: None, + flags: ReprFlags::IS_SIMD, + field_shuffle_seed: _, + } = adt_def.repr() + else { + return false; + }; + if adt_def.destructor(tcx).is_some() { + return false; + } + + let field_types = adt_def + .non_enum_variant() + .fields + .iter() + .map(|f| tcx.type_of(f.did).instantiate_identity()); + field_types.dedup().exactly_one().is_ok_and(|elem_ty| { + matches!( + elem_ty.kind(), + ty::Bool | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Param(_) + ) + }) + }); + + if valid_non_array_simd_struct { + tcx.dcx() + .struct_span_warn( + tcx.def_span(def_id), + "[Rust-GPU] temporarily re-allowing old-style `#[repr(simd)]` (with fields)", + ) + .with_note("removed upstream by https://github.com/rust-lang/rust/pull/129403") + .with_note("in favor of the new `#[repr(simd)] struct TxN([T; N]);` style") + .with_note("(taking effect since `nightly-2024-09-12` / `1.83.0` stable)") + .emit(); + return Ok(()); + } + + (rustc_interface::DEFAULT_QUERY_PROVIDERS.check_well_formed)(tcx, def_id) + }; + + // HACK(eddyb) work around https://github.com/rust-lang/rust/pull/132173 + // (and further changes from https://github.com/rust-lang/rust/pull/132843) + // starting to ban SIMD ABI misuse (or at least starting to warn about it). + // + // FIXME(eddyb) same as the FIXME comment on `check_well_formed`: + // need to migrate away from `#[repr(simd)]` ASAP. + providers.check_mono_item = |_, _| {}; } /// If a struct contains a pointer to itself, even indirectly, then doing a naiive recursive walk @@ -363,9 +460,9 @@ impl<'tcx> ConvSpirvType<'tcx> for TyAndLayout<'tcx> { // Note: ty.layout is orthogonal to ty.ty, e.g. `ManuallyDrop>` has abi // `ScalarPair`. - // There's a few layers that we go through here. First we inspect layout.abi, then if relevant, layout.fields, etc. - match self.abi { - Abi::Uninhabited => SpirvType::Adt { + // There's a few layers that we go through here. First we inspect layout.backend_repr, then if relevant, layout.fields, etc. + match self.backend_repr { + BackendRepr::Uninhabited => SpirvType::Adt { def_id: def_id_for_spirv_type_adt(*self), size: Some(Size::ZERO), align: Align::from_bytes(0).unwrap(), @@ -374,13 +471,13 @@ impl<'tcx> ConvSpirvType<'tcx> for TyAndLayout<'tcx> { field_names: None, } .def_with_name(cx, span, TyLayoutNameKey::from(*self)), - Abi::Scalar(scalar) => trans_scalar(cx, span, *self, scalar, Size::ZERO), - Abi::ScalarPair(a, b) => { - // NOTE(eddyb) unlike `Abi::Scalar`'s simpler newtype-unpacking - // behavior, `Abi::ScalarPair` can be composed in two ways: - // * two `Abi::Scalar` fields (and any number of ZST fields), + BackendRepr::Scalar(scalar) => trans_scalar(cx, span, *self, scalar, Size::ZERO), + BackendRepr::ScalarPair(a, b) => { + // NOTE(eddyb) unlike `BackendRepr::Scalar`'s simpler newtype-unpacking + // behavior, `BackendRepr::ScalarPair` can be composed in two ways: + // * two `BackendRepr::Scalar` fields (and any number of ZST fields), // gets handled the same as a `struct { a, b }`, further below - // * an `Abi::ScalarPair` field (and any number of ZST fields), + // * an `BackendRepr::ScalarPair` field (and any number of ZST fields), // which requires more work to allow taking a reference to // that field, and there are two potential approaches: // 1. wrapping that field's SPIR-V type in a single-field @@ -390,7 +487,7 @@ impl<'tcx> ConvSpirvType<'tcx> for TyAndLayout<'tcx> { // 2. reusing that field's SPIR-V type, instead of defining // a new one, offering the `(a, b)` shape `rustc_codegen_ssa` // expects, while letting noop pointercasts access the sole - // `Abi::ScalarPair` field - this is the approach taken here + // `BackendRepr::ScalarPair` field - this is the approach taken here let mut non_zst_fields = (0..self.fields.count()) .map(|i| (i, self.field(cx, i))) .filter(|(_, field)| !field.is_zst()); @@ -404,7 +501,7 @@ impl<'tcx> ConvSpirvType<'tcx> for TyAndLayout<'tcx> { if self.fields.offset(i) == Size::ZERO && field.size == self.size && field.align == self.align - && field.abi == self.abi + && field.backend_repr == self.backend_repr { return field.spirv_type(span, cx); } @@ -445,7 +542,7 @@ impl<'tcx> ConvSpirvType<'tcx> for TyAndLayout<'tcx> { } .def_with_name(cx, span, TyLayoutNameKey::from(*self)) } - Abi::Vector { element, count } => { + BackendRepr::Vector { element, count } => { let elem_spirv = trans_scalar(cx, span, *self, element, Size::ZERO); SpirvType::Vector { element: elem_spirv, @@ -453,12 +550,12 @@ impl<'tcx> ConvSpirvType<'tcx> for TyAndLayout<'tcx> { } .def(span, cx) } - Abi::Aggregate { sized: _ } => trans_aggregate(cx, span, *self), + BackendRepr::Memory { sized: _ } => trans_aggregate(cx, span, *self), } } } -/// Only pub for `LayoutTypeMethods::scalar_pair_element_backend_type`. Think about what you're +/// Only pub for `LayoutTypeCodegenMethods::scalar_pair_element_backend_type`. Think about what you're /// doing before calling this. pub fn scalar_pair_element_backend_type<'tcx>( cx: &CodegenCx<'tcx>, @@ -466,8 +563,8 @@ pub fn scalar_pair_element_backend_type<'tcx>( ty: TyAndLayout<'tcx>, index: usize, ) -> Word { - let [a, b] = match ty.layout.abi() { - Abi::ScalarPair(a, b) => [a, b], + let [a, b] = match ty.layout.backend_repr() { + BackendRepr::ScalarPair(a, b) => [a, b], other => span_bug!( span, "scalar_pair_element_backend_type invalid abi: {:?}", @@ -501,13 +598,12 @@ fn trans_scalar<'tcx>( } match scalar.primitive() { - Primitive::Int(width, signedness) => { - SpirvType::Integer(width.size().bits() as u32, signedness).def(span, cx) + Primitive::Int(int_kind, signedness) => { + SpirvType::Integer(int_kind.size().bits() as u32, signedness).def(span, cx) + } + Primitive::Float(float_kind) => { + SpirvType::Float(float_kind.size().bits() as u32).def(span, cx) } - Primitive::F16 => SpirvType::Float(16).def(span, cx), - Primitive::F32 => SpirvType::Float(32).def(span, cx), - Primitive::F64 => SpirvType::Float(64).def(span, cx), - Primitive::F128 => SpirvType::Float(128).def(span, cx), Primitive::Pointer(_) => { let pointee_ty = dig_scalar_pointee(cx, ty, offset); // Pointers can be recursive. So, record what we're currently translating, and if we're already translating @@ -549,7 +645,7 @@ fn dig_scalar_pointee<'tcx>( TyKind::Ref(_, pointee_ty, _) | TyKind::RawPtr(pointee_ty, _) => { PointeeTy::Ty(cx.layout_of(pointee_ty)) } - TyKind::FnPtr(sig) => PointeeTy::Fn(sig), + TyKind::FnPtr(sig_tys, hdr) => PointeeTy::Fn(sig_tys.with(hdr)), _ => bug!("Pointer is not `&T`, `*T` or `fn` pointer: {:#?}", layout), }; return pointee; @@ -815,7 +911,7 @@ fn trans_intrinsic_type<'tcx>( // ) -> P { // let adt_def = const_.ty.ty_adt_def().unwrap(); // assert!(adt_def.is_enum()); - // let destructured = cx.tcx.destructure_const(ParamEnv::reveal_all().and(const_)); + // let destructured = cx.tcx.destructure_const(TypingEnv::fully_monomorphized().and(const_)); // let idx = destructured.variant.unwrap(); // let value = const_.ty.discriminant_for_variant(cx.tcx, idx).unwrap().val as u64; // <_>::from_u64(value).unwrap() @@ -862,41 +958,44 @@ fn trans_intrinsic_type<'tcx>( // let image_format: spirv::ImageFormat = // type_from_variant_discriminant(cx, args.const_at(6)); - trait FromU128Const: Sized { - fn from_u128_const(n: u128) -> Option; + trait FromScalarInt: Sized { + fn from_scalar_int(n: ScalarInt) -> Option; } - impl FromU128Const for u32 { - fn from_u128_const(n: u128) -> Option { - u32::from_u128(n) + impl FromScalarInt for u32 { + fn from_scalar_int(n: ScalarInt) -> Option { + Some(n.try_to_bits(Size::from_bits(32)).ok()?.try_into().unwrap()) } } - impl FromU128Const for Dim { - fn from_u128_const(n: u128) -> Option { - Dim::from_u32(u32::from_u128(n)?) + impl FromScalarInt for Dim { + fn from_scalar_int(n: ScalarInt) -> Option { + Dim::from_u32(u32::from_scalar_int(n)?) } } - impl FromU128Const for ImageFormat { - fn from_u128_const(n: u128) -> Option { - ImageFormat::from_u32(u32::from_u128(n)?) + impl FromScalarInt for ImageFormat { + fn from_scalar_int(n: ScalarInt) -> Option { + ImageFormat::from_u32(u32::from_scalar_int(n)?) } } - fn const_int_value<'tcx, P: FromU128Const>( + fn const_int_value<'tcx, P: FromScalarInt>( cx: &CodegenCx<'tcx>, const_: Const<'tcx>, ) -> Result { - assert!(const_.ty().is_integral()); - let value = const_.eval_bits(cx.tcx, ParamEnv::reveal_all()); - match P::from_u128_const(value) { - Some(v) => Ok(v), - None => Err(cx - .tcx - .dcx() - .err(format!("Invalid value for Image const generic: {value}"))), - } + let (const_val, const_ty) = const_ + .try_to_valtree() + .expect("expected monomorphic const in codegen"); + assert!(const_ty.is_integral()); + const_val + .try_to_scalar_int() + .and_then(P::from_scalar_int) + .ok_or_else(|| { + cx.tcx + .dcx() + .err(format!("invalid value for Image const generic: {const_}")) + }) } let dim = const_int_value(cx, args.const_at(1))?; diff --git a/crates/rustc_codegen_spirv/src/attr.rs b/crates/rustc_codegen_spirv/src/attr.rs index d3976747ba..bd94159f04 100644 --- a/crates/rustc_codegen_spirv/src/attr.rs +++ b/crates/rustc_codegen_spirv/src/attr.rs @@ -9,7 +9,7 @@ use rustc_ast::Attribute; use rustc_hir as hir; use rustc_hir::def_id::LocalModDefId; use rustc_hir::intravisit::{self, Visitor}; -use rustc_hir::{HirId, MethodKind, Target, CRATE_HIR_ID}; +use rustc_hir::{CRATE_HIR_ID, HirId, MethodKind, Target}; use rustc_middle::hir::nested_filter; use rustc_middle::query::Providers; use rustc_middle::ty::TyCtxt; @@ -182,15 +182,14 @@ impl AggregatedSpirvAttributes { span: Span, category: &'static str, ) -> Result<(), MultipleAttrs> { - match slot { - Some(prev) => Err(MultipleAttrs { + if let Some(prev) = slot { + Err(MultipleAttrs { prev_span: prev.span, category, - }), - None => { - *slot = Some(Spanned { value, span }); - Ok(()) - } + }) + } else { + *slot = Some(Spanned { value, span }); + Ok(()) } } diff --git a/crates/rustc_codegen_spirv/src/builder/builder_methods.rs b/crates/rustc_codegen_spirv/src/builder/builder_methods.rs index c97a8a2ecb..7e61c1b989 100644 --- a/crates/rustc_codegen_spirv/src/builder/builder_methods.rs +++ b/crates/rustc_codegen_spirv/src/builder/builder_methods.rs @@ -1,22 +1,26 @@ +// HACK(eddyb) avoids rewriting all of the imports (see `lib.rs` and `build.rs`). +use crate::maybe_pqp_cg_ssa as rustc_codegen_ssa; + use super::Builder; use crate::abi::ConvSpirvType; use crate::builder_spirv::{BuilderCursor, SpirvConst, SpirvValue, SpirvValueExt, SpirvValueKind}; +use crate::codegen_cx::CodegenCx; use crate::custom_insts::{CustomInst, CustomOp}; -use crate::rustc_codegen_ssa::traits::BaseTypeMethods; use crate::spirv_type::SpirvType; use itertools::Itertools; use rspirv::dr::{InsertPoint, Instruction, Operand}; use rspirv::spirv::{Capability, MemoryModel, MemorySemantics, Op, Scope, StorageClass, Word}; -use rustc_apfloat::{ieee, Float, Round, Status}; +use rustc_apfloat::{Float, Round, Status, ieee}; +use rustc_codegen_ssa::MemFlags; use rustc_codegen_ssa::common::{ AtomicOrdering, AtomicRmwBinOp, IntPredicate, RealPredicate, SynchronizationScope, TypeKind, }; use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue}; use rustc_codegen_ssa::mir::place::PlaceRef; use rustc_codegen_ssa::traits::{ - BackendTypes, BuilderMethods, ConstMethods, LayoutTypeMethods, OverflowOp, + BackendTypes, BaseTypeCodegenMethods, BuilderMethods, ConstCodegenMethods, + LayoutTypeCodegenMethods, OverflowOp, }; -use rustc_codegen_ssa::MemFlags; use rustc_data_structures::fx::FxHashSet; use rustc_middle::bug; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; @@ -24,7 +28,7 @@ use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, Ty}; use rustc_span::Span; use rustc_target::abi::call::FnAbi; -use rustc_target::abi::{Abi, Align, Scalar, Size, WrappingRange}; +use rustc_target::abi::{Align, BackendRepr, Scalar, Size, WrappingRange}; use smallvec::SmallVec; use std::borrow::Cow; use std::cell::Cell; @@ -49,12 +53,11 @@ macro_rules! simple_op { let size = Size::from_bits(bits); let as_u128 = |const_val| { let x = match const_val { - SpirvConst::U32(x) => x as u128, - SpirvConst::U64(x) => x as u128, + SpirvConst::Scalar(x) => x, _ => return None, }; Some(if signed { - size.sign_extend(x) + size.sign_extend(x) as u128 } else { size.truncate(x) }) @@ -225,7 +228,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } SpirvType::Array { element, count } => { let elem_pat = self.memset_const_pattern(&self.lookup_type(element), fill_byte); - let count = self.builder.lookup_const_u64(count).unwrap() as usize; + let count = self.builder.lookup_const_scalar(count).unwrap() as usize; self.constant_composite( ty.def(self.span(), self), iter::repeat(elem_pat).take(count), @@ -269,7 +272,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { SpirvType::Adt { .. } => self.fatal("memset on structs not implemented yet"), SpirvType::Array { element, count } => { let elem_pat = self.memset_dynamic_pattern(&self.lookup_type(element), fill_var); - let count = self.builder.lookup_const_u64(count).unwrap() as usize; + let count = self.builder.lookup_const_scalar(count).unwrap() as usize; self.emit() .composite_construct( ty.def(self.span(), self), @@ -327,7 +330,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { .lookup_type(pat.ty) .sizeof(self) .expect("Unable to memset a dynamic sized object"); - let size_elem_const = self.constant_int(size_bytes.ty, size_elem.bytes()); + let size_elem_const = self.constant_int(size_bytes.ty, size_elem.bytes().into()); let zero = self.constant_int(size_bytes.ty, 0); let one = self.constant_int(size_bytes.ty, 1); let zero_align = Align::from_bytes(0).unwrap(); @@ -337,7 +340,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let exit_bb = self.append_sibling_block("memset_exit"); let count = self.udiv(size_bytes, size_elem_const); - let index = self.alloca(count.ty, zero_align); + let index = self.alloca(self.lookup_type(count.ty).sizeof(self).unwrap(), zero_align); self.store(zero, index, zero_align); self.br(header_bb); @@ -595,8 +598,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // - dynamic indexing of a single array let const_ptr_offset = self .builder - .lookup_const_u64(ptr_base_index) - .and_then(|idx| Some(idx * self.lookup_type(ty).sizeof(self)?)); + .lookup_const_scalar(ptr_base_index) + .and_then(|idx| Some(u64::try_from(idx).ok()? * self.lookup_type(ty).sizeof(self)?)); if let Some(const_ptr_offset) = const_ptr_offset { if let Some((base_indices, base_pointee_ty)) = self.recover_access_chain_from_offset( original_pointee_ty, @@ -707,7 +710,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let mut emit = self.emit(); let non_zero_ptr_base_index = - ptr_base_index.filter(|&idx| self.builder.lookup_const_u64(idx) != Some(0)); + ptr_base_index.filter(|&idx| self.builder.lookup_const_scalar(idx) != Some(0)); if let Some(ptr_base_index) = non_zero_ptr_base_index { let result = if is_inbounds { emit.in_bounds_ptr_access_chain( @@ -917,9 +920,47 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { s1 } } + + // HACK(eddyb) helper shared by `typed_alloca` and `alloca`. + fn declare_func_local_var( + &mut self, + ty: ::Type, + _align: Align, + ) -> SpirvValue { + let ptr_ty = self.type_ptr_to(ty); + + // "All OpVariable instructions in a function must be the first instructions in the first block." + let mut builder = self.emit(); + builder.select_block(Some(0)).unwrap(); + let index = { + let block = &builder.module_ref().functions[builder.selected_function().unwrap()] + .blocks[builder.selected_block().unwrap()]; + block + .instructions + .iter() + .enumerate() + .find_map(|(index, inst)| { + if inst.class.opcode != Op::Variable { + Some(InsertPoint::FromBegin(index)) + } else { + None + } + }) + .unwrap_or(InsertPoint::End) + }; + // TODO: rspirv doesn't have insert_variable function + let result_id = builder.id(); + let inst = Instruction::new(Op::Variable, Some(ptr_ty), Some(result_id), vec![ + Operand::StorageClass(StorageClass::Function), + ]); + builder.insert_into_block(index, inst).unwrap(); + result_id.with_type(ptr_ty) + } } impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { + type CodegenCx = CodegenCx<'tcx>; + fn build(cx: &'a Self::CodegenCx, llbb: Self::BasicBlock) -> Self { let cursor = cx.builder.select_block_by_id(llbb); // FIXME(eddyb) change `Self::Function` to be more like a function index. @@ -936,7 +977,6 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { cx, cursor, current_fn, - basic_block: llbb, current_span: Default::default(), } } @@ -946,7 +986,8 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { } fn llbb(&self) -> Self::BasicBlock { - self.basic_block + // FIXME(eddyb) `llbb` should be removed from `rustc_codegen_ssa::traits`. + unreachable!("dead code within `rustc_codegen_ssa`") } fn set_span(&mut self, span: Span) { @@ -983,16 +1024,13 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { let ((line_start, col_start), (line_end, col_end)) = (line_col_range.start, line_col_range.end); - self.custom_inst( - void_ty, - CustomInst::SetDebugSrcLoc { - file: Operand::IdRef(file.file_name_op_string_id), - line_start: Operand::IdRef(self.const_u32(line_start).def(self)), - line_end: Operand::IdRef(self.const_u32(line_end).def(self)), - col_start: Operand::IdRef(self.const_u32(col_start).def(self)), - col_end: Operand::IdRef(self.const_u32(col_end).def(self)), - }, - ); + self.custom_inst(void_ty, CustomInst::SetDebugSrcLoc { + file: Operand::IdRef(file.file_name_op_string_id), + line_start: Operand::IdRef(self.const_u32(line_start).def(self)), + line_end: Operand::IdRef(self.const_u32(line_end).def(self)), + col_start: Operand::IdRef(self.const_u32(col_start).def(self)), + col_end: Operand::IdRef(self.const_u32(col_end).def(self)), + }); } // HACK(eddyb) remove the previous instruction if made irrelevant. @@ -1083,8 +1121,8 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { // HACK(eddyb) constant-fold branches early on, as the `core` library is // starting to get a lot of `if cfg!(debug_assertions)` added to it. match self.builder.lookup_const_by_id(cond) { - Some(SpirvConst::Bool(true)) => self.br(then_llbb), - Some(SpirvConst::Bool(false)) => self.br(else_llbb), + Some(SpirvConst::Scalar(1)) => self.br(then_llbb), + Some(SpirvConst::Scalar(0)) => self.br(else_llbb), _ => { self.emit() .branch_conditional(cond, then_llbb, else_llbb, empty()) @@ -1340,14 +1378,11 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { let signed = match ty.kind() { ty::Int(_) => true, ty::Uint(_) => false, - other => self.fatal(format!( - "Unexpected {} type: {other:#?}", - match oop { - OverflowOp::Add => "checked add", - OverflowOp::Sub => "checked sub", - OverflowOp::Mul => "checked mul", - } - )), + other => self.fatal(format!("Unexpected {} type: {other:#?}", match oop { + OverflowOp::Add => "checked add", + OverflowOp::Sub => "checked sub", + OverflowOp::Mul => "checked mul", + })), }; let result = if is_add { @@ -1413,41 +1448,17 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { val } - fn alloca(&mut self, ty: Self::Type, _align: Align) -> Self::Value { - let ptr_ty = self.type_ptr_to(ty); - // "All OpVariable instructions in a function must be the first instructions in the first block." - let mut builder = self.emit(); - builder.select_block(Some(0)).unwrap(); - let index = { - let block = &builder.module_ref().functions[builder.selected_function().unwrap()] - .blocks[builder.selected_block().unwrap()]; - block - .instructions - .iter() - .enumerate() - .find_map(|(index, inst)| { - if inst.class.opcode != Op::Variable { - Some(InsertPoint::FromBegin(index)) - } else { - None - } - }) - .unwrap_or(InsertPoint::End) - }; - // TODO: rspirv doesn't have insert_variable function - let result_id = builder.id(); - let inst = Instruction::new( - Op::Variable, - Some(ptr_ty), - Some(result_id), - vec![Operand::StorageClass(StorageClass::Function)], - ); - builder.insert_into_block(index, inst).unwrap(); - result_id.with_type(ptr_ty) + // HACK(eddyb) new method patched into `pqp_cg_ssa` (see `build.rs`). + #[cfg(not(rustc_codegen_spirv_disable_pqp_cg_ssa))] + fn typed_alloca(&mut self, ty: Self::Type, align: Align) -> Self::Value { + self.declare_func_local_var(ty, align) + } + fn alloca(&mut self, size: Size, align: Align) -> Self::Value { + self.declare_func_local_var(self.type_array(self.type_i8(), size.bytes()), align) } - fn byte_array_alloca(&mut self, _len: Self::Value, _align: Align) -> Self::Value { - self.fatal("array alloca not supported yet") + fn dynamic_alloca(&mut self, _len: Self::Value, _align: Align) -> Self::Value { + self.fatal("dynamic alloca not supported yet") } fn load(&mut self, ty: Self::Type, ptr: Self::Value, _align: Align) -> Self::Value { @@ -1512,7 +1523,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { place.val.align, ); OperandValue::Immediate(self.to_immediate(llval, place.layout)) - } else if let Abi::ScalarPair(a, b) = place.layout.abi { + } else if let BackendRepr::ScalarPair(a, b) = place.layout.backend_repr { let b_offset = a .primitive() .size(self) @@ -2003,13 +2014,11 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { SpirvType::Pointer { .. } => match op { IntEQ => { if self.emit().version().unwrap() > (1, 3) { - let ptr_equal = - self.emit().ptr_equal(b, None, lhs.def(self), rhs.def(self)); - - ptr_equal.map(|result| { - self.zombie_ptr_equal(result, "OpPtrEqual"); - result - }) + self.emit() + .ptr_equal(b, None, lhs.def(self), rhs.def(self)) + .inspect(|&result| { + self.zombie_ptr_equal(result, "OpPtrEqual"); + }) } else { let int_ty = self.type_usize(); let lhs = self @@ -2022,16 +2031,15 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { .convert_ptr_to_u(int_ty, None, rhs.def(self)) .unwrap(); self.zombie_convert_ptr_to_u(rhs); - self.emit().i_not_equal(b, None, lhs, rhs) + self.emit().i_equal(b, None, lhs, rhs) } } IntNE => { if self.emit().version().unwrap() > (1, 3) { self.emit() .ptr_not_equal(b, None, lhs.def(self), rhs.def(self)) - .map(|result| { + .inspect(|&result| { self.zombie_ptr_equal(result, "OpPtrNotEqual"); - result }) } else { let int_ty = self.type_usize(); @@ -2232,7 +2240,10 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { "memcpy with mem flags is not supported yet: {flags:?}" )); } - let const_size = self.builder.lookup_const_u64(size).map(Size::from_bytes); + let const_size = self + .builder + .lookup_const_scalar(size) + .and_then(|size| Some(Size::from_bytes(u64::try_from(size).ok()?))); if const_size == Some(Size::ZERO) { // Nothing to do! return; @@ -2306,6 +2317,12 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { "memset with mem flags is not supported yet: {flags:?}" )); } + + let const_size = self + .builder + .lookup_const_scalar(size) + .and_then(|size| Some(Size::from_bytes(u64::try_from(size).ok()?))); + let elem_ty = match self.lookup_type(ptr.ty) { SpirvType::Pointer { pointee } => pointee, _ => self.fatal(format!( @@ -2314,13 +2331,13 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { )), }; let elem_ty_spv = self.lookup_type(elem_ty); - let pat = match self.builder.lookup_const_u64(fill_byte) { + let pat = match self.builder.lookup_const_scalar(fill_byte) { Some(fill_byte) => self.memset_const_pattern(&elem_ty_spv, fill_byte as u8), None => self.memset_dynamic_pattern(&elem_ty_spv, fill_byte.def(self)), } .with_type(elem_ty); - match self.builder.lookup_const_u64(size) { - Some(size) => self.memset_constant_size(ptr, pat, size), + match const_size { + Some(size) => self.memset_constant_size(ptr, pat, size.bytes()), None => self.memset_dynamic_size(ptr, pat, size), } } @@ -2354,7 +2371,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { SpirvType::Vector { element, .. } => element, other => self.fatal(format!("extract_element not implemented on type {other:?}")), }; - match self.builder.lookup_const_u64(idx) { + match self.builder.lookup_const_scalar(idx) { Some(const_index) => self.emit().composite_extract( result_type, None, @@ -2651,16 +2668,6 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { // ignore } - fn instrprof_increment( - &mut self, - _fn_name: Self::Value, - _hash: Self::Value, - _num_counters: Self::Value, - _index: Self::Value, - ) { - todo!() - } - fn call( &mut self, callee_ty: Self::Type, @@ -2771,7 +2778,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { /// /// E.g. for `format_args!("{a} {b:x}")` they'll be: /// * `&a` with `typeof a` and ' ', - /// *`&b` with `typeof b` and 'x' + /// * `&b` with `typeof b` and 'x' ref_arg_ids_with_ty_and_spec: SmallVec<[(Word, Ty<'tcx>, char); 2]>, } struct FormatArgsNotRecognized(String); @@ -2781,27 +2788,26 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { let mut decoded_format_args = DecodedFormatArgs::default(); let const_u32_as_usize = |ct_id| match self.builder.lookup_const_by_id(ct_id)? { - SpirvConst::U32(x) => Some(x as usize), + SpirvConst::Scalar(x) => Some(u32::try_from(x).ok()? as usize), _ => None, }; - let const_slice_as_elem_ids = |slice_ptr_and_len_ids: &[Word]| { - if let [ptr_id, len_id] = slice_ptr_and_len_ids[..] { - if let SpirvConst::PtrTo { pointee } = - self.builder.lookup_const_by_id(ptr_id)? + let const_slice_as_elem_ids = |ptr_id: Word, len: usize| { + if let SpirvConst::PtrTo { pointee } = + self.builder.lookup_const_by_id(ptr_id)? + { + if let SpirvConst::Composite(elems) = + self.builder.lookup_const_by_id(pointee)? { - if let SpirvConst::Composite(elems) = - self.builder.lookup_const_by_id(pointee)? - { - if elems.len() == const_u32_as_usize(len_id)? { - return Some(elems); - } + if elems.len() == len { + return Some(elems); } } } None }; - let const_str_as_utf8 = |str_ptr_and_len_ids: &[Word]| { - let piece_str_bytes = const_slice_as_elem_ids(str_ptr_and_len_ids)? + let const_str_as_utf8 = |&[str_ptr_id, str_len_id]: &[Word; 2]| { + let str_len = const_u32_as_usize(str_len_id)?; + let piece_str_bytes = const_slice_as_elem_ids(str_ptr_id, str_len)? .iter() .map(|&id| u8::try_from(const_u32_as_usize(id)?).ok()) .collect::>>()?; @@ -2818,22 +2824,34 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { kind: SpirvValueKind::Def(b_id), .. }, - // NOTE(fee1-dead): the standard `panic` takes in a `Location` due to `track_caller`. - // but for `panic_nounwind` it does not, therefore we only look at the first two arguments. - ] = args[..2] + ref other_args @ .., + ] = args[..] { - if let Some(const_msg) = const_str_as_utf8(&[a_id, b_id]) { - decoded_format_args.const_pieces = Some([const_msg].into_iter().collect()); - return Ok(decoded_format_args); + // Optional `&'static panic::Location<'static>`. + if other_args.len() <= 1 { + if let Some(const_msg) = const_str_as_utf8(&[a_id, b_id]) { + decoded_format_args.const_pieces = + Some([const_msg].into_iter().collect()); + return Ok(decoded_format_args); + } } } - let format_args_id = match args { - &[ + let format_args_id = match *args { + // HACK(eddyb) `panic_nounwind_fmt` takes an extra argument. + [ + SpirvValue { + kind: SpirvValueKind::Def(format_args_id), + .. + }, + _, // `&'static panic::Location<'static>` + ] + | [ SpirvValue { kind: SpirvValueKind::Def(format_args_id), .. }, + _, // `force_no_backtrace: bool` _, // `&'static panic::Location<'static>` ] => format_args_id, @@ -2936,10 +2954,10 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { match (inst.class.opcode, inst.result_id, &id_operands[..]) { (Op::Bitcast, Some(r), &[x]) => Inst::Bitcast(r, x), (Op::InBoundsAccessChain, Some(r), &[p, i]) => { - if let Some(SpirvConst::U32(i)) = + if let Some(SpirvConst::Scalar(i)) = self.builder.lookup_const_by_id(i) { - Inst::InBoundsAccessChain(r, p, i) + Inst::InBoundsAccessChain(r, p, i as u32) } else { Inst::Unsupported(inst.class.opcode) } @@ -2963,42 +2981,36 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { "fmt::Arguments::new call: ran out of instructions".into(), ) })?; - let ((pieces_slice_ptr_id, pieces_len_id), (rt_args_slice_ptr_id, rt_args_count)) = + let ((pieces_slice_ptr_id, pieces_len), (rt_args_slice_ptr_id, rt_args_count)) = match fmt_args_new_call_insts[..] { [ Inst::Call(call_ret_id, callee_id, ref call_args), Inst::Store(st_dst_id, st_val_id), Inst::Load(ld_val_id, ld_src_id), - ] if self.fmt_args_new_fn_ids.borrow().contains(&callee_id) - && call_ret_id == st_val_id + ] if call_ret_id == st_val_id && st_dst_id == ld_src_id && ld_val_id == format_args_id => { require_local_var(st_dst_id, "fmt::Arguments::new destination")?; + let Some(&(pieces_len, rt_args_count)) = + self.fmt_args_new_fn_ids.borrow().get(&callee_id) + else { + return Err(FormatArgsNotRecognized( + "fmt::Arguments::new callee not registered".into(), + )); + }; + match call_args[..] { // `::new_v1` - [ - pieces_slice_ptr_id, - pieces_len_id, - rt_args_slice_ptr_id, - rt_args_len_id, - ] => ( - (pieces_slice_ptr_id, pieces_len_id), - ( - Some(rt_args_slice_ptr_id), - const_u32_as_usize(rt_args_len_id).ok_or_else(|| { - FormatArgsNotRecognized( - "fmt::Arguments::new: args.len() not constant" - .into(), - ) - })?, - ), + [pieces_slice_ptr_id, rt_args_slice_ptr_id] => ( + (pieces_slice_ptr_id, pieces_len), + (Some(rt_args_slice_ptr_id), rt_args_count), ), // `::new_const` - [pieces_slice_ptr_id, pieces_len_id] => { - ((pieces_slice_ptr_id, pieces_len_id), (None, 0)) + [pieces_slice_ptr_id] if rt_args_count == 0 => { + ((pieces_slice_ptr_id, pieces_len), (None, rt_args_count)) } _ => { @@ -3030,21 +3042,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { // arguments (from e.g. new `assert!`s being added to `core`), // we have to confirm their many instructions for removal. if rt_args_count > 0 { - let rt_args_slice_ptr_id = rt_args_slice_ptr_id.unwrap(); - let rt_args_array_ptr_id = match try_rev_take(1).ok_or_else(|| { - FormatArgsNotRecognized( - "&[fmt::rt::Argument] bitcast: ran out of instructions".into(), - ) - })?[..] - { - [Inst::Bitcast(out_id, in_id)] if out_id == rt_args_slice_ptr_id => in_id, - _ => { - return Err(FormatArgsNotRecognized( - "&[fmt::rt::Argument] bitcast".into(), - )); - } - }; - require_local_var(rt_args_array_ptr_id, "[fmt::rt::Argument; N]")?; + let rt_args_array_ptr_id = rt_args_slice_ptr_id.unwrap(); // Each runtime argument has 4 instructions to call one of // the `fmt::rt::Argument::new_*` functions (and temporarily @@ -3124,13 +3122,15 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { _ => pieces_slice_ptr_id, }; decoded_format_args.const_pieces = - const_slice_as_elem_ids(&[pieces_slice_ptr_id, pieces_len_id]).and_then( + const_slice_as_elem_ids(pieces_slice_ptr_id, pieces_len).and_then( |piece_ids| { piece_ids .iter() .map(|&piece_id| { match self.builder.lookup_const_by_id(piece_id)? { - SpirvConst::Composite(piece) => const_str_as_utf8(piece), + SpirvConst::Composite(piece) => { + const_str_as_utf8(piece.try_into().ok()?) + } _ => None, } }) @@ -3160,12 +3160,14 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { .map(|s| Cow::Owned(s.replace('%', "%%"))) .interleave(ref_arg_ids_with_ty_and_spec.iter().map( |&(ref_id, ty, spec)| { - use rustc_target::abi::{Integer::*, Primitive::*}; + use rustc_target::abi::{ + Float::*, Integer::*, Primitive::*, + }; let layout = self.layout_of(ty); - let scalar = match layout.abi { - Abi::Scalar(scalar) => Some(scalar.primitive()), + let scalar = match layout.backend_repr { + BackendRepr::Scalar(scalar) => Some(scalar.primitive()), _ => None, }; let debug_printf_fmt = match (spec, scalar) { @@ -3174,7 +3176,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { (' ' | '?', Some(Int(I32, false))) => "%u", ('x', Some(Int(I32, false))) => "%x", (' ' | '?', Some(Int(I32, true))) => "%i", - (' ' | '?', Some(F32)) => "%f", + (' ' | '?', Some(Float(F32))) => "%f", _ => "", }; diff --git a/crates/rustc_codegen_spirv/src/builder/byte_addressable_buffer.rs b/crates/rustc_codegen_spirv/src/builder/byte_addressable_buffer.rs index 1248da7f80..76260a7765 100644 --- a/crates/rustc_codegen_spirv/src/builder/byte_addressable_buffer.rs +++ b/crates/rustc_codegen_spirv/src/builder/byte_addressable_buffer.rs @@ -1,3 +1,6 @@ +// HACK(eddyb) avoids rewriting all of the imports (see `lib.rs` and `build.rs`). +use crate::maybe_pqp_cg_ssa as rustc_codegen_ssa; + use super::Builder; use crate::builder_spirv::{SpirvValue, SpirvValueExt, SpirvValueKind}; use crate::spirv_type::SpirvType; @@ -111,7 +114,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { count, ), SpirvType::Array { element, count } => { - let count = match self.builder.lookup_const_u64(count) { + let count = match self.builder.lookup_const_scalar(count) { Some(count) => count as u32, None => return self.load_err(original_type, result_type), }; @@ -301,7 +304,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { count, ), SpirvType::Array { element, count } => { - let count = match self.builder.lookup_const_u64(count) { + let count = match self.builder.lookup_const_scalar(count) { Some(count) => count as u32, None => return self.store_err(original_type, value), }; diff --git a/crates/rustc_codegen_spirv/src/builder/intrinsics.rs b/crates/rustc_codegen_spirv/src/builder/intrinsics.rs index 121cc23db4..6896ad0e2e 100644 --- a/crates/rustc_codegen_spirv/src/builder/intrinsics.rs +++ b/crates/rustc_codegen_spirv/src/builder/intrinsics.rs @@ -1,3 +1,6 @@ +// HACK(eddyb) avoids rewriting all of the imports (see `lib.rs` and `build.rs`). +use crate::maybe_pqp_cg_ssa as rustc_codegen_ssa; + use super::Builder; use crate::abi::ConvSpirvType; use crate::builder_spirv::{SpirvValue, SpirvValueExt}; @@ -8,12 +11,12 @@ use rspirv::dr::Operand; use rspirv::spirv::GLOp; use rustc_codegen_ssa::mir::operand::OperandRef; use rustc_codegen_ssa::mir::place::PlaceRef; -use rustc_codegen_ssa::traits::{BuilderMethods, IntrinsicCallMethods}; +use rustc_codegen_ssa::traits::{BuilderMethods, IntrinsicCallBuilderMethods}; use rustc_middle::ty::layout::LayoutOf; -use rustc_middle::ty::{FnDef, Instance, ParamEnv, Ty, TyKind}; +use rustc_middle::ty::{FnDef, Instance, Ty, TyKind, TypingEnv}; use rustc_middle::{bug, ty}; -use rustc_span::sym; use rustc_span::Span; +use rustc_span::sym; use rustc_target::abi::call::{FnAbi, PassMode}; use std::assert_matches::assert_matches; @@ -63,7 +66,7 @@ impl Builder<'_, '_> { } } -impl<'a, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'tcx> { +impl<'a, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'tcx> { fn codegen_intrinsic_call( &mut self, instance: Instance<'tcx>, @@ -72,7 +75,7 @@ impl<'a, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'tcx> { llresult: Self::Value, _span: Span, ) -> Result<(), ty::Instance<'tcx>> { - let callee_ty = instance.ty(self.tcx, ParamEnv::reveal_all()); + let callee_ty = instance.ty(self.tcx, TypingEnv::fully_monomorphized()); let (def_id, fn_args) = match *callee_ty.kind() { FnDef(def_id, fn_args) => (def_id, fn_args), @@ -82,7 +85,7 @@ impl<'a, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'tcx> { let sig = callee_ty.fn_sig(self.tcx); let sig = self .tcx - .normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), sig); + .normalize_erasing_late_bound_regions(TypingEnv::fully_monomorphized(), sig); let arg_tys = sig.inputs(); let name = self.tcx.item_name(def_id); @@ -158,11 +161,10 @@ impl<'a, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'tcx> { } sym::sinf32 | sym::sinf64 => self.gl_op(GLOp::Sin, ret_ty, [args[0].immediate()]), sym::cosf32 | sym::cosf64 => self.gl_op(GLOp::Cos, ret_ty, [args[0].immediate()]), - sym::powf32 | sym::powf64 => self.gl_op( - GLOp::Pow, - ret_ty, - [args[0].immediate(), args[1].immediate()], - ), + sym::powf32 | sym::powf64 => self.gl_op(GLOp::Pow, ret_ty, [ + args[0].immediate(), + args[1].immediate(), + ]), sym::expf32 | sym::expf64 => self.gl_op(GLOp::Exp, ret_ty, [args[0].immediate()]), sym::exp2f32 | sym::exp2f64 => self.gl_op(GLOp::Exp2, ret_ty, [args[0].immediate()]), sym::logf32 | sym::logf64 => self.gl_op(GLOp::Log, ret_ty, [args[0].immediate()]), @@ -174,26 +176,20 @@ impl<'a, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'tcx> { let ln = self.gl_op(GLOp::Log, ret_ty, [args[0].immediate()]); self.mul(mul, ln) } - sym::fmaf32 | sym::fmaf64 => self.gl_op( - GLOp::Fma, - ret_ty, - [ - args[0].immediate(), - args[1].immediate(), - args[2].immediate(), - ], - ), + sym::fmaf32 | sym::fmaf64 => self.gl_op(GLOp::Fma, ret_ty, [ + args[0].immediate(), + args[1].immediate(), + args[2].immediate(), + ]), sym::fabsf32 | sym::fabsf64 => self.gl_op(GLOp::FAbs, ret_ty, [args[0].immediate()]), - sym::minnumf32 | sym::minnumf64 => self.gl_op( - GLOp::FMin, - ret_ty, - [args[0].immediate(), args[1].immediate()], - ), - sym::maxnumf32 | sym::maxnumf64 => self.gl_op( - GLOp::FMax, - ret_ty, - [args[0].immediate(), args[1].immediate()], - ), + sym::minnumf32 | sym::minnumf64 => self.gl_op(GLOp::FMin, ret_ty, [ + args[0].immediate(), + args[1].immediate(), + ]), + sym::maxnumf32 | sym::maxnumf64 => self.gl_op(GLOp::FMax, ret_ty, [ + args[0].immediate(), + args[1].immediate(), + ]), sym::copysignf32 | sym::copysignf64 => { let val = args[0].immediate(); let sign = args[1].immediate(); @@ -379,7 +375,7 @@ impl<'a, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'tcx> { cond } - fn type_test(&mut self, _pointer: Self::Value, _typeid: Self::Value) -> Self::Value { + fn type_test(&mut self, _pointer: Self::Value, _typeid: Self::Metadata) -> Self::Value { todo!() } @@ -387,7 +383,7 @@ impl<'a, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'tcx> { &mut self, _llvtable: Self::Value, _vtable_byte_offset: u64, - _typeid: Self::Value, + _typeid: Self::Metadata, ) -> Self::Value { todo!() } @@ -415,21 +411,18 @@ impl Builder<'_, '_> { // so the best thing we can do is use our own custom instruction. let kind_id = self.emit().string(kind); let message_debug_printf_fmt_str_id = self.emit().string(message_debug_printf_fmt_str); - self.custom_inst( - void_ty, - CustomInst::Abort { - kind: Operand::IdRef(kind_id), - message_debug_printf: [message_debug_printf_fmt_str_id] - .into_iter() - .chain( - message_debug_printf_args - .into_iter() - .map(|arg| arg.def(self)), - ) - .map(Operand::IdRef) - .collect(), - }, - ); + self.custom_inst(void_ty, CustomInst::Abort { + kind: Operand::IdRef(kind_id), + message_debug_printf: [message_debug_printf_fmt_str_id] + .into_iter() + .chain( + message_debug_printf_args + .into_iter() + .map(|arg| arg.def(self)), + ) + .map(Operand::IdRef) + .collect(), + }); self.unreachable(); // HACK(eddyb) we still need an active block in case the user of this diff --git a/crates/rustc_codegen_spirv/src/builder/libm_intrinsics.rs b/crates/rustc_codegen_spirv/src/builder/libm_intrinsics.rs index 3604ce5e5d..8c62126820 100644 --- a/crates/rustc_codegen_spirv/src/builder/libm_intrinsics.rs +++ b/crates/rustc_codegen_spirv/src/builder/libm_intrinsics.rs @@ -1,3 +1,6 @@ +// HACK(eddyb) avoids rewriting all of the imports (see `lib.rs` and `build.rs`). +use crate::maybe_pqp_cg_ssa as rustc_codegen_ssa; + use super::Builder; use crate::builder_spirv::{SpirvValue, SpirvValueExt}; use rspirv::spirv::{GLOp, Word}; @@ -227,11 +230,10 @@ impl Builder<'_, '_> { } LibmIntrinsic::Custom(LibmCustomIntrinsic::Cbrt) => { assert_eq!(args.len(), 1); - self.gl_op( - GLOp::Pow, - result_type, - [args[0], self.constant_float(args[0].ty, 1.0 / 3.0)], - ) + self.gl_op(GLOp::Pow, result_type, [ + args[0], + self.constant_float(args[0].ty, 1.0 / 3.0), + ]) } LibmIntrinsic::Custom(LibmCustomIntrinsic::Log10) => { assert_eq!(args.len(), 1); diff --git a/crates/rustc_codegen_spirv/src/builder/mod.rs b/crates/rustc_codegen_spirv/src/builder/mod.rs index 62c6d6dd32..972432267e 100644 --- a/crates/rustc_codegen_spirv/src/builder/mod.rs +++ b/crates/rustc_codegen_spirv/src/builder/mod.rs @@ -9,6 +9,9 @@ pub use ext_inst::ExtInst; use rustc_span::DUMMY_SP; pub use spirv_asm::InstructionTable; +// HACK(eddyb) avoids rewriting all of the imports (see `lib.rs` and `build.rs`). +use crate::maybe_pqp_cg_ssa as rustc_codegen_ssa; + use crate::abi::ConvSpirvType; use crate::builder_spirv::{BuilderCursor, SpirvValue, SpirvValueExt}; use crate::codegen_cx::CodegenCx; @@ -17,19 +20,20 @@ use rspirv::spirv::Word; use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue}; use rustc_codegen_ssa::mir::place::PlaceRef; use rustc_codegen_ssa::traits::{ - AbiBuilderMethods, ArgAbiMethods, BackendTypes, BuilderMethods, CoverageInfoBuilderMethods, - DebugInfoBuilderMethods, HasCodegen, StaticBuilderMethods, TypeMembershipMethods, + AbiBuilderMethods, ArgAbiBuilderMethods, BackendTypes, BuilderMethods, + CoverageInfoBuilderMethods, DebugInfoBuilderMethods, StaticBuilderMethods, + TypeMembershipCodegenMethods, }; use rustc_errors::{Diag, DiagMessage}; use rustc_middle::mir::coverage::CoverageKind; use rustc_middle::span_bug; use rustc_middle::ty::layout::{ - FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, HasTyCtxt, LayoutError, LayoutOfHelpers, - TyAndLayout, + FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasTyCtxt, HasTypingEnv, LayoutError, + LayoutOfHelpers, TyAndLayout, }; -use rustc_middle::ty::{Instance, ParamEnv, Ty, TyCtxt}; -use rustc_span::def_id::DefId; +use rustc_middle::ty::{Instance, Ty, TyCtxt, TypingEnv}; use rustc_span::Span; +use rustc_span::def_id::DefId; use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode}; use rustc_target::abi::{HasDataLayout, Size, TargetDataLayout}; use rustc_target::spec::{HasTargetSpec, Target}; @@ -39,7 +43,6 @@ pub struct Builder<'a, 'tcx> { cx: &'a CodegenCx<'tcx>, cursor: BuilderCursor, current_fn: ::Function, - basic_block: ::BasicBlock, current_span: Option, } @@ -113,8 +116,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { other.debug(shift.ty, self) )), }; - let int_size = self.constant_int(shift.ty, width as u64); - let mask = self.constant_int(shift.ty, (width - 1) as u64); + let int_size = self.constant_int(shift.ty, width.into()); + let mask = self.constant_int(shift.ty, (width - 1).into()); let zero = self.constant_int(shift.ty, 0); let bool = SpirvType::Bool.def(self.span(), self); // https://stackoverflow.com/a/10134877 @@ -168,6 +171,14 @@ impl<'a, 'tcx> DebugInfoBuilderMethods for Builder<'a, 'tcx> { todo!() } + fn clear_dbg_loc(&mut self) { + todo!() + } + + fn get_dbg_loc(&self) -> Option { + None + } + fn insert_reference_to_gdb_debug_scripts_section_global(&mut self) { todo!() } @@ -177,7 +188,7 @@ impl<'a, 'tcx> DebugInfoBuilderMethods for Builder<'a, 'tcx> { } } -impl<'a, 'tcx> ArgAbiMethods<'tcx> for Builder<'a, 'tcx> { +impl<'a, 'tcx> ArgAbiBuilderMethods<'tcx> for Builder<'a, 'tcx> { fn store_fn_arg( &mut self, arg_abi: &ArgAbi<'tcx, Ty<'tcx>>, @@ -245,7 +256,9 @@ impl<'a, 'tcx> StaticBuilderMethods for Builder<'a, 'tcx> { impl<'a, 'tcx> BackendTypes for Builder<'a, 'tcx> { type Value = as BackendTypes>::Value; + type Metadata = as BackendTypes>::Metadata; type Function = as BackendTypes>::Function; + type BasicBlock = as BackendTypes>::BasicBlock; type Type = as BackendTypes>::Type; type Funclet = as BackendTypes>::Funclet; @@ -255,13 +268,9 @@ impl<'a, 'tcx> BackendTypes for Builder<'a, 'tcx> { type DILocation = as BackendTypes>::DILocation; } -impl<'a, 'tcx> HasCodegen<'tcx> for Builder<'a, 'tcx> { - type CodegenCx = CodegenCx<'tcx>; -} - -impl<'a, 'tcx> HasParamEnv<'tcx> for Builder<'a, 'tcx> { - fn param_env(&self) -> ParamEnv<'tcx> { - self.cx.param_env() +impl<'a, 'tcx> HasTypingEnv<'tcx> for Builder<'a, 'tcx> { + fn typing_env(&self) -> TypingEnv<'tcx> { + self.cx.typing_env() } } @@ -306,4 +315,4 @@ impl<'tcx> FnAbiOfHelpers<'tcx> for Builder<'_, 'tcx> { } } -impl<'tcx> TypeMembershipMethods<'tcx> for CodegenCx<'tcx> {} +impl<'tcx> TypeMembershipCodegenMethods<'tcx> for CodegenCx<'tcx> {} diff --git a/crates/rustc_codegen_spirv/src/builder/spirv_asm.rs b/crates/rustc_codegen_spirv/src/builder/spirv_asm.rs index 9d7ad00057..91da22473d 100644 --- a/crates/rustc_codegen_spirv/src/builder/spirv_asm.rs +++ b/crates/rustc_codegen_spirv/src/builder/spirv_asm.rs @@ -1,9 +1,12 @@ +// HACK(eddyb) avoids rewriting all of the imports (see `lib.rs` and `build.rs`). +use crate::maybe_pqp_cg_ssa as rustc_codegen_ssa; + use super::Builder; use crate::builder_spirv::{BuilderCursor, SpirvValue}; use crate::codegen_cx::CodegenCx; use crate::spirv_type::SpirvType; use rspirv::dr; -use rspirv::grammar::{reflect, LogicalOperand, OperandKind, OperandQuantifier}; +use rspirv::grammar::{LogicalOperand, OperandKind, OperandQuantifier, reflect}; use rspirv::spirv::{ CooperativeMatrixOperands, FPFastMathMode, FragmentShadingRate, FunctionControl, GroupOperation, ImageOperands, KernelProfilingInfo, LoopControl, MemoryAccess, MemorySemantics, @@ -14,7 +17,7 @@ use rustc_codegen_ssa::mir::place::PlaceRef; use rustc_codegen_ssa::traits::{AsmBuilderMethods, InlineAsmOperandRef}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_middle::{bug, ty::Instance}; -use rustc_span::{Span, DUMMY_SP}; +use rustc_span::{DUMMY_SP, Span}; use rustc_target::asm::{InlineAsmRegClass, InlineAsmRegOrRegClass, SpirVInlineAsmRegClass}; pub struct InstructionTable { @@ -607,7 +610,7 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> { id_to_type_map: &FxHashMap, instruction: &dr::Instruction, ) -> Option { - use crate::spirv_type_constraints::{instruction_signatures, InstSig, TyListPat, TyPat}; + use crate::spirv_type_constraints::{InstSig, TyListPat, TyPat, instruction_signatures}; #[derive(Debug)] struct Unapplicable; @@ -854,12 +857,11 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> { place, } => { self.check_reg(span, reg); - match place { - Some(place) => Some(OutRegister::Place(*place)), - None => { - self.tcx.dcx().span_err(span, "missing place for register"); - None - } + if let Some(place) = place { + Some(OutRegister::Place(*place)) + } else { + self.tcx.dcx().span_err(span, "missing place for register"); + None } } InlineAsmOperandRef::InOut { @@ -869,12 +871,11 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> { out_place, } => { self.check_reg(span, reg); - match out_place { - Some(out_place) => Some(OutRegister::Place(*out_place)), - None => { - self.tcx.dcx().span_err(span, "missing place for register"); - None - } + if let Some(out_place) = out_place { + Some(OutRegister::Place(*out_place)) + } else { + self.tcx.dcx().span_err(span, "missing place for register"); + None } } InlineAsmOperandRef::Const { string: _ } => { @@ -950,8 +951,8 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> { place, } => { self.check_reg(span, reg); - match place { - Some(place) => match self.lookup_type(place.val.llval.ty) { + if let Some(place) = place { + match self.lookup_type(place.val.llval.ty) { SpirvType::Pointer { pointee } => Some(pointee), other => { self.tcx.dcx().span_err( @@ -963,13 +964,12 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> { ); None } - }, - None => { - self.tcx - .dcx() - .span_err(span, "missing place for out register typeof"); - None } + } else { + self.tcx + .dcx() + .span_err(span, "missing place for out register typeof"); + None } } InlineAsmOperandRef::InOut { diff --git a/crates/rustc_codegen_spirv/src/builder_spirv.rs b/crates/rustc_codegen_spirv/src/builder_spirv.rs index 339c16d18c..3c91b48872 100644 --- a/crates/rustc_codegen_spirv/src/builder_spirv.rs +++ b/crates/rustc_codegen_spirv/src/builder_spirv.rs @@ -1,15 +1,19 @@ +// HACK(eddyb) avoids rewriting all of the imports (see `lib.rs` and `build.rs`). +use crate::maybe_pqp_cg_ssa as rustc_codegen_ssa; + use crate::builder; use crate::codegen_cx::CodegenCx; use crate::spirv_type::SpirvType; use crate::symbols::Symbols; use crate::target::SpirvTarget; use crate::target_feature::TargetFeature; -use rspirv::dr::{Block, Builder, Module, Operand}; +use rspirv::dr::{Block, Builder, Instruction, Module, Operand}; use rspirv::spirv::{ AddressingModel, Capability, MemoryModel, Op, SourceLanguage, StorageClass, Word, }; use rspirv::{binary::Assemble, binary::Disassemble}; use rustc_arena::DroplessArena; +use rustc_codegen_ssa::traits::ConstCodegenMethods as _; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync::Lrc; use rustc_middle::bug; @@ -17,7 +21,8 @@ use rustc_middle::mir::interpret::ConstAllocation; use rustc_middle::ty::TyCtxt; use rustc_span::source_map::SourceMap; use rustc_span::symbol::Symbol; -use rustc_span::{FileName, FileNameDisplayPreference, SourceFile, Span, DUMMY_SP}; +use rustc_span::{DUMMY_SP, FileName, FileNameDisplayPreference, SourceFile, Span}; +use rustc_target::abi::Size; use std::assert_matches::assert_matches; use std::cell::{RefCell, RefMut}; use std::hash::{Hash, Hasher}; @@ -221,13 +226,8 @@ impl SpirvValueExt for Word { #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub enum SpirvConst<'a, 'tcx> { - U32(u32), - U64(u64), - /// f32 isn't hash, so store bits - F32(u32), - /// f64 isn't hash, so store bits - F64(u64), - Bool(bool), + /// Constants of boolean, integer or floating-point type (up to 128-bit). + Scalar(u128), Null, Undef, @@ -273,11 +273,7 @@ impl<'tcx> SpirvConst<'_, 'tcx> { match self { // FIXME(eddyb) these are all noop cases, could they be automated? - SpirvConst::U32(v) => SpirvConst::U32(v), - SpirvConst::U64(v) => SpirvConst::U64(v), - SpirvConst::F32(v) => SpirvConst::F32(v), - SpirvConst::F64(v) => SpirvConst::F64(v), - SpirvConst::Bool(v) => SpirvConst::Bool(v), + SpirvConst::Scalar(v) => SpirvConst::Scalar(v), SpirvConst::Null => SpirvConst::Null, SpirvConst::Undef => SpirvConst::Undef, SpirvConst::ZombieUndefForFnAddr => SpirvConst::ZombieUndefForFnAddr, @@ -570,8 +566,26 @@ impl<'tcx> BuilderSpirv<'tcx> { val: SpirvConst<'_, 'tcx>, cx: &CodegenCx<'tcx>, ) -> SpirvValue { + let scalar_ty = match val { + SpirvConst::Scalar(_) => Some(cx.lookup_type(ty)), + _ => None, + }; + + // HACK(eddyb) this is done so late (just before interning `val`) to + // minimize any potential misuse from direct `def_constant` calls. + let val = match (val, scalar_ty) { + (SpirvConst::Scalar(val), Some(SpirvType::Integer(bits, signed))) => { + let size = Size::from_bits(bits); + SpirvConst::Scalar(if signed { + size.sign_extend(val) as u128 + } else { + size.truncate(val) + }) + } + _ => val, + }; + let val_with_type = WithType { ty, val }; - let mut builder = self.builder(BuilderCursor::default()); if let Some(entry) = self.const_to_id.borrow().get(&val_with_type) { // FIXME(eddyb) deduplicate this `if`-`else` and its other copies. let kind = if entry.legal.is_ok() { @@ -582,16 +596,99 @@ impl<'tcx> BuilderSpirv<'tcx> { return SpirvValue { kind, ty }; } let val = val_with_type.val; + + // FIXME(eddyb) make this an extension method on `rspirv::dr::Builder`? + let const_op = |builder: &mut Builder, op, lhs, maybe_rhs: Option<_>| { + // HACK(eddyb) remove after `OpSpecConstantOp` support gets added to SPIR-T. + let spirt_has_const_op = false; + + if !spirt_has_const_op { + let zombie = builder.undef(ty, None); + cx.zombie_with_span( + zombie, + DUMMY_SP, + &format!("unsupported constant of type `{}`", cx.debug_type(ty)), + ); + return zombie; + } + + let id = builder.id(); + builder + .module_mut() + .types_global_values + .push(Instruction::new( + Op::SpecConstantOp, + Some(ty), + Some(id), + [ + Operand::LiteralSpecConstantOpInteger(op), + Operand::IdRef(lhs), + ] + .into_iter() + .chain(maybe_rhs.map(Operand::IdRef)) + .collect(), + )); + id + }; + + let mut builder = self.builder(BuilderCursor::default()); let id = match val { - SpirvConst::U32(v) | SpirvConst::F32(v) => builder.constant_bit32(ty, v), - SpirvConst::U64(v) | SpirvConst::F64(v) => builder.constant_bit64(ty, v), - SpirvConst::Bool(v) => { - if v { - builder.constant_true(ty) - } else { - builder.constant_false(ty) + SpirvConst::Scalar(v) => match scalar_ty.unwrap() { + SpirvType::Integer(..=32, _) | SpirvType::Float(..=32) => { + builder.constant_bit32(ty, v as u32) } - } + SpirvType::Integer(64, _) | SpirvType::Float(64) => { + builder.constant_bit64(ty, v as u64) + } + SpirvType::Integer(128, false) => { + // HACK(eddyb) avoid borrow conflicts. + drop(builder); + + let const_64_u32_id = cx.const_u32(64).def_cx(cx); + let [lo_id, hi_id] = + [v as u64, (v >> 64) as u64].map(|half| cx.const_u64(half).def_cx(cx)); + + builder = self.builder(BuilderCursor::default()); + let mut const_op = + |op, lhs, maybe_rhs| const_op(&mut builder, op, lhs, maybe_rhs); + let [lo_u128_id, hi_shifted_u128_id] = + [(lo_id, None), (hi_id, Some(const_64_u32_id))].map( + |(half_u64_id, shift)| { + let mut half_u128_id = const_op(Op::UConvert, half_u64_id, None); + if let Some(shift_amount_id) = shift { + half_u128_id = const_op( + Op::ShiftLeftLogical, + half_u128_id, + Some(shift_amount_id), + ); + } + half_u128_id + }, + ); + const_op(Op::BitwiseOr, lo_u128_id, Some(hi_shifted_u128_id)) + } + SpirvType::Integer(128, true) | SpirvType::Float(128) => { + // HACK(eddyb) avoid borrow conflicts. + drop(builder); + + let v_u128_id = cx.const_u128(v).def_cx(cx); + + builder = self.builder(BuilderCursor::default()); + const_op(&mut builder, Op::Bitcast, v_u128_id, None) + } + SpirvType::Bool => match v { + 0 => builder.constant_false(ty), + 1 => builder.constant_true(ty), + _ => cx + .tcx + .dcx() + .fatal(format!("invalid constant value for bool: {v}")), + }, + other => cx.tcx.dcx().fatal(format!( + "SpirvConst::Scalar does not support type {}", + other.debug(ty, cx) + )), + }, SpirvConst::Null => builder.constant_null(ty), SpirvConst::Undef @@ -606,11 +703,7 @@ impl<'tcx> BuilderSpirv<'tcx> { }; #[allow(clippy::match_same_arms)] let legal = match val { - SpirvConst::U32(_) - | SpirvConst::U64(_) - | SpirvConst::F32(_) - | SpirvConst::F64(_) - | SpirvConst::Bool(_) => Ok(()), + SpirvConst::Scalar(_) => Ok(()), SpirvConst::Null => { // FIXME(eddyb) check that the type supports `OpConstantNull`. @@ -712,10 +805,9 @@ impl<'tcx> BuilderSpirv<'tcx> { } } - pub fn lookup_const_u64(&self, def: SpirvValue) -> Option { + pub fn lookup_const_scalar(&self, def: SpirvValue) -> Option { match self.lookup_const(def)? { - SpirvConst::U32(v) => Some(v as u64), - SpirvConst::U64(v) => Some(v), + SpirvConst::Scalar(v) => Some(v), _ => None, } } diff --git a/crates/rustc_codegen_spirv/src/codegen_cx/constant.rs b/crates/rustc_codegen_spirv/src/codegen_cx/constant.rs index 04b8d72f91..162eb9dc8c 100644 --- a/crates/rustc_codegen_spirv/src/codegen_cx/constant.rs +++ b/crates/rustc_codegen_spirv/src/codegen_cx/constant.rs @@ -1,14 +1,17 @@ +// HACK(eddyb) avoids rewriting all of the imports (see `lib.rs` and `build.rs`). +use crate::maybe_pqp_cg_ssa as rustc_codegen_ssa; + use super::CodegenCx; use crate::abi::ConvSpirvType; use crate::builder_spirv::{SpirvConst, SpirvValue, SpirvValueExt, SpirvValueKind}; use crate::spirv_type::SpirvType; use rspirv::spirv::Word; -use rustc_codegen_ssa::traits::{ConstMethods, MiscMethods, StaticMethods}; +use rustc_codegen_ssa::traits::{ConstCodegenMethods, MiscCodegenMethods, StaticCodegenMethods}; use rustc_middle::bug; -use rustc_middle::mir::interpret::{alloc_range, ConstAllocation, GlobalAlloc, Scalar}; +use rustc_middle::mir::interpret::{ConstAllocation, GlobalAlloc, Scalar, alloc_range}; use rustc_middle::ty::layout::LayoutOf; -use rustc_span::{Span, DUMMY_SP}; -use rustc_target::abi::{self, AddressSpace, HasDataLayout, Integer, Primitive, Size}; +use rustc_span::{DUMMY_SP, Span}; +use rustc_target::abi::{self, AddressSpace, Float, HasDataLayout, Integer, Primitive, Size}; impl<'tcx> CodegenCx<'tcx> { pub fn def_constant(&self, ty: Word, val: SpirvConst<'_, 'tcx>) -> SpirvValue { @@ -16,90 +19,68 @@ impl<'tcx> CodegenCx<'tcx> { } pub fn constant_u8(&self, span: Span, val: u8) -> SpirvValue { - let ty = SpirvType::Integer(8, false).def(span, self); - self.def_constant(ty, SpirvConst::U32(val as u32)) + self.constant_int_from_native_unsigned(span, val) } pub fn constant_i8(&self, span: Span, val: i8) -> SpirvValue { - let ty = SpirvType::Integer(8, true).def(span, self); - self.def_constant(ty, SpirvConst::U32(val as u32)) + self.constant_int_from_native_signed(span, val) } pub fn constant_i16(&self, span: Span, val: i16) -> SpirvValue { - let ty = SpirvType::Integer(16, true).def(span, self); - self.def_constant(ty, SpirvConst::U32(val as u32)) + self.constant_int_from_native_signed(span, val) } pub fn constant_u16(&self, span: Span, val: u16) -> SpirvValue { - let ty = SpirvType::Integer(16, false).def(span, self); - self.def_constant(ty, SpirvConst::U32(val as u32)) + self.constant_int_from_native_unsigned(span, val) } pub fn constant_i32(&self, span: Span, val: i32) -> SpirvValue { - let ty = SpirvType::Integer(32, true).def(span, self); - self.def_constant(ty, SpirvConst::U32(val as u32)) + self.constant_int_from_native_signed(span, val) } pub fn constant_u32(&self, span: Span, val: u32) -> SpirvValue { - let ty = SpirvType::Integer(32, false).def(span, self); - self.def_constant(ty, SpirvConst::U32(val)) + self.constant_int_from_native_unsigned(span, val) } pub fn constant_u64(&self, span: Span, val: u64) -> SpirvValue { - let ty = SpirvType::Integer(64, false).def(span, self); - self.def_constant(ty, SpirvConst::U64(val)) + self.constant_int_from_native_unsigned(span, val) } - pub fn constant_int(&self, ty: Word, val: u64) -> SpirvValue { - match self.lookup_type(ty) { - SpirvType::Integer(bits @ 8..=32, signed) => { - let size = Size::from_bits(bits); - let val = val as u128; - self.def_constant( - ty, - SpirvConst::U32(if signed { - size.sign_extend(val) - } else { - size.truncate(val) - } as u32), - ) - } - SpirvType::Integer(64, _) => self.def_constant(ty, SpirvConst::U64(val)), - SpirvType::Bool => match val { - 0 | 1 => self.def_constant(ty, SpirvConst::Bool(val != 0)), - _ => self - .tcx - .dcx() - .fatal(format!("Invalid constant value for bool: {val}")), - }, - SpirvType::Integer(128, _) => { - let result = self.undef(ty); - self.zombie_no_span(result.def_cx(self), "u128 constant"); - result - } - other => self.tcx.dcx().fatal(format!( - "constant_int invalid on type {}", - other.debug(ty, self) - )), - } + fn constant_int_from_native_unsigned(&self, span: Span, val: impl Into) -> SpirvValue { + let size = Size::from_bytes(std::mem::size_of_val(&val)); + let ty = SpirvType::Integer(size.bits() as u32, false).def(span, self); + self.constant_int(ty, val.into()) + } + + fn constant_int_from_native_signed(&self, span: Span, val: impl Into) -> SpirvValue { + let size = Size::from_bytes(std::mem::size_of_val(&val)); + let ty = SpirvType::Integer(size.bits() as u32, false).def(span, self); + self.constant_int(ty, val.into() as u128) + } + + pub fn constant_int(&self, ty: Word, val: u128) -> SpirvValue { + self.def_constant(ty, SpirvConst::Scalar(val)) } pub fn constant_f32(&self, span: Span, val: f32) -> SpirvValue { let ty = SpirvType::Float(32).def(span, self); - self.def_constant(ty, SpirvConst::F32(val.to_bits())) + self.def_constant(ty, SpirvConst::Scalar(val.to_bits().into())) } pub fn constant_f64(&self, span: Span, val: f64) -> SpirvValue { let ty = SpirvType::Float(64).def(span, self); - self.def_constant(ty, SpirvConst::F64(val.to_bits())) + self.def_constant(ty, SpirvConst::Scalar(val.to_bits().into())) } pub fn constant_float(&self, ty: Word, val: f64) -> SpirvValue { match self.lookup_type(ty) { - SpirvType::Float(32) => self.def_constant(ty, SpirvConst::F32((val as f32).to_bits())), - SpirvType::Float(64) => self.def_constant(ty, SpirvConst::F64(val.to_bits())), + // FIXME(eddyb) use `rustc_apfloat` to support all float sizes. + SpirvType::Float(32) => { + self.def_constant(ty, SpirvConst::Scalar((val as f32).to_bits().into())) + } + SpirvType::Float(64) => self.def_constant(ty, SpirvConst::Scalar(val.to_bits().into())), other => self.tcx.dcx().fatal(format!( - "constant_float invalid on type {}", + "constant_float does not support type {}", other.debug(ty, self) )), } @@ -107,7 +88,7 @@ impl<'tcx> CodegenCx<'tcx> { pub fn constant_bool(&self, span: Span, val: bool) -> SpirvValue { let ty = SpirvType::Bool.def(span, self); - self.def_constant(ty, SpirvConst::Bool(val)) + self.def_constant(ty, SpirvConst::Scalar(val as u128)) } pub fn constant_composite(&self, ty: Word, fields: impl Iterator) -> SpirvValue { @@ -124,7 +105,7 @@ impl<'tcx> CodegenCx<'tcx> { } } -impl<'tcx> ConstMethods<'tcx> for CodegenCx<'tcx> { +impl<'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'tcx> { fn const_null(&self, t: Self::Type) -> Self::Value { self.constant_null(t) } @@ -136,27 +117,13 @@ impl<'tcx> ConstMethods<'tcx> for CodegenCx<'tcx> { self.const_undef(ty) } fn const_int(&self, t: Self::Type, i: i64) -> Self::Value { - self.constant_int(t, i as u64) + self.constant_int(t, i as u128) } fn const_uint(&self, t: Self::Type, i: u64) -> Self::Value { - self.constant_int(t, i) + self.constant_int(t, i.into()) } - // FIXME(eddyb) support `u128`. fn const_uint_big(&self, t: Self::Type, i: u128) -> Self::Value { - let i_as_u64 = i as u64; - let c = self.constant_int(t, i_as_u64); - match self.lookup_type(t) { - SpirvType::Integer(width, _) if width > 64 => { - if u128::from(i_as_u64) != i { - self.zombie_no_span( - c.def_cx(self), - "const_uint_big truncated a 128-bit constant to 64 bits", - ); - } - } - _ => {} - } - c + self.constant_int(t, i) } fn const_bool(&self, val: bool) -> Self::Value { self.constant_bool(DUMMY_SP, val) @@ -183,7 +150,7 @@ impl<'tcx> ConstMethods<'tcx> for CodegenCx<'tcx> { fn const_usize(&self, i: u64) -> Self::Value { let ptr_size = self.tcx.data_layout.pointer_size.bits() as u32; let t = SpirvType::Integer(ptr_size, false).def(DUMMY_SP, self); - self.constant_int(t, i) + self.constant_int(t, i.into()) } fn const_u8(&self, i: u8) -> Self::Value { self.constant_u8(DUMMY_SP, i) @@ -198,17 +165,11 @@ impl<'tcx> ConstMethods<'tcx> for CodegenCx<'tcx> { .layout_of(self.tcx.types.str_) .spirv_type(DUMMY_SP, self); ( - self.def_constant( - self.type_ptr_to(str_ty), - SpirvConst::PtrTo { - pointee: self - .constant_composite( - str_ty, - s.bytes().map(|b| self.const_u8(b).def_cx(self)), - ) - .def_cx(self), - }, - ), + self.def_constant(self.type_ptr_to(str_ty), SpirvConst::PtrTo { + pointee: self + .constant_composite(str_ty, s.bytes().map(|b| self.const_u8(b).def_cx(self))) + .def_cx(self), + }), self.const_usize(len as u64), ) } @@ -228,18 +189,22 @@ impl<'tcx> ConstMethods<'tcx> for CodegenCx<'tcx> { .def(DUMMY_SP, self); self.constant_composite(struct_ty, elts.iter().map(|f| f.def_cx(self))) } + fn const_vector(&self, elts: &[Self::Value]) -> Self::Value { + let vector_ty = SpirvType::Vector { + element: elts[0].ty, + count: elts.len() as u32, + } + .def(DUMMY_SP, self); + self.constant_composite(vector_ty, elts.iter().map(|elt| elt.def_cx(self))) + } fn const_to_opt_uint(&self, v: Self::Value) -> Option { - self.builder.lookup_const_u64(v) - } - fn const_to_opt_u128(&self, v: Self::Value, sign_ext: bool) -> Option { - self.builder.lookup_const_u64(v).map(|v| { - if sign_ext { - v as i64 as i128 as u128 - } else { - v as u128 - } - }) + self.builder.lookup_const_scalar(v)?.try_into().ok() + } + // FIXME(eddyb) what's the purpose of the `sign_ext` argument, and can it + // differ from the signedness of `v`? + fn const_to_opt_u128(&self, v: Self::Value, _sign_ext: bool) -> Option { + self.builder.lookup_const_scalar(v) } fn scalar_to_backend( @@ -251,58 +216,21 @@ impl<'tcx> ConstMethods<'tcx> for CodegenCx<'tcx> { match scalar { Scalar::Int(int) => { assert_eq!(int.size(), layout.primitive().size(self)); - let data = int.assert_uint(int.size()); - - match layout.primitive() { - Primitive::Int(int_size, int_signedness) => match self.lookup_type(ty) { - SpirvType::Integer(width, spirv_signedness) => { - assert_eq!(width as u64, int_size.size().bits()); - assert_eq!(spirv_signedness, int_signedness); - self.constant_int(ty, data as u64) - } - SpirvType::Bool => match data { - 0 => self.constant_bool(DUMMY_SP, false), - 1 => self.constant_bool(DUMMY_SP, true), - _ => self - .tcx - .dcx() - .fatal(format!("Invalid constant value for bool: {data}")), - }, - other => self.tcx.dcx().fatal(format!( - "scalar_to_backend Primitive::Int not supported on type {}", - other.debug(ty, self) - )), - }, - Primitive::F16 => self - .tcx - .dcx() - .fatal("scalar_to_backend Primitive::F16 not supported"), - Primitive::F32 => { - let res = self.constant_f32(DUMMY_SP, f32::from_bits(data as u32)); - assert_eq!(res.ty, ty); - res - } - Primitive::F64 => { - let res = self.constant_f64(DUMMY_SP, f64::from_bits(data as u64)); - assert_eq!(res.ty, ty); - res - } - Primitive::F128 => self - .tcx - .dcx() - .fatal("scalar_to_backend Primitive::F128 not supported"), - Primitive::Pointer(_) => { - if data == 0 { - self.constant_null(ty) - } else { - let result = self.undef(ty); - self.zombie_no_span( - result.def_cx(self), - "pointer has non-null integer address", - ); - result - } + let data = int.to_uint(int.size()); + + if let Primitive::Pointer(_) = layout.primitive() { + if data == 0 { + self.constant_null(ty) + } else { + let result = self.undef(ty); + self.zombie_no_span( + result.def_cx(self), + "pointer has non-null integer address", + ); + result } + } else { + self.def_constant(ty, SpirvConst::Scalar(data)) } } Scalar::Ptr(ptr, _) => { @@ -321,14 +249,14 @@ impl<'tcx> ConstMethods<'tcx> for CodegenCx<'tcx> { let value = self.static_addr_of(init, alloc.inner().align, None); (value, AddressSpace::DATA) } - GlobalAlloc::Function(fn_instance) => ( - self.get_fn_addr(fn_instance.polymorphize(self.tcx)), + GlobalAlloc::Function { instance } => ( + self.get_fn_addr(instance.polymorphize(self.tcx)), self.data_layout().instruction_address_space, ), - GlobalAlloc::VTable(vty, trait_ref) => { + GlobalAlloc::VTable(vty, dyn_ty) => { let alloc = self .tcx - .global_alloc(self.tcx.vtable_allocation((vty, trait_ref))) + .global_alloc(self.tcx.vtable_allocation((vty, dyn_ty.principal()))) .unwrap_memory(); let pointee = match self.lookup_type(ty) { SpirvType::Pointer { pointee } => pointee, @@ -378,7 +306,21 @@ impl<'tcx> ConstMethods<'tcx> for CodegenCx<'tcx> { self.def_constant(void_type, SpirvConst::ConstDataFromAlloc(alloc)) } - fn const_bitcast(&self, val: Self::Value, ty: Self::Type) -> Self::Value { + fn const_ptr_byte_offset(&self, val: Self::Value, offset: Size) -> Self::Value { + if offset == Size::ZERO { + val + } else { + // FIXME(eddyb) implement via `OpSpecConstantOp`. + // FIXME(eddyb) this zombies the original value without creating a new one. + let result = val; + self.zombie_no_span(result.def_cx(self), "const_ptr_byte_offset"); + result + } + } +} + +impl<'tcx> CodegenCx<'tcx> { + pub fn const_bitcast(&self, val: SpirvValue, ty: Word) -> SpirvValue { // HACK(eddyb) special-case `const_data_from_alloc` + `static_addr_of` // as the old `from_const_alloc` (now `OperandRef::from_const_alloc`). if let SpirvValueKind::IllegalConst(_) = val.kind { @@ -405,20 +347,7 @@ impl<'tcx> ConstMethods<'tcx> for CodegenCx<'tcx> { result } } - fn const_ptr_byte_offset(&self, val: Self::Value, offset: Size) -> Self::Value { - if offset == Size::ZERO { - val - } else { - // FIXME(eddyb) implement via `OpSpecConstantOp`. - // FIXME(eddyb) this zombies the original value without creating a new one. - let result = val; - self.zombie_no_span(result.def_cx(self), "const_ptr_byte_offset"); - result - } - } -} -impl<'tcx> CodegenCx<'tcx> { // This function comes from `ty::layout`'s `layout_of_uncached`, // where it's named `scalar_unit`. pub fn primitive_to_scalar(&self, value: Primitive) -> abi::Scalar { @@ -472,8 +401,8 @@ impl<'tcx> CodegenCx<'tcx> { let size = ty_concrete.sizeof(self).unwrap(); let primitive = match ty_concrete { SpirvType::Bool => Primitive::Int(Integer::fit_unsigned(0), false), - SpirvType::Integer(int_size, int_signedness) => { - let integer = match int_size { + SpirvType::Integer(int_size, int_signedness) => Primitive::Int( + match int_size { 8 => Integer::I8, 16 => Integer::I16, 32 => Integer::I32, @@ -484,18 +413,20 @@ impl<'tcx> CodegenCx<'tcx> { .dcx() .fatal(format!("invalid size for integer: {other}")); } - }; - Primitive::Int(integer, int_signedness) - } - SpirvType::Float(float_size) => match float_size { - 32 => Primitive::F32, - 64 => Primitive::F64, + }, + int_signedness, + ), + SpirvType::Float(float_size) => Primitive::Float(match float_size { + 16 => Float::F16, + 32 => Float::F32, + 64 => Float::F64, + 128 => Float::F128, other => { self.tcx .dcx() .fatal(format!("invalid size for float: {other}")); } - }, + }), SpirvType::Pointer { .. } => Primitive::Pointer(AddressSpace::DATA), unsupported_spirv_type => bug!( "invalid spirv type internal to create_alloc_const2: {:?}", @@ -550,7 +481,7 @@ impl<'tcx> CodegenCx<'tcx> { self.constant_composite(ty, values.into_iter()) } SpirvType::Array { element, count } => { - let count = self.builder.lookup_const_u64(count).unwrap() as usize; + let count = self.builder.lookup_const_scalar(count).unwrap() as usize; let values = (0..count).map(|_| { self.read_from_const_alloc(alloc, offset, element) .def_cx(self) diff --git a/crates/rustc_codegen_spirv/src/codegen_cx/declare.rs b/crates/rustc_codegen_spirv/src/codegen_cx/declare.rs index 858897b8c9..eae83d8e93 100644 --- a/crates/rustc_codegen_spirv/src/codegen_cx/declare.rs +++ b/crates/rustc_codegen_spirv/src/codegen_cx/declare.rs @@ -1,3 +1,6 @@ +// HACK(eddyb) avoids rewriting all of the imports (see `lib.rs` and `build.rs`). +use crate::maybe_pqp_cg_ssa as rustc_codegen_ssa; + use super::CodegenCx; use crate::abi::ConvSpirvType; use crate::attr::AggregatedSpirvAttributes; @@ -7,15 +10,15 @@ use crate::spirv_type::SpirvType; use itertools::Itertools; use rspirv::spirv::{FunctionControl, LinkageType, StorageClass, Word}; use rustc_attr::InlineAttr; -use rustc_codegen_ssa::traits::{PreDefineMethods, StaticMethods}; +use rustc_codegen_ssa::traits::{PreDefineCodegenMethods, StaticCodegenMethods}; use rustc_hir::def::DefKind; use rustc_middle::bug; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; use rustc_middle::mir::mono::{Linkage, MonoItem, Visibility}; use rustc_middle::ty::layout::{FnAbiOf, LayoutOf}; -use rustc_middle::ty::{self, Instance, ParamEnv, TypeVisitableExt}; -use rustc_span::def_id::DefId; +use rustc_middle::ty::{self, Instance, TypeVisitableExt, TypingEnv}; use rustc_span::Span; +use rustc_span::def_id::DefId; use rustc_target::abi::Align; fn attrs_to_spirv(attrs: &CodegenFnAttrs) -> FunctionControl { @@ -55,9 +58,9 @@ impl<'tcx> CodegenCx<'tcx> { } // The call graph of how this is reachable is a little tangled, so: - // MiscMethods::get_fn -> get_fn_ext -> declare_fn_ext - // MiscMethods::get_fn_addr -> get_fn_ext -> declare_fn_ext - // PreDefineMethods::predefine_fn -> declare_fn_ext + // MiscCodegenMethods::get_fn -> get_fn_ext -> declare_fn_ext + // MiscCodegenMethods::get_fn_addr -> get_fn_ext -> declare_fn_ext + // PreDefineCodegenMethods::predefine_fn -> declare_fn_ext fn declare_fn_ext(&self, instance: Instance<'tcx>, linkage: Option) -> SpirvValue { let def_id = instance.def_id(); @@ -128,16 +131,13 @@ impl<'tcx> CodegenCx<'tcx> { let declared = fn_id.with_type(function_type); - let attrs = AggregatedSpirvAttributes::parse( - self, - match self.tcx.def_kind(def_id) { - // This was made to ICE cross-crate at some point, but then got - // reverted in https://github.com/rust-lang/rust/pull/111381. - // FIXME(eddyb) remove this workaround once we rustup past that. - DefKind::Closure => &[], - _ => self.tcx.get_attrs_unchecked(def_id), - }, - ); + let attrs = AggregatedSpirvAttributes::parse(self, match self.tcx.def_kind(def_id) { + // This was made to ICE cross-crate at some point, but then got + // reverted in https://github.com/rust-lang/rust/pull/111381. + // FIXME(eddyb) remove this workaround once we rustup past that. + DefKind::Closure => &[], + _ => self.tcx.get_attrs_unchecked(def_id), + }); if let Some(entry) = attrs.entry.map(|attr| attr.value) { let entry_name = entry .name @@ -190,13 +190,26 @@ impl<'tcx> CodegenCx<'tcx> { // HACK(eddyb) there is no good way to identify these definitions // (e.g. no `#[lang = "..."]` attribute), but this works well enough. - if [ - "::new_v1", - "::new_const", - ] - .contains(&&demangled_symbol_name[..]) + if demangled_symbol_name == "core::panicking::panic_nounwind_fmt" { + self.panic_entry_points.borrow_mut().insert(def_id); + } + if let Some(pieces_len) = demangled_symbol_name + .strip_prefix("::new_const::<") + .and_then(|s| s.strip_suffix(">")) + { + self.fmt_args_new_fn_ids + .borrow_mut() + .insert(fn_id, (pieces_len.parse().unwrap(), 0)); + } + if let Some(generics) = demangled_symbol_name + .strip_prefix("::new_v1::<") + .and_then(|s| s.strip_suffix(">")) { - self.fmt_args_new_fn_ids.borrow_mut().insert(fn_id); + let (pieces_len, rt_args_len) = generics.split_once(", ").unwrap(); + self.fmt_args_new_fn_ids.borrow_mut().insert( + fn_id, + (pieces_len.parse().unwrap(), rt_args_len.parse().unwrap()), + ); } // HACK(eddyb) there is no good way to identify these definitions @@ -244,7 +257,7 @@ impl<'tcx> CodegenCx<'tcx> { "get_static() should always hit the cache for statics defined in the same CGU, but did not for `{def_id:?}`" ); - let ty = instance.ty(self.tcx, ParamEnv::reveal_all()); + let ty = instance.ty(self.tcx, TypingEnv::fully_monomorphized()); let sym = self.tcx.symbol_name(instance).name; let span = self.tcx.def_span(def_id); let g = self.declare_global(span, self.layout_of(ty).spirv_type(span, self)); @@ -267,7 +280,7 @@ impl<'tcx> CodegenCx<'tcx> { } } -impl<'tcx> PreDefineMethods<'tcx> for CodegenCx<'tcx> { +impl<'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'tcx> { fn predefine_static( &self, def_id: DefId, @@ -276,7 +289,7 @@ impl<'tcx> PreDefineMethods<'tcx> for CodegenCx<'tcx> { symbol_name: &str, ) { let instance = Instance::mono(self.tcx, def_id); - let ty = instance.ty(self.tcx, ParamEnv::reveal_all()); + let ty = instance.ty(self.tcx, TypingEnv::fully_monomorphized()); let span = self.tcx.def_span(def_id); let spvty = self.layout_of(ty).spirv_type(span, self); let linkage = match linkage { @@ -324,14 +337,11 @@ impl<'tcx> PreDefineMethods<'tcx> for CodegenCx<'tcx> { } } -impl<'tcx> StaticMethods for CodegenCx<'tcx> { +impl<'tcx> StaticCodegenMethods for CodegenCx<'tcx> { fn static_addr_of(&self, cv: Self::Value, _align: Align, _kind: Option<&str>) -> Self::Value { - self.def_constant( - self.type_ptr_to(cv.ty), - SpirvConst::PtrTo { - pointee: cv.def_cx(self), - }, - ) + self.def_constant(self.type_ptr_to(cv.ty), SpirvConst::PtrTo { + pointee: cv.def_cx(self), + }) } fn codegen_static(&self, def_id: DefId) { diff --git a/crates/rustc_codegen_spirv/src/codegen_cx/entry.rs b/crates/rustc_codegen_spirv/src/codegen_cx/entry.rs index 865bcc7a77..7dcd22d291 100644 --- a/crates/rustc_codegen_spirv/src/codegen_cx/entry.rs +++ b/crates/rustc_codegen_spirv/src/codegen_cx/entry.rs @@ -1,3 +1,6 @@ +// HACK(eddyb) avoids rewriting all of the imports (see `lib.rs` and `build.rs`). +use crate::maybe_pqp_cg_ssa as rustc_codegen_ssa; + use super::CodegenCx; use crate::abi::ConvSpirvType; use crate::attr::{AggregatedSpirvAttributes, Entry, Spanned, SpecConstant}; @@ -8,7 +11,7 @@ use rspirv::dr::Operand; use rspirv::spirv::{ Capability, Decoration, Dim, ExecutionModel, FunctionControl, StorageClass, Word, }; -use rustc_codegen_ssa::traits::{BaseTypeMethods, BuilderMethods}; +use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, BuilderMethods}; use rustc_data_structures::fx::FxHashMap; use rustc_errors::MultiSpan; use rustc_hir as hir; @@ -79,11 +82,7 @@ impl<'tcx> CodegenCx<'tcx> { .span_err(span, format!("cannot declare {name} as an entry point")); return; }; - let body = self - .tcx - .hir() - .body(self.tcx.hir().body_owned_by(fn_local_def_id)); - body.params + self.tcx.hir().body_owned_by(fn_local_def_id).params }; for (arg_abi, hir_param) in fn_abi.args.iter().zip(hir_params) { match arg_abi.mode { @@ -241,7 +240,7 @@ impl<'tcx> CodegenCx<'tcx> { if is_ref && !value_layout .ty - .is_freeze(self.tcx, ty::ParamEnv::reveal_all()) => + .is_freeze(self.tcx, ty::TypingEnv::fully_monomorphized()) => { hir::Mutability::Mut } @@ -355,13 +354,10 @@ impl<'tcx> CodegenCx<'tcx> { if !ref_is_read_only && storage_class_requires_read_only { let mut err = self.tcx.dcx().struct_span_err( hir_param.ty_span, - format!( - "entry-point requires {}...", - match explicit_mutbl { - hir::Mutability::Not => "interior mutability", - hir::Mutability::Mut => "a mutable reference", - } - ), + format!("entry-point requires {}...", match explicit_mutbl { + hir::Mutability::Not => "interior mutability", + hir::Mutability::Mut => "a mutable reference", + }), ); { let note_message = @@ -449,11 +445,9 @@ impl<'tcx> CodegenCx<'tcx> { let mut emit = self.emit_global(); let spec_const_id = emit.spec_constant_bit32(value_spirv_type, default.unwrap_or(0)); - emit.decorate( - spec_const_id, - Decoration::SpecId, - [Operand::LiteralBit32(id)], - ); + emit.decorate(spec_const_id, Decoration::SpecId, [Operand::LiteralBit32( + id, + )]); ( Err("`#[spirv(spec_constant)]` is not an entry-point interface variable"), Ok(spec_const_id), @@ -745,13 +739,12 @@ impl<'tcx> CodegenCx<'tcx> { .. } => true, SpirvType::RuntimeArray { element: elt, .. } - | SpirvType::Array { element: elt, .. } => matches!( - self.lookup_type(elt), - SpirvType::Image { + | SpirvType::Array { element: elt, .. } => { + matches!(self.lookup_type(elt), SpirvType::Image { dim: Dim::DimSubpassData, .. - } - ), + }) + } _ => false, }; if let Some(attachment_index) = attrs.input_attachment_index { @@ -832,8 +825,10 @@ impl<'tcx> CodegenCx<'tcx> { } } } - // Emitted earlier. - Err(SpecConstant { .. }) => {} + Err(not_var) => { + // Emitted earlier. + let SpecConstant { .. } = not_var; + } } } diff --git a/crates/rustc_codegen_spirv/src/codegen_cx/mod.rs b/crates/rustc_codegen_spirv/src/codegen_cx/mod.rs index c3175155df..f806a5e3a3 100644 --- a/crates/rustc_codegen_spirv/src/codegen_cx/mod.rs +++ b/crates/rustc_codegen_spirv/src/codegen_cx/mod.rs @@ -10,26 +10,30 @@ use crate::spirv_type::{SpirvType, SpirvTypePrinter, TypeCache}; use crate::symbols::Symbols; use crate::target::SpirvTarget; +// HACK(eddyb) avoids rewriting all of the imports (see `lib.rs` and `build.rs`). +use crate::maybe_pqp_cg_ssa as rustc_codegen_ssa; + use itertools::Itertools as _; use rspirv::dr::{Module, Operand}; use rspirv::spirv::{Decoration, LinkageType, Op, Word}; use rustc_ast::ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_codegen_ssa::mir::debuginfo::{FunctionDebugContext, VariableKind}; use rustc_codegen_ssa::traits::{ - AsmMethods, BackendTypes, DebugInfoMethods, GlobalAsmOperandRef, MiscMethods, + AsmCodegenMethods, BackendTypes, DebugInfoCodegenMethods, GlobalAsmOperandRef, + MiscCodegenMethods, }; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir::def_id::DefId; use rustc_middle::mir; use rustc_middle::mir::mono::CodegenUnit; -use rustc_middle::ty::layout::{HasParamEnv, HasTyCtxt}; -use rustc_middle::ty::{Instance, ParamEnv, PolyExistentialTraitRef, Ty, TyCtxt}; +use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv}; +use rustc_middle::ty::{Instance, PolyExistentialTraitRef, Ty, TyCtxt, TypingEnv}; use rustc_session::Session; use rustc_span::symbol::Symbol; -use rustc_span::{SourceFile, Span, DUMMY_SP}; +use rustc_span::{DUMMY_SP, SourceFile, Span}; use rustc_target::abi::call::{FnAbi, PassMode}; use rustc_target::abi::{AddressSpace, HasDataLayout, TargetDataLayout}; -use rustc_target::spec::{HasTargetSpec, Target, TargetTriple}; +use rustc_target::spec::{HasTargetSpec, Target, TargetTuple}; use std::cell::RefCell; use std::collections::BTreeSet; use std::iter::once; @@ -68,7 +72,7 @@ pub struct CodegenCx<'tcx> { pub panic_entry_points: RefCell>, /// `core::fmt::Arguments::new_{v1,const}` instances (for Rust 2021 panics). - pub fmt_args_new_fn_ids: RefCell>, + pub fmt_args_new_fn_ids: RefCell>, /// `core::fmt::rt::Argument::new_*::` instances (for panics' `format_args!`), /// with their `T` type (i.e. of the value being formatted), and formatting @@ -90,15 +94,15 @@ pub struct CodegenCx<'tcx> { impl<'tcx> CodegenCx<'tcx> { pub fn new(tcx: TyCtxt<'tcx>, codegen_unit: &'tcx CodegenUnit<'tcx>) -> Self { // Validate the target spec, as the backend doesn't control `--target`. - let target_triple = tcx.sess.opts.target_triple.triple(); - let target: SpirvTarget = target_triple.parse().unwrap_or_else(|_| { - let qualifier = if !target_triple.starts_with("spirv-") { + let target_tuple = tcx.sess.opts.target_triple.tuple(); + let target: SpirvTarget = target_tuple.parse().unwrap_or_else(|_| { + let qualifier = if !target_tuple.starts_with("spirv-") { "non-SPIR-V " } else { "" }; tcx.dcx().fatal(format!( - "{qualifier}target `{target_triple}` not supported by `rustc_codegen_spirv`", + "{qualifier}target `{target_tuple}` not supported by `rustc_codegen_spirv`", )) }); let target_spec_mismatched_jsons = { @@ -115,12 +119,12 @@ impl<'tcx> CodegenCx<'tcx> { // ideally `spirv-builder` can be forced to pass an exact match. // // FIXME(eddyb) consider the `RUST_TARGET_PATH` env var alternative. - TargetTriple::TargetTriple(_) => { + TargetTuple::TargetTuple(_) => { // FIXME(eddyb) this case should be impossible as upstream // `rustc` doesn't support `spirv-*` targets! (expected != found).then(|| [expected, found].map(|spec| spec.to_json())) } - TargetTriple::TargetJson { contents, .. } => { + TargetTuple::TargetJson { contents, .. } => { let expected = expected.to_json(); let found = serde_json::from_str(contents).unwrap(); (expected != found).then_some([expected, found]) @@ -135,12 +139,12 @@ impl<'tcx> CodegenCx<'tcx> { .filter(|k| expected.get(k) != found.get(k)); tcx.dcx() - .struct_fatal(format!("mismatched `{target_triple}` target spec")) + .struct_fatal(format!("mismatched `{target_tuple}` target spec")) .with_note(format!( "expected (built into `rustc_codegen_spirv`):\n{expected:#}" )) .with_note(match &tcx.sess.opts.target_triple { - TargetTriple::TargetJson { + TargetTuple::TargetJson { path_for_rustdoc, contents, .. @@ -595,12 +599,11 @@ impl CodegenArgs { let matches_opt_path = |name| matches.opt_str(name).map(PathBuf::from); let matches_opt_dump_dir_path = |name| { - matches_opt_path(name).map(|path| { + matches_opt_path(name).inspect(|path| { if path.is_file() { - std::fs::remove_file(&path).unwrap(); + std::fs::remove_file(path).unwrap(); } - std::fs::create_dir_all(&path).unwrap(); - path + std::fs::create_dir_all(path).unwrap(); }) }; // FIXME(eddyb) should these be handled as `-C linker-args="..."` instead? @@ -804,6 +807,7 @@ impl FromStr for ModuleOutputType { impl<'tcx> BackendTypes for CodegenCx<'tcx> { type Value = SpirvValue; + type Metadata = (); type Function = SpirvValue; type BasicBlock = Word; @@ -835,13 +839,13 @@ impl<'tcx> HasTargetSpec for CodegenCx<'tcx> { } } -impl<'tcx> HasParamEnv<'tcx> for CodegenCx<'tcx> { - fn param_env(&self) -> ParamEnv<'tcx> { - ParamEnv::reveal_all() +impl<'tcx> HasTypingEnv<'tcx> for CodegenCx<'tcx> { + fn typing_env(&self) -> TypingEnv<'tcx> { + TypingEnv::fully_monomorphized() } } -impl<'tcx> MiscMethods<'tcx> for CodegenCx<'tcx> { +impl<'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'tcx> { #[allow(clippy::type_complexity)] fn vtables( &self, @@ -849,10 +853,6 @@ impl<'tcx> MiscMethods<'tcx> for CodegenCx<'tcx> { &self.vtables } - fn check_overflow(&self) -> bool { - self.tcx.sess.overflow_checks() - } - fn get_fn(&self, instance: Instance<'tcx>) -> Self::Function { self.get_fn_ext(instance) } @@ -906,7 +906,7 @@ impl<'tcx> MiscMethods<'tcx> for CodegenCx<'tcx> { } } -impl<'tcx> DebugInfoMethods<'tcx> for CodegenCx<'tcx> { +impl<'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'tcx> { fn create_vtable_debuginfo( &self, _ty: Ty<'tcx>, @@ -964,7 +964,7 @@ impl<'tcx> DebugInfoMethods<'tcx> for CodegenCx<'tcx> { } } -impl<'tcx> AsmMethods<'tcx> for CodegenCx<'tcx> { +impl<'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'tcx> { fn codegen_global_asm( &self, _template: &[InlineAsmTemplatePiece], diff --git a/crates/rustc_codegen_spirv/src/codegen_cx/type_.rs b/crates/rustc_codegen_spirv/src/codegen_cx/type_.rs index 599c5ff9b7..f0005a9e42 100644 --- a/crates/rustc_codegen_spirv/src/codegen_cx/type_.rs +++ b/crates/rustc_codegen_spirv/src/codegen_cx/type_.rs @@ -1,18 +1,21 @@ +// HACK(eddyb) avoids rewriting all of the imports (see `lib.rs` and `build.rs`). +use crate::maybe_pqp_cg_ssa as rustc_codegen_ssa; + use super::CodegenCx; use crate::abi::ConvSpirvType; use crate::spirv_type::SpirvType; use rspirv::spirv::Word; use rustc_codegen_ssa::common::TypeKind; -use rustc_codegen_ssa::traits::{BaseTypeMethods, LayoutTypeMethods}; +use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, LayoutTypeCodegenMethods}; +use rustc_middle::ty::Ty; use rustc_middle::ty::layout::{ FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOfHelpers, TyAndLayout, }; -use rustc_middle::ty::Ty; use rustc_middle::{bug, span_bug}; use rustc_span::source_map::Spanned; -use rustc_span::{Span, DUMMY_SP}; +use rustc_span::{DUMMY_SP, Span}; use rustc_target::abi::call::{CastTarget, FnAbi, Reg}; -use rustc_target::abi::{Abi, AddressSpace}; +use rustc_target::abi::{AddressSpace, BackendRepr}; impl<'tcx> LayoutOfHelpers<'tcx> for CodegenCx<'tcx> { type LayoutOfResult = TyAndLayout<'tcx>; @@ -61,7 +64,7 @@ impl<'tcx> FnAbiOfHelpers<'tcx> for CodegenCx<'tcx> { } } -impl<'tcx> LayoutTypeMethods<'tcx> for CodegenCx<'tcx> { +impl<'tcx> LayoutTypeCodegenMethods<'tcx> for CodegenCx<'tcx> { fn backend_type(&self, layout: TyAndLayout<'tcx>) -> Self::Type { layout.spirv_type(DUMMY_SP, self) } @@ -93,17 +96,20 @@ impl<'tcx> LayoutTypeMethods<'tcx> for CodegenCx<'tcx> { } fn is_backend_immediate(&self, layout: TyAndLayout<'tcx>) -> bool { - match layout.abi { - Abi::Scalar(_) | Abi::Vector { .. } => true, - Abi::ScalarPair(..) => false, - Abi::Uninhabited | Abi::Aggregate { .. } => layout.is_zst(), + match layout.backend_repr { + BackendRepr::Scalar(_) | BackendRepr::Vector { .. } => true, + BackendRepr::ScalarPair(..) => false, + BackendRepr::Uninhabited | BackendRepr::Memory { .. } => layout.is_zst(), } } fn is_backend_scalar_pair(&self, layout: TyAndLayout<'tcx>) -> bool { - match layout.abi { - Abi::ScalarPair(..) => true, - Abi::Uninhabited | Abi::Scalar(_) | Abi::Vector { .. } | Abi::Aggregate { .. } => false, + match layout.backend_repr { + BackendRepr::ScalarPair(..) => true, + BackendRepr::Uninhabited + | BackendRepr::Scalar(_) + | BackendRepr::Vector { .. } + | BackendRepr::Memory { .. } => false, } } @@ -124,10 +130,7 @@ impl<'tcx> CodegenCx<'tcx> { } } -impl<'tcx> BaseTypeMethods<'tcx> for CodegenCx<'tcx> { - fn type_i1(&self) -> Self::Type { - SpirvType::Bool.def(DUMMY_SP, self) - } +impl<'tcx> BaseTypeCodegenMethods<'tcx> for CodegenCx<'tcx> { fn type_i8(&self) -> Self::Type { SpirvType::Integer(8, false).def(DUMMY_SP, self) } @@ -176,19 +179,6 @@ impl<'tcx> BaseTypeMethods<'tcx> for CodegenCx<'tcx> { } .def(DUMMY_SP, self) } - fn type_struct(&self, els: &[Self::Type], _packed: bool) -> Self::Type { - // FIXME(eddyb) use `AccumulateVec`s just like `rustc` itself does. - let (field_offsets, size, align) = crate::abi::auto_struct_layout(self, els); - SpirvType::Adt { - def_id: None, - align, - size, - field_types: els, - field_offsets: &field_offsets, - field_names: None, - } - .def(DUMMY_SP, self) - } fn type_kind(&self, ty: Self::Type) -> TypeKind { match self.lookup_type(ty) { SpirvType::Void => TypeKind::Void, diff --git a/crates/rustc_codegen_spirv/src/custom_decorations.rs b/crates/rustc_codegen_spirv/src/custom_decorations.rs index 2193c1bd45..e2cf68158c 100644 --- a/crates/rustc_codegen_spirv/src/custom_decorations.rs +++ b/crates/rustc_codegen_spirv/src/custom_decorations.rs @@ -4,17 +4,15 @@ use crate::builder_spirv::BuilderSpirv; use crate::custom_insts::{self, CustomInst}; use either::Either; -use itertools::Itertools; use rspirv::dr::{Instruction, Module, Operand}; use rspirv::spirv::{Decoration, Op, Word}; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::sync::Lrc; -use rustc_span::{source_map::SourceMap, Span}; use rustc_span::{FileName, SourceFile}; +use rustc_span::{Span, source_map::SourceMap}; use smallvec::SmallVec; use std::borrow::Cow; use std::marker::PhantomData; -use std::ops::Range; use std::path::PathBuf; use std::{fmt, iter, slice, str}; @@ -41,16 +39,11 @@ pub trait CustomDecoration<'a>: Sized { let mut encoded = Self::ENCODING_PREFIX.to_string(); self.encode(&mut encoded).unwrap(); - Instruction::new( - Op::DecorateString, - None, - None, - vec![ - Operand::IdRef(id), - Operand::Decoration(Decoration::UserTypeGOOGLE), - Operand::LiteralString(encoded), - ], - ) + Instruction::new(Op::DecorateString, None, None, vec![ + Operand::IdRef(id), + Operand::Decoration(Decoration::UserTypeGOOGLE), + Operand::LiteralString(encoded), + ]) } fn try_decode_from_inst(inst: &Instruction) -> Option<(Word, LazilyDecoded<'_, Self>)> { @@ -61,13 +54,10 @@ pub trait CustomDecoration<'a>: Sized { let prefixed_encoded = inst.operands[2].unwrap_literal_string(); let encoded = prefixed_encoded.strip_prefix(Self::ENCODING_PREFIX)?; - Some(( - id, - LazilyDecoded { - encoded, - _marker: PhantomData, - }, - )) + Some((id, LazilyDecoded { + encoded, + _marker: PhantomData, + })) } else { None } @@ -495,61 +485,18 @@ impl<'a> SpanRegenerator<'a> { // called with `line`/`col` values that are near eachother - thankfully, // this code should only be hit on the error reporting path anyway. let line_col_to_bpos = |line: u32, col: u32| { - let line_bpos_range = file.line_bounds(line.checked_sub(1)? as usize); - - // Find the special cases (`MultiByteChar`s/`NonNarrowChar`s) in the line. - let multibyte_chars = { - let find = |bpos| { - file.multibyte_chars - .binary_search_by_key(&file.relative_position(bpos), |mbc| mbc.pos) - .unwrap_or_else(|x| x) - }; - let Range { start, end } = line_bpos_range; - file.multibyte_chars[find(start)..find(end)].iter() - }; - let non_narrow_chars = { - let find = |bpos| { - file.non_narrow_chars - .binary_search_by_key(&file.relative_position(bpos), |nnc| nnc.pos()) - .unwrap_or_else(|x| x) - }; - let Range { start, end } = line_bpos_range; - file.non_narrow_chars[find(start)..find(end)].iter() - }; - let mut special_chars = multibyte_chars - .merge_join_by(non_narrow_chars, |mbc, nnc| mbc.pos.cmp(&nnc.pos())) - .peekable(); - - // Increment the `BytePos` until we reach the right `col_display`, using - // `MultiByteChar`s/`NonNarrowChar`s to track non-trivial contributions - // (this may look inefficient, but lines tend to be short, and `rustc` - // itself is even worse than this, when it comes to `BytePos` lookups). + let line_idx_in_file = line.checked_sub(1)? as usize; + let line_bpos_range = file.line_bounds(line_idx_in_file); + let line_contents = file.get_line(line_idx_in_file)?; + + // Increment the `BytePos` until we reach the right `col_display`. let (mut cur_bpos, mut cur_col_display) = (line_bpos_range.start, 0); + let mut line_chars = line_contents.chars(); while cur_bpos < line_bpos_range.end && cur_col_display < col { - let next_special_bpos = special_chars - .peek() - .map(|special| { - special - .as_ref() - .map_any(|mbc| mbc.pos, |nnc| nnc.pos()) - .reduce(|x, _| x) - }) - .map(|rel_bpos| file.absolute_position(rel_bpos)); - - // Batch trivial chars (i.e. chars 1:1 wrt `BytePos` vs `col_display`). - let following_trivial_chars = - next_special_bpos.unwrap_or(line_bpos_range.end).0 - cur_bpos.0; - if following_trivial_chars > 0 { - let wanted_trivial_chars = following_trivial_chars.min(col - cur_col_display); - cur_bpos.0 += wanted_trivial_chars; - cur_col_display += wanted_trivial_chars; - continue; - } - - // Add a special char's `BytePos` and `col_display` contributions. - let mbc_nnc = special_chars.next().unwrap(); - cur_bpos.0 += mbc_nnc.as_ref().left().map_or(1, |mbc| mbc.bytes as u32); - cur_col_display += mbc_nnc.as_ref().right().map_or(1, |nnc| nnc.width() as u32); + // Add each char's `BytePos` and `col_display` contributions. + let ch = line_chars.next()?; + cur_bpos.0 += ch.len_utf8() as u32; + cur_col_display += rustc_span::char_width(ch) as u32; } Some(cur_bpos) }; diff --git a/crates/rustc_codegen_spirv/src/custom_insts.rs b/crates/rustc_codegen_spirv/src/custom_insts.rs index d5721c2485..54a1331c9f 100644 --- a/crates/rustc_codegen_spirv/src/custom_insts.rs +++ b/crates/rustc_codegen_spirv/src/custom_insts.rs @@ -43,13 +43,12 @@ lazy_static! { /// achieved by hashing the `SCHEMA` constant from `def_custom_insts!` below pub static ref CUSTOM_EXT_INST_SET: String = { let schema_hash = { - use rustc_data_structures::stable_hasher::StableHasher; + use rustc_data_structures::stable_hasher::{Hash128, StableHasher}; use std::hash::Hash; let mut hasher = StableHasher::new(); SCHEMA.hash(&mut hasher); - let (lo, hi) = hasher.finalize(); - (lo as u128) | ((hi as u128) << 64) + hasher.finish::().as_u128() }; let version = join_cargo_pkg_version_major_minor_patch!("_"); format!("{CUSTOM_EXT_INST_SET_PREFIX}{version}.{schema_hash:x}") @@ -58,38 +57,31 @@ lazy_static! { pub fn register_to_spirt_context(cx: &spirt::Context) { use spirt::spv::spec::{ExtInstSetDesc, ExtInstSetInstructionDesc}; - cx.register_custom_ext_inst_set( - &CUSTOM_EXT_INST_SET, - ExtInstSetDesc { - // HACK(eddyb) this is the most compact form I've found, that isn't - // outright lossy by omitting "Rust vs Rust-GPU" or the version. - short_alias: Some( - concat!("Rust-GPU ", join_cargo_pkg_version_major_minor_patch!(".")).into(), - ), - instructions: SCHEMA - .iter() - .map(|&(i, name, operand_names)| { - ( - i, - ExtInstSetInstructionDesc { - name: name.into(), - operand_names: operand_names - .iter() - .map(|name| { - name.strip_prefix("..") - .unwrap_or(name) - .replace('_', " ") - .into() - }) - .collect(), - is_debuginfo: name.contains("Debug") - || name.contains("InlinedCallFrame"), - }, - ) + cx.register_custom_ext_inst_set(&CUSTOM_EXT_INST_SET, ExtInstSetDesc { + // HACK(eddyb) this is the most compact form I've found, that isn't + // outright lossy by omitting "Rust vs Rust-GPU" or the version. + short_alias: Some( + concat!("Rust-GPU ", join_cargo_pkg_version_major_minor_patch!(".")).into(), + ), + instructions: SCHEMA + .iter() + .map(|&(i, name, operand_names)| { + (i, ExtInstSetInstructionDesc { + name: name.into(), + operand_names: operand_names + .iter() + .map(|name| { + name.strip_prefix("..") + .unwrap_or(name) + .replace('_', " ") + .into() + }) + .collect(), + is_debuginfo: name.contains("Debug") || name.contains("InlinedCallFrame"), }) - .collect(), - }, - ); + }) + .collect(), + }); } macro_rules! def_custom_insts { diff --git a/crates/rustc_codegen_spirv/src/lib.rs b/crates/rustc_codegen_spirv/src/lib.rs index 3d430d8db4..f5ab65665d 100644 --- a/crates/rustc_codegen_spirv/src/lib.rs +++ b/crates/rustc_codegen_spirv/src/lib.rs @@ -1,3 +1,19 @@ +// HACK(eddyb) start of `rustc_codegen_ssa` crate-level attributes (see `build.rs`). +#![allow(internal_features)] +#![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::untranslatable_diagnostic)] +#![feature(assert_matches)] +#![feature(box_patterns)] +#![feature(debug_closure_helpers)] +#![feature(file_buffered)] +#![feature(if_let_guard)] +#![feature(let_chains)] +#![feature(negative_impls)] +#![feature(rustdoc_internals)] +#![feature(trait_alias)] +#![feature(try_blocks)] +// HACK(eddyb) end of `rustc_codegen_ssa` crate-level attributes (see `build.rs`). + //! Welcome to the API documentation for the `rust-gpu` project, this API is //! unstable and mainly intended for developing on the project itself. This is //! the API documentation for `rustc_codegen_spirv` which is not that useful on @@ -16,16 +32,17 @@ //! [`spirv-tools`]: https://rust-gpu.github.io/rust-gpu/api/spirv_tools //! [`spirv-tools-sys`]: https://rust-gpu.github.io/rust-gpu/api/spirv_tools_sys #![feature(rustc_private)] -#![feature(assert_matches)] #![feature(result_flattening)] -#![feature(lint_reasons)] -#![feature(lazy_cell)] // crate-specific exceptions: #![allow( unsafe_code, // rustc_codegen_ssa requires unsafe functions in traits to be impl'd clippy::match_on_vec_items, // rustc_codegen_spirv has less strict panic requirements than other embark projects clippy::enum_glob_use, // pretty useful pattern with some codegen'd enums (e.g. rspirv::spirv::Op) clippy::todo, // still lots to implement :) + + // FIXME(eddyb) new warnings from 1.83 rustup, apply their suggested changes. + elided_named_lifetimes, + clippy::needless_lifetimes, )] // Unfortunately, this will not fail fast when compiling, but rather will wait for @@ -39,21 +56,57 @@ compile_error!( "Either \"use-compiled-tools\" (enabled by default) or \"use-installed-tools\" may be enabled." ); +// HACK(eddyb) `build.rs` copies `rustc_codegen_ssa` (from the `rustc-dev` component) +// and patches it to produce a "pqp" ("pre-`qptr`-patched") version that maintains +// compatibility with "legacy" Rust-GPU pointer handling (mainly typed `alloca`s). +// +// FIXME(eddyb) get rid of this as soon as it's not needed anymore. +#[cfg(not(rustc_codegen_spirv_disable_pqp_cg_ssa))] +include!(concat!(env!("OUT_DIR"), "/pqp_cg_ssa.rs")); + +// HACK(eddyb) guide `rustc` to finding the right deps in the sysroot, which +// (sadly) has to be outside `include!` to have any effect whatsoever. +// FIXME(eddyb) this only really handles `bitflags`, not `object`. +#[cfg(not(rustc_codegen_spirv_disable_pqp_cg_ssa))] +mod _rustc_codegen_ssa_transitive_deps_hack { + extern crate rustc_codegen_ssa as _; +} + +// NOTE(eddyb) `mod maybe_pqp_cg_ssa` is defined by the above `include`, when +// in the (default for now) `pqp_cg_ssa` mode (see `build.rs`). +#[cfg(rustc_codegen_spirv_disable_pqp_cg_ssa)] +use rustc_codegen_ssa as maybe_pqp_cg_ssa; + +// FIXME(eddyb) remove all `#[cfg(rustc_codegen_spirv_disable_pqp_cg_ssa)]` +// as soon as they're not needed anymore (i.e. using `rustc_codegen_ssa` again). extern crate rustc_apfloat; +#[cfg(rustc_codegen_spirv_disable_pqp_cg_ssa)] extern crate rustc_arena; +#[cfg(rustc_codegen_spirv_disable_pqp_cg_ssa)] extern crate rustc_ast; +#[cfg(rustc_codegen_spirv_disable_pqp_cg_ssa)] extern crate rustc_attr; +#[cfg(rustc_codegen_spirv_disable_pqp_cg_ssa)] extern crate rustc_codegen_ssa; +#[cfg(rustc_codegen_spirv_disable_pqp_cg_ssa)] extern crate rustc_data_structures; extern crate rustc_driver; +#[cfg(rustc_codegen_spirv_disable_pqp_cg_ssa)] extern crate rustc_errors; +#[cfg(rustc_codegen_spirv_disable_pqp_cg_ssa)] extern crate rustc_hir; +#[cfg(rustc_codegen_spirv_disable_pqp_cg_ssa)] extern crate rustc_index; extern crate rustc_interface; +#[cfg(rustc_codegen_spirv_disable_pqp_cg_ssa)] extern crate rustc_metadata; +#[cfg(rustc_codegen_spirv_disable_pqp_cg_ssa)] extern crate rustc_middle; +#[cfg(rustc_codegen_spirv_disable_pqp_cg_ssa)] extern crate rustc_session; +#[cfg(rustc_codegen_spirv_disable_pqp_cg_ssa)] extern crate rustc_span; +#[cfg(rustc_codegen_spirv_disable_pqp_cg_ssa)] extern crate rustc_target; macro_rules! assert_ty_eq { @@ -84,32 +137,32 @@ mod target_feature; use builder::Builder; use codegen_cx::CodegenCx; -use rspirv::binary::Assemble; -use rustc_ast::expand::allocator::AllocatorKind; -use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule}; -use rustc_codegen_ssa::back::write::{ +use maybe_pqp_cg_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule}; +use maybe_pqp_cg_ssa::back::write::{ CodegenContext, FatLtoInput, ModuleConfig, OngoingCodegen, TargetMachineFactoryConfig, }; -use rustc_codegen_ssa::base::maybe_create_entry_wrapper; -use rustc_codegen_ssa::mono_item::MonoItemExt; -use rustc_codegen_ssa::traits::{ +use maybe_pqp_cg_ssa::base::maybe_create_entry_wrapper; +use maybe_pqp_cg_ssa::mono_item::MonoItemExt; +use maybe_pqp_cg_ssa::traits::{ CodegenBackend, ExtraBackendMethods, ModuleBufferMethods, ThinBufferMethods, WriteBackendMethods, }; -use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleCodegen, ModuleKind}; +use maybe_pqp_cg_ssa::{CodegenResults, CompiledModule, ModuleCodegen, ModuleKind}; +use rspirv::binary::Assemble; +use rustc_ast::expand::allocator::AllocatorKind; use rustc_data_structures::fx::FxIndexMap; -use rustc_errors::{DiagCtxt, ErrorGuaranteed, FatalError}; +use rustc_errors::{DiagCtxtHandle, ErrorGuaranteed, FatalError}; use rustc_metadata::EncodedMetadata; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; use rustc_middle::mir::mono::{MonoItem, MonoItemData}; use rustc_middle::mir::pretty::write_mir_pretty; use rustc_middle::ty::print::with_no_trimmed_paths; -use rustc_middle::ty::{self, Instance, InstanceDef, TyCtxt}; -use rustc_session::config::{self, OutputFilenames, OutputType}; +use rustc_middle::ty::{self, Instance, InstanceKind, TyCtxt}; use rustc_session::Session; -use rustc_span::symbol::{sym, Symbol}; +use rustc_session::config::{self, OutputFilenames, OutputType}; +use rustc_span::symbol::{Symbol, sym}; use std::any::Any; -use std::fs::{create_dir_all, File}; +use std::fs::{File, create_dir_all}; use std::io::Cursor; use std::io::Write; use std::path::Path; @@ -120,7 +173,7 @@ fn dump_mir(tcx: TyCtxt<'_>, mono_items: &[(MonoItem<'_>, MonoItemData)], path: let mut file = File::create(path).unwrap(); for &(mono_item, _) in mono_items { if let MonoItem::Fn(instance) = mono_item { - if matches!(instance.def, InstanceDef::Item(_)) { + if matches!(instance.def, InstanceKind::Item(_)) { let mut mir = Cursor::new(Vec::new()); if write_mir_pretty(tcx, Some(instance.def_id()), &mut mir).is_ok() { writeln!(file, "{}", String::from_utf8(mir.into_inner()).unwrap()).unwrap(); @@ -136,18 +189,18 @@ fn is_blocklisted_fn<'tcx>( instance: Instance<'tcx>, ) -> bool { // TODO: These sometimes have a constant value of an enum variant with a hole - if let InstanceDef::Item(def_id) = instance.def { + if let InstanceKind::Item(def_id) = instance.def { if let Some(debug_trait_def_id) = tcx.get_diagnostic_item(sym::Debug) { // Helper for detecting `<_ as core::fmt::Debug>::fmt` (in impls). let is_debug_fmt_method = |def_id| match tcx.opt_associated_item(def_id) { Some(assoc) if assoc.ident(tcx).name == sym::fmt => match assoc.container { - ty::ImplContainer => { + ty::AssocItemContainer::Impl => { let impl_def_id = assoc.container_id(tcx); tcx.impl_trait_ref(impl_def_id) .map(|tr| tr.skip_binder().def_id) == Some(debug_trait_def_id) } - ty::TraitContainer => false, + ty::AssocItemContainer::Trait => false, }, _ => false, }; @@ -185,6 +238,9 @@ impl ThinBufferMethods for SpirvThinBuffer { fn data(&self) -> &[u8] { spirv_tools::binary::from_binary(&self.0) } + fn thin_link_data(&self) -> &[u8] { + &[] + } } #[derive(Clone)] @@ -222,7 +278,7 @@ impl CodegenBackend for SpirvCodegenBackend { metadata: EncodedMetadata, need_metadata_module: bool, ) -> Box { - Box::new(rustc_codegen_ssa::base::codegen_crate( + Box::new(maybe_pqp_cg_ssa::base::codegen_crate( Self, tcx, tcx.sess @@ -277,7 +333,7 @@ impl WriteBackendMethods for SpirvCodegenBackend { fn run_link( _cgcx: &CodegenContext, - _diag_handler: &DiagCtxt, + _diag_handler: DiagCtxtHandle<'_>, _modules: Vec>, ) -> Result, FatalError> { todo!() @@ -309,7 +365,7 @@ impl WriteBackendMethods for SpirvCodegenBackend { unsafe fn optimize( _: &CodegenContext, - _: &DiagCtxt, + _: DiagCtxtHandle<'_>, _: &ModuleCodegen, _: &ModuleConfig, ) -> Result<(), FatalError> { @@ -340,7 +396,7 @@ impl WriteBackendMethods for SpirvCodegenBackend { unsafe fn codegen( cgcx: &CodegenContext, - _diag_handler: &DiagCtxt, + _diag_handler: DiagCtxtHandle<'_>, module: ModuleCodegen, _config: &ModuleConfig, ) -> Result { @@ -364,7 +420,10 @@ impl WriteBackendMethods for SpirvCodegenBackend { }) } - fn prepare_thin(module: ModuleCodegen) -> (String, Self::ThinBuffer) { + fn prepare_thin( + module: ModuleCodegen, + _want_summary: bool, + ) -> (String, Self::ThinBuffer) { (module.name, SpirvThinBuffer(module.module_llvm)) } @@ -482,16 +541,13 @@ impl Drop for DumpModuleOnPanic<'_, '_, '_> { #[no_mangle] pub fn __rustc_codegen_backend() -> Box { // Tweak rustc's default ICE panic hook, to direct people to `rust-gpu`. - rustc_driver::install_ice_hook( - "https://github.com/rust-gpu/rust-gpu/issues/new", - |handler| { - handler.note(concat!( - "`rust-gpu` version `", - env!("CARGO_PKG_VERSION"), - "`" - )); - }, - ); + rustc_driver::install_ice_hook("https://github.com/rust-gpu/rust-gpu/issues/new", |dcx| { + dcx.handle().note(concat!( + "`rust-gpu` version `", + env!("CARGO_PKG_VERSION"), + "`" + )); + }); Box::new(SpirvCodegenBackend) } diff --git a/crates/rustc_codegen_spirv/src/link.rs b/crates/rustc_codegen_spirv/src/link.rs index cedd92ff17..4c702b7c78 100644 --- a/crates/rustc_codegen_spirv/src/link.rs +++ b/crates/rustc_codegen_spirv/src/link.rs @@ -1,5 +1,8 @@ +// HACK(eddyb) avoids rewriting all of the imports (see `lib.rs` and `build.rs`). +use crate::maybe_pqp_cg_ssa as rustc_codegen_ssa; + use crate::codegen_cx::{CodegenArgs, SpirvMetadata}; -use crate::{linker, SpirvCodegenBackend, SpirvModuleBuffer, SpirvThinBuffer}; +use crate::{SpirvCodegenBackend, SpirvModuleBuffer, SpirvThinBuffer, linker}; use ar::{Archive, GnuBuilder, Header}; use rspirv::binary::Assemble; use rspirv::dr::Module; @@ -14,12 +17,12 @@ use rustc_metadata::fs::METADATA_FILENAME; use rustc_middle::bug; use rustc_middle::dep_graph::WorkProduct; use rustc_middle::middle::dependency_format::Linkage; +use rustc_session::Session; use rustc_session::config::{ CrateType, DebugInfo, Lto, OptLevel, OutFileName, OutputFilenames, OutputType, }; use rustc_session::output::{check_file_is_writeable, invalid_output_for_target, out_filename}; use rustc_session::utils::NativeLibKind; -use rustc_session::Session; use rustc_span::Symbol; use std::collections::BTreeMap; use std::ffi::{CString, OsStr}; @@ -601,12 +604,11 @@ fn do_link( disambiguated_crate_name_for_dumps, ); - match link_result { - Ok(v) => v, - Err(rustc_errors::ErrorGuaranteed { .. }) => { - sess.dcx().abort_if_errors(); - bug!("Linker errored, but no error reported"); - } + if let Ok(v) = link_result { + v + } else { + sess.dcx().abort_if_errors(); + bug!("Linker errored, but no error reported"); } } diff --git a/crates/rustc_codegen_spirv/src/linker/dce.rs b/crates/rustc_codegen_spirv/src/linker/dce.rs index 3cc865a741..c21429a535 100644 --- a/crates/rustc_codegen_spirv/src/linker/dce.rs +++ b/crates/rustc_codegen_spirv/src/linker/dce.rs @@ -103,7 +103,7 @@ fn is_rooted(inst: &Instruction, rooted: &FxIndexSet) -> bool { // referenced by roots inst.operands .iter() - .any(|op| op.id_ref_any().map_or(false, |w| rooted.contains(&w))) + .any(|op| op.id_ref_any().is_some_and(|w| rooted.contains(&w))) } } diff --git a/crates/rustc_codegen_spirv/src/linker/duplicates.rs b/crates/rustc_codegen_spirv/src/linker/duplicates.rs index 0f8a36d8a0..6b1b45d8cd 100644 --- a/crates/rustc_codegen_spirv/src/linker/duplicates.rs +++ b/crates/rustc_codegen_spirv/src/linker/duplicates.rs @@ -401,12 +401,11 @@ pub fn remove_duplicate_debuginfo(module: &mut Module) { // as it needs to reset callee-side `DbgLocInst`, // but we can replace it in-place and hope later // it get nop'd out by some real `DbgLocInst`. - insts[inst_idx].operands.splice( - 1.., - [Operand::LiteralExtInstInteger( + insts[inst_idx] + .operands + .splice(1.., [Operand::LiteralExtInstInteger( CustomOp::ClearDebugSrcLoc as u32, - )], - ); + )]); dbg = DbgState { loc: Some(DbgLocInst { inst_idx, diff --git a/crates/rustc_codegen_spirv/src/linker/inline.rs b/crates/rustc_codegen_spirv/src/linker/inline.rs index 295e3e79b2..60c735aefc 100644 --- a/crates/rustc_codegen_spirv/src/linker/inline.rs +++ b/crates/rustc_codegen_spirv/src/linker/inline.rs @@ -142,14 +142,9 @@ pub fn inline(sess: &Session, module: &mut Module) -> super::Result<()> { custom_ext_inst_set_import: custom_ext_inst_set_import.unwrap_or_else(|| { let id = next_id(header); - let inst = Instruction::new( - Op::ExtInstImport, - None, - Some(id), - vec![Operand::LiteralString( - custom_insts::CUSTOM_EXT_INST_SET.to_string(), - )], - ); + let inst = Instruction::new(Op::ExtInstImport, None, Some(id), vec![ + Operand::LiteralString(custom_insts::CUSTOM_EXT_INST_SET.to_string()), + ]); module.ext_inst_imports.push(inst); id }), @@ -184,10 +179,10 @@ pub fn inline(sess: &Session, module: &mut Module) -> super::Result<()> { // Drop OpName etc. for inlined functions module.debug_names.retain(|inst| { - !inst.operands.iter().any(|op| { - op.id_ref_any() - .map_or(false, |id| dropped_ids.contains(&id)) - }) + !inst + .operands + .iter() + .any(|op| op.id_ref_any().is_some_and(|id| dropped_ids.contains(&id))) }); Ok(()) @@ -658,15 +653,12 @@ impl Inliner<'_, '_> { if let Some(call_result_type) = call_result_type { // Generate the storage space for the return value: Do this *after* the split above, // because if block_idx=0, inserting a variable here shifts call_index. - insert_opvariables( - &mut caller.blocks[0], - [Instruction::new( - Op::Variable, - Some(self.ptr_ty(call_result_type)), - Some(return_variable.unwrap()), - vec![Operand::StorageClass(StorageClass::Function)], - )], - ); + insert_opvariables(&mut caller.blocks[0], [Instruction::new( + Op::Variable, + Some(self.ptr_ty(call_result_type)), + Some(return_variable.unwrap()), + vec![Operand::StorageClass(StorageClass::Function)], + )]); } // Insert non-entry inlined callee blocks just after the pre-call block. @@ -856,12 +848,10 @@ impl Inliner<'_, '_> { .entry(callee_name) .or_insert_with(|| { let id = next_id(self.header); - self.debug_string_source.push(Instruction::new( - Op::String, - None, - Some(id), - vec![Operand::LiteralString(callee_name.to_string())], - )); + self.debug_string_source + .push(Instruction::new(Op::String, None, Some(id), vec![ + Operand::LiteralString(callee_name.to_string()), + ])); id }); let mut mk_debuginfo_prefix_and_suffix = |include_callee_frame| { @@ -944,15 +934,12 @@ impl Inliner<'_, '_> { if let Op::Return | Op::ReturnValue = terminator.class.opcode { if Op::ReturnValue == terminator.class.opcode { let return_value = terminator.operands[0].id_ref_any().unwrap(); - block.instructions.push(Instruction::new( - Op::Store, - None, - None, - vec![ + block + .instructions + .push(Instruction::new(Op::Store, None, None, vec![ Operand::IdRef(return_variable.unwrap()), Operand::IdRef(return_value), - ], - )); + ])); } else { assert!(return_variable.is_none()); } diff --git a/crates/rustc_codegen_spirv/src/linker/mem2reg.rs b/crates/rustc_codegen_spirv/src/linker/mem2reg.rs index ab567203f1..a79d00ae0b 100644 --- a/crates/rustc_codegen_spirv/src/linker/mem2reg.rs +++ b/crates/rustc_codegen_spirv/src/linker/mem2reg.rs @@ -239,13 +239,10 @@ fn collect_access_chains( } let mut variables = FxHashMap::default(); - variables.insert( - base_var, - VarInfo { - ty: base_var_ty, - indices: vec![], - }, - ); + variables.insert(base_var, VarInfo { + ty: base_var_ty, + indices: vec![], + }); // Loop in case a previous block references a later AccessChain loop { let mut changed = false; @@ -334,21 +331,17 @@ fn split_copy_memory( } }; let temp_id = id(header); - block.instructions[inst_index] = Instruction::new( - Op::Load, - Some(ty), - Some(temp_id), - vec![Operand::IdRef(source)], - ); + block.instructions[inst_index] = + Instruction::new(Op::Load, Some(ty), Some(temp_id), vec![Operand::IdRef( + source, + )]); inst_index += 1; block.instructions.insert( inst_index, - Instruction::new( - Op::Store, - None, - None, - vec![Operand::IdRef(target), Operand::IdRef(temp_id)], - ), + Instruction::new(Op::Store, None, None, vec![ + Operand::IdRef(target), + Operand::IdRef(temp_id), + ]), ); } inst_index += 1; @@ -455,12 +448,10 @@ impl Renamer<'_> { let new_id = id(self.header); self.blocks[block].instructions.insert( 0, - Instruction::new( - Op::Phi, - Some(self.base_var_type), - Some(new_id), - vec![Operand::IdRef(top_def), Operand::IdRef(from_block_label)], - ), + Instruction::new(Op::Phi, Some(self.base_var_type), Some(new_id), vec![ + Operand::IdRef(top_def), + Operand::IdRef(from_block_label), + ]), ); self.phi_defs.insert(new_id); new_id diff --git a/crates/rustc_codegen_spirv/src/linker/mod.rs b/crates/rustc_codegen_spirv/src/linker/mod.rs index 543b58b592..036c1d920b 100644 --- a/crates/rustc_codegen_spirv/src/linker/mod.rs +++ b/crates/rustc_codegen_spirv/src/linker/mod.rs @@ -23,12 +23,12 @@ use crate::custom_decorations::{CustomDecoration, SrcLocDecoration, ZombieDecora use crate::custom_insts; use either::Either; use rspirv::binary::{Assemble, Consumer}; -use rspirv::dr::{Block, Instruction, Loader, Module, ModuleHeader, Operand}; +use rspirv::dr::{Block, Loader, Module, ModuleHeader, Operand}; use rspirv::spirv::{Op, StorageClass, Word}; use rustc_data_structures::fx::FxHashMap; use rustc_errors::ErrorGuaranteed; -use rustc_session::config::OutputFilenames; use rustc_session::Session; +use rustc_session::config::OutputFilenames; use std::collections::BTreeMap; use std::ffi::{OsStr, OsString}; use std::path::PathBuf; @@ -87,33 +87,22 @@ fn id(header: &mut ModuleHeader) -> Word { } fn apply_rewrite_rules(rewrite_rules: &FxHashMap, blocks: &mut [Block]) { - let apply = |inst: &mut Instruction| { - if let Some(ref mut id) = &mut inst.result_id { - if let Some(&rewrite) = rewrite_rules.get(id) { - *id = rewrite; - } - } - - if let Some(ref mut id) = &mut inst.result_type { - if let Some(&rewrite) = rewrite_rules.get(id) { - *id = rewrite; - } - } - - inst.operands.iter_mut().for_each(|op| { - if let Some(id) = op.id_ref_any_mut() { - if let Some(&rewrite) = rewrite_rules.get(id) { - *id = rewrite; - } - } + let all_ids_mut = blocks + .iter_mut() + .flat_map(|b| b.label.iter_mut().chain(b.instructions.iter_mut())) + .flat_map(|inst| { + inst.result_id + .iter_mut() + .chain(inst.result_type.iter_mut()) + .chain( + inst.operands + .iter_mut() + .filter_map(|op| op.id_ref_any_mut()), + ) }); - }; - for block in blocks { - for inst in &mut block.label { - apply(inst); - } - for inst in &mut block.instructions { - apply(inst); + for id in all_ids_mut { + if let Some(&rewrite) = rewrite_rules.get(id) { + *id = rewrite; } } } @@ -345,27 +334,23 @@ pub fn link( for func in &mut output.functions { simple_passes::block_ordering_pass(func); } - output = specializer::specialize( - opts, - output, - specializer::SimpleSpecialization { - specialize_operand: |operand| { - matches!(operand, Operand::StorageClass(StorageClass::Generic)) - }, - - // NOTE(eddyb) this can be anything that is guaranteed to pass - // validation - there are no constraints so this is either some - // unused pointer, or perhaps one created using `OpConstantNull` - // and simply never mixed with pointers that have a storage class. - // It would be nice to use `Generic` itself here so that we leave - // some kind of indication of it being unconstrained, but `Generic` - // requires additional capabilities, so we use `Function` instead. - // TODO(eddyb) investigate whether this can end up in a pointer - // type that's the value of a module-scoped variable, and whether - // `Function` is actually invalid! (may need `Private`) - concrete_fallback: Operand::StorageClass(StorageClass::Function), + output = specializer::specialize(opts, output, specializer::SimpleSpecialization { + specialize_operand: |operand| { + matches!(operand, Operand::StorageClass(StorageClass::Generic)) }, - ); + + // NOTE(eddyb) this can be anything that is guaranteed to pass + // validation - there are no constraints so this is either some + // unused pointer, or perhaps one created using `OpConstantNull` + // and simply never mixed with pointers that have a storage class. + // It would be nice to use `Generic` itself here so that we leave + // some kind of indication of it being unconstrained, but `Generic` + // requires additional capabilities, so we use `Function` instead. + // TODO(eddyb) investigate whether this can end up in a pointer + // type that's the value of a module-scoped variable, and whether + // `Function` is actually invalid! (may need `Private`) + concrete_fallback: Operand::StorageClass(StorageClass::Function), + }); } // NOTE(eddyb) with SPIR-T, we can do `mem2reg` before inlining, too! @@ -642,13 +627,10 @@ pub fn link( module.entry_points.push(entry.clone()); let entry_name = entry.operands[2].unwrap_literal_string().to_string(); let mut file_stem = OsString::from( - sanitize_filename::sanitize_with_options( - &entry_name, - sanitize_filename::Options { - replacement: "-", - ..Default::default() - }, - ) + sanitize_filename::sanitize_with_options(&entry_name, sanitize_filename::Options { + replacement: "-", + ..Default::default() + }) .replace("--", "-"), ); // It's always possible to find an unambiguous `file_stem`, but it diff --git a/crates/rustc_codegen_spirv/src/linker/peephole_opts.rs b/crates/rustc_codegen_spirv/src/linker/peephole_opts.rs index 3947b300ba..6a0df87bfd 100644 --- a/crates/rustc_codegen_spirv/src/linker/peephole_opts.rs +++ b/crates/rustc_codegen_spirv/src/linker/peephole_opts.rs @@ -332,15 +332,11 @@ fn process_instruction( } let vector_width = vector_ty_inst.operands[1].unwrap_literal_bit32(); // `results` is the defining instruction for each scalar component of the final result. - let results = match inst + let results = inst .operands .iter() .map(|op| defs.get(&op.unwrap_id_ref())) - .collect::>>() - { - Some(r) => r, - None => return None, - }; + .collect::>>()?; let operation_opcode = results[0].class.opcode; // Figure out the operands for the vectorized instruction. @@ -455,10 +451,7 @@ fn can_fuse_bool( inst: &Instruction, ) -> bool { fn constant_value(types: &FxHashMap, val: Word) -> Option { - let inst = match types.get(&val) { - None => return None, - Some(inst) => inst, - }; + let inst = types.get(&val)?; if inst.class.opcode != Op::Constant { return None; } diff --git a/crates/rustc_codegen_spirv/src/linker/simple_passes.rs b/crates/rustc_codegen_spirv/src/linker/simple_passes.rs index b7673f1175..f6c6a19a7f 100644 --- a/crates/rustc_codegen_spirv/src/linker/simple_passes.rs +++ b/crates/rustc_codegen_spirv/src/linker/simple_passes.rs @@ -1,4 +1,4 @@ -use super::{get_name, get_names, Result}; +use super::{Result, get_name, get_names}; use rspirv::dr::{Block, Function, Module}; use rspirv::spirv::{ExecutionModel, Op, Word}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; diff --git a/crates/rustc_codegen_spirv/src/linker/specializer.rs b/crates/rustc_codegen_spirv/src/linker/specializer.rs index 6a32de5cd5..84114325d5 100644 --- a/crates/rustc_codegen_spirv/src/linker/specializer.rs +++ b/crates/rustc_codegen_spirv/src/linker/specializer.rs @@ -637,15 +637,12 @@ impl Specializer { // Inference variables become "generic" parameters. if param_count > 0 { - self.generics.insert( - result_id, - Generic { - param_count, - def: inst.clone(), - param_values, - replacements, - }, - ); + self.generics.insert(result_id, Generic { + param_count, + def: inst.clone(), + param_values, + replacements, + }); } } } @@ -2128,13 +2125,10 @@ impl<'a, S: Specialization> InferCx<'a, S> { Op::Return => {} - _ => self.instantiate_instruction( - inst, - InstructionLocation::FnBody { - block_idx, - inst_idx, - }, - ), + _ => self.instantiate_instruction(inst, InstructionLocation::FnBody { + block_idx, + inst_idx, + }), } } } diff --git a/crates/rustc_codegen_spirv/src/linker/spirt_passes/controlflow.rs b/crates/rustc_codegen_spirv/src/linker/spirt_passes/controlflow.rs index 7c5155cbe8..83b603c88b 100644 --- a/crates/rustc_codegen_spirv/src/linker/spirt_passes/controlflow.rs +++ b/crates/rustc_codegen_spirv/src/linker/spirt_passes/controlflow.rs @@ -4,8 +4,8 @@ use crate::custom_insts::{self, CustomInst, CustomOp}; use smallvec::SmallVec; use spirt::func_at::FuncAt; use spirt::{ - cfg, spv, Attr, AttrSet, ConstDef, ConstKind, ControlNodeKind, DataInstFormDef, DataInstKind, - DeclDef, EntityDefs, ExportKey, Exportee, Module, Type, TypeDef, TypeKind, TypeOrConst, Value, + Attr, AttrSet, ConstDef, ConstKind, ControlNodeKind, DataInstFormDef, DataInstKind, DeclDef, + EntityDefs, ExportKey, Exportee, Module, Type, TypeDef, TypeKind, TypeOrConst, Value, cfg, spv, }; use std::fmt::Write as _; @@ -228,17 +228,14 @@ pub fn convert_custom_aborts_to_unstructured_returns_in_entry_points( }; let block_insts_maybe_custom = func_at_block_insts.into_iter().map(|func_at_inst| { let data_inst_def = func_at_inst.def(); - ( - func_at_inst, - match cx[data_inst_def.form].kind { - DataInstKind::SpvExtInst { ext_set, inst } - if ext_set == custom_ext_inst_set => - { - Some(CustomOp::decode(inst).with_operands(&data_inst_def.inputs)) - } - _ => None, - }, - ) + (func_at_inst, match cx[data_inst_def.form].kind { + DataInstKind::SpvExtInst { ext_set, inst } + if ext_set == custom_ext_inst_set => + { + Some(CustomOp::decode(inst).with_operands(&data_inst_def.inputs)) + } + _ => None, + }) }); let custom_terminator_inst = block_insts_maybe_custom .clone() diff --git a/crates/rustc_codegen_spirv/src/linker/spirt_passes/debuginfo.rs b/crates/rustc_codegen_spirv/src/linker/spirt_passes/debuginfo.rs index 9d1944ced8..e89e079c9d 100644 --- a/crates/rustc_codegen_spirv/src/linker/spirt_passes/debuginfo.rs +++ b/crates/rustc_codegen_spirv/src/linker/spirt_passes/debuginfo.rs @@ -6,8 +6,8 @@ use smallvec::SmallVec; use spirt::transform::{InnerInPlaceTransform, Transformer}; use spirt::visit::InnerVisit; use spirt::{ - spv, Attr, AttrSetDef, ConstKind, Context, ControlNode, ControlNodeKind, DataInstKind, - InternedStr, Module, OrdAssertEq, Value, + Attr, AttrSetDef, ConstKind, Context, ControlNode, ControlNodeKind, DataInstKind, InternedStr, + Module, OrdAssertEq, Value, spv, }; /// Replace our custom extended instruction debuginfo with standard SPIR-V ones. diff --git a/crates/rustc_codegen_spirv/src/linker/spirt_passes/diagnostics.rs b/crates/rustc_codegen_spirv/src/linker/spirt_passes/diagnostics.rs index ea5a95040f..948f14fe8e 100644 --- a/crates/rustc_codegen_spirv/src/linker/spirt_passes/diagnostics.rs +++ b/crates/rustc_codegen_spirv/src/linker/spirt_passes/diagnostics.rs @@ -5,14 +5,14 @@ use crate::custom_insts::{self, CustomInst, CustomOp}; use rustc_data_structures::fx::FxIndexSet; use rustc_errors::EmissionGuarantee; use rustc_session::Session; -use rustc_span::{Span, DUMMY_SP}; +use rustc_span::{DUMMY_SP, Span}; use smallvec::SmallVec; use spirt::func_at::FuncAt; use spirt::visit::{InnerVisit, Visitor}; use spirt::{ - spv, Attr, AttrSet, AttrSetDef, Const, ConstKind, Context, ControlNode, ControlNodeKind, + Attr, AttrSet, AttrSetDef, Const, ConstKind, Context, ControlNode, ControlNodeKind, DataInstDef, DataInstForm, DataInstKind, Diag, DiagLevel, ExportKey, Exportee, Func, FuncDecl, - GlobalVar, InternedStr, Module, Type, Value, + GlobalVar, InternedStr, Module, Type, Value, spv, }; use std::marker::PhantomData; use std::{mem, str}; diff --git a/crates/rustc_codegen_spirv/src/linker/spirt_passes/mod.rs b/crates/rustc_codegen_spirv/src/linker/spirt_passes/mod.rs index e2e3d4f972..a8962db011 100644 --- a/crates/rustc_codegen_spirv/src/linker/spirt_passes/mod.rs +++ b/crates/rustc_codegen_spirv/src/linker/spirt_passes/mod.rs @@ -12,9 +12,9 @@ use spirt::func_at::FuncAt; use spirt::transform::InnerInPlaceTransform; use spirt::visit::{InnerVisit, Visitor}; use spirt::{ - spv, AttrSet, Const, Context, ControlNode, ControlNodeKind, ControlRegion, DataInstDef, + AttrSet, Const, Context, ControlNode, ControlNodeKind, ControlRegion, DataInstDef, DataInstForm, DataInstFormDef, DataInstKind, DeclDef, EntityOrientedDenseMap, Func, - FuncDefBody, GlobalVar, Module, Type, Value, + FuncDefBody, GlobalVar, Module, Type, Value, spv, }; use std::collections::VecDeque; use std::iter; diff --git a/crates/rustc_codegen_spirv/src/linker/spirt_passes/reduce.rs b/crates/rustc_codegen_spirv/src/linker/spirt_passes/reduce.rs index aa1b96b2cb..fa0728afa3 100644 --- a/crates/rustc_codegen_spirv/src/linker/spirt_passes/reduce.rs +++ b/crates/rustc_codegen_spirv/src/linker/spirt_passes/reduce.rs @@ -4,10 +4,10 @@ use spirt::func_at::{FuncAt, FuncAtMut}; use spirt::transform::InnerInPlaceTransform; use spirt::visit::InnerVisit; use spirt::{ - spv, Const, ConstDef, ConstKind, Context, ControlNode, ControlNodeDef, ControlNodeKind, + Const, ConstDef, ConstKind, Context, ControlNode, ControlNodeDef, ControlNodeKind, ControlNodeOutputDecl, ControlRegion, ControlRegionInputDecl, DataInst, DataInstDef, DataInstFormDef, DataInstKind, EntityOrientedDenseMap, FuncDefBody, SelectionKind, Type, - TypeDef, TypeKind, Value, + TypeDef, TypeKind, Value, spv, }; use std::collections::hash_map::Entry; use std::{iter, slice}; diff --git a/crates/rustc_codegen_spirv/src/linker/test.rs b/crates/rustc_codegen_spirv/src/linker/test.rs index 573516fc6d..529b4c697b 100644 --- a/crates/rustc_codegen_spirv/src/linker/test.rs +++ b/crates/rustc_codegen_spirv/src/linker/test.rs @@ -1,8 +1,8 @@ -use super::{link, LinkResult}; +use super::{LinkResult, link}; use rspirv::dr::{Loader, Module}; use rustc_errors::registry::Registry; -use rustc_session::config::{Input, OutputFilenames, OutputTypes}; use rustc_session::CompilerIO; +use rustc_session::config::{Input, OutputFilenames, OutputTypes}; use rustc_span::FileName; use std::io::Write; use std::sync::{Arc, Mutex}; @@ -66,15 +66,12 @@ fn load(bytes: &[u8]) -> Module { // FIXME(eddyb) shouldn't this be named just `link`? (`assemble_spirv` is separate) fn assemble_and_link(binaries: &[&[u8]]) -> Result { - link_with_linker_opts( - binaries, - &crate::linker::Options { - compact_ids: true, - dce: true, - keep_link_exports: true, - ..Default::default() - }, - ) + link_with_linker_opts(binaries, &crate::linker::Options { + compact_ids: true, + dce: true, + keep_link_exports: true, + ..Default::default() + }) } fn link_with_linker_opts( @@ -141,6 +138,7 @@ fn link_with_linker_opts( file_loader: Box::new(rustc_span::source_map::RealFileLoader), path_mapping: sopts.file_path_mapping(), hash_kind: sopts.unstable_opts.src_hash_algorithm(&target), + checksum_hash_kind: None, }; rustc_span::create_session_globals_then(sopts.edition, Some(sm_inputs), || { let mut sess = rustc_session::build_session( @@ -169,7 +167,9 @@ fn link_with_linker_opts( // HACK(eddyb) inject `write_diags` into `sess`, to work around // the removals in https://github.com/rust-lang/rust/pull/102992. - sess.psess.dcx = { + sess.psess = { + let source_map = sess.psess.clone_source_map(); + let fallback_bundle = { extern crate rustc_error_messages; rustc_error_messages::fallback_fluent_bundle( @@ -179,10 +179,13 @@ fn link_with_linker_opts( }; let emitter = rustc_errors::emitter::HumanEmitter::new(Box::new(buf), fallback_bundle) - .sm(Some(sess.psess.clone_source_map())); + .sm(Some(source_map.clone())); - rustc_errors::DiagCtxt::new(Box::new(emitter)) - .with_flags(sess.opts.unstable_opts.dcx_flags(true)) + rustc_session::parse::ParseSess::with_dcx( + rustc_errors::DiagCtxt::new(Box::new(emitter)) + .with_flags(sess.opts.unstable_opts.dcx_flags(true)), + source_map, + ) }; let res = link( diff --git a/crates/rustc_codegen_spirv/src/linker/zombies.rs b/crates/rustc_codegen_spirv/src/linker/zombies.rs index dd35113419..9b9423a4b9 100644 --- a/crates/rustc_codegen_spirv/src/linker/zombies.rs +++ b/crates/rustc_codegen_spirv/src/linker/zombies.rs @@ -8,7 +8,7 @@ use rspirv::spirv::{Op, Word}; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_errors::Diag; use rustc_session::Session; -use rustc_span::{Span, DUMMY_SP}; +use rustc_span::{DUMMY_SP, Span}; use smallvec::SmallVec; #[derive(Copy, Clone)] diff --git a/crates/rustc_codegen_spirv/src/spirv_type.rs b/crates/rustc_codegen_spirv/src/spirv_type.rs index f4ebd399bb..0c8ce42ba0 100644 --- a/crates/rustc_codegen_spirv/src/spirv_type.rs +++ b/crates/rustc_codegen_spirv/src/spirv_type.rs @@ -340,7 +340,12 @@ impl SpirvType<'_> { } Self::Matrix { element, count } => cx.lookup_type(element).sizeof(cx)? * count as u64, Self::Array { element, count } => { - cx.lookup_type(element).sizeof(cx)? * cx.builder.lookup_const_u64(count).unwrap() + cx.lookup_type(element).sizeof(cx)? + * cx.builder + .lookup_const_scalar(count) + .unwrap() + .try_into() + .unwrap() } Self::Pointer { .. } => cx.tcx.data_layout.pointer_size, Self::Image { .. } @@ -543,7 +548,7 @@ impl fmt::Debug for SpirvTypePrinter<'_, '_> { &self .cx .builder - .lookup_const_u64(count) + .lookup_const_scalar(count) .expect("Array type has invalid count value"), ) .finish(), @@ -694,7 +699,7 @@ impl SpirvTypePrinter<'_, '_> { write!(f, "x{count}") } SpirvType::Array { element, count } => { - let len = self.cx.builder.lookup_const_u64(count); + let len = self.cx.builder.lookup_const_scalar(count); let len = len.expect("Array type has invalid count value"); f.write_str("[")?; ty(self.cx, stack, f, element)?; diff --git a/crates/rustc_codegen_spirv/src/symbols.rs b/crates/rustc_codegen_spirv/src/symbols.rs index d19db967e4..787cacff9f 100644 --- a/crates/rustc_codegen_spirv/src/symbols.rs +++ b/crates/rustc_codegen_spirv/src/symbols.rs @@ -1,10 +1,10 @@ use crate::attr::{Entry, ExecutionModeExtra, IntrinsicType, SpecConstant, SpirvAttribute}; use crate::builder::libm_intrinsics; use rspirv::spirv::{BuiltIn, ExecutionMode, ExecutionModel, StorageClass}; -use rustc_ast::ast::{AttrKind, Attribute, LitIntType, LitKind, MetaItemLit, NestedMetaItem}; +use rustc_ast::ast::{AttrKind, Attribute, LitIntType, LitKind, MetaItemInner, MetaItemLit}; use rustc_data_structures::fx::FxHashMap; -use rustc_span::symbol::{Ident, Symbol}; use rustc_span::Span; +use rustc_span::symbol::{Ident, Symbol}; use std::rc::Rc; /// Various places in the codebase (mostly attribute parsing) need to compare rustc Symbols to particular keywords. @@ -508,7 +508,7 @@ pub(crate) fn parse_attrs_for_checking<'a>( fn parse_spec_constant_attr( sym: &Symbols, - arg: &NestedMetaItem, + arg: &MetaItemInner, ) -> Result { let mut id = None; let mut default = None; @@ -538,7 +538,7 @@ fn parse_spec_constant_attr( }) } -fn parse_attr_int_value(arg: &NestedMetaItem) -> Result { +fn parse_attr_int_value(arg: &MetaItemInner) -> Result { let arg = match arg.meta_item() { Some(arg) => arg, None => return Err((arg.span(), "attribute must have value".to_string())), @@ -552,7 +552,7 @@ fn parse_attr_int_value(arg: &NestedMetaItem) -> Result { } } -fn parse_local_size_attr(arg: &NestedMetaItem) -> Result<[u32; 3], ParseAttrError> { +fn parse_local_size_attr(arg: &MetaItemInner) -> Result<[u32; 3], ParseAttrError> { let arg = match arg.meta_item() { Some(arg) => arg, None => return Err((arg.span(), "attribute must have value".to_string())), @@ -562,7 +562,7 @@ fn parse_local_size_attr(arg: &NestedMetaItem) -> Result<[u32; 3], ParseAttrErro let mut local_size = [1; 3]; for (idx, lit) in tuple.iter().enumerate() { match lit { - NestedMetaItem::Lit(MetaItemLit { + MetaItemInner::Lit(MetaItemLit { kind: LitKind::Int(x, LitIntType::Unsuffixed), .. }) if *x <= u32::MAX as u128 => local_size[idx] = x.get() as u32, @@ -592,7 +592,7 @@ fn parse_local_size_attr(arg: &NestedMetaItem) -> Result<[u32; 3], ParseAttrErro // ie #[spirv(fragment(origin_lower_left))] or #[spirv(gl_compute(local_size_x=64, local_size_y=8))] fn parse_entry_attrs( sym: &Symbols, - arg: &NestedMetaItem, + arg: &MetaItemInner, name: &Ident, execution_model: ExecutionModel, ) -> Result { diff --git a/crates/rustc_codegen_spirv/src/target.rs b/crates/rustc_codegen_spirv/src/target.rs index 2f319e611f..313c0a474b 100644 --- a/crates/rustc_codegen_spirv/src/target.rs +++ b/crates/rustc_codegen_spirv/src/target.rs @@ -113,7 +113,7 @@ impl std::str::FromStr for SpirvTarget { let mut iter = target.split('-'); let error = || InvalidTarget(target.into()); - if iter.next().map_or(true, |arch| arch != ARCH) { + if iter.next() != Some(ARCH) { return Err(error()); } diff --git a/crates/spirv-builder/src/lib.rs b/crates/spirv-builder/src/lib.rs index 46483050e5..a2f4d5278d 100644 --- a/crates/spirv-builder/src/lib.rs +++ b/crates/spirv-builder/src/lib.rs @@ -1,3 +1,5 @@ +// FIXME(eddyb) update/review these lints. +// // BEGIN - Embark standard lints v0.4 // do not change or add/remove here, but one can add exceptions after this section // for more info see: @@ -38,7 +40,6 @@ clippy::match_same_arms, clippy::match_wildcard_for_single_variants, clippy::mem_forget, - clippy::mismatched_target_os, clippy::mut_mut, clippy::mutex_integer, clippy::needless_borrow, @@ -835,9 +836,9 @@ fn invoke_rustc(builder: &SpirvBuilder) -> Result { // inner invocation of Cargo (because e.g. build scripts might read them), // before we set any of our own below. for (key, _) in env::vars_os() { - let remove = key.to_str().map_or(false, |s| { - s.starts_with("CARGO_FEATURES_") || s.starts_with("CARGO_CFG_") - }); + let remove = key + .to_str() + .is_some_and(|s| s.starts_with("CARGO_FEATURES_") || s.starts_with("CARGO_CFG_")); if remove { cargo.env_remove(key); } diff --git a/crates/spirv-builder/src/watch.rs b/crates/spirv-builder/src/watch.rs index 051adf7f6e..9c011fd649 100644 --- a/crates/spirv-builder/src/watch.rs +++ b/crates/spirv-builder/src/watch.rs @@ -3,7 +3,7 @@ use std::{collections::HashSet, sync::mpsc::sync_channel}; use notify::{Event, RecursiveMode, Watcher}; use rustc_codegen_spirv_types::CompileResult; -use crate::{leaf_deps, SpirvBuilder, SpirvBuilderError}; +use crate::{SpirvBuilder, SpirvBuilderError, leaf_deps}; impl SpirvBuilder { /// Watches the module for changes using [`notify`](https://crates.io/crates/notify), diff --git a/crates/spirv-std/Cargo.toml b/crates/spirv-std/Cargo.toml index 44590a02c4..822223a52e 100644 --- a/crates/spirv-std/Cargo.toml +++ b/crates/spirv-std/Cargo.toml @@ -7,8 +7,8 @@ edition.workspace = true license.workspace = true repository.workspace = true -[lints.rust] -unexpected_cfgs = { level = "allow", check-cfg = ['cfg(target_arch, values("spirv"))'] } +[lints] +workspace = true [dependencies] spirv-std-types.workspace = true diff --git a/crates/spirv-std/macros/Cargo.toml b/crates/spirv-std/macros/Cargo.toml index f714c29cf6..a9d0f0721f 100644 --- a/crates/spirv-std/macros/Cargo.toml +++ b/crates/spirv-std/macros/Cargo.toml @@ -7,8 +7,8 @@ edition.workspace = true license.workspace = true repository.workspace = true -[lints.rust] -unexpected_cfgs = { level = "allow", check-cfg = ['cfg(target_arch, values("spirv"))'] } +[lints] +workspace = true [lib] proc-macro = true diff --git a/crates/spirv-std/macros/src/image.rs b/crates/spirv-std/macros/src/image.rs index b6566e78d4..7cecb637a1 100644 --- a/crates/spirv-std/macros/src/image.rs +++ b/crates/spirv-std/macros/src/image.rs @@ -1,6 +1,6 @@ use proc_macro2::Ident; -use quote::{quote, TokenStreamExt}; +use quote::{TokenStreamExt, quote}; use spirv_std_types::image_params::*; use syn::parse::{Parse, ParseStream}; diff --git a/crates/spirv-std/macros/src/lib.rs b/crates/spirv-std/macros/src/lib.rs index 3cf1b499b7..589dfcd296 100644 --- a/crates/spirv-std/macros/src/lib.rs +++ b/crates/spirv-std/macros/src/lib.rs @@ -1,3 +1,5 @@ +// FIXME(eddyb) update/review these lints. +// // BEGIN - Embark standard lints v0.4 // do not change or add/remove here, but one can add exceptions after this section // for more info see: @@ -38,7 +40,6 @@ clippy::match_same_arms, clippy::match_wildcard_for_single_variants, clippy::mem_forget, - clippy::mismatched_target_os, clippy::mut_mut, clippy::mutex_integer, clippy::needless_borrow, @@ -77,10 +78,10 @@ use proc_macro::TokenStream; use proc_macro2::{Delimiter, Group, Ident, Span, TokenTree}; use syn::{ - punctuated::Punctuated, spanned::Spanned, visit_mut::VisitMut, ImplItemFn, ItemFn, Token, + ImplItemFn, ItemFn, Token, punctuated::Punctuated, spanned::Spanned, visit_mut::VisitMut, }; -use quote::{quote, ToTokens}; +use quote::{ToTokens, quote}; use std::fmt::Write; /// A macro for creating SPIR-V `OpTypeImage` types. Always produces a diff --git a/crates/spirv-std/shared/Cargo.toml b/crates/spirv-std/shared/Cargo.toml index c2c26a5dde..2c128f1f28 100644 --- a/crates/spirv-std/shared/Cargo.toml +++ b/crates/spirv-std/shared/Cargo.toml @@ -7,6 +7,5 @@ edition.workspace = true license.workspace = true repository.workspace = true -[lints.rust] -unexpected_cfgs = { level = "allow", check-cfg = ['cfg(target_arch, values("spirv"))'] } - +[lints] +workspace = true diff --git a/crates/spirv-std/src/image.rs b/crates/spirv-std/src/image.rs index 0a9924dbd9..e37fe641df 100644 --- a/crates/spirv-std/src/image.rs +++ b/crates/spirv-std/src/image.rs @@ -18,13 +18,13 @@ pub use spirv_std_types::image_params::{ use sample_with::{NoneTy, SampleParams, SomeTy}; -use crate::{float::Float, integer::Integer, vector::Vector, Sampler}; +use crate::{Sampler, float::Float, integer::Integer, vector::Vector}; /// Re-export of primitive types to ensure the `Image` proc macro always points /// to the right type. #[doc(hidden)] pub mod __private { - pub use {f32, f64, i16, i32, i64, i8, u16, u32, u64, u8}; + pub use {f32, f64, i8, i16, i32, i64, u8, u16, u32, u64}; } /// A 1d image used with a sampler. @@ -1039,6 +1039,8 @@ impl< /// `SampledImage`. #[spirv(sampled_image)] #[derive(Copy, Clone)] +// HACK(eddyb) false positive due to `rustc` not understanding e.g. entry-points. +#[allow(dead_code)] pub struct SampledImage { _image: I, } diff --git a/crates/spirv-std/src/image/sample_with.rs b/crates/spirv-std/src/image/sample_with.rs index 2f65952b61..af59834361 100644 --- a/crates/spirv-std/src/image/sample_with.rs +++ b/crates/spirv-std/src/image/sample_with.rs @@ -17,9 +17,10 @@ pub struct NoneTy; /// Helper struct that denotes that the type does exist and is of type T, analog to `Option::Some(T)` pub struct SomeTy(pub T); -/// Helper struct that allows building image operands. Start with a global function that returns this -/// struct, and then chain additional calls. No care is taken to avoid stating multiple operands that, -/// together, make no sense, such as Lod and Grad. +/// Helper struct that allows building image operands. +/// +/// Start with a global function that returns this struct, and then chain additional calls. +/// No care is taken to avoid stating multiple operands that, together, make no sense, such as Lod and Grad. /// Example: `image.sample_with(coords, sample_with::bias(3.0).sample_index(1))` pub struct SampleParams { /// 'Bias' image operand diff --git a/crates/spirv-std/src/lib.rs b/crates/spirv-std/src/lib.rs index f50e719fe0..61c84dfc47 100644 --- a/crates/spirv-std/src/lib.rs +++ b/crates/spirv-std/src/lib.rs @@ -2,14 +2,10 @@ #![cfg_attr( target_arch = "spirv", allow(internal_features), - feature( - asm_const, - asm_experimental_arch, - core_intrinsics, - lang_items, - repr_simd, - ) + feature(asm_experimental_arch, core_intrinsics, lang_items, repr_simd) )] +// FIXME(eddyb) update/review these lints. +// // BEGIN - Embark standard lints v0.4 // do not change or add/remove here, but one can add exceptions after this section // for more info see: @@ -50,7 +46,6 @@ clippy::match_same_arms, clippy::match_wildcard_for_single_variants, clippy::mem_forget, - clippy::mismatched_target_os, clippy::mut_mut, clippy::mutex_integer, clippy::needless_borrow, diff --git a/crates/spirv-std/src/ray_tracing.rs b/crates/spirv-std/src/ray_tracing.rs index 4c9f345f54..f24de07bab 100644 --- a/crates/spirv-std/src/ray_tracing.rs +++ b/crates/spirv-std/src/ray_tracing.rs @@ -198,6 +198,8 @@ pub enum CommittedIntersection { #[spirv(ray_query)] // HACK(eddyb) avoids "transparent newtype of `_anti_zst_padding`" misinterpretation. #[repr(C)] +// HACK(eddyb) false positive due to `rustc` not understanding e.g. `ray_query!`. +#[allow(dead_code)] pub struct RayQuery { // HACK(eddyb) avoids the layout becoming ZST (and being elided in one way // or another, before `#[spirv(ray_query)]` can special-case it). diff --git a/crates/spirv-std/src/runtime_array.rs b/crates/spirv-std/src/runtime_array.rs index 896866368e..5d5df01dfb 100644 --- a/crates/spirv-std/src/runtime_array.rs +++ b/crates/spirv-std/src/runtime_array.rs @@ -2,13 +2,15 @@ use core::arch::asm; use core::marker::PhantomData; +/// SPIR-V "runtime array", similar to `[T]`, but with no way of knowing its length. +/// /// Dynamically-sized arrays in Rust carry around their length as the second half of a tuple. /// Unfortunately, sometimes SPIR-V provides an unsized array with no way of obtaining its length. -/// Hence, this type represents something very similar to a slice, but with no way of knowing its -/// length. #[spirv(runtime_array)] // HACK(eddyb) avoids "transparent newtype of `_anti_zst_padding`" misinterpretation. #[repr(C)] +// HACK(eddyb) false positive due to `rustc` not understanding e.g. entry-points. +#[allow(dead_code)] pub struct RuntimeArray { // HACK(eddyb) avoids the layout becoming ZST (and being elided in one way // or another, before `#[spirv(runtime_array)]` can special-case it). diff --git a/crates/spirv-std/src/scalar.rs b/crates/spirv-std/src/scalar.rs index e9ab3ae758..72e0d8dfaf 100644 --- a/crates/spirv-std/src/scalar.rs +++ b/crates/spirv-std/src/scalar.rs @@ -1,6 +1,6 @@ //! Traits related to scalars. -use crate::vector::{create_dim, VectorOrScalar}; +use crate::vector::{VectorOrScalar, create_dim}; use core::num::NonZeroUsize; /// Abstract trait representing a SPIR-V scalar type. diff --git a/crates/spirv-std/src/typed_buffer.rs b/crates/spirv-std/src/typed_buffer.rs index 13e1a0911a..7b04f541f1 100644 --- a/crates/spirv-std/src/typed_buffer.rs +++ b/crates/spirv-std/src/typed_buffer.rs @@ -14,6 +14,8 @@ use core::ops::{Deref, DerefMut}; #[spirv(typed_buffer)] // HACK(eddyb) avoids "transparent newtype of `_anti_zst_padding`" misinterpretation. #[repr(C)] +// HACK(eddyb) false positive due to `rustc` not understanding e.g. entry-points. +#[allow(dead_code)] pub struct TypedBuffer { // HACK(eddyb) avoids the layout becoming ZST (and being elided in one way // or another, before `#[spirv(runtime_array)]` can special-case it). diff --git a/deny.toml b/deny.toml index 0316f50b7c..4d3bb20c52 100644 --- a/deny.toml +++ b/deny.toml @@ -3,8 +3,9 @@ # https://embarkstudios.github.io/cargo-deny/checks/advisories/cfg.html [advisories] ignore = [ - # safemem transitive dependency, old and unmaintained but not critical and stable - "RUSTSEC-2023-0081", + # HACK(eddyb) `instant` is unmaintained (`web-time` suggested replacement), + # non-trivial to remove as e.g. even the latest `minifb` still uses it. + "RUSTSEC-2024-0384", ] # This section is considered when running `cargo deny check bans`. diff --git a/examples/runners/ash/src/main.rs b/examples/runners/ash/src/main.rs index 03ee7b6add..ca92e2a3ad 100644 --- a/examples/runners/ash/src/main.rs +++ b/examples/runners/ash/src/main.rs @@ -1,3 +1,5 @@ +// FIXME(eddyb) update/review these lints. +// // BEGIN - Embark standard lints v0.4 // do not change or add/remove here, but one can add exceptions after this section // for more info see: @@ -38,7 +40,6 @@ clippy::match_same_arms, clippy::match_wildcard_for_single_variants, clippy::mem_forget, - clippy::mismatched_target_os, clippy::mut_mut, clippy::mutex_integer, clippy::needless_borrow, @@ -87,7 +88,7 @@ use std::{ collections::HashMap, ffi::{CStr, CString}, fs::File, - sync::mpsc::{sync_channel, TryRecvError, TrySendError}, + sync::mpsc::{TryRecvError, TrySendError, sync_channel}, thread, }; @@ -125,21 +126,18 @@ pub fn main() { for SpvFile { name, data } in shaders { ctx.insert_shader_module(name, &data); } - ctx.build_pipelines( - vk::PipelineCache::null(), - vec![( - // HACK(eddyb) used to be `module: "sky_shader"` but we need `multimodule` - // for `debugPrintf` instrumentation to work (see `compile_shaders`). - VertexShaderEntryPoint { - module: "sky_shader::main_vs".into(), - entry_point: "main_vs".into(), - }, - FragmentShaderEntryPoint { - module: "sky_shader::main_fs".into(), - entry_point: "main_fs".into(), - }, - )], - ); + ctx.build_pipelines(vk::PipelineCache::null(), vec![( + // HACK(eddyb) used to be `module: "sky_shader"` but we need `multimodule` + // for `debugPrintf` instrumentation to work (see `compile_shaders`). + VertexShaderEntryPoint { + module: "sky_shader::main_vs".into(), + entry_point: "main_vs".into(), + }, + FragmentShaderEntryPoint { + module: "sky_shader::main_fs".into(), + entry_point: "main_fs".into(), + }, + )]); let (compiler_sender, compiler_receiver) = sync_channel(1); diff --git a/examples/runners/cpu/src/main.rs b/examples/runners/cpu/src/main.rs index 30c12a9420..813c350222 100644 --- a/examples/runners/cpu/src/main.rs +++ b/examples/runners/cpu/src/main.rs @@ -1,3 +1,5 @@ +// FIXME(eddyb) update/review these lints. +// // BEGIN - Embark standard lints v0.4 // do not change or add/remove here, but one can add exceptions after this section // for more info see: @@ -38,7 +40,6 @@ clippy::match_same_arms, clippy::match_wildcard_for_single_variants, clippy::mem_forget, - clippy::mismatched_target_os, clippy::mut_mut, clippy::mutex_integer, clippy::needless_borrow, @@ -72,8 +73,8 @@ use minifb::{Key, Window, WindowOptions}; use rayon::prelude::*; -use shared::glam::{vec2, Vec2, Vec4}; use shared::ShaderConstants; +use shared::glam::{Vec2, Vec4, vec2}; use std::time::Instant; use sky_shader as shader_module; diff --git a/examples/runners/wgpu/src/compute.rs b/examples/runners/wgpu/src/compute.rs index 534e4f0ede..e010e0f010 100644 --- a/examples/runners/wgpu/src/compute.rs +++ b/examples/runners/wgpu/src/compute.rs @@ -1,4 +1,4 @@ -use crate::{maybe_watch, CompiledShaderModules, Options}; +use crate::{CompiledShaderModules, Options, maybe_watch}; use std::time::Duration; use wgpu::util::DeviceExt; diff --git a/examples/runners/wgpu/src/graphics.rs b/examples/runners/wgpu/src/graphics.rs index 33fb68a90e..253c55d2eb 100644 --- a/examples/runners/wgpu/src/graphics.rs +++ b/examples/runners/wgpu/src/graphics.rs @@ -1,4 +1,4 @@ -use crate::{maybe_watch, CompiledShaderModules, Options}; +use crate::{CompiledShaderModules, Options, maybe_watch}; use shared::ShaderConstants; use winit::{ diff --git a/examples/runners/wgpu/src/lib.rs b/examples/runners/wgpu/src/lib.rs index 02ae52778a..82d0e758fb 100644 --- a/examples/runners/wgpu/src/lib.rs +++ b/examples/runners/wgpu/src/lib.rs @@ -1,3 +1,5 @@ +// FIXME(eddyb) update/review these lints. +// // BEGIN - Embark standard lints v0.4 // do not change or add/remove here, but one can add exceptions after this section // for more info see: @@ -38,7 +40,6 @@ clippy::match_same_arms, clippy::match_wildcard_for_single_variants, clippy::mem_forget, - clippy::mismatched_target_os, clippy::mut_mut, clippy::mutex_integer, clippy::needless_borrow, diff --git a/examples/shaders/compute-shader/Cargo.toml b/examples/shaders/compute-shader/Cargo.toml index 334e043793..4a7d4324fe 100644 --- a/examples/shaders/compute-shader/Cargo.toml +++ b/examples/shaders/compute-shader/Cargo.toml @@ -7,6 +7,9 @@ edition.workspace = true license.workspace = true repository.workspace = true +[lints] +workspace = true + [lib] crate-type = ["dylib", "lib"] diff --git a/examples/shaders/mouse-shader/Cargo.toml b/examples/shaders/mouse-shader/Cargo.toml index ea4144463a..1955c82de6 100644 --- a/examples/shaders/mouse-shader/Cargo.toml +++ b/examples/shaders/mouse-shader/Cargo.toml @@ -7,6 +7,9 @@ edition.workspace = true license.workspace = true repository.workspace = true +[lints] +workspace = true + [lib] crate-type = ["dylib"] diff --git a/examples/shaders/mouse-shader/src/lib.rs b/examples/shaders/mouse-shader/src/lib.rs index a3044ccf9d..36b7347f7a 100644 --- a/examples/shaders/mouse-shader/src/lib.rs +++ b/examples/shaders/mouse-shader/src/lib.rs @@ -3,7 +3,7 @@ #![deny(warnings)] use core::f32::consts::PI; -use glam::{vec2, vec3, vec4, Mat2, Vec2, Vec3, Vec4, Vec4Swizzles}; +use glam::{Mat2, Vec2, Vec3, Vec4, Vec4Swizzles, vec2, vec3, vec4}; use shared::*; use spirv_std::spirv; diff --git a/examples/shaders/reduce/Cargo.toml b/examples/shaders/reduce/Cargo.toml index 870f110b00..a67f74232f 100644 --- a/examples/shaders/reduce/Cargo.toml +++ b/examples/shaders/reduce/Cargo.toml @@ -7,6 +7,9 @@ edition.workspace = true license.workspace = true repository.workspace = true +[lints] +workspace = true + [lib] crate-type = ["dylib", "lib"] diff --git a/examples/shaders/shared/Cargo.toml b/examples/shaders/shared/Cargo.toml index 66b69c4369..61ed12111b 100644 --- a/examples/shaders/shared/Cargo.toml +++ b/examples/shaders/shared/Cargo.toml @@ -7,6 +7,9 @@ edition.workspace = true license.workspace = true repository.workspace = true +[lints] +workspace = true + [dependencies] spirv-std = { workspace = true } bytemuck = { version = "1.18.0", features = ["derive"] } diff --git a/examples/shaders/shared/src/lib.rs b/examples/shaders/shared/src/lib.rs index 37979f4d7c..ceb192116c 100644 --- a/examples/shaders/shared/src/lib.rs +++ b/examples/shaders/shared/src/lib.rs @@ -3,7 +3,7 @@ #![cfg_attr(target_arch = "spirv", no_std)] use core::f32::consts::PI; -use glam::{vec3, Vec3}; +use glam::{Vec3, vec3}; pub use spirv_std::glam; diff --git a/examples/shaders/simplest-shader/Cargo.toml b/examples/shaders/simplest-shader/Cargo.toml index 975e93d484..d86220025e 100644 --- a/examples/shaders/simplest-shader/Cargo.toml +++ b/examples/shaders/simplest-shader/Cargo.toml @@ -7,6 +7,9 @@ edition.workspace = true license.workspace = true repository.workspace = true +[lints] +workspace = true + [lib] crate-type = ["dylib"] diff --git a/examples/shaders/simplest-shader/src/lib.rs b/examples/shaders/simplest-shader/src/lib.rs index 11f8a44048..68f24c09e6 100644 --- a/examples/shaders/simplest-shader/src/lib.rs +++ b/examples/shaders/simplest-shader/src/lib.rs @@ -2,7 +2,7 @@ // HACK(eddyb) can't easily see warnings otherwise from `spirv-builder` builds. #![deny(warnings)] -use shared::glam::{vec4, Vec4}; +use shared::glam::{Vec4, vec4}; use spirv_std::spirv; #[spirv(fragment)] diff --git a/examples/shaders/sky-shader/Cargo.toml b/examples/shaders/sky-shader/Cargo.toml index dfd7b64238..3fbbe6061f 100644 --- a/examples/shaders/sky-shader/Cargo.toml +++ b/examples/shaders/sky-shader/Cargo.toml @@ -7,6 +7,9 @@ edition.workspace = true license.workspace = true repository.workspace = true +[lints] +workspace = true + [lib] crate-type = ["lib", "dylib"] diff --git a/examples/shaders/sky-shader/src/lib.rs b/examples/shaders/sky-shader/src/lib.rs index 5096df0dd9..a11af317d5 100644 --- a/examples/shaders/sky-shader/src/lib.rs +++ b/examples/shaders/sky-shader/src/lib.rs @@ -5,7 +5,7 @@ #![deny(warnings)] use core::f32::consts::PI; -use glam::{vec2, vec3, Vec2, Vec3, Vec4}; +use glam::{Vec2, Vec3, Vec4, vec2, vec3}; use shared::*; use spirv_std::spirv; diff --git a/rust-toolchain.toml b/rust-toolchain.toml index e31153b5c2..551cee7f67 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,7 +1,7 @@ [toolchain] -channel = "nightly-2024-04-24" +channel = "nightly-2024-11-22" components = ["rust-src", "rustc-dev", "llvm-tools"] -# commit_hash = 244da22fabd9fa677bbd0ac601a88e5ca6917526 +# commit_hash = b19329a37cedf2027517ae22c87cf201f93d776e # Whenever changing the nightly channel, update the commit hash above, and make # sure to change `REQUIRED_TOOLCHAIN` in `crates/rustc_codegen_spirv/build.rs` also. diff --git a/rustfmt.toml b/rustfmt.toml index 7fdb399317..3501136812 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -1,3 +1 @@ -# HACK(eddyb) needed to format array/slice patterns at all, because it was a -# breaking change (see https://github.com/rust-lang/rustfmt/pull/4994). -version = "Two" +style_edition = "2024" diff --git a/tests/src/main.rs b/tests/src/main.rs index 7b48e14185..551e6eb92f 100644 --- a/tests/src/main.rs +++ b/tests/src/main.rs @@ -122,7 +122,7 @@ impl Runner { "--crate-type dylib", "-Zunstable-options", "-Zcrate-attr=no_std", - "-Zcrate-attr=feature(asm_const,asm_experimental_arch)", + "-Zcrate-attr=feature(asm_experimental_arch)", ] .join(" ") } @@ -155,18 +155,14 @@ impl Runner { let target = format!("{SPIRV_TARGET_PREFIX}{env}"); let libs = build_deps(&self.deps_target_dir, &self.codegen_backend_path, &target); - let mut flags = test_rustc_flags( - &self.codegen_backend_path, - &libs, - &[ - &self - .deps_target_dir - .join(DepKind::SpirvLib.target_dir_suffix(&target)), - &self - .deps_target_dir - .join(DepKind::ProcMacro.target_dir_suffix(&target)), - ], - ); + let mut flags = test_rustc_flags(&self.codegen_backend_path, &libs, &[ + &self + .deps_target_dir + .join(DepKind::SpirvLib.target_dir_suffix(&target)), + &self + .deps_target_dir + .join(DepKind::ProcMacro.target_dir_suffix(&target)), + ]); flags += variation.extra_flags; let config = compiletest::Config { @@ -308,7 +304,7 @@ fn find_lib( && ends_with_dash_hash(name.to_str().unwrap()); let extension_matches = path .extension() - .map_or(false, |ext| ext == expected_extension); + .is_some_and(|ext| ext == expected_extension); name_matches && extension_matches }) diff --git a/tests/ui/arch/all.stderr b/tests/ui/arch/all.stderr new file mode 100644 index 0000000000..8226745fbd --- /dev/null +++ b/tests/ui/arch/all.stderr @@ -0,0 +1,12 @@ +warning: [Rust-GPU] temporarily re-allowing old-style `#[repr(simd)]` (with fields) + --> $DIR/all.rs:15:1 + | +15 | struct Vec2(T, T); + | ^^^^^^^^^^^^^^ + | + = note: removed upstream by https://github.com/rust-lang/rust/pull/129403 + = note: in favor of the new `#[repr(simd)] struct TxN([T; N]);` style + = note: (taking effect since `nightly-2024-09-12` / `1.83.0` stable) + +warning: 1 warning emitted + diff --git a/tests/ui/arch/any.stderr b/tests/ui/arch/any.stderr new file mode 100644 index 0000000000..ff776148f5 --- /dev/null +++ b/tests/ui/arch/any.stderr @@ -0,0 +1,12 @@ +warning: [Rust-GPU] temporarily re-allowing old-style `#[repr(simd)]` (with fields) + --> $DIR/any.rs:15:1 + | +15 | struct Vec2(T, T); + | ^^^^^^^^^^^^^^ + | + = note: removed upstream by https://github.com/rust-lang/rust/pull/129403 + = note: in favor of the new `#[repr(simd)] struct TxN([T; N]);` style + = note: (taking effect since `nightly-2024-09-12` / `1.83.0` stable) + +warning: 1 warning emitted + diff --git a/tests/ui/arch/debug_printf_type_checking.stderr b/tests/ui/arch/debug_printf_type_checking.stderr index 7213a02020..b8ce41a270 100644 --- a/tests/ui/arch/debug_printf_type_checking.stderr +++ b/tests/ui/arch/debug_printf_type_checking.stderr @@ -75,9 +75,9 @@ help: the return type of this call is `u32` due to the type of the argument pass | | | this argument influences the return type of `spirv_std` note: function defined here - --> $SPIRV_STD_SRC/lib.rs:139:8 + --> $SPIRV_STD_SRC/lib.rs:134:8 | -139 | pub fn debug_printf_assert_is_type(ty: T) -> T { +134 | pub fn debug_printf_assert_is_type(ty: T) -> T { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the macro `debug_printf` (in Nightly builds, run with -Z macro-backtrace for more info) help: change the type of the numeric literal from `u32` to `f32` @@ -102,9 +102,9 @@ help: the return type of this call is `f32` due to the type of the argument pass | | | this argument influences the return type of `spirv_std` note: function defined here - --> $SPIRV_STD_SRC/lib.rs:139:8 + --> $SPIRV_STD_SRC/lib.rs:134:8 | -139 | pub fn debug_printf_assert_is_type(ty: T) -> T { +134 | pub fn debug_printf_assert_is_type(ty: T) -> T { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the macro `debug_printf` (in Nightly builds, run with -Z macro-backtrace for more info) help: change the type of the numeric literal from `f32` to `u32` @@ -119,22 +119,22 @@ error[E0277]: the trait bound `{float}: Vector` is not satisfied | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Vector` is not implemented for `{float}` | = help: the following other types implement trait `Vector`: - > - > - > - > - > - > - > - > + `DVec2` implements `Vector` + `DVec3` implements `Vector` + `DVec4` implements `Vector` + `IVec2` implements `Vector` + `IVec3` implements `Vector` + `IVec4` implements `Vector` + `UVec2` implements `Vector` + `UVec3` implements `Vector` and 5 others note: required by a bound in `debug_printf_assert_is_vector` - --> $SPIRV_STD_SRC/lib.rs:146:8 + --> $SPIRV_STD_SRC/lib.rs:141:8 | -144 | pub fn debug_printf_assert_is_vector< +139 | pub fn debug_printf_assert_is_vector< | ----------------------------- required by a bound in this function -145 | TY: crate::scalar::Scalar, -146 | V: crate::vector::Vector, +140 | TY: crate::scalar::Scalar, +141 | V: crate::vector::Vector, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `debug_printf_assert_is_vector` = note: this error originates in the macro `debug_printf` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -155,9 +155,9 @@ help: the return type of this call is `Vec2` due to the type of the argument pas | | | this argument influences the return type of `spirv_std` note: function defined here - --> $SPIRV_STD_SRC/lib.rs:139:8 + --> $SPIRV_STD_SRC/lib.rs:134:8 | -139 | pub fn debug_printf_assert_is_type(ty: T) -> T { +134 | pub fn debug_printf_assert_is_type(ty: T) -> T { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the macro `debug_printf` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/byte_addressable_buffer/arr.rs b/tests/ui/byte_addressable_buffer/arr.rs index 798c3cd515..b9396ffb85 100644 --- a/tests/ui/byte_addressable_buffer/arr.rs +++ b/tests/ui/byte_addressable_buffer/arr.rs @@ -1,7 +1,7 @@ // build-pass use spirv_std::spirv; -use spirv_std::{glam::Vec4, ByteAddressableBuffer}; +use spirv_std::{ByteAddressableBuffer, glam::Vec4}; #[spirv(fragment)] pub fn load( diff --git a/tests/ui/byte_addressable_buffer/big_struct.rs b/tests/ui/byte_addressable_buffer/big_struct.rs index 233cb87fae..5ffe96c097 100644 --- a/tests/ui/byte_addressable_buffer/big_struct.rs +++ b/tests/ui/byte_addressable_buffer/big_struct.rs @@ -1,7 +1,7 @@ // build-pass -use spirv_std::spirv; use spirv_std::ByteAddressableBuffer; +use spirv_std::spirv; pub struct BigStruct { a: u32, diff --git a/tests/ui/byte_addressable_buffer/complex.rs b/tests/ui/byte_addressable_buffer/complex.rs index b9e3edf128..1932755415 100644 --- a/tests/ui/byte_addressable_buffer/complex.rs +++ b/tests/ui/byte_addressable_buffer/complex.rs @@ -1,7 +1,7 @@ // build-pass use spirv_std::spirv; -use spirv_std::{glam::Vec2, ByteAddressableBuffer}; +use spirv_std::{ByteAddressableBuffer, glam::Vec2}; pub struct Complex { x: u32, diff --git a/tests/ui/byte_addressable_buffer/empty_struct.rs b/tests/ui/byte_addressable_buffer/empty_struct.rs index 1425526112..e8afc34c4c 100644 --- a/tests/ui/byte_addressable_buffer/empty_struct.rs +++ b/tests/ui/byte_addressable_buffer/empty_struct.rs @@ -1,7 +1,7 @@ // build-pass -use spirv_std::spirv; use spirv_std::ByteAddressableBuffer; +use spirv_std::spirv; pub struct EmptyStruct {} diff --git a/tests/ui/byte_addressable_buffer/f32.rs b/tests/ui/byte_addressable_buffer/f32.rs index 2b82f89d16..602016a10d 100644 --- a/tests/ui/byte_addressable_buffer/f32.rs +++ b/tests/ui/byte_addressable_buffer/f32.rs @@ -1,7 +1,7 @@ // build-pass -use spirv_std::spirv; use spirv_std::ByteAddressableBuffer; +use spirv_std::spirv; #[spirv(fragment)] pub fn load(#[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buf: &[u32], out: &mut f32) { diff --git a/tests/ui/byte_addressable_buffer/small_struct.rs b/tests/ui/byte_addressable_buffer/small_struct.rs index 948af2dd92..2fb315ac13 100644 --- a/tests/ui/byte_addressable_buffer/small_struct.rs +++ b/tests/ui/byte_addressable_buffer/small_struct.rs @@ -1,7 +1,7 @@ // build-pass -use spirv_std::spirv; use spirv_std::ByteAddressableBuffer; +use spirv_std::spirv; pub struct SmallStruct { a: u32, diff --git a/tests/ui/byte_addressable_buffer/u32.rs b/tests/ui/byte_addressable_buffer/u32.rs index d0e1e44624..0b4b709608 100644 --- a/tests/ui/byte_addressable_buffer/u32.rs +++ b/tests/ui/byte_addressable_buffer/u32.rs @@ -1,7 +1,7 @@ // build-pass -use spirv_std::spirv; use spirv_std::ByteAddressableBuffer; +use spirv_std::spirv; #[spirv(fragment)] pub fn load(#[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buf: &[u32], out: &mut u32) { diff --git a/tests/ui/byte_addressable_buffer/vec.rs b/tests/ui/byte_addressable_buffer/vec.rs index e934071b12..2f3342aa0b 100644 --- a/tests/ui/byte_addressable_buffer/vec.rs +++ b/tests/ui/byte_addressable_buffer/vec.rs @@ -1,7 +1,7 @@ // build-pass use spirv_std::spirv; -use spirv_std::{glam::Vec4, ByteAddressableBuffer}; +use spirv_std::{ByteAddressableBuffer, glam::Vec4}; #[spirv(matrix)] pub struct Mat4 { diff --git a/tests/ui/dis/issue-1062.stderr b/tests/ui/dis/issue-1062.stderr index 3a056d9326..e62cf988bf 100644 --- a/tests/ui/dis/issue-1062.stderr +++ b/tests/ui/dis/issue-1062.stderr @@ -4,7 +4,7 @@ OpLine %5 11 12 %6 = OpLoad %7 %8 OpLine %5 11 35 %9 = OpLoad %7 %10 -OpLine %11 1145 4 +OpLine %11 1199 4 %12 = OpBitwiseAnd %7 %9 %13 %14 = OpISub %7 %15 %12 %16 = OpShiftLeftLogical %7 %6 %12 diff --git a/tests/ui/dis/panic_builtin_bounds_check.stderr b/tests/ui/dis/panic_builtin_bounds_check.stderr index f1a394f28f..e1c8f3b28c 100644 --- a/tests/ui/dis/panic_builtin_bounds_check.stderr +++ b/tests/ui/dis/panic_builtin_bounds_check.stderr @@ -10,27 +10,27 @@ OpExtension "SPV_KHR_shader_clock" OpMemoryModel Logical Simple OpEntryPoint Fragment %2 "main" OpExecutionMode %2 OriginUpperLeft -%3 = OpString "/n[Rust panicked at $SYSROOT/lib/rustlib/src/rust/library/core/src/panicking.rs:275:5]/n index out of bounds: the len is %u but the index is %u/n in main()/n" -%4 = OpString $SYSROOT/lib/rustlib/src/rust/library/core/src/panicking.rs" -%5 = OpString "$DIR/panic_builtin_bounds_check.rs" -%6 = OpTypeVoid -%7 = OpTypeFunction %6 -%8 = OpTypeBool -%9 = OpTypeInt 32 0 -%10 = OpConstant %9 5 -%11 = OpConstant %9 4 -%2 = OpFunction %6 None %7 +%3 = OpString "/n[Rust panicked at $DIR/panic_builtin_bounds_check.rs:25:5]/n index out of bounds: the len is %u but the index is %u/n in main()/n" +%4 = OpString "$DIR/panic_builtin_bounds_check.rs" +%5 = OpTypeVoid +%6 = OpTypeFunction %5 +%7 = OpTypeBool +%8 = OpTypeInt 32 0 +%9 = OpConstant %8 5 +%10 = OpConstant %8 4 +%11 = OpUndef %8 +%2 = OpFunction %5 None %6 %12 = OpLabel -OpLine %5 25 4 -%13 = OpULessThan %8 %10 %11 +OpLine %4 25 4 +%13 = OpULessThan %7 %9 %10 OpNoLine OpSelectionMerge %14 None OpBranchConditional %13 %15 %16 %15 = OpLabel OpBranch %14 %16 = OpLabel -OpLine %4 275 4 -%17 = OpExtInst %6 %1 1 %3 %11 %10 +OpLine %4 25 4 +%17 = OpExtInst %5 %1 1 %3 %11 %9 OpNoLine OpReturn %14 = OpLabel diff --git a/tests/ui/dis/ptr_copy.normal.stderr b/tests/ui/dis/ptr_copy.normal.stderr index 9dacf13e91..e376de2e58 100644 --- a/tests/ui/dis/ptr_copy.normal.stderr +++ b/tests/ui/dis/ptr_copy.normal.stderr @@ -1,13 +1,13 @@ error: cannot memcpy dynamically sized data - --> $CORE_SRC/intrinsics.rs:3076:9 + --> $CORE_SRC/intrinsics/mod.rs:4158:9 | -3076 | copy(src, dst, count) +4158 | copy(src, dst, count) | ^^^^^^^^^^^^^^^^^^^^^ | note: used from within `core::intrinsics::copy::` - --> $CORE_SRC/intrinsics.rs:3055:21 + --> $CORE_SRC/intrinsics/mod.rs:4134:21 | -3055 | pub const unsafe fn copy(src: *const T, dst: *mut T, count: usize) { +4134 | pub const unsafe fn copy(src: *const T, dst: *mut T, count: usize) { | ^^^^ note: called by `ptr_copy::copy_via_raw_ptr` --> $DIR/ptr_copy.rs:28:18 @@ -28,27 +28,27 @@ note: called by `main` error: cannot cast between pointer types from `*f32` to `*struct () { }` - --> $CORE_SRC/intrinsics.rs:3064:9 + --> $CORE_SRC/intrinsics/mod.rs:4146:9 | -3064 | / ub_checks::assert_unsafe_precondition!( -3065 | | check_language_ub, -3066 | | "ptr::copy_nonoverlapping requires that both pointer arguments are aligned and non-null / -3067 | | and the specified memory ranges do not overlap", +4146 | / ub_checks::assert_unsafe_precondition!( +4147 | | check_language_ub, +4148 | | "ptr::copy requires that both pointer arguments are aligned and non-null", +4149 | | ( ... | -3074 | | && ub_checks::is_aligned_and_not_null(dst, align) -3075 | | ); +4156 | | && ub_checks::maybe_is_aligned_and_not_null(dst, align, zero_size) +4157 | | ); | |_________^ | note: used from within `core::intrinsics::copy::` - --> $CORE_SRC/intrinsics.rs:3064:9 + --> $CORE_SRC/intrinsics/mod.rs:4146:9 | -3064 | / ub_checks::assert_unsafe_precondition!( -3065 | | check_language_ub, -3066 | | "ptr::copy_nonoverlapping requires that both pointer arguments are aligned and non-null / -3067 | | and the specified memory ranges do not overlap", +4146 | / ub_checks::assert_unsafe_precondition!( +4147 | | check_language_ub, +4148 | | "ptr::copy requires that both pointer arguments are aligned and non-null", +4149 | | ( ... | -3074 | | && ub_checks::is_aligned_and_not_null(dst, align) -3075 | | ); +4156 | | && ub_checks::maybe_is_aligned_and_not_null(dst, align, zero_size) +4157 | | ); | |_________^ note: called by `ptr_copy::copy_via_raw_ptr` --> $DIR/ptr_copy.rs:28:18 diff --git a/tests/ui/dis/ptr_read.stderr b/tests/ui/dis/ptr_read.stderr index 24e9eb7fc8..ee8fd2aab4 100644 --- a/tests/ui/dis/ptr_read.stderr +++ b/tests/ui/dis/ptr_read.stderr @@ -2,7 +2,7 @@ %4 = OpFunctionParameter %5 %6 = OpFunctionParameter %5 %7 = OpLabel -OpLine %8 1297 8 +OpLine %8 1374 8 %9 = OpLoad %10 %4 OpLine %11 7 13 OpStore %6 %9 diff --git a/tests/ui/dis/ptr_read_method.stderr b/tests/ui/dis/ptr_read_method.stderr index 24e9eb7fc8..ee8fd2aab4 100644 --- a/tests/ui/dis/ptr_read_method.stderr +++ b/tests/ui/dis/ptr_read_method.stderr @@ -2,7 +2,7 @@ %4 = OpFunctionParameter %5 %6 = OpFunctionParameter %5 %7 = OpLabel -OpLine %8 1297 8 +OpLine %8 1374 8 %9 = OpLoad %10 %4 OpLine %11 7 13 OpStore %6 %9 diff --git a/tests/ui/dis/ptr_write.stderr b/tests/ui/dis/ptr_write.stderr index cdeee70f1f..2ca3b239fc 100644 --- a/tests/ui/dis/ptr_write.stderr +++ b/tests/ui/dis/ptr_write.stderr @@ -4,7 +4,7 @@ %7 = OpLabel OpLine %8 7 35 %9 = OpLoad %10 %4 -OpLine %11 1506 8 +OpLine %11 1578 8 OpStore %6 %9 OpNoLine OpReturn diff --git a/tests/ui/dis/ptr_write_method.stderr b/tests/ui/dis/ptr_write_method.stderr index 2aa446920a..5ff386ef8c 100644 --- a/tests/ui/dis/ptr_write_method.stderr +++ b/tests/ui/dis/ptr_write_method.stderr @@ -4,7 +4,7 @@ %7 = OpLabel OpLine %8 7 37 %9 = OpLoad %10 %4 -OpLine %11 1506 8 +OpLine %11 1578 8 OpStore %6 %9 OpNoLine OpReturn diff --git a/tests/ui/image/components.rs b/tests/ui/image/components.rs index f63c7ea0c7..34e010fbcd 100644 --- a/tests/ui/image/components.rs +++ b/tests/ui/image/components.rs @@ -3,7 +3,7 @@ use glam::{Vec2, Vec3, Vec4}; use spirv_std::spirv; -use spirv_std::{arch, Image}; +use spirv_std::{Image, arch}; #[spirv(fragment)] pub fn main( diff --git a/tests/ui/image/fetch.rs b/tests/ui/image/fetch.rs index c21cfadb9c..674c3400bb 100644 --- a/tests/ui/image/fetch.rs +++ b/tests/ui/image/fetch.rs @@ -1,7 +1,7 @@ // build-pass use spirv_std::spirv; -use spirv_std::{arch, Image}; +use spirv_std::{Image, arch}; #[spirv(fragment)] pub fn main( diff --git a/tests/ui/image/format.rs b/tests/ui/image/format.rs index 5b4232b172..e9f2386c10 100644 --- a/tests/ui/image/format.rs +++ b/tests/ui/image/format.rs @@ -1,7 +1,7 @@ // build-pass use spirv_std::spirv; -use spirv_std::{arch, Image}; +use spirv_std::{Image, arch}; #[spirv(fragment)] pub fn main( diff --git a/tests/ui/image/gather.rs b/tests/ui/image/gather.rs index 9e11f440e9..d4a555193b 100644 --- a/tests/ui/image/gather.rs +++ b/tests/ui/image/gather.rs @@ -3,7 +3,7 @@ use core::arch::asm; use spirv_std::spirv; -use spirv_std::{arch, Image, Sampler}; +use spirv_std::{Image, Sampler, arch}; #[spirv(fragment)] pub fn main( diff --git a/tests/ui/image/gather_err.rs b/tests/ui/image/gather_err.rs index 917b447327..e44da14565 100644 --- a/tests/ui/image/gather_err.rs +++ b/tests/ui/image/gather_err.rs @@ -2,7 +2,7 @@ // normalize-stderr-test "\S*/crates/spirv-std/src/" -> "$$SPIRV_STD_SRC/" // compile-flags: -Ctarget-feature=+Sampled1D -use spirv_std::{arch, spirv, Image, Sampler}; +use spirv_std::{Image, Sampler, arch, spirv}; #[spirv(fragment)] pub fn main( diff --git a/tests/ui/image/image_with.rs b/tests/ui/image/image_with.rs index 461503b194..90d8d62b2f 100644 --- a/tests/ui/image/image_with.rs +++ b/tests/ui/image/image_with.rs @@ -1,7 +1,7 @@ // build-pass use spirv_std::spirv; -use spirv_std::{arch, image::sample_with, image::ImageWithMethods, Image, Sampler}; +use spirv_std::{Image, Sampler, arch, image::ImageWithMethods, image::sample_with}; #[spirv(fragment)] pub fn main( diff --git a/tests/ui/image/implicit_not_in_fragment.rs b/tests/ui/image/implicit_not_in_fragment.rs index c4d78bcebe..1daee18713 100644 --- a/tests/ui/image/implicit_not_in_fragment.rs +++ b/tests/ui/image/implicit_not_in_fragment.rs @@ -1,7 +1,7 @@ // build-fail use spirv_std::spirv; -use spirv_std::{arch, Image, Sampler}; +use spirv_std::{Image, Sampler, arch}; fn deeper_stack(image2d: &Image!(2D, type=f32, sampled), sampler: &Sampler) -> glam::Vec4 { let v2 = glam::Vec2::new(0.0, 1.0); diff --git a/tests/ui/image/issue-330.rs b/tests/ui/image/issue-330.rs index 5d60ac88c7..37130eac4f 100644 --- a/tests/ui/image/issue-330.rs +++ b/tests/ui/image/issue-330.rs @@ -1,6 +1,6 @@ use spirv_std::glam::Vec4; use spirv_std::spirv; -use spirv_std::{image::Image2dArray, Sampler}; +use spirv_std::{Sampler, image::Image2dArray}; #[spirv(fragment)] pub fn ps_main_stereo( diff --git a/tests/ui/image/query/query_levels.rs b/tests/ui/image/query/query_levels.rs index 79f51bd7a5..061dc4bacc 100644 --- a/tests/ui/image/query/query_levels.rs +++ b/tests/ui/image/query/query_levels.rs @@ -2,7 +2,7 @@ // compile-flags: -C target-feature=+ImageQuery use spirv_std::spirv; -use spirv_std::{arch, Image}; +use spirv_std::{Image, arch}; #[spirv(fragment)] pub fn main( diff --git a/tests/ui/image/query/query_levels_err.rs b/tests/ui/image/query/query_levels_err.rs index c22c7ea9d5..1fa5581a41 100644 --- a/tests/ui/image/query/query_levels_err.rs +++ b/tests/ui/image/query/query_levels_err.rs @@ -2,7 +2,7 @@ // normalize-stderr-test "\S*/crates/spirv-std/src/" -> "$$SPIRV_STD_SRC/" // compile-flags: -C target-feature=+ImageQuery -use spirv_std::{arch, spirv, Image}; +use spirv_std::{Image, arch, spirv}; #[spirv(fragment)] pub fn main( diff --git a/tests/ui/image/query/query_lod.rs b/tests/ui/image/query/query_lod.rs index a36e835ecc..4d764d0514 100644 --- a/tests/ui/image/query/query_lod.rs +++ b/tests/ui/image/query/query_lod.rs @@ -2,7 +2,7 @@ // compile-flags: -C target-feature=+ImageQuery use spirv_std::spirv; -use spirv_std::{arch, Image, Sampler}; +use spirv_std::{Image, Sampler, arch}; #[spirv(fragment)] pub fn main( diff --git a/tests/ui/image/query/query_lod_err.rs b/tests/ui/image/query/query_lod_err.rs index f07564c990..74e86972f1 100644 --- a/tests/ui/image/query/query_lod_err.rs +++ b/tests/ui/image/query/query_lod_err.rs @@ -2,7 +2,7 @@ // normalize-stderr-test "\S*/crates/spirv-std/src/" -> "$$SPIRV_STD_SRC/" // compile-flags: -C target-feature=+ImageQuery -use spirv_std::{arch, spirv, Image, Sampler}; +use spirv_std::{Image, Sampler, arch, spirv}; #[spirv(fragment)] pub fn main( diff --git a/tests/ui/image/query/query_samples.rs b/tests/ui/image/query/query_samples.rs index eeeb1e15cf..fb5db92ded 100644 --- a/tests/ui/image/query/query_samples.rs +++ b/tests/ui/image/query/query_samples.rs @@ -2,7 +2,7 @@ // compile-flags: -C target-feature=+ImageQuery use spirv_std::spirv; -use spirv_std::{arch, Image}; +use spirv_std::{Image, arch}; #[spirv(fragment)] pub fn main( diff --git a/tests/ui/image/query/query_size.rs b/tests/ui/image/query/query_size.rs index af2a71994c..ba2b12afa4 100644 --- a/tests/ui/image/query/query_size.rs +++ b/tests/ui/image/query/query_size.rs @@ -2,7 +2,7 @@ // compile-flags: -C target-feature=+ImageQuery use spirv_std::spirv; -use spirv_std::{arch, Image}; +use spirv_std::{Image, arch}; #[spirv(fragment)] pub fn main( diff --git a/tests/ui/image/query/query_size_err.rs b/tests/ui/image/query/query_size_err.rs index afc59a467b..c526f3bd6b 100644 --- a/tests/ui/image/query/query_size_err.rs +++ b/tests/ui/image/query/query_size_err.rs @@ -2,7 +2,7 @@ // normalize-stderr-test "\S*/crates/spirv-std/src/" -> "$$SPIRV_STD_SRC/" // compile-flags: -C target-feature=+ImageQuery -use spirv_std::{arch, spirv, Image}; +use spirv_std::{Image, arch, spirv}; #[spirv(fragment)] pub fn main( diff --git a/tests/ui/image/query/query_size_lod.rs b/tests/ui/image/query/query_size_lod.rs index c80c0ca216..dd6c7f1855 100644 --- a/tests/ui/image/query/query_size_lod.rs +++ b/tests/ui/image/query/query_size_lod.rs @@ -2,7 +2,7 @@ // compile-flags: -C target-feature=+ImageQuery use spirv_std::spirv; -use spirv_std::{arch, Image}; +use spirv_std::{Image, arch}; #[spirv(fragment)] pub fn main( diff --git a/tests/ui/image/query/query_size_lod_err.rs b/tests/ui/image/query/query_size_lod_err.rs index c106689f6c..8b2e9e8ff1 100644 --- a/tests/ui/image/query/query_size_lod_err.rs +++ b/tests/ui/image/query/query_size_lod_err.rs @@ -2,7 +2,7 @@ // normalize-stderr-test "\S*/crates/spirv-std/src/" -> "$$SPIRV_STD_SRC/" // compile-flags: -C target-feature=+ImageQuery -use spirv_std::{arch, spirv, Image}; +use spirv_std::{Image, arch, spirv}; #[spirv(fragment)] pub fn main( diff --git a/tests/ui/image/read.rs b/tests/ui/image/read.rs index 295708b873..0c1fb23ba3 100644 --- a/tests/ui/image/read.rs +++ b/tests/ui/image/read.rs @@ -3,7 +3,7 @@ // compile-flags: -C target-feature=+StorageImageReadWithoutFormat use spirv_std::spirv; -use spirv_std::{arch, Image}; +use spirv_std::{Image, arch}; #[spirv(fragment)] pub fn main( diff --git a/tests/ui/image/read_subpass.rs b/tests/ui/image/read_subpass.rs index 475233698b..1dd84965d0 100644 --- a/tests/ui/image/read_subpass.rs +++ b/tests/ui/image/read_subpass.rs @@ -2,7 +2,7 @@ // compile-flags: -C target-feature=+InputAttachment use spirv_std::spirv; -use spirv_std::{arch, Image}; +use spirv_std::{Image, arch}; #[spirv(fragment)] pub fn main( diff --git a/tests/ui/image/sample.rs b/tests/ui/image/sample.rs index bc5cc44757..e480828900 100644 --- a/tests/ui/image/sample.rs +++ b/tests/ui/image/sample.rs @@ -2,7 +2,7 @@ // build-pass use spirv_std::spirv; -use spirv_std::{arch, Image, Sampler}; +use spirv_std::{Image, Sampler, arch}; #[spirv(fragment)] pub fn main( diff --git a/tests/ui/image/sample_bias.rs b/tests/ui/image/sample_bias.rs index 09d3bfa9a7..4aace83047 100644 --- a/tests/ui/image/sample_bias.rs +++ b/tests/ui/image/sample_bias.rs @@ -2,7 +2,7 @@ // build-pass use spirv_std::spirv; -use spirv_std::{arch, Image, Sampler}; +use spirv_std::{Image, Sampler, arch}; #[spirv(fragment)] pub fn main( diff --git a/tests/ui/image/sample_depth_reference/sample.rs b/tests/ui/image/sample_depth_reference/sample.rs index 4de6b2c311..f0a379b254 100644 --- a/tests/ui/image/sample_depth_reference/sample.rs +++ b/tests/ui/image/sample_depth_reference/sample.rs @@ -2,7 +2,7 @@ // build-pass use spirv_std::spirv; -use spirv_std::{arch, Image, Sampler}; +use spirv_std::{Image, Sampler, arch}; #[spirv(fragment)] pub fn main( diff --git a/tests/ui/image/sample_depth_reference_with_project_coordinate/sample.rs b/tests/ui/image/sample_depth_reference_with_project_coordinate/sample.rs index e0d9987440..b846e8b5f3 100644 --- a/tests/ui/image/sample_depth_reference_with_project_coordinate/sample.rs +++ b/tests/ui/image/sample_depth_reference_with_project_coordinate/sample.rs @@ -2,7 +2,7 @@ // build-pass use spirv_std::spirv; -use spirv_std::{arch, Image, Sampler}; +use spirv_std::{Image, Sampler, arch}; #[spirv(fragment)] pub fn main( diff --git a/tests/ui/image/sample_gradient.rs b/tests/ui/image/sample_gradient.rs index a8336c5838..ca2930276e 100644 --- a/tests/ui/image/sample_gradient.rs +++ b/tests/ui/image/sample_gradient.rs @@ -2,7 +2,7 @@ // build-pass use spirv_std::spirv; -use spirv_std::{arch, Image, Sampler}; +use spirv_std::{Image, Sampler, arch}; #[spirv(fragment)] pub fn main( diff --git a/tests/ui/image/sample_lod.rs b/tests/ui/image/sample_lod.rs index 0280bd3faa..7d4a628514 100644 --- a/tests/ui/image/sample_lod.rs +++ b/tests/ui/image/sample_lod.rs @@ -2,7 +2,7 @@ // build-pass use spirv_std::spirv; -use spirv_std::{arch, image::SampledImage, Image, Sampler}; +use spirv_std::{Image, Sampler, arch, image::SampledImage}; #[spirv(fragment)] pub fn main( diff --git a/tests/ui/image/sample_with_project_coordinate/sample_gradient.rs b/tests/ui/image/sample_with_project_coordinate/sample_gradient.rs index 7d39d801de..73ce1eb6ee 100644 --- a/tests/ui/image/sample_with_project_coordinate/sample_gradient.rs +++ b/tests/ui/image/sample_with_project_coordinate/sample_gradient.rs @@ -2,7 +2,7 @@ // build-pass use spirv_std::spirv; -use spirv_std::{arch, Image, Sampler}; +use spirv_std::{Image, Sampler, arch}; #[spirv(fragment)] pub fn main( diff --git a/tests/ui/image/sample_with_project_coordinate/sample_lod.rs b/tests/ui/image/sample_with_project_coordinate/sample_lod.rs index aa4245c7e0..99361164d4 100644 --- a/tests/ui/image/sample_with_project_coordinate/sample_lod.rs +++ b/tests/ui/image/sample_with_project_coordinate/sample_lod.rs @@ -2,7 +2,7 @@ // build-pass use spirv_std::spirv; -use spirv_std::{arch, Image, Sampler}; +use spirv_std::{Image, Sampler, arch}; #[spirv(fragment)] pub fn main( diff --git a/tests/ui/image/write.rs b/tests/ui/image/write.rs index 314f0f4ba4..34dfae1350 100644 --- a/tests/ui/image/write.rs +++ b/tests/ui/image/write.rs @@ -3,7 +3,7 @@ // compile-flags: -C target-feature=+StorageImageWriteWithoutFormat use spirv_std::spirv; -use spirv_std::{arch, Image}; +use spirv_std::{Image, arch}; #[spirv(fragment)] pub fn main( diff --git a/tests/ui/lang/core/unwrap_or.stderr b/tests/ui/lang/core/unwrap_or.stderr index 0b39d5b926..7f46d10973 100644 --- a/tests/ui/lang/core/unwrap_or.stderr +++ b/tests/ui/lang/core/unwrap_or.stderr @@ -3,9 +3,9 @@ OpLine %5 13 11 %6 = OpCompositeInsert %7 %8 %9 0 %10 = OpCompositeExtract %11 %6 1 -OpLine %12 953 14 +OpLine %12 993 14 %13 = OpBitcast %14 %8 -OpLine %12 953 8 +OpLine %12 993 8 %15 = OpIEqual %16 %13 %17 OpNoLine OpSelectionMerge %18 None diff --git a/tests/ui/spirv-attr/bad-deduce-storage-class.rs b/tests/ui/spirv-attr/bad-deduce-storage-class.rs index 91c19b63fd..ef1a523ecf 100644 --- a/tests/ui/spirv-attr/bad-deduce-storage-class.rs +++ b/tests/ui/spirv-attr/bad-deduce-storage-class.rs @@ -1,7 +1,7 @@ // Tests that storage class deduction (from entry-point signature) fails correctly // build-fail -use spirv_std::{spirv, Image}; +use spirv_std::{Image, spirv}; #[spirv(vertex)] pub fn main( diff --git a/tests/ui/storage_class/runtime_descriptor_array_error.rs b/tests/ui/storage_class/runtime_descriptor_array_error.rs index 24fcd044ec..5ccefec3de 100644 --- a/tests/ui/storage_class/runtime_descriptor_array_error.rs +++ b/tests/ui/storage_class/runtime_descriptor_array_error.rs @@ -1,6 +1,6 @@ // build-fail -use spirv_std::{spirv, Image, RuntimeArray}; +use spirv_std::{Image, RuntimeArray, spirv}; #[spirv(fragment)] pub fn main( diff --git a/tests/ui/storage_class/typed_buffer.rs b/tests/ui/storage_class/typed_buffer.rs index 3820ca95d5..f9f74bd3bd 100644 --- a/tests/ui/storage_class/typed_buffer.rs +++ b/tests/ui/storage_class/typed_buffer.rs @@ -1,8 +1,8 @@ // build-pass use glam::Vec4; -use spirv_std::spirv; use spirv_std::TypedBuffer; +use spirv_std::spirv; #[spirv(fragment)] pub fn main( diff --git a/tests/ui/storage_class/typed_buffer_slice.rs b/tests/ui/storage_class/typed_buffer_slice.rs index 079553bec8..b5bb2b84d9 100644 --- a/tests/ui/storage_class/typed_buffer_slice.rs +++ b/tests/ui/storage_class/typed_buffer_slice.rs @@ -1,8 +1,8 @@ // build-pass use glam::Vec4; -use spirv_std::spirv; use spirv_std::TypedBuffer; +use spirv_std::spirv; #[spirv(fragment)] pub fn main(