Skip to main content

rustc_codegen_spirv_types/
target.rs

1use std::fmt::{Debug, Formatter};
2use thiserror::Error;
3
4pub const SPIRV_ARCH: &str = "spirv";
5pub const SPIRV_TARGET_PREFIX: &str = "spirv-unknown-";
6
7/// A well-formed rust-gpu target.
8///
9/// The constructors only check whether the target is well-formed, not whether it is valid. Since `spirv-builder` is
10/// backwards compatible with older rust-gpu compilers, only the compiler itself knows what targets it can and cannot
11/// support. This also allows adding new targets to the compiler without having to update `spirv-builder` and
12/// `cargo-gpu`.
13///
14/// Differentiates between a full target (e.g. `spirv-unknown-vulkan1.3`) and a target env (e.g. `vulkan1.3`). Use
15/// [`Self::parse_target`] and [`Self::target`] to parse or format a full target, or use [`Self::parse_env`] and
16/// [`Self::env`] when dealing with just target envs. The convenience function [`Self::parse`] accepts both targets and
17/// target envs. Does not implement `Display`, since it is unclear whether the user wants a target or target env, though
18/// a `Debug` implementation is provided.
19#[derive(Clone)]
20pub struct SpirvTarget {
21    target: String,
22}
23
24impl SpirvTarget {
25    /// Try to parse either a full target or a target env
26    pub fn parse(target_or_env: &str) -> Result<Self, TargetError> {
27        Self::parse_target(target_or_env).or_else(|_| Self::parse_env(target_or_env))
28    }
29
30    /// Parse a full target, e.g. `spirv-unknown-vulkan1.3`
31    pub fn parse_target(target: &str) -> Result<Self, TargetError> {
32        let _target_env = target.strip_prefix(SPIRV_TARGET_PREFIX).ok_or_else(|| {
33            TargetError::NonSpirvTarget {
34                target: target.to_string(),
35            }
36        })?;
37        Ok(Self {
38            target: target.to_string(),
39        })
40    }
41
42    /// Parse a target env, e.g. `vulkan1.3`
43    pub fn parse_env(target_env: &str) -> Result<Self, TargetError> {
44        Ok(Self {
45            target: format!("{SPIRV_TARGET_PREFIX}{target_env}"),
46        })
47    }
48
49    /// returns the full target, e.g. `spirv-unknown-vulkan1.3`
50    pub fn target(&self) -> &str {
51        &self.target
52    }
53
54    /// returns the target env, e.g. `vulkan1.3`
55    pub fn env(&self) -> &str {
56        &self.target[SPIRV_TARGET_PREFIX.len()..]
57    }
58}
59
60impl Debug for SpirvTarget {
61    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
62        f.debug_tuple("Target").field(&self.target).finish()
63    }
64}
65
66#[derive(Debug, Error)]
67#[non_exhaustive]
68pub enum TargetError {
69    #[error("SPIR-V target must start with `{SPIRV_TARGET_PREFIX}...`, was `{target}`")]
70    NonSpirvTarget { target: String },
71}