diff --git a/bootstrap.example.toml b/bootstrap.example.toml index e0cbb0c0e747c..c8be474fb18a5 100644 --- a/bootstrap.example.toml +++ b/bootstrap.example.toml @@ -126,7 +126,7 @@ # the resulting rustc being unable to compile for the disabled architectures. # # To add support for new targets, see https://rustc-dev-guide.rust-lang.org/building/new-target.html. -#llvm.targets = "AArch64;AMDGPU;ARM;BPF;Hexagon;LoongArch;MSP430;Mips;NVPTX;PowerPC;RISCV;Sparc;SystemZ;WebAssembly;X86" +#llvm.targets = "AArch64;AMDGPU;ARM;BPF;Hexagon;LoongArch;MSP430;Mips;NVPTX;PowerPC;RISCV;Sparc;SPIRV;SystemZ;WebAssembly;X86" # LLVM experimental targets to build support for. These targets are specified in # the same format as above, but since these targets are experimental, they are diff --git a/compiler/rustc_llvm/build.rs b/compiler/rustc_llvm/build.rs index c58dd64cca5f7..769d9483a0c9a 100644 --- a/compiler/rustc_llvm/build.rs +++ b/compiler/rustc_llvm/build.rs @@ -15,6 +15,7 @@ const OPTIONAL_COMPONENTS: &[&str] = &[ "csky", "mips", "powerpc", + "spirv", "systemz", "webassembly", "msp430", diff --git a/compiler/rustc_llvm/src/lib.rs b/compiler/rustc_llvm/src/lib.rs index a565e1feeb5e5..96fc826f1df00 100644 --- a/compiler/rustc_llvm/src/lib.rs +++ b/compiler/rustc_llvm/src/lib.rs @@ -167,6 +167,13 @@ pub fn initialize_available_targets() { LLVMInitializePowerPCAsmPrinter, LLVMInitializePowerPCAsmParser ); + init_target!( + llvm_component = "spirv", + LLVMInitializeSPIRVTargetInfo, + LLVMInitializeSPIRVTarget, + LLVMInitializeSPIRVTargetMC, + LLVMInitializeSPIRVAsmPrinter + ); init_target!( llvm_component = "systemz", LLVMInitializeSystemZTargetInfo, diff --git a/compiler/rustc_target/src/callconv/mod.rs b/compiler/rustc_target/src/callconv/mod.rs index 092d99e911188..c8c3d0580c8ec 100644 --- a/compiler/rustc_target/src/callconv/mod.rs +++ b/compiler/rustc_target/src/callconv/mod.rs @@ -28,6 +28,7 @@ mod riscv; mod s390x; mod sparc; mod sparc64; +mod spirv; mod wasm; mod x86; mod x86_64; @@ -703,7 +704,8 @@ impl<'a, Ty> FnAbi<'a, Ty> { Arch::RiscV32 | Arch::RiscV64 => riscv::compute_abi_info(cx, self), Arch::Wasm32 | Arch::Wasm64 => wasm::compute_abi_info(cx, self), Arch::Bpf => bpf::compute_abi_info(cx, self), - arch @ (Arch::PowerPC64LE | Arch::SpirV | Arch::Other(_)) => { + Arch::SpirV => spirv::compute_abi_info(cx, self), + arch @ (Arch::PowerPC64LE | Arch::Other(_)) => { panic!("no lowering implemented for {arch}") } } diff --git a/compiler/rustc_target/src/callconv/spirv.rs b/compiler/rustc_target/src/callconv/spirv.rs new file mode 100644 index 0000000000000..98ab3ce8eb746 --- /dev/null +++ b/compiler/rustc_target/src/callconv/spirv.rs @@ -0,0 +1,40 @@ +use rustc_abi::{HasDataLayout, TyAbiInterface}; + +use crate::callconv::{ArgAbi, FnAbi}; + +fn classify_ret<'a, Ty, C>(_cx: &C, ret: &mut ArgAbi<'a, Ty>) +where + Ty: TyAbiInterface<'a, C> + Copy, + C: HasDataLayout, +{ + ret.extend_integer_width_to(32); +} + +fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) +where + Ty: TyAbiInterface<'a, C> + Copy, + C: HasDataLayout, +{ + if arg.layout.pass_indirectly_in_non_rustic_abis(cx) { + arg.make_indirect(); + return; + } + arg.extend_integer_width_to(32); +} + +pub(crate) fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) +where + Ty: TyAbiInterface<'a, C> + Copy, + C: HasDataLayout, +{ + if !fn_abi.ret.is_ignore() { + classify_ret(cx, &mut fn_abi.ret); + } + + for arg in fn_abi.args.iter_mut() { + if arg.is_ignore() { + continue; + } + classify_arg(cx, arg); + } +} diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 89c9fdc935cc5..8923b835f30d3 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1715,6 +1715,8 @@ supported_targets! { ("amdgcn-amd-amdhsa", amdgcn_amd_amdhsa), + ("spirv-unknown-vulkan1.3", spirv_unknown_vulkan1_3), + ("xtensa-esp32-none-elf", xtensa_esp32_none_elf), ("xtensa-esp32-espidf", xtensa_esp32_espidf), ("xtensa-esp32s2-none-elf", xtensa_esp32s2_none_elf), @@ -1990,6 +1992,7 @@ crate::target_spec_enum! { VexOs = "vexos", VisionOs = "visionos", Vita = "vita", + Vulkan = "vulkan", VxWorks = "vxworks", Wasi = "wasi", WatchOs = "watchos", diff --git a/compiler/rustc_target/src/spec/targets/spirv_unknown_vulkan1_3.rs b/compiler/rustc_target/src/spec/targets/spirv_unknown_vulkan1_3.rs new file mode 100644 index 0000000000000..b657adca7cda1 --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/spirv_unknown_vulkan1_3.rs @@ -0,0 +1,37 @@ +use crate::spec::{ + Arch, LinkerFlavor, Os, PanicStrategy, Target, TargetMetadata, TargetOptions +}; + +pub(crate) fn target() -> Target { + Target { + llvm_target: "spirv-unknown-vulkan1.3".into(), + metadata: TargetMetadata { + description: Some("Vulkan 1.3".into()), + tier: Some(3), + host_tools: Some(false), + std: Some(false), + }, + pointer_width: 64, + data_layout: "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64-G10".into(), + arch: Arch::SpirV, + options: TargetOptions { + os: Os::Vulkan, + vendor: "unknown".into(), + linker_flavor: LinkerFlavor::Llbc, + max_atomic_width: Some(32), + panic_strategy: PanicStrategy::Abort, + // Allow `cdylib` crate type. + dynamic_linking: true, + obj_is_bitcode: true, + only_cdylib: true, + dll_prefix: "".into(), + dll_suffix: ".spvt".into(), + // The LLVM backend does not support stack canaries for this target + supports_stack_protector: false, + + // Static initializers must not have cycles on this target + static_initializer_must_be_acyclic: true, + ..Default::default() + }, + } +} diff --git a/library/compiler-builtins/compiler-builtins/build.rs b/library/compiler-builtins/compiler-builtins/build.rs index 6e1d230e3cd26..2f100a1d74dba 100644 --- a/library/compiler-builtins/compiler-builtins/build.rs +++ b/library/compiler-builtins/compiler-builtins/build.rs @@ -39,6 +39,7 @@ fn main() { || (target.triple.contains("sgx") && target.triple.contains("fortanix")) || target.triple.contains("-none") || target.triple.contains("nvptx") + || target.triple.contains("spirv") || target.triple.contains("uefi") || target.triple.contains("xous") { @@ -67,7 +68,7 @@ fn main() { // Don't use a C compiler for these targets: // // * nvptx - everything is bitcode, not compatible with mixed C/Rust - if !target.arch.contains("nvptx") { + if !target.arch.contains("nvptx") && !target.arch.contains("spirv") { #[cfg(feature = "c")] c::compile(&llvm_target, &target); } diff --git a/library/core/src/ffi/va_list.rs b/library/core/src/ffi/va_list.rs index d5166baf0c7ca..f676c68f1b341 100644 --- a/library/core/src/ffi/va_list.rs +++ b/library/core/src/ffi/va_list.rs @@ -275,6 +275,7 @@ impl<'f> Drop for VaList<'f> { // Checks (via an assert in `compiler/rustc_ty_utils/src/abi.rs`) that the C ABI for the current // target correctly implements `rustc_pass_indirectly_in_non_rustic_abis`. +#[cfg(not(target_arch = "spirv"))] const _: () = { #[repr(C)] #[rustc_pass_indirectly_in_non_rustic_abis] diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index c3935d9810e99..9bef6a34c539d 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -329,7 +329,7 @@ impl Step for Llvm { Some(s) => s, None => { "AArch64;AMDGPU;ARM;BPF;Hexagon;LoongArch;MSP430;Mips;NVPTX;PowerPC;RISCV;\ - Sparc;SystemZ;WebAssembly;X86" + Sparc;SPIRV;SystemZ;WebAssembly;X86" } }; diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs index b95533e112029..a836985945b5f 100644 --- a/src/bootstrap/src/core/builder/cargo.rs +++ b/src/bootstrap/src/core/builder/cargo.rs @@ -254,6 +254,10 @@ impl Cargo { fn configure_linker(&mut self, builder: &Builder<'_>) -> &mut Cargo { let target = self.target; let compiler = self.compiler; + + if target.contains("spirv") { + return self; + } // Dealing with rpath here is a little special, so let's go into some // detail. First off, `-rpath` is a linker option on Unix platforms diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs index 67f4eb37b2c11..912ff85d611dc 100644 --- a/src/bootstrap/src/core/sanity.rs +++ b/src/bootstrap/src/core/sanity.rs @@ -38,6 +38,7 @@ pub struct Finder { const STAGE0_MISSING_TARGETS: &[&str] = &[ // just a dummy comment so the list doesn't get onelined "riscv64im-unknown-none-elf", + "spirv-unknown-vulkan1.3", ]; /// Minimum version threshold for libstdc++ required when using prebuilt LLVM @@ -244,6 +245,10 @@ than building it. continue; } + if target.contains("spirv") { + continue; + } + // skip check for cross-targets if skip_target_sanity && target != &build.host_target { continue; @@ -352,7 +357,7 @@ than building it. } } - if (target.contains("-none-") || target.contains("nvptx")) + if (target.contains("-none-") || target.contains("nvptx") || target.contains("spirv")) && build.no_std(*target) == Some(false) { panic!("All the *-none-* and nvptx* targets are no-std targets") diff --git a/src/bootstrap/src/utils/cc_detect.rs b/src/bootstrap/src/utils/cc_detect.rs index 0662ae304ac06..a0b6cab254c92 100644 --- a/src/bootstrap/src/utils/cc_detect.rs +++ b/src/bootstrap/src/utils/cc_detect.rs @@ -105,6 +105,10 @@ pub fn fill_target_compiler(build: &mut Build, target: TargetSelection) { cfg.compiler(cc); } + if target.contains("spirv") { + return; + } + let compiler = cfg.get_compiler(); let ar = if let ar @ Some(..) = config.and_then(|c| c.ar.clone()) { ar diff --git a/src/bootstrap/src/utils/helpers.rs b/src/bootstrap/src/utils/helpers.rs index c670ae88fc549..8d76145935cac 100644 --- a/src/bootstrap/src/utils/helpers.rs +++ b/src/bootstrap/src/utils/helpers.rs @@ -219,6 +219,7 @@ pub fn use_host_linker(target: TargetSelection) -> bool { !(target.contains("emscripten") || target.contains("wasm32") || target.contains("nvptx") + || target.contains("spirv") || target.contains("fortanix") || target.contains("fuchsia") || target.contains("bpf") diff --git a/src/build_helper/src/targets.rs b/src/build_helper/src/targets.rs index cccc413368bc9..ed9037a56a7be 100644 --- a/src/build_helper/src/targets.rs +++ b/src/build_helper/src/targets.rs @@ -7,5 +7,6 @@ pub fn target_supports_std(target_tuple: &str) -> bool { !(target_tuple.contains("-none") || target_tuple.contains("nvptx") - || target_tuple.contains("switch")) + || target_tuple.contains("switch") + || target_tuple.contains("spirv")) } diff --git a/tests/assembly-llvm/targets/targets-spirv.rs b/tests/assembly-llvm/targets/targets-spirv.rs new file mode 100644 index 0000000000000..5704d790dbddd --- /dev/null +++ b/tests/assembly-llvm/targets/targets-spirv.rs @@ -0,0 +1,29 @@ +// @ add-minicore +//@ assembly-output: emit-asm +//@ revisions: spirv_unknown_vulkan1_3 +//@ [spirv_unknown_vulkan1_3] compile-flags: --target spirv-unknown-vulkan1.3 +//@ [spirv_unknown_vulkan1_3] needs-llvm-components: spirv + +// Sanity-check that each target can produce assembly code. + +#![feature(no_core, lang_items, never_type)] +#![no_std] +// #![no_core] +#![crate_type = "lib"] + +pub enum A { + Foo(u8), + Bar(u32), +} + +// extern crate minicore; +// use minicore::*; +#[unsafe(no_mangle)] +pub fn test(x: &mut A) -> u8 { + match x { + A::Foo(x) => *x, + A::Bar(b) => *b as u8 + 2, + } +} + +// CHECK: what