Skip to content

Commit a276ee9

Browse files
committed
target enum: make SpirvTargetEnv::parse_triple() return a Result
1 parent f5b0291 commit a276ee9

File tree

7 files changed

+53
-28
lines changed

7 files changed

+53
-28
lines changed

Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/rustc_codegen_spirv-target-specs/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ repository.workspace = true
1010
[features]
1111
include_str = []
1212
dir_path = []
13+
serde = ["dep:serde"]
1314

1415
[dependencies]
1516
strum = { version = "0.26.3", features = ["derive"] }
17+
thiserror = "2.0.12"
18+
serde = { version = "1.0", features = ["derive"], optional = true }

crates/rustc_codegen_spirv-target-specs/src/lib.rs

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
#![doc = include_str!("../README.md")]
22

3+
use core::str::FromStr;
4+
use std::fmt::{Debug, Display, Formatter};
35
use strum::{Display, EnumIter, EnumString, IntoStaticStr};
6+
use thiserror::Error;
47

58
/// directory with all the `target-specs` jsons for our codegen backend
69
#[cfg(feature = "dir_path")]
@@ -11,10 +14,12 @@ mod include_str;
1114

1215
pub const SPIRV_ARCH: &str = "spirv";
1316
pub const SPIRV_VENDOR: &str = "unknown";
17+
pub const SPIRV_TARGET_PREFIX: &str = "spirv-unknown-";
1418

15-
/// All target envs rust-gpu supports
19+
/// All target envs rust-gpu supports. The corresponding target tripple is `spirv-unknown-ENV` with `ENV` replaced by any of the values below.
1620
#[allow(non_camel_case_types, clippy::upper_case_acronyms)]
1721
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, EnumString, IntoStaticStr, EnumIter, Display)]
22+
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
1823
pub enum SpirvTargetEnv {
1924
#[strum(to_string = "opengl4.0")]
2025
OpenGL_4_0,
@@ -54,29 +59,46 @@ pub enum SpirvTargetEnv {
5459
Vulkan_1_4,
5560
}
5661

62+
#[derive(Error)]
63+
pub enum SpirvTargetParseError {
64+
#[error("Expected `rustc_codegen_spirv` target with prefix `{SPIRV_TARGET_PREFIX}`, got `{0}`")]
65+
WrongPrefix(String),
66+
#[error(
67+
"Target `{SPIRV_TARGET_PREFIX}{0}` not supported by `rustc_codegen_spirv`, see `enum SpirvTargetEnv` for possible env values"
68+
)]
69+
UnknownEnv(String),
70+
}
71+
72+
impl Debug for SpirvTargetParseError {
73+
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
74+
Display::fmt(self, f)
75+
}
76+
}
77+
5778
impl SpirvTargetEnv {
58-
pub fn parse_triple(target: &str) -> Option<Self> {
59-
target
60-
.strip_prefix(&format!("{SPIRV_ARCH}-{SPIRV_VENDOR}-"))
61-
.and_then(|env| TryFrom::try_from(env).ok())
79+
pub fn parse_triple(target: &str) -> Result<Self, SpirvTargetParseError> {
80+
let env = target
81+
.strip_prefix(SPIRV_TARGET_PREFIX)
82+
.ok_or_else(|| SpirvTargetParseError::WrongPrefix(target.to_string()))?;
83+
FromStr::from_str(env).map_err(|_| SpirvTargetParseError::UnknownEnv(env.to_string()))
6284
}
6385

6486
pub fn as_str(&self) -> &'static str {
6587
self.into()
6688
}
6789

6890
pub fn target_triple(&self) -> String {
69-
format!("{SPIRV_ARCH}-{SPIRV_VENDOR}-{}", self.as_str())
91+
format!("{SPIRV_TARGET_PREFIX}{}", self.as_str())
7092
}
7193

7294
pub fn target_json_file_name(&self) -> String {
73-
format!("{SPIRV_ARCH}-{SPIRV_VENDOR}-{}.json", self.as_str())
95+
format!("{SPIRV_TARGET_PREFIX}{}.json", self.as_str())
7496
}
7597

7698
#[cfg(feature = "dir_path")]
7799
pub fn target_json_path(&self) -> String {
78100
format!(
79-
"{TARGET_SPEC_DIR_PATH}/{SPIRV_ARCH}-{SPIRV_VENDOR}-{}.json",
101+
"{TARGET_SPEC_DIR_PATH}/{SPIRV_TARGET_PREFIX}{}.json",
80102
self.as_str()
81103
)
82104
}
@@ -91,9 +113,17 @@ mod tests {
91113
use super::*;
92114

93115
#[test]
94-
pub fn test_parse_as_str_loop() {
116+
pub fn test_prefix() {
117+
assert_eq!(
118+
SPIRV_TARGET_PREFIX,
119+
&format!("{SPIRV_ARCH}-{SPIRV_VENDOR}-")
120+
);
121+
}
122+
123+
#[test]
124+
pub fn test_triple_parse_loop() {
95125
for target in SpirvTargetEnv::iter() {
96-
let parsed = SpirvTargetEnv::parse_triple(target.as_str()).unwrap();
126+
let parsed = SpirvTargetEnv::parse_triple(&target.target_triple()).unwrap();
97127
assert_eq!(target, parsed);
98128
}
99129
}
@@ -103,7 +133,7 @@ mod tests {
103133
pub fn test_target_json_path() {
104134
for target in SpirvTargetEnv::iter() {
105135
let file = std::path::PathBuf::from(target.target_json_path());
106-
assert!(file.is_file());
136+
assert!(file.is_file(), "{}", file.display());
107137
}
108138
}
109139

crates/rustc_codegen_spirv/src/codegen_cx/mod.rs

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -100,16 +100,7 @@ impl<'tcx> CodegenCx<'tcx> {
100100
pub fn new(tcx: TyCtxt<'tcx>, codegen_unit: &'tcx CodegenUnit<'tcx>) -> Self {
101101
// Validate the target spec, as the backend doesn't control `--target`.
102102
let target_tuple = tcx.sess.opts.target_triple.tuple();
103-
let target = SpirvTargetEnv::parse_triple(target_tuple).unwrap_or_else(|| {
104-
let qualifier = if !target_tuple.starts_with("spirv-") {
105-
"non-SPIR-V "
106-
} else {
107-
""
108-
};
109-
tcx.dcx().fatal(format!(
110-
"{qualifier}target `{target_tuple}` not supported by `rustc_codegen_spirv`",
111-
))
112-
});
103+
let target = SpirvTargetEnv::parse_triple(target_tuple).unwrap();
113104
let target_spec_mismatched_jsons = {
114105
use rustc_target::json::ToJson;
115106

crates/spirv-builder/src/lib.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,6 @@ mod depfile;
7777
mod watch;
7878

7979
use raw_string::{RawStr, RawString};
80-
use rustc_codegen_spirv_target_specs::SpirvTargetEnv;
8180
use semver::Version;
8281
use serde::Deserialize;
8382
use std::borrow::Borrow;
@@ -89,6 +88,7 @@ use std::path::{Path, PathBuf};
8988
use std::process::{Command, Stdio};
9089
use thiserror::Error;
9190

91+
pub use rustc_codegen_spirv_target_specs::{SpirvTargetEnv, SpirvTargetParseError};
9292
pub use rustc_codegen_spirv_types::*;
9393

9494
#[cfg(feature = "include-target-specs")]
@@ -99,8 +99,8 @@ pub use rustc_codegen_spirv_target_specs::TARGET_SPEC_DIR_PATH;
9999
pub enum SpirvBuilderError {
100100
#[error("`target` must be set, for example `spirv-unknown-vulkan1.2`")]
101101
MissingTarget,
102-
#[error("Unknown target `{target}`")]
103-
UnknownTarget { target: String },
102+
#[error("Error parsing target: {0}")]
103+
SpirvTargetParseError(#[from] SpirvTargetParseError),
104104
#[error("`path_to_crate` must be set")]
105105
MissingCratePath,
106106
#[error("crate path '{0}' does not exist")]
@@ -760,9 +760,7 @@ fn invoke_rustc(builder: &SpirvBuilder) -> Result<PathBuf, SpirvBuilderError> {
760760
.target
761761
.as_ref()
762762
.ok_or(SpirvBuilderError::MissingTarget)?;
763-
let target = SpirvTargetEnv::parse_triple(target).ok_or(SpirvBuilderError::UnknownTarget {
764-
target: target.clone(),
765-
})?;
763+
let target = SpirvTargetEnv::parse_triple(target)?;
766764
let path_to_crate = builder
767765
.path_to_crate
768766
.as_ref()

tests/compiletests/src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ impl Runner {
138138
} else {
139139
SpirvTargetEnv::parse_triple(&format!("spirv-unknown-{target}"))
140140
}
141-
.unwrap_or_else(|| panic!("unknown target {}", target));
141+
.unwrap();
142142

143143
// HACK(eddyb) in order to allow *some* tests to have separate output
144144
// in different testing variations (i.e. experimental features), while

tests/difftests/tests/Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)