rustup: update to nightly-2023-07-08.

This commit is contained in:
Eduard-Mihai Burtescu 2023-07-25 23:23:06 +03:00 committed by Eduard-Mihai Burtescu
parent c2f98b612a
commit 50ebb52619
23 changed files with 288 additions and 224 deletions

View File

@ -29,6 +29,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased] ## [Unreleased]
### Changed 🛠
- [PR#1085](https://github.com/EmbarkStudios/rust-gpu/pull/1085) updated toolchain to `nightly-2023-07-08`
## [0.9.0] ## [0.9.0]
### Added ⭐ ### Added ⭐

4
Cargo.lock generated
View File

@ -1837,9 +1837,9 @@ dependencies = [
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.47" version = "1.0.66"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]

View File

@ -10,9 +10,9 @@ use std::process::{Command, ExitCode};
/// `cargo publish`. We need to figure out a way to do this properly, but let's hardcode it for now :/ /// `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 = include_str!("../../rust-toolchain.toml");
const REQUIRED_RUST_TOOLCHAIN: &str = r#"[toolchain] const REQUIRED_RUST_TOOLCHAIN: &str = r#"[toolchain]
channel = "nightly-2023-05-27" channel = "nightly-2023-07-08"
components = ["rust-src", "rustc-dev", "llvm-tools-preview"] components = ["rust-src", "rustc-dev", "llvm-tools-preview"]
# commit_hash = 1a5f8bce74ee432f7cc3aa131bc3d6920e06de10"#; # commit_hash = cb80ff132a0e9aa71529b701427e4e6c243b58df"#;
fn get_rustc_commit_hash() -> Result<String, Box<dyn Error>> { fn get_rustc_commit_hash() -> Result<String, Box<dyn Error>> {
let rustc = std::env::var("RUSTC").unwrap_or_else(|_| String::from("rustc")); let rustc = std::env::var("RUSTC").unwrap_or_else(|_| String::from("rustc"));

View File

@ -201,7 +201,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
64 => self 64 => self
.constant_u64(self.span(), memset_fill_u64(fill_byte)) .constant_u64(self.span(), memset_fill_u64(fill_byte))
.def(self), .def(self),
_ => self.fatal(&format!( _ => self.fatal(format!(
"memset on integer width {width} not implemented yet" "memset on integer width {width} not implemented yet"
)), )),
}, },
@ -212,9 +212,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
64 => self 64 => self
.constant_f64(self.span(), f64::from_bits(memset_fill_u64(fill_byte))) .constant_f64(self.span(), f64::from_bits(memset_fill_u64(fill_byte)))
.def(self), .def(self),
_ => self.fatal(&format!( _ => self.fatal(format!("memset on float width {width} not implemented yet")),
"memset on float width {width} not implemented yet"
)),
}, },
SpirvType::Adt { .. } => self.fatal("memset on structs not implemented yet"), SpirvType::Adt { .. } => self.fatal("memset on structs not implemented yet"),
SpirvType::Vector { element, count } | SpirvType::Matrix { element, count } => { SpirvType::Vector { element, count } | SpirvType::Matrix { element, count } => {
@ -259,16 +257,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
16 => memset_dynamic_scalar(self, fill_var, 2, false), 16 => memset_dynamic_scalar(self, fill_var, 2, false),
32 => memset_dynamic_scalar(self, fill_var, 4, false), 32 => memset_dynamic_scalar(self, fill_var, 4, false),
64 => memset_dynamic_scalar(self, fill_var, 8, false), 64 => memset_dynamic_scalar(self, fill_var, 8, false),
_ => self.fatal(&format!( _ => self.fatal(format!(
"memset on integer width {width} not implemented yet" "memset on integer width {width} not implemented yet"
)), )),
}, },
SpirvType::Float(width) => match width { SpirvType::Float(width) => match width {
32 => memset_dynamic_scalar(self, fill_var, 4, true), 32 => memset_dynamic_scalar(self, fill_var, 4, true),
64 => memset_dynamic_scalar(self, fill_var, 8, true), 64 => memset_dynamic_scalar(self, fill_var, 8, true),
_ => self.fatal(&format!( _ => self.fatal(format!("memset on float width {width} not implemented yet")),
"memset on float width {width} not implemented yet"
)),
}, },
SpirvType::Adt { .. } => self.fatal("memset on structs not implemented yet"), SpirvType::Adt { .. } => self.fatal("memset on structs not implemented yet"),
SpirvType::Array { element, count } => { SpirvType::Array { element, count } => {
@ -805,7 +801,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
) { ) {
fn construct_8(self_: &Builder<'_, '_>, signed: bool, v: u128) -> Operand { fn construct_8(self_: &Builder<'_, '_>, signed: bool, v: u128) -> Operand {
if v > u8::MAX as u128 { if v > u8::MAX as u128 {
self_.fatal(&format!( self_.fatal(format!(
"Switches to values above u8::MAX not supported: {v:?}" "Switches to values above u8::MAX not supported: {v:?}"
)) ))
} else if signed { } else if signed {
@ -817,7 +813,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
} }
fn construct_16(self_: &Builder<'_, '_>, signed: bool, v: u128) -> Operand { fn construct_16(self_: &Builder<'_, '_>, signed: bool, v: u128) -> Operand {
if v > u16::MAX as u128 { if v > u16::MAX as u128 {
self_.fatal(&format!( self_.fatal(format!(
"Switches to values above u16::MAX not supported: {v:?}" "Switches to values above u16::MAX not supported: {v:?}"
)) ))
} else if signed { } else if signed {
@ -828,7 +824,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
} }
fn construct_32(self_: &Builder<'_, '_>, _signed: bool, v: u128) -> Operand { fn construct_32(self_: &Builder<'_, '_>, _signed: bool, v: u128) -> Operand {
if v > u32::MAX as u128 { if v > u32::MAX as u128 {
self_.fatal(&format!( self_.fatal(format!(
"Switches to values above u32::MAX not supported: {v:?}" "Switches to values above u32::MAX not supported: {v:?}"
)) ))
} else { } else {
@ -837,7 +833,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
} }
fn construct_64(self_: &Builder<'_, '_>, _signed: bool, v: u128) -> Operand { fn construct_64(self_: &Builder<'_, '_>, _signed: bool, v: u128) -> Operand {
if v > u64::MAX as u128 { if v > u64::MAX as u128 {
self_.fatal(&format!( self_.fatal(format!(
"Switches to values above u64::MAX not supported: {v:?}" "Switches to values above u64::MAX not supported: {v:?}"
)) ))
} else { } else {
@ -852,13 +848,13 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
16 => construct_16, 16 => construct_16,
32 => construct_32, 32 => construct_32,
64 => construct_64, 64 => construct_64,
other => self.fatal(&format!( other => self.fatal(format!(
"switch selector cannot have width {other} (only 8, 16, 32, and 64 bits allowed)" "switch selector cannot have width {other} (only 8, 16, 32, and 64 bits allowed)"
)), )),
}; };
(signed, construct_case) (signed, construct_case)
} }
other => self.fatal(&format!( other => self.fatal(format!(
"switch selector cannot have non-integer type {}", "switch selector cannot have non-integer type {}",
other.debug(v.ty, self) other.debug(v.ty, self)
)), )),
@ -947,7 +943,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
SpirvType::Bool => self SpirvType::Bool => self
.emit() .emit()
.logical_and(ty, None, lhs.def(self), rhs.def(self)), .logical_and(ty, None, lhs.def(self), rhs.def(self)),
o => self.fatal(&format!( o => self.fatal(format!(
"and() not implemented for type {}", "and() not implemented for type {}",
o.debug(ty, self) o.debug(ty, self)
)), )),
@ -966,7 +962,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
SpirvType::Bool => self SpirvType::Bool => self
.emit() .emit()
.logical_or(ty, None, lhs.def(self), rhs.def(self)), .logical_or(ty, None, lhs.def(self), rhs.def(self)),
o => self.fatal(&format!( o => self.fatal(format!(
"or() not implemented for type {}", "or() not implemented for type {}",
o.debug(ty, self) o.debug(ty, self)
)), )),
@ -986,7 +982,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
self.emit() self.emit()
.logical_not_equal(ty, None, lhs.def(self), rhs.def(self)) .logical_not_equal(ty, None, lhs.def(self), rhs.def(self))
} }
o => self.fatal(&format!( o => self.fatal(format!(
"xor() not implemented for type {}", "xor() not implemented for type {}",
o.debug(ty, self) o.debug(ty, self)
)), )),
@ -1003,7 +999,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
self.emit() self.emit()
.logical_not_equal(val.ty, None, val.def(self), true_.def(self)) .logical_not_equal(val.ty, None, val.def(self), true_.def(self))
} }
o => self.fatal(&format!( o => self.fatal(format!(
"not() not implemented for type {}", "not() not implemented for type {}",
o.debug(val.ty, self) o.debug(val.ty, self)
)), )),
@ -1104,7 +1100,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
assert_ty_eq!(self, ty, pointee); assert_ty_eq!(self, ty, pointee);
pointee pointee
} }
ty => self.fatal(&format!( ty => self.fatal(format!(
"load called on variable that wasn't a pointer: {ty:?}" "load called on variable that wasn't a pointer: {ty:?}"
)), )),
}; };
@ -1133,7 +1129,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
assert_ty_eq!(self, ty, pointee); assert_ty_eq!(self, ty, pointee);
pointee pointee
} }
ty => self.fatal(&format!( ty => self.fatal(format!(
"atomic_load called on variable that wasn't a pointer: {ty:?}" "atomic_load called on variable that wasn't a pointer: {ty:?}"
)), )),
}; };
@ -1160,7 +1156,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
place: PlaceRef<'tcx, Self::Value>, place: PlaceRef<'tcx, Self::Value>,
) -> OperandRef<'tcx, Self::Value> { ) -> OperandRef<'tcx, Self::Value> {
if place.layout.is_zst() { if place.layout.is_zst() {
return OperandRef::new_zst(self, place.layout); return OperandRef::zero_sized(place.layout);
} }
let val = if let Some(llextra) = place.llextra { let val = if let Some(llextra) = place.llextra {
@ -1236,7 +1232,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
fn store(&mut self, val: Self::Value, ptr: Self::Value, _align: Align) -> Self::Value { fn store(&mut self, val: Self::Value, ptr: Self::Value, _align: Align) -> Self::Value {
let ptr_elem_ty = match self.lookup_type(ptr.ty) { let ptr_elem_ty = match self.lookup_type(ptr.ty) {
SpirvType::Pointer { pointee } => pointee, SpirvType::Pointer { pointee } => pointee,
ty => self.fatal(&format!( ty => self.fatal(format!(
"store called on variable that wasn't a pointer: {ty:?}" "store called on variable that wasn't a pointer: {ty:?}"
)), )),
}; };
@ -1268,7 +1264,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
flags: MemFlags, flags: MemFlags,
) -> Self::Value { ) -> Self::Value {
if flags != MemFlags::empty() { if flags != MemFlags::empty() {
self.err(&format!("store_with_flags is not supported yet: {flags:?}")); self.err(format!("store_with_flags is not supported yet: {flags:?}"));
} }
self.store(val, ptr, align) self.store(val, ptr, align)
} }
@ -1282,7 +1278,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
) { ) {
let ptr_elem_ty = match self.lookup_type(ptr.ty) { let ptr_elem_ty = match self.lookup_type(ptr.ty) {
SpirvType::Pointer { pointee } => pointee, SpirvType::Pointer { pointee } => pointee,
ty => self.fatal(&format!( ty => self.fatal(format!(
"atomic_store called on variable that wasn't a pointer: {ty:?}" "atomic_store called on variable that wasn't a pointer: {ty:?}"
)), )),
}; };
@ -1320,7 +1316,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
assert_ty_eq!(self, ty, pointee); assert_ty_eq!(self, ty, pointee);
pointee pointee
} }
other => self.fatal(&format!( other => self.fatal(format!(
"struct_gep not on pointer type: {other:?}, index {idx}" "struct_gep not on pointer type: {other:?}, index {idx}"
)), )),
}; };
@ -1335,7 +1331,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
assert_eq!(idx, 0); assert_eq!(idx, 0);
inner_type inner_type
} }
other => self.fatal(&format!( other => self.fatal(format!(
"struct_gep not on struct, array, or vector type: {other:?}, index {idx}" "struct_gep not on struct, array, or vector type: {other:?}, index {idx}"
)), )),
}; };
@ -1480,7 +1476,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
fn ptrtoint(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value { fn ptrtoint(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value {
match self.lookup_type(val.ty) { match self.lookup_type(val.ty) {
SpirvType::Pointer { .. } => (), SpirvType::Pointer { .. } => (),
other => self.fatal(&format!( other => self.fatal(format!(
"ptrtoint called on non-pointer source type: {other:?}" "ptrtoint called on non-pointer source type: {other:?}"
)), )),
} }
@ -1500,7 +1496,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
fn inttoptr(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value { fn inttoptr(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value {
match self.lookup_type(dest_ty) { match self.lookup_type(dest_ty) {
SpirvType::Pointer { .. } => (), SpirvType::Pointer { .. } => (),
other => self.fatal(&format!( other => self.fatal(format!(
"inttoptr called on non-pointer dest type: {other:?}" "inttoptr called on non-pointer dest type: {other:?}"
)), )),
} }
@ -1603,7 +1599,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
.unwrap() .unwrap()
.with_type(dest_ty) .with_type(dest_ty)
} }
(val_ty, dest_ty_spv) => self.fatal(&format!( (val_ty, dest_ty_spv) => self.fatal(format!(
"TODO: intcast not implemented yet: val={val:?} val.ty={val_ty:?} dest_ty={dest_ty_spv:?} is_signed={is_signed}" "TODO: intcast not implemented yet: val={val:?} val.ty={val_ty:?} dest_ty={dest_ty_spv:?} is_signed={is_signed}"
)), )),
} }
@ -1628,14 +1624,14 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
_ => match self.lookup_type(val.ty) { _ => match self.lookup_type(val.ty) {
SpirvType::Pointer { pointee } => (val, pointee), SpirvType::Pointer { pointee } => (val, pointee),
other => self.fatal(&format!( other => self.fatal(format!(
"pointercast called on non-pointer source type: {other:?}" "pointercast called on non-pointer source type: {other:?}"
)), )),
}, },
}; };
let dest_pointee = match self.lookup_type(dest_ty) { let dest_pointee = match self.lookup_type(dest_ty) {
SpirvType::Pointer { pointee } => pointee, SpirvType::Pointer { pointee } => pointee,
other => self.fatal(&format!( other => self.fatal(format!(
"pointercast called on non-pointer dest type: {other:?}" "pointercast called on non-pointer dest type: {other:?}"
)), )),
}; };
@ -1860,7 +1856,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
IntSLT => self.fatal("TODO: boolean operator IntSLT not implemented yet"), IntSLT => self.fatal("TODO: boolean operator IntSLT not implemented yet"),
IntSLE => self.fatal("TODO: boolean operator IntSLE not implemented yet"), IntSLE => self.fatal("TODO: boolean operator IntSLE not implemented yet"),
}, },
other => self.fatal(&format!( other => self.fatal(format!(
"Int comparison not implemented on {}", "Int comparison not implemented on {}",
other.debug(lhs.ty, self) other.debug(lhs.ty, self)
)), )),
@ -1930,7 +1926,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
flags: MemFlags, flags: MemFlags,
) { ) {
if flags != MemFlags::empty() { if flags != MemFlags::empty() {
self.err(&format!( self.err(format!(
"memcpy with mem flags is not supported yet: {flags:?}" "memcpy with mem flags is not supported yet: {flags:?}"
)); ));
} }
@ -1988,13 +1984,13 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
flags: MemFlags, flags: MemFlags,
) { ) {
if flags != MemFlags::empty() { if flags != MemFlags::empty() {
self.err(&format!( self.err(format!(
"memset with mem flags is not supported yet: {flags:?}" "memset with mem flags is not supported yet: {flags:?}"
)); ));
} }
let elem_ty = match self.lookup_type(ptr.ty) { let elem_ty = match self.lookup_type(ptr.ty) {
SpirvType::Pointer { pointee } => pointee, SpirvType::Pointer { pointee } => pointee,
_ => self.fatal(&format!( _ => self.fatal(format!(
"memset called on non-pointer type: {}", "memset called on non-pointer type: {}",
self.debug_type(ptr.ty) self.debug_type(ptr.ty)
)), )),
@ -2038,9 +2034,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
fn extract_element(&mut self, vec: Self::Value, idx: Self::Value) -> Self::Value { fn extract_element(&mut self, vec: Self::Value, idx: Self::Value) -> Self::Value {
let result_type = match self.lookup_type(vec.ty) { let result_type = match self.lookup_type(vec.ty) {
SpirvType::Vector { element, .. } => element, SpirvType::Vector { element, .. } => element,
other => self.fatal(&format!( other => self.fatal(format!("extract_element not implemented on type {other:?}")),
"extract_element not implemented on type {other:?}"
)),
}; };
match self.builder.lookup_const_u64(idx) { match self.builder.lookup_const_u64(idx) {
Some(const_index) => self.emit().composite_extract( Some(const_index) => self.emit().composite_extract(
@ -2084,7 +2078,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
SpirvType::Array { element, .. } SpirvType::Array { element, .. }
| SpirvType::Vector { element, .. } | SpirvType::Vector { element, .. }
| SpirvType::Matrix { element, .. } => element, | SpirvType::Matrix { element, .. } => element,
other => self.fatal(&format!( other => self.fatal(format!(
"extract_value not implemented on type {}", "extract_value not implemented on type {}",
other.debug(agg_val.ty, self) other.debug(agg_val.ty, self)
)), )),
@ -2105,7 +2099,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
SpirvType::Adt { field_types, .. } => { SpirvType::Adt { field_types, .. } => {
assert_ty_eq!(self, field_types[idx as usize], elt.ty); assert_ty_eq!(self, field_types[idx as usize], elt.ty);
} }
other => self.fatal(&format!("insert_value not implemented on type {other:?}")), other => self.fatal(format!("insert_value not implemented on type {other:?}")),
}; };
self.emit() self.emit()
.composite_insert( .composite_insert(
@ -2173,7 +2167,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
) -> Self::Value { ) -> Self::Value {
let dst_pointee_ty = match self.lookup_type(dst.ty) { let dst_pointee_ty = match self.lookup_type(dst.ty) {
SpirvType::Pointer { pointee } => pointee, SpirvType::Pointer { pointee } => pointee,
ty => self.fatal(&format!( ty => self.fatal(format!(
"atomic_cmpxchg called on variable that wasn't a pointer: {ty:?}" "atomic_cmpxchg called on variable that wasn't a pointer: {ty:?}"
)), )),
}; };
@ -2209,7 +2203,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
) -> Self::Value { ) -> Self::Value {
let dst_pointee_ty = match self.lookup_type(dst.ty) { let dst_pointee_ty = match self.lookup_type(dst.ty) {
SpirvType::Pointer { pointee } => pointee, SpirvType::Pointer { pointee } => pointee,
ty => self.fatal(&format!( ty => self.fatal(format!(
"atomic_rmw called on variable that wasn't a pointer: {ty:?}" "atomic_rmw called on variable that wasn't a pointer: {ty:?}"
)), )),
}; };
@ -2562,8 +2556,8 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
enum Inst<'tcx, ID> { enum Inst<'tcx, ID> {
Bitcast(ID, ID), Bitcast(ID, ID),
CompositeExtract(ID, ID, u32), CompositeExtract(ID, ID, u32),
AccessChain(ID, ID, SpirvConst<'tcx>), AccessChain(ID, ID, SpirvConst<'tcx, 'tcx>),
InBoundsAccessChain(ID, ID, SpirvConst<'tcx>), InBoundsAccessChain(ID, ID, SpirvConst<'tcx, 'tcx>),
Store(ID, ID), Store(ID, ID),
Load(ID, ID), Load(ID, ID),
Call(ID, ID, SmallVec<[ID; 4]>), Call(ID, ID, SmallVec<[ID; 4]>),

View File

@ -10,7 +10,7 @@ use rustc_target::abi::{Align, Size};
impl<'a, 'tcx> Builder<'a, 'tcx> { impl<'a, 'tcx> Builder<'a, 'tcx> {
fn load_err(&mut self, original_type: Word, invalid_type: Word) -> SpirvValue { fn load_err(&mut self, original_type: Word, invalid_type: Word) -> SpirvValue {
let mut err = self.struct_err(&format!( let mut err = self.struct_err(format!(
"cannot load type {} in an untyped buffer load", "cannot load type {} in an untyped buffer load",
self.debug_type(original_type) self.debug_type(original_type)
)); ));
@ -191,7 +191,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// Signature: fn load<T>(array: &[u32], index: u32) -> T; // Signature: fn load<T>(array: &[u32], index: u32) -> T;
if args.len() != 3 { if args.len() != 3 {
self.fatal(&format!( self.fatal(format!(
"buffer_load_intrinsic should have 3 args, it has {}", "buffer_load_intrinsic should have 3 args, it has {}",
args.len() args.len()
)); ));
@ -205,7 +205,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
} }
fn store_err(&mut self, original_type: Word, value: SpirvValue) -> Result<(), ErrorGuaranteed> { fn store_err(&mut self, original_type: Word, value: SpirvValue) -> Result<(), ErrorGuaranteed> {
let mut err = self.struct_err(&format!( let mut err = self.struct_err(format!(
"cannot store type {} in an untyped buffer store", "cannot store type {} in an untyped buffer store",
self.debug_type(original_type) self.debug_type(original_type)
)); ));
@ -358,7 +358,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}; };
let expected_args = if is_pair { 5 } else { 4 }; let expected_args = if is_pair { 5 } else { 4 };
if args.len() != expected_args { if args.len() != expected_args {
self.fatal(&format!( self.fatal(format!(
"buffer_store_intrinsic should have {} args, it has {}", "buffer_store_intrinsic should have {} args, it has {}",
expected_args, expected_args,
args.len() args.len()

View File

@ -124,7 +124,7 @@ impl<'a, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'tcx> {
self.add(args[0].immediate(), args[1].immediate()) self.add(args[0].immediate(), args[1].immediate())
} }
TyKind::Float(_) => self.fadd(args[0].immediate(), args[1].immediate()), TyKind::Float(_) => self.fadd(args[0].immediate(), args[1].immediate()),
other => self.fatal(&format!( other => self.fatal(format!(
"Unimplemented saturating_add intrinsic type: {other:#?}" "Unimplemented saturating_add intrinsic type: {other:#?}"
)), )),
}; };
@ -139,7 +139,7 @@ impl<'a, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'tcx> {
self.sub(args[0].immediate(), args[1].immediate()) self.sub(args[0].immediate(), args[1].immediate())
} }
TyKind::Float(_) => self.fsub(args[0].immediate(), args[1].immediate()), TyKind::Float(_) => self.fsub(args[0].immediate(), args[1].immediate()),
other => self.fatal(&format!( other => self.fatal(format!(
"Unimplemented saturating_sub intrinsic type: {other:#?}" "Unimplemented saturating_sub intrinsic type: {other:#?}"
)), )),
}; };
@ -327,7 +327,7 @@ impl<'a, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'tcx> {
} }
} }
_ => self.fatal(&format!("TODO: Unknown intrinsic '{name}'")), _ => self.fatal(format!("TODO: Unknown intrinsic '{name}'")),
}; };
if !fn_abi.ret.is_ignore() { if !fn_abi.ret.is_ignore() {

View File

@ -20,10 +20,8 @@ use rustc_codegen_ssa::traits::{
AbiBuilderMethods, ArgAbiMethods, BackendTypes, BuilderMethods, CoverageInfoBuilderMethods, AbiBuilderMethods, ArgAbiMethods, BackendTypes, BuilderMethods, CoverageInfoBuilderMethods,
DebugInfoBuilderMethods, HasCodegen, StaticBuilderMethods, TypeMembershipMethods, DebugInfoBuilderMethods, HasCodegen, StaticBuilderMethods, TypeMembershipMethods,
}; };
use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed}; use rustc_errors::{DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed};
use rustc_middle::mir::coverage::{ use rustc_middle::mir::Coverage;
CodeRegion, CounterValueReference, ExpressionOperandId, InjectedExpressionId, Op,
};
use rustc_middle::span_bug; use rustc_middle::span_bug;
use rustc_middle::ty::layout::{ use rustc_middle::ty::layout::{
FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, HasTyCtxt, LayoutError, LayoutOfHelpers, FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, HasTyCtxt, LayoutError, LayoutOfHelpers,
@ -70,7 +68,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
} }
} }
pub fn struct_err(&self, msg: &str) -> DiagnosticBuilder<'_, ErrorGuaranteed> { #[track_caller]
pub fn struct_err(
&self,
msg: impl Into<DiagnosticMessage>,
) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
if let Some(current_span) = self.current_span { if let Some(current_span) = self.current_span {
self.tcx.sess.struct_span_err(current_span, msg) self.tcx.sess.struct_span_err(current_span, msg)
} else { } else {
@ -78,7 +80,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
} }
} }
pub fn err(&self, msg: &str) { #[track_caller]
pub fn err(&self, msg: impl Into<DiagnosticMessage>) {
if let Some(current_span) = self.current_span { if let Some(current_span) = self.current_span {
self.tcx.sess.span_err(current_span, msg); self.tcx.sess.span_err(current_span, msg);
} else { } else {
@ -86,7 +89,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
} }
} }
pub fn fatal(&self, msg: &str) -> ! { #[track_caller]
pub fn fatal(&self, msg: impl Into<DiagnosticMessage>) -> ! {
if let Some(current_span) = self.current_span { if let Some(current_span) = self.current_span {
self.tcx.sess.span_fatal(current_span, msg) self.tcx.sess.span_fatal(current_span, msg)
} else { } else {
@ -136,7 +140,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
assert_ty_eq!(self, ty, pointee); assert_ty_eq!(self, ty, pointee);
pointee pointee
} }
other_type => self.fatal(&format!( other_type => self.fatal(format!(
"GEP first deref not implemented for type {other_type:?}" "GEP first deref not implemented for type {other_type:?}"
)), )),
}; };
@ -144,7 +148,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
result_indices.push(index.def(self)); result_indices.push(index.def(self));
result_pointee_type = match self.lookup_type(result_pointee_type) { result_pointee_type = match self.lookup_type(result_pointee_type) {
SpirvType::Array { element, .. } | SpirvType::RuntimeArray { element } => element, SpirvType::Array { element, .. } | SpirvType::RuntimeArray { element } => element,
_ => self.fatal(&format!( _ => self.fatal(format!(
"GEP not implemented for type {}", "GEP not implemented for type {}",
self.debug_type(result_pointee_type) self.debug_type(result_pointee_type)
)), )),
@ -218,7 +222,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
fn rotate(&mut self, value: SpirvValue, shift: SpirvValue, is_left: bool) -> SpirvValue { fn rotate(&mut self, value: SpirvValue, shift: SpirvValue, is_left: bool) -> SpirvValue {
let width = match self.lookup_type(shift.ty) { let width = match self.lookup_type(shift.ty) {
SpirvType::Integer(width, _) => width, SpirvType::Integer(width, _) => width,
other => self.fatal(&format!( other => self.fatal(format!(
"cannot rotate non-integer type: {}", "cannot rotate non-integer type: {}",
other.debug(shift.ty, self) other.debug(shift.ty, self)
)), )),
@ -257,31 +261,7 @@ impl<'a, 'tcx> Deref for Builder<'a, 'tcx> {
} }
impl<'a, 'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'a, 'tcx> { impl<'a, 'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'a, 'tcx> {
fn set_function_source_hash(&mut self, _: rustc_middle::ty::Instance<'tcx>, _: u64) -> bool { fn add_coverage(&mut self, _instance: Instance<'tcx>, _coverage: &Coverage) {}
todo!()
}
fn add_coverage_counter(
&mut self,
_: Instance<'tcx>,
_: CounterValueReference,
_: CodeRegion,
) -> bool {
todo!()
}
fn add_coverage_counter_expression(
&mut self,
_: Instance<'tcx>,
_: InjectedExpressionId,
_: ExpressionOperandId,
_: Op,
_: ExpressionOperandId,
_: Option<CodeRegion>,
) -> bool {
todo!()
}
fn add_coverage_unreachable(&mut self, _: Instance<'tcx>, _: CodeRegion) -> bool {
todo!()
}
} }
impl<'a, 'tcx> DebugInfoBuilderMethods for Builder<'a, 'tcx> { impl<'a, 'tcx> DebugInfoBuilderMethods for Builder<'a, 'tcx> {

View File

@ -64,7 +64,7 @@ impl<'a, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'tcx> {
const SUPPORTED_OPTIONS: InlineAsmOptions = InlineAsmOptions::NORETURN; const SUPPORTED_OPTIONS: InlineAsmOptions = InlineAsmOptions::NORETURN;
let unsupported_options = options & !SUPPORTED_OPTIONS; let unsupported_options = options & !SUPPORTED_OPTIONS;
if !unsupported_options.is_empty() { if !unsupported_options.is_empty() {
self.err(&format!("asm flags not supported: {unsupported_options:?}")); self.err(format!("asm flags not supported: {unsupported_options:?}"));
} }
// vec of lines, and each line is vec of tokens // vec of lines, and each line is vec of tokens
let mut tokens = vec![vec![]]; let mut tokens = vec![vec![]];
@ -162,14 +162,14 @@ impl<'a, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'tcx> {
} }
(false, AsmBlock::Open) => (), (false, AsmBlock::Open) => (),
(false, AsmBlock::End(terminator)) => { (false, AsmBlock::End(terminator)) => {
self.err(&format!( self.err(format!(
"trailing terminator `Op{terminator:?}` requires `options(noreturn)`" "trailing terminator `Op{terminator:?}` requires `options(noreturn)`"
)); ));
} }
} }
for (id, num) in id_map { for (id, num) in id_map {
if !defined_ids.contains(&num) { if !defined_ids.contains(&num) {
self.err(&format!("%{id} is used but not defined")); self.err(format!("%{id} is used but not defined"));
} }
} }
} }
@ -232,7 +232,7 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> {
Some('\'') => '\'', Some('\'') => '\'',
Some('"') => '"', Some('"') => '"',
Some(escape) => { Some(escape) => {
self.err(&format!("invalid escape '\\{escape}'")); self.err(format!("invalid escape '\\{escape}'"));
return None; return None;
} }
}; };
@ -359,7 +359,7 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> {
// NOTE(eddyb) allowing the instruction to be added below avoids // NOTE(eddyb) allowing the instruction to be added below avoids
// spurious "`noreturn` requires a terminator at the end" errors. // spurious "`noreturn` requires a terminator at the end" errors.
if let Op::Return | Op::ReturnValue = op { if let Op::Return | Op::ReturnValue = op {
self.struct_err(&format!( self.struct_err(format!(
"using `Op{op:?}` to return from within `asm!` is disallowed" "using `Op{op:?}` to return from within `asm!` is disallowed"
)) ))
.note( .note(
@ -383,7 +383,7 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> {
} }
AsmBlock::End(terminator) => { AsmBlock::End(terminator) => {
if op != Op::Label { if op != Op::Label {
self.err(&format!( self.err(format!(
"expected `OpLabel` after terminator `Op{terminator:?}`" "expected `OpLabel` after terminator `Op{terminator:?}`"
)); ));
} }
@ -466,7 +466,7 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> {
let inst_class = if let Some(inst) = inst_class { let inst_class = if let Some(inst) = inst_class {
inst inst
} else { } else {
self.err(&format!("unknown spirv instruction {inst_name}")); self.err(format!("unknown spirv instruction {inst_name}"));
return; return;
}; };
let result_id = match out_register { let result_id = match out_register {
@ -521,7 +521,7 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> {
if kind == OperandKind::IdResult { if kind == OperandKind::IdResult {
assert_eq!(quantifier, OperandQuantifier::One); assert_eq!(quantifier, OperandQuantifier::One);
if instruction.result_id.is_none() { if instruction.result_id.is_none() {
self.err(&format!( self.err(format!(
"instruction {} expects a result id", "instruction {} expects a result id",
instruction.class.opname instruction.class.opname
)); ));
@ -539,7 +539,7 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> {
instruction.result_type = Some(id); instruction.result_type = Some(id);
} }
} else { } else {
self.err(&format!( self.err(format!(
"instruction {} expects a result type", "instruction {} expects a result type",
instruction.class.opname instruction.class.opname
)); ));
@ -552,7 +552,7 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> {
match quantifier { match quantifier {
OperandQuantifier::One => { OperandQuantifier::One => {
if !self.parse_one_operand(id_map, instruction, kind, &mut tokens) { if !self.parse_one_operand(id_map, instruction, kind, &mut tokens) {
self.err(&format!( self.err(format!(
"expected operand after instruction: {}", "expected operand after instruction: {}",
instruction.class.opname instruction.class.opname
)); ));
@ -576,7 +576,7 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> {
} }
if !saw_id_result && instruction.result_id.is_some() { if !saw_id_result && instruction.result_id.is_some() {
self.err(&format!( self.err(format!(
"instruction {} does not expect a result id", "instruction {} does not expect a result id",
instruction.class.opname instruction.class.opname
)); ));
@ -593,7 +593,7 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> {
match self.infer_result_type(id_to_type_map, instruction) { match self.infer_result_type(id_to_type_map, instruction) {
Some(result_type) => instruction.result_type = Some(result_type), Some(result_type) => instruction.result_type = Some(result_type),
None => self.err(&format!( None => self.err(format!(
"instruction {} cannot have its result type inferred", "instruction {} cannot have its result type inferred",
instruction.class.opname instruction.class.opname
)), )),
@ -816,7 +816,7 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> {
Some(OutRegister::Regular({ Some(OutRegister::Regular({
let num = *id_map.entry(id).or_insert_with(|| self.emit().id()); let num = *id_map.entry(id).or_insert_with(|| self.emit().id());
if !defined_ids.insert(num) { if !defined_ids.insert(num) {
self.err(&format!("%{id} is defined more than once")); self.err(format!("%{id} is defined more than once"));
} }
num num
})) }))
@ -1078,7 +1078,7 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> {
(OperandKind::LiteralInteger, Some(word)) => match word.parse() { (OperandKind::LiteralInteger, Some(word)) => match word.parse() {
Ok(v) => inst.operands.push(dr::Operand::LiteralInt32(v)), Ok(v) => inst.operands.push(dr::Operand::LiteralInt32(v)),
Err(e) => self.err(&format!("invalid integer: {e}")), Err(e) => self.err(format!("invalid integer: {e}")),
}, },
(OperandKind::LiteralString, _) => { (OperandKind::LiteralString, _) => {
if let Token::String(value) = token { if let Token::String(value) = token {
@ -1128,12 +1128,12 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> {
} }
match parse(self.lookup_type(ty), word) { match parse(self.lookup_type(ty), word) {
Ok(op) => inst.operands.push(op), Ok(op) => inst.operands.push(op),
Err(err) => self.err(&err), Err(err) => self.err(err),
} }
} }
(OperandKind::LiteralExtInstInteger, Some(word)) => match word.parse() { (OperandKind::LiteralExtInstInteger, Some(word)) => match word.parse() {
Ok(v) => inst.operands.push(dr::Operand::LiteralExtInstInteger(v)), Ok(v) => inst.operands.push(dr::Operand::LiteralExtInstInteger(v)),
Err(e) => self.err(&format!("invalid integer: {e}")), Err(e) => self.err(format!("invalid integer: {e}")),
}, },
(OperandKind::LiteralSpecConstantOpInteger, Some(word)) => { (OperandKind::LiteralSpecConstantOpInteger, Some(word)) => {
match self.instruction_table.table.get(word) { match self.instruction_table.table.get(word) {
@ -1154,11 +1154,11 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> {
Some(Token::Word(word)) => match word.parse() { Some(Token::Word(word)) => match word.parse() {
Ok(v) => inst.operands.push(dr::Operand::LiteralInt32(v)), Ok(v) => inst.operands.push(dr::Operand::LiteralInt32(v)),
Err(e) => { Err(e) => {
self.err(&format!("invalid integer: {e}")); self.err(format!("invalid integer: {e}"));
} }
}, },
Some(Token::String(_)) => { Some(Token::String(_)) => {
self.err(&format!("expected a literal, not a string for a {kind:?}")); self.err(format!("expected a literal, not a string for a {kind:?}"));
} }
Some(Token::Placeholder(_, span)) => { Some(Token::Placeholder(_, span)) => {
self.tcx.sess.span_err( self.tcx.sess.span_err(
@ -1195,172 +1195,172 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> {
(OperandKind::ImageOperands, Some(word)) => { (OperandKind::ImageOperands, Some(word)) => {
match parse_bitflags_operand(IMAGE_OPERANDS, word) { match parse_bitflags_operand(IMAGE_OPERANDS, word) {
Some(x) => inst.operands.push(dr::Operand::ImageOperands(x)), Some(x) => inst.operands.push(dr::Operand::ImageOperands(x)),
None => self.err(&format!("Unknown ImageOperands {word}")), None => self.err(format!("Unknown ImageOperands {word}")),
} }
} }
(OperandKind::FPFastMathMode, Some(word)) => { (OperandKind::FPFastMathMode, Some(word)) => {
match parse_bitflags_operand(FP_FAST_MATH_MODE, word) { match parse_bitflags_operand(FP_FAST_MATH_MODE, word) {
Some(x) => inst.operands.push(dr::Operand::FPFastMathMode(x)), Some(x) => inst.operands.push(dr::Operand::FPFastMathMode(x)),
None => self.err(&format!("Unknown FPFastMathMode {word}")), None => self.err(format!("Unknown FPFastMathMode {word}")),
} }
} }
(OperandKind::SelectionControl, Some(word)) => { (OperandKind::SelectionControl, Some(word)) => {
match parse_bitflags_operand(SELECTION_CONTROL, word) { match parse_bitflags_operand(SELECTION_CONTROL, word) {
Some(x) => inst.operands.push(dr::Operand::SelectionControl(x)), Some(x) => inst.operands.push(dr::Operand::SelectionControl(x)),
None => self.err(&format!("Unknown SelectionControl {word}")), None => self.err(format!("Unknown SelectionControl {word}")),
} }
} }
(OperandKind::LoopControl, Some(word)) => { (OperandKind::LoopControl, Some(word)) => {
match parse_bitflags_operand(LOOP_CONTROL, word) { match parse_bitflags_operand(LOOP_CONTROL, word) {
Some(x) => inst.operands.push(dr::Operand::LoopControl(x)), Some(x) => inst.operands.push(dr::Operand::LoopControl(x)),
None => self.err(&format!("Unknown LoopControl {word}")), None => self.err(format!("Unknown LoopControl {word}")),
} }
} }
(OperandKind::FunctionControl, Some(word)) => { (OperandKind::FunctionControl, Some(word)) => {
match parse_bitflags_operand(FUNCTION_CONTROL, word) { match parse_bitflags_operand(FUNCTION_CONTROL, word) {
Some(x) => inst.operands.push(dr::Operand::FunctionControl(x)), Some(x) => inst.operands.push(dr::Operand::FunctionControl(x)),
None => self.err(&format!("Unknown FunctionControl {word}")), None => self.err(format!("Unknown FunctionControl {word}")),
} }
} }
(OperandKind::MemorySemantics, Some(word)) => { (OperandKind::MemorySemantics, Some(word)) => {
match parse_bitflags_operand(MEMORY_SEMANTICS, word) { match parse_bitflags_operand(MEMORY_SEMANTICS, word) {
Some(x) => inst.operands.push(dr::Operand::MemorySemantics(x)), Some(x) => inst.operands.push(dr::Operand::MemorySemantics(x)),
None => self.err(&format!("Unknown MemorySemantics {word}")), None => self.err(format!("Unknown MemorySemantics {word}")),
} }
} }
(OperandKind::MemoryAccess, Some(word)) => { (OperandKind::MemoryAccess, Some(word)) => {
match parse_bitflags_operand(MEMORY_ACCESS, word) { match parse_bitflags_operand(MEMORY_ACCESS, word) {
Some(x) => inst.operands.push(dr::Operand::MemoryAccess(x)), Some(x) => inst.operands.push(dr::Operand::MemoryAccess(x)),
None => self.err(&format!("Unknown MemoryAccess {word}")), None => self.err(format!("Unknown MemoryAccess {word}")),
} }
} }
(OperandKind::KernelProfilingInfo, Some(word)) => { (OperandKind::KernelProfilingInfo, Some(word)) => {
match parse_bitflags_operand(KERNEL_PROFILING_INFO, word) { match parse_bitflags_operand(KERNEL_PROFILING_INFO, word) {
Some(x) => inst.operands.push(dr::Operand::KernelProfilingInfo(x)), Some(x) => inst.operands.push(dr::Operand::KernelProfilingInfo(x)),
None => self.err(&format!("Unknown KernelProfilingInfo {word}")), None => self.err(format!("Unknown KernelProfilingInfo {word}")),
} }
} }
(OperandKind::RayFlags, Some(word)) => match parse_bitflags_operand(RAY_FLAGS, word) { (OperandKind::RayFlags, Some(word)) => match parse_bitflags_operand(RAY_FLAGS, word) {
Some(x) => inst.operands.push(dr::Operand::RayFlags(x)), Some(x) => inst.operands.push(dr::Operand::RayFlags(x)),
None => self.err(&format!("Unknown RayFlags {word}")), None => self.err(format!("Unknown RayFlags {word}")),
}, },
(OperandKind::FragmentShadingRate, Some(word)) => { (OperandKind::FragmentShadingRate, Some(word)) => {
match parse_bitflags_operand(FRAGMENT_SHADING_RATE, word) { match parse_bitflags_operand(FRAGMENT_SHADING_RATE, word) {
Some(x) => inst.operands.push(dr::Operand::FragmentShadingRate(x)), Some(x) => inst.operands.push(dr::Operand::FragmentShadingRate(x)),
None => self.err(&format!("Unknown FragmentShadingRate {word}")), None => self.err(format!("Unknown FragmentShadingRate {word}")),
} }
} }
(OperandKind::SourceLanguage, Some(word)) => match word.parse() { (OperandKind::SourceLanguage, Some(word)) => match word.parse() {
Ok(x) => inst.operands.push(dr::Operand::SourceLanguage(x)), Ok(x) => inst.operands.push(dr::Operand::SourceLanguage(x)),
Err(()) => self.err(&format!("Unknown SourceLanguage {word}")), Err(()) => self.err(format!("Unknown SourceLanguage {word}")),
}, },
(OperandKind::ExecutionModel, Some(word)) => match word.parse() { (OperandKind::ExecutionModel, Some(word)) => match word.parse() {
Ok(x) => inst.operands.push(dr::Operand::ExecutionModel(x)), Ok(x) => inst.operands.push(dr::Operand::ExecutionModel(x)),
Err(()) => self.err(&format!("unknown ExecutionModel {word}")), Err(()) => self.err(format!("unknown ExecutionModel {word}")),
}, },
(OperandKind::AddressingModel, Some(word)) => match word.parse() { (OperandKind::AddressingModel, Some(word)) => match word.parse() {
Ok(x) => inst.operands.push(dr::Operand::AddressingModel(x)), Ok(x) => inst.operands.push(dr::Operand::AddressingModel(x)),
Err(()) => self.err(&format!("unknown AddressingModel {word}")), Err(()) => self.err(format!("unknown AddressingModel {word}")),
}, },
(OperandKind::MemoryModel, Some(word)) => match word.parse() { (OperandKind::MemoryModel, Some(word)) => match word.parse() {
Ok(x) => inst.operands.push(dr::Operand::MemoryModel(x)), Ok(x) => inst.operands.push(dr::Operand::MemoryModel(x)),
Err(()) => self.err(&format!("unknown MemoryModel {word}")), Err(()) => self.err(format!("unknown MemoryModel {word}")),
}, },
(OperandKind::ExecutionMode, Some(word)) => match word.parse() { (OperandKind::ExecutionMode, Some(word)) => match word.parse() {
Ok(x) => inst.operands.push(dr::Operand::ExecutionMode(x)), Ok(x) => inst.operands.push(dr::Operand::ExecutionMode(x)),
Err(()) => self.err(&format!("unknown ExecutionMode {word}")), Err(()) => self.err(format!("unknown ExecutionMode {word}")),
}, },
(OperandKind::StorageClass, Some(word)) => match word.parse() { (OperandKind::StorageClass, Some(word)) => match word.parse() {
Ok(x) => inst.operands.push(dr::Operand::StorageClass(x)), Ok(x) => inst.operands.push(dr::Operand::StorageClass(x)),
Err(()) => self.err(&format!("unknown StorageClass {word}")), Err(()) => self.err(format!("unknown StorageClass {word}")),
}, },
(OperandKind::Dim, Some(word)) => match word.parse() { (OperandKind::Dim, Some(word)) => match word.parse() {
Ok(x) => inst.operands.push(dr::Operand::Dim(x)), Ok(x) => inst.operands.push(dr::Operand::Dim(x)),
Err(()) => self.err(&format!("unknown Dim {word}")), Err(()) => self.err(format!("unknown Dim {word}")),
}, },
(OperandKind::SamplerAddressingMode, Some(word)) => match word.parse() { (OperandKind::SamplerAddressingMode, Some(word)) => match word.parse() {
Ok(x) => inst.operands.push(dr::Operand::SamplerAddressingMode(x)), Ok(x) => inst.operands.push(dr::Operand::SamplerAddressingMode(x)),
Err(()) => self.err(&format!("unknown SamplerAddressingMode {word}")), Err(()) => self.err(format!("unknown SamplerAddressingMode {word}")),
}, },
(OperandKind::SamplerFilterMode, Some(word)) => match word.parse() { (OperandKind::SamplerFilterMode, Some(word)) => match word.parse() {
Ok(x) => inst.operands.push(dr::Operand::SamplerFilterMode(x)), Ok(x) => inst.operands.push(dr::Operand::SamplerFilterMode(x)),
Err(()) => self.err(&format!("unknown SamplerFilterMode {word}")), Err(()) => self.err(format!("unknown SamplerFilterMode {word}")),
}, },
(OperandKind::ImageFormat, Some(word)) => match word.parse() { (OperandKind::ImageFormat, Some(word)) => match word.parse() {
Ok(x) => inst.operands.push(dr::Operand::ImageFormat(x)), Ok(x) => inst.operands.push(dr::Operand::ImageFormat(x)),
Err(()) => self.err(&format!("unknown ImageFormat {word}")), Err(()) => self.err(format!("unknown ImageFormat {word}")),
}, },
(OperandKind::ImageChannelOrder, Some(word)) => match word.parse() { (OperandKind::ImageChannelOrder, Some(word)) => match word.parse() {
Ok(x) => inst.operands.push(dr::Operand::ImageChannelOrder(x)), Ok(x) => inst.operands.push(dr::Operand::ImageChannelOrder(x)),
Err(()) => self.err(&format!("unknown ImageChannelOrder {word}")), Err(()) => self.err(format!("unknown ImageChannelOrder {word}")),
}, },
(OperandKind::ImageChannelDataType, Some(word)) => match word.parse() { (OperandKind::ImageChannelDataType, Some(word)) => match word.parse() {
Ok(x) => inst.operands.push(dr::Operand::ImageChannelDataType(x)), Ok(x) => inst.operands.push(dr::Operand::ImageChannelDataType(x)),
Err(()) => self.err(&format!("unknown ImageChannelDataType {word}")), Err(()) => self.err(format!("unknown ImageChannelDataType {word}")),
}, },
(OperandKind::FPRoundingMode, Some(word)) => match word.parse() { (OperandKind::FPRoundingMode, Some(word)) => match word.parse() {
Ok(x) => inst.operands.push(dr::Operand::FPRoundingMode(x)), Ok(x) => inst.operands.push(dr::Operand::FPRoundingMode(x)),
Err(()) => self.err(&format!("unknown FPRoundingMode {word}")), Err(()) => self.err(format!("unknown FPRoundingMode {word}")),
}, },
(OperandKind::LinkageType, Some(word)) => match word.parse() { (OperandKind::LinkageType, Some(word)) => match word.parse() {
Ok(x) => inst.operands.push(dr::Operand::LinkageType(x)), Ok(x) => inst.operands.push(dr::Operand::LinkageType(x)),
Err(()) => self.err(&format!("unknown LinkageType {word}")), Err(()) => self.err(format!("unknown LinkageType {word}")),
}, },
(OperandKind::AccessQualifier, Some(word)) => match word.parse() { (OperandKind::AccessQualifier, Some(word)) => match word.parse() {
Ok(x) => inst.operands.push(dr::Operand::AccessQualifier(x)), Ok(x) => inst.operands.push(dr::Operand::AccessQualifier(x)),
Err(()) => self.err(&format!("unknown AccessQualifier {word}")), Err(()) => self.err(format!("unknown AccessQualifier {word}")),
}, },
(OperandKind::FunctionParameterAttribute, Some(word)) => match word.parse() { (OperandKind::FunctionParameterAttribute, Some(word)) => match word.parse() {
Ok(x) => inst Ok(x) => inst
.operands .operands
.push(dr::Operand::FunctionParameterAttribute(x)), .push(dr::Operand::FunctionParameterAttribute(x)),
Err(()) => self.err(&format!("unknown FunctionParameterAttribute {word}")), Err(()) => self.err(format!("unknown FunctionParameterAttribute {word}")),
}, },
(OperandKind::Decoration, Some(word)) => match word.parse() { (OperandKind::Decoration, Some(word)) => match word.parse() {
Ok(x) => inst.operands.push(dr::Operand::Decoration(x)), Ok(x) => inst.operands.push(dr::Operand::Decoration(x)),
Err(()) => self.err(&format!("unknown Decoration {word}")), Err(()) => self.err(format!("unknown Decoration {word}")),
}, },
(OperandKind::BuiltIn, Some(word)) => match word.parse() { (OperandKind::BuiltIn, Some(word)) => match word.parse() {
Ok(x) => inst.operands.push(dr::Operand::BuiltIn(x)), Ok(x) => inst.operands.push(dr::Operand::BuiltIn(x)),
Err(()) => self.err(&format!("unknown BuiltIn {word}")), Err(()) => self.err(format!("unknown BuiltIn {word}")),
}, },
(OperandKind::Scope, Some(word)) => match word.parse() { (OperandKind::Scope, Some(word)) => match word.parse() {
Ok(x) => inst.operands.push(dr::Operand::Scope(x)), Ok(x) => inst.operands.push(dr::Operand::Scope(x)),
Err(()) => self.err(&format!("unknown Scope {word}")), Err(()) => self.err(format!("unknown Scope {word}")),
}, },
(OperandKind::GroupOperation, Some(word)) => match word.parse() { (OperandKind::GroupOperation, Some(word)) => match word.parse() {
Ok(x) => inst.operands.push(dr::Operand::GroupOperation(x)), Ok(x) => inst.operands.push(dr::Operand::GroupOperation(x)),
Err(()) => self.err(&format!("unknown GroupOperation {word}")), Err(()) => self.err(format!("unknown GroupOperation {word}")),
}, },
(OperandKind::KernelEnqueueFlags, Some(word)) => match word.parse() { (OperandKind::KernelEnqueueFlags, Some(word)) => match word.parse() {
Ok(x) => inst.operands.push(dr::Operand::KernelEnqueueFlags(x)), Ok(x) => inst.operands.push(dr::Operand::KernelEnqueueFlags(x)),
Err(()) => self.err(&format!("unknown KernelEnqueueFlags {word}")), Err(()) => self.err(format!("unknown KernelEnqueueFlags {word}")),
}, },
(OperandKind::Capability, Some(word)) => match word.parse() { (OperandKind::Capability, Some(word)) => match word.parse() {
Ok(x) => inst.operands.push(dr::Operand::Capability(x)), Ok(x) => inst.operands.push(dr::Operand::Capability(x)),
Err(()) => self.err(&format!("unknown Capability {word}")), Err(()) => self.err(format!("unknown Capability {word}")),
}, },
(OperandKind::RayQueryIntersection, Some(word)) => match word.parse() { (OperandKind::RayQueryIntersection, Some(word)) => match word.parse() {
Ok(x) => inst.operands.push(dr::Operand::RayQueryIntersection(x)), Ok(x) => inst.operands.push(dr::Operand::RayQueryIntersection(x)),
Err(()) => self.err(&format!("unknown RayQueryIntersection {word}")), Err(()) => self.err(format!("unknown RayQueryIntersection {word}")),
}, },
(OperandKind::RayQueryCommittedIntersectionType, Some(word)) => match word.parse() { (OperandKind::RayQueryCommittedIntersectionType, Some(word)) => match word.parse() {
Ok(x) => inst Ok(x) => inst
.operands .operands
.push(dr::Operand::RayQueryCommittedIntersectionType(x)), .push(dr::Operand::RayQueryCommittedIntersectionType(x)),
Err(()) => self.err(&format!("unknown RayQueryCommittedIntersectionType {word}")), Err(()) => self.err(format!("unknown RayQueryCommittedIntersectionType {word}")),
}, },
(OperandKind::RayQueryCandidateIntersectionType, Some(word)) => match word.parse() { (OperandKind::RayQueryCandidateIntersectionType, Some(word)) => match word.parse() {
Ok(x) => inst Ok(x) => inst
.operands .operands
.push(dr::Operand::RayQueryCandidateIntersectionType(x)), .push(dr::Operand::RayQueryCandidateIntersectionType(x)),
Err(()) => self.err(&format!("unknown RayQueryCandidateIntersectionType {word}")), Err(()) => self.err(format!("unknown RayQueryCandidateIntersectionType {word}")),
}, },
(kind, None) => match token { (kind, None) => match token {
Token::Word(_) => bug!(), Token::Word(_) => bug!(),
Token::String(_) => { Token::String(_) => {
self.err(&format!("expected a literal, not a string for a {kind:?}")); self.err(format!("expected a literal, not a string for a {kind:?}"));
} }
Token::Placeholder(_, span) => { Token::Placeholder(_, span) => {
self.tcx.sess.span_err( self.tcx.sess.span_err(

View File

@ -13,6 +13,7 @@ use rustc_arena::DroplessArena;
use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::sync::Lrc; use rustc_data_structures::sync::Lrc;
use rustc_middle::bug; use rustc_middle::bug;
use rustc_middle::mir::interpret::ConstAllocation;
use rustc_middle::ty::TyCtxt; use rustc_middle::ty::TyCtxt;
use rustc_span::source_map::SourceMap; use rustc_span::source_map::SourceMap;
use rustc_span::symbol::Symbol; use rustc_span::symbol::Symbol;
@ -206,8 +207,8 @@ impl SpirvValueExt for Word {
} }
} }
#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum SpirvConst<'tcx> { pub enum SpirvConst<'a, 'tcx> {
U32(u32), U32(u32),
U64(u64), U64(u64),
/// f32 isn't hash, so store bits /// f32 isn't hash, so store bits
@ -225,16 +226,23 @@ pub enum SpirvConst<'tcx> {
// different functions, but of the same type, don't overlap their zombies. // different functions, but of the same type, don't overlap their zombies.
ZombieUndefForFnAddr, ZombieUndefForFnAddr,
Composite(&'tcx [Word]), Composite(&'a [Word]),
/// Pointer to constant data, i.e. `&pointee`, represented as an `OpVariable` /// Pointer to constant data, i.e. `&pointee`, represented as an `OpVariable`
/// in the `Private` storage class, and with `pointee` as its initializer. /// in the `Private` storage class, and with `pointee` as its initializer.
PtrTo { PtrTo {
pointee: Word, pointee: Word,
}, },
/// Symbolic result for the `const_data_from_alloc` method, to allow deferring
/// the actual value generation until after a pointer to this value is cast
/// to its final type (e.g. that will be loaded as).
//
// FIXME(eddyb) replace this with `qptr` handling of constant data.
ConstDataFromAlloc(ConstAllocation<'tcx>),
} }
impl SpirvConst<'_> { impl<'tcx> SpirvConst<'_, 'tcx> {
/// Replace `&[T]` fields with `&'tcx [T]` ones produced by calling /// Replace `&[T]` fields with `&'tcx [T]` ones produced by calling
/// `tcx.arena.dropless.alloc_slice(...)` - this is done late for two reasons: /// `tcx.arena.dropless.alloc_slice(...)` - this is done late for two reasons:
/// 1. it avoids allocating in the arena when the cache would be hit anyway, /// 1. it avoids allocating in the arena when the cache would be hit anyway,
@ -242,7 +250,7 @@ impl SpirvConst<'_> {
/// (ideally these would also be interned, but that's even more refactors) /// (ideally these would also be interned, but that's even more refactors)
/// 2. an empty slice is disallowed (as it's usually handled as a special /// 2. an empty slice is disallowed (as it's usually handled as a special
/// case elsewhere, e.g. `rustc`'s `ty::List` - sadly we can't use that) /// case elsewhere, e.g. `rustc`'s `ty::List` - sadly we can't use that)
fn tcx_arena_alloc_slices<'tcx>(self, cx: &CodegenCx<'tcx>) -> SpirvConst<'tcx> { fn tcx_arena_alloc_slices(self, cx: &CodegenCx<'tcx>) -> SpirvConst<'tcx, 'tcx> {
fn arena_alloc_slice<'tcx, T: Copy>(cx: &CodegenCx<'tcx>, xs: &[T]) -> &'tcx [T] { fn arena_alloc_slice<'tcx, T: Copy>(cx: &CodegenCx<'tcx>, xs: &[T]) -> &'tcx [T] {
if xs.is_empty() { if xs.is_empty() {
&[] &[]
@ -264,6 +272,8 @@ impl SpirvConst<'_> {
SpirvConst::PtrTo { pointee } => SpirvConst::PtrTo { pointee }, SpirvConst::PtrTo { pointee } => SpirvConst::PtrTo { pointee },
SpirvConst::Composite(fields) => SpirvConst::Composite(arena_alloc_slice(cx, fields)), SpirvConst::Composite(fields) => SpirvConst::Composite(arena_alloc_slice(cx, fields)),
SpirvConst::ConstDataFromAlloc(alloc) => SpirvConst::ConstDataFromAlloc(alloc),
} }
} }
} }
@ -282,6 +292,12 @@ enum LeafIllegalConst {
/// as its operands, and `OpVariable`s are never considered constant. /// as its operands, and `OpVariable`s are never considered constant.
// FIXME(eddyb) figure out if this is an accidental omission in SPIR-V. // FIXME(eddyb) figure out if this is an accidental omission in SPIR-V.
CompositeContainsPtrTo, CompositeContainsPtrTo,
/// `ConstDataFromAlloc` constant, which cannot currently be materialized
/// to SPIR-V (and requires to be wrapped in `PtrTo` and bitcast, first).
//
// FIXME(eddyb) replace this with `qptr` handling of constant data.
UntypedConstDataFromAlloc,
} }
impl LeafIllegalConst { impl LeafIllegalConst {
@ -290,6 +306,10 @@ impl LeafIllegalConst {
Self::CompositeContainsPtrTo => { Self::CompositeContainsPtrTo => {
"constant arrays/structs cannot contain pointers to other constants" "constant arrays/structs cannot contain pointers to other constants"
} }
Self::UntypedConstDataFromAlloc => {
"`const_data_from_alloc` result wasn't passed through `static_addr_of`, \
then `const_bitcast` (which would've given it a type)"
}
} }
} }
} }
@ -391,8 +411,8 @@ pub struct BuilderSpirv<'tcx> {
// (e.g. `OpConstant...`) instruction. // (e.g. `OpConstant...`) instruction.
// NOTE(eddyb) both maps have `WithConstLegality` around their keys, which // NOTE(eddyb) both maps have `WithConstLegality` around their keys, which
// allows getting that legality information without additional lookups. // allows getting that legality information without additional lookups.
const_to_id: RefCell<FxHashMap<WithType<SpirvConst<'tcx>>, WithConstLegality<Word>>>, const_to_id: RefCell<FxHashMap<WithType<SpirvConst<'tcx, 'tcx>>, WithConstLegality<Word>>>,
id_to_const: RefCell<FxHashMap<Word, WithConstLegality<SpirvConst<'tcx>>>>, id_to_const: RefCell<FxHashMap<Word, WithConstLegality<SpirvConst<'tcx, 'tcx>>>>,
debug_file_cache: RefCell<FxHashMap<DebugFileKey, DebugFileSpirv<'tcx>>>, debug_file_cache: RefCell<FxHashMap<DebugFileKey, DebugFileSpirv<'tcx>>>,
@ -535,7 +555,7 @@ impl<'tcx> BuilderSpirv<'tcx> {
pub(crate) fn def_constant_cx( pub(crate) fn def_constant_cx(
&self, &self,
ty: Word, ty: Word,
val: SpirvConst<'_>, val: SpirvConst<'_, 'tcx>,
cx: &CodegenCx<'tcx>, cx: &CodegenCx<'tcx>,
) -> SpirvValue { ) -> SpirvValue {
let val_with_type = WithType { ty, val }; let val_with_type = WithType { ty, val };
@ -564,7 +584,9 @@ impl<'tcx> BuilderSpirv<'tcx> {
} }
SpirvConst::Null => builder.constant_null(ty), SpirvConst::Null => builder.constant_null(ty),
SpirvConst::Undef | SpirvConst::ZombieUndefForFnAddr => builder.undef(ty, None), SpirvConst::Undef
| SpirvConst::ZombieUndefForFnAddr
| SpirvConst::ConstDataFromAlloc(_) => builder.undef(ty, None),
SpirvConst::Composite(v) => builder.constant_composite(ty, v.iter().copied()), SpirvConst::Composite(v) => builder.constant_composite(ty, v.iter().copied()),
@ -635,6 +657,10 @@ impl<'tcx> BuilderSpirv<'tcx> {
Err(IllegalConst::Indirect(cause)) Err(IllegalConst::Indirect(cause))
} }
}, },
SpirvConst::ConstDataFromAlloc(_) => Err(IllegalConst::Shallow(
LeafIllegalConst::UntypedConstDataFromAlloc,
)),
}; };
let val = val.tcx_arena_alloc_slices(cx); let val = val.tcx_arena_alloc_slices(cx);
assert_matches!( assert_matches!(
@ -658,11 +684,11 @@ impl<'tcx> BuilderSpirv<'tcx> {
SpirvValue { kind, ty } SpirvValue { kind, ty }
} }
pub fn lookup_const_by_id(&self, id: Word) -> Option<SpirvConst<'tcx>> { pub fn lookup_const_by_id(&self, id: Word) -> Option<SpirvConst<'tcx, 'tcx>> {
Some(self.id_to_const.borrow().get(&id)?.val) Some(self.id_to_const.borrow().get(&id)?.val)
} }
pub fn lookup_const(&self, def: SpirvValue) -> Option<SpirvConst<'tcx>> { pub fn lookup_const(&self, def: SpirvValue) -> Option<SpirvConst<'tcx, 'tcx>> {
match def.kind { match def.kind {
SpirvValueKind::Def(id) | SpirvValueKind::IllegalConst(id) => { SpirvValueKind::Def(id) | SpirvValueKind::IllegalConst(id) => {
self.lookup_const_by_id(id) self.lookup_const_by_id(id)

View File

@ -1,18 +1,17 @@
use super::CodegenCx; use super::CodegenCx;
use crate::abi::ConvSpirvType; use crate::abi::ConvSpirvType;
use crate::builder_spirv::{SpirvConst, SpirvValue, SpirvValueExt}; use crate::builder_spirv::{SpirvConst, SpirvValue, SpirvValueExt, SpirvValueKind};
use crate::spirv_type::SpirvType; use crate::spirv_type::SpirvType;
use rspirv::spirv::Word; use rspirv::spirv::Word;
use rustc_codegen_ssa::mir::place::PlaceRef;
use rustc_codegen_ssa::traits::{BaseTypeMethods, ConstMethods, MiscMethods, StaticMethods}; use rustc_codegen_ssa::traits::{BaseTypeMethods, ConstMethods, MiscMethods, StaticMethods};
use rustc_middle::bug; use rustc_middle::bug;
use rustc_middle::mir::interpret::{alloc_range, ConstAllocation, GlobalAlloc, Scalar}; use rustc_middle::mir::interpret::{alloc_range, ConstAllocation, GlobalAlloc, Scalar};
use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; use rustc_middle::ty::layout::LayoutOf;
use rustc_span::{Span, DUMMY_SP}; use rustc_span::{Span, DUMMY_SP};
use rustc_target::abi::{self, AddressSpace, HasDataLayout, Integer, Primitive, Size}; use rustc_target::abi::{self, AddressSpace, HasDataLayout, Integer, Primitive, Size};
impl<'tcx> CodegenCx<'tcx> { impl<'tcx> CodegenCx<'tcx> {
pub fn def_constant(&self, ty: Word, val: SpirvConst<'_>) -> SpirvValue { pub fn def_constant(&self, ty: Word, val: SpirvConst<'_, 'tcx>) -> SpirvValue {
self.builder.def_constant_cx(ty, val, self) self.builder.def_constant_cx(ty, val, self)
} }
@ -137,8 +136,22 @@ impl<'tcx> ConstMethods<'tcx> for CodegenCx<'tcx> {
fn const_uint(&self, t: Self::Type, i: u64) -> Self::Value { fn const_uint(&self, t: Self::Type, i: u64) -> Self::Value {
self.constant_int(t, i) self.constant_int(t, i)
} }
fn const_uint_big(&self, t: Self::Type, u: u128) -> Self::Value { // FIXME(eddyb) support `u128`.
self.constant_int(t, u as u64) 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
} }
fn const_bool(&self, val: bool) -> Self::Value { fn const_bool(&self, val: bool) -> Self::Value {
self.constant_bool(DUMMY_SP, val) self.constant_bool(DUMMY_SP, val)
@ -155,6 +168,10 @@ impl<'tcx> ConstMethods<'tcx> for CodegenCx<'tcx> {
fn const_u64(&self, i: u64) -> Self::Value { fn const_u64(&self, i: u64) -> Self::Value {
self.constant_u64(DUMMY_SP, i) self.constant_u64(DUMMY_SP, i)
} }
fn const_u128(&self, i: u128) -> Self::Value {
let ty = SpirvType::Integer(128, false).def(DUMMY_SP, self);
self.const_uint_big(ty, i)
}
fn const_usize(&self, i: u64) -> Self::Value { fn const_usize(&self, i: u64) -> Self::Value {
let ptr_size = self.tcx.data_layout.pointer_size.bits() as u32; let ptr_size = self.tcx.data_layout.pointer_size.bits() as u32;
let t = SpirvType::Integer(ptr_size, false).def(DUMMY_SP, self); let t = SpirvType::Integer(ptr_size, false).def(DUMMY_SP, self);
@ -335,36 +352,64 @@ impl<'tcx> ConstMethods<'tcx> for CodegenCx<'tcx> {
} }
} }
// FIXME(eddyb) this shouldn't exist, and is only used by vtable creation, // HACK(eddyb) this uses a symbolic `ConstDataFromAlloc`, to allow deferring
// see https://github.com/rust-lang/rust/pull/86475#discussion_r680792727. // the actual value generation until after a pointer to this value is cast
fn const_data_from_alloc(&self, _alloc: ConstAllocation<'tcx>) -> Self::Value { // to its final type (e.g. that will be loaded as).
let undef = self.undef(SpirvType::Void.def(DUMMY_SP, self)); // FIXME(eddyb) replace this with `qptr` handling of constant data.
self.zombie_no_span(undef.def_cx(self), "const_data_from_alloc"); fn const_data_from_alloc(&self, alloc: ConstAllocation<'tcx>) -> Self::Value {
undef let void_type = SpirvType::Void.def(DUMMY_SP, self);
} self.def_constant(void_type, SpirvConst::ConstDataFromAlloc(alloc))
fn from_const_alloc(
&self,
layout: TyAndLayout<'tcx>,
alloc: ConstAllocation<'tcx>,
offset: Size,
) -> PlaceRef<'tcx, Self::Value> {
assert_eq!(offset, Size::ZERO);
let ty = layout.spirv_type(DUMMY_SP, self);
let init = self.create_const_alloc(alloc, ty);
let result = self.static_addr_of(init, alloc.inner().align, None);
PlaceRef::new_sized(result, layout)
} }
// FIXME(eddyb) is this just redundant with `const_bitcast`?!
fn const_ptrcast(&self, val: Self::Value, ty: Self::Type) -> Self::Value { fn const_ptrcast(&self, val: Self::Value, ty: Self::Type) -> Self::Value {
if val.ty == ty { if val.ty == ty {
val val
} else { } else {
// constant ptrcast is not supported in spir-v // FIXME(eddyb) implement via `OpSpecConstantOp`.
// FIXME(eddyb) this zombies the original value without creating a new one.
let result = val.def_cx(self).with_type(ty); let result = val.def_cx(self).with_type(ty);
self.zombie_no_span(result.def_cx(self), "const_ptrcast"); self.zombie_no_span(result.def_cx(self), "const_ptrcast");
result result
} }
} }
fn const_bitcast(&self, val: Self::Value, ty: Self::Type) -> Self::Value {
// 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 {
if let Some(SpirvConst::PtrTo { pointee }) = self.builder.lookup_const(val) {
if let Some(SpirvConst::ConstDataFromAlloc(alloc)) =
self.builder.lookup_const_by_id(pointee)
{
if let SpirvType::Pointer { pointee } = self.lookup_type(ty) {
let init = self.create_const_alloc(alloc, pointee);
return self.static_addr_of(init, alloc.inner().align, None);
}
}
}
}
if val.ty == ty {
val
} else {
// FIXME(eddyb) implement via `OpSpecConstantOp`.
// FIXME(eddyb) this zombies the original value without creating a new one.
let result = val.def_cx(self).with_type(ty);
self.zombie_no_span(result.def_cx(self), "const_bitcast");
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> { impl<'tcx> CodegenCx<'tcx> {

View File

@ -15,8 +15,7 @@ use rspirv::spirv::{Decoration, LinkageType, Op, Word};
use rustc_ast::ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_ast::ast::{InlineAsmOptions, InlineAsmTemplatePiece};
use rustc_codegen_ssa::mir::debuginfo::{FunctionDebugContext, VariableKind}; use rustc_codegen_ssa::mir::debuginfo::{FunctionDebugContext, VariableKind};
use rustc_codegen_ssa::traits::{ use rustc_codegen_ssa::traits::{
AsmMethods, BackendTypes, CoverageInfoMethods, DebugInfoMethods, GlobalAsmOperandRef, AsmMethods, BackendTypes, DebugInfoMethods, GlobalAsmOperandRef, MiscMethods,
MiscMethods,
}; };
use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_middle::mir::mono::CodegenUnit; use rustc_middle::mir::mono::CodegenUnit;
@ -24,7 +23,6 @@ use rustc_middle::mir::Body;
use rustc_middle::ty::layout::{HasParamEnv, HasTyCtxt}; use rustc_middle::ty::layout::{HasParamEnv, HasTyCtxt};
use rustc_middle::ty::{Instance, ParamEnv, PolyExistentialTraitRef, Ty, TyCtxt}; use rustc_middle::ty::{Instance, ParamEnv, PolyExistentialTraitRef, Ty, TyCtxt};
use rustc_session::Session; use rustc_session::Session;
use rustc_span::def_id::DefId;
use rustc_span::symbol::Symbol; use rustc_span::symbol::Symbol;
use rustc_span::{SourceFile, Span, DUMMY_SP}; use rustc_span::{SourceFile, Span, DUMMY_SP};
use rustc_target::abi::call::{FnAbi, PassMode}; use rustc_target::abi::call::{FnAbi, PassMode};
@ -885,18 +883,6 @@ impl<'tcx> DebugInfoMethods<'tcx> for CodegenCx<'tcx> {
} }
} }
impl<'tcx> CoverageInfoMethods<'tcx> for CodegenCx<'tcx> {
fn coverageinfo_finalize(&self) {
todo!()
}
fn get_pgo_func_name_var(&self, _: Instance<'tcx>) -> SpirvValue {
todo!()
}
fn define_unused_fn(&self, _: DefId) {
todo!()
}
}
impl<'tcx> AsmMethods<'tcx> for CodegenCx<'tcx> { impl<'tcx> AsmMethods<'tcx> for CodegenCx<'tcx> {
fn codegen_global_asm( fn codegen_global_asm(
&self, &self,

View File

@ -9,7 +9,7 @@ use rustc_middle::ty::layout::{
}; };
use rustc_middle::ty::Ty; use rustc_middle::ty::Ty;
use rustc_middle::{bug, span_bug}; use rustc_middle::{bug, span_bug};
use rustc_span::source_map::{Span, DUMMY_SP}; use rustc_span::source_map::{Span, Spanned, DUMMY_SP};
use rustc_target::abi::call::{CastTarget, FnAbi, Reg}; use rustc_target::abi::call::{CastTarget, FnAbi, Reg};
use rustc_target::abi::{Abi, AddressSpace, FieldsShape}; use rustc_target::abi::{Abi, AddressSpace, FieldsShape};
@ -37,16 +37,13 @@ impl<'tcx> FnAbiOfHelpers<'tcx> for CodegenCx<'tcx> {
fn_abi_request: FnAbiRequest<'tcx>, fn_abi_request: FnAbiRequest<'tcx>,
) -> ! { ) -> ! {
if let FnAbiError::Layout(LayoutError::SizeOverflow(_)) = err { if let FnAbiError::Layout(LayoutError::SizeOverflow(_)) = err {
self.tcx.sess.span_fatal(span, err.to_string()) self.tcx.sess.emit_fatal(Spanned { span, node: err })
} else { } else {
match fn_abi_request { match fn_abi_request {
FnAbiRequest::OfFnPtr { sig, extra_args } => { FnAbiRequest::OfFnPtr { sig, extra_args } => {
span_bug!( span_bug!(
span, span,
"`fn_abi_of_fn_ptr({}, {:?})` failed: {}", "`fn_abi_of_fn_ptr({sig}, {extra_args:?})` failed: {err:?}",
sig,
extra_args,
err
); );
} }
FnAbiRequest::OfInstance { FnAbiRequest::OfInstance {
@ -55,10 +52,7 @@ impl<'tcx> FnAbiOfHelpers<'tcx> for CodegenCx<'tcx> {
} => { } => {
span_bug!( span_bug!(
span, span,
"`fn_abi_of_instance({}, {:?})` failed: {}", "`fn_abi_of_instance({instance}, {extra_args:?})` failed: {err:?}",
instance,
extra_args,
err
); );
} }
} }

View File

@ -97,7 +97,7 @@ use rustc_codegen_ssa::traits::{
WriteBackendMethods, WriteBackendMethods,
}; };
use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleCodegen, ModuleKind}; use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleCodegen, ModuleKind};
use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxIndexMap;
use rustc_errors::{ErrorGuaranteed, FatalError, Handler}; use rustc_errors::{ErrorGuaranteed, FatalError, Handler};
use rustc_metadata::EncodedMetadata; use rustc_metadata::EncodedMetadata;
use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
@ -257,7 +257,7 @@ impl CodegenBackend for SpirvCodegenBackend {
ongoing_codegen: Box<dyn Any>, ongoing_codegen: Box<dyn Any>,
sess: &Session, sess: &Session,
_outputs: &OutputFilenames, _outputs: &OutputFilenames,
) -> Result<(CodegenResults, FxHashMap<WorkProductId, WorkProduct>), ErrorGuaranteed> { ) -> Result<(CodegenResults, FxIndexMap<WorkProductId, WorkProduct>), ErrorGuaranteed> {
let (codegen_results, work_products) = ongoing_codegen let (codegen_results, work_products) = ongoing_codegen
.downcast::<OngoingCodegen<Self>>() .downcast::<OngoingCodegen<Self>>()
.expect("Expected OngoingCodegen, found Box<Any>") .expect("Expected OngoingCodegen, found Box<Any>")

View File

@ -14,7 +14,9 @@ use rustc_metadata::fs::METADATA_FILENAME;
use rustc_middle::bug; use rustc_middle::bug;
use rustc_middle::dep_graph::WorkProduct; use rustc_middle::dep_graph::WorkProduct;
use rustc_middle::middle::dependency_format::Linkage; use rustc_middle::middle::dependency_format::Linkage;
use rustc_session::config::{CrateType, DebugInfo, Lto, OptLevel, OutputFilenames, OutputType}; 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::output::{check_file_is_writeable, invalid_output_for_target, out_filename};
use rustc_session::utils::NativeLibKind; use rustc_session::utils::NativeLibKind;
use rustc_session::Session; use rustc_session::Session;
@ -60,9 +62,11 @@ pub fn link(
if outputs.outputs.should_codegen() { if outputs.outputs.should_codegen() {
let out_filename = out_filename(sess, crate_type, outputs, Symbol::intern(crate_name)); let out_filename = out_filename(sess, crate_type, outputs, Symbol::intern(crate_name));
let out_filename_file_for_writing =
out_filename.file_for_writing(outputs, OutputType::Exe, None);
match crate_type { match crate_type {
CrateType::Rlib => { CrateType::Rlib => {
link_rlib(sess, codegen_results, &out_filename); link_rlib(sess, codegen_results, &out_filename_file_for_writing);
} }
CrateType::Executable | CrateType::Cdylib | CrateType::Dylib => { CrateType::Executable | CrateType::Cdylib | CrateType::Dylib => {
// HACK(eddyb) there's no way way to access `outputs.filestem`, // HACK(eddyb) there's no way way to access `outputs.filestem`,
@ -76,7 +80,7 @@ pub fn link(
link_exe( link_exe(
sess, sess,
crate_type, crate_type,
&out_filename, &out_filename_file_for_writing,
codegen_results, codegen_results,
outputs, outputs,
&disambiguated_crate_name_for_dumps, &disambiguated_crate_name_for_dumps,
@ -86,6 +90,21 @@ pub fn link(
sess.err(format!("CrateType {other:?} not supported yet")); sess.err(format!("CrateType {other:?} not supported yet"));
} }
} }
match out_filename {
OutFileName::Real(_) => {
// Already written to, above.
}
OutFileName::Stdout => {
// HACK(eddyb) wrote a file above, time to read it back out.
std::io::copy(
&mut std::io::BufReader::new(
std::fs::File::open(out_filename_file_for_writing).unwrap(),
),
&mut std::io::stdout(),
)
.unwrap();
}
}
} }
} }
} }

View File

@ -95,11 +95,20 @@ fn link_with_linker_opts(
// is really a silent unwinding device, that should be treated the same as // is really a silent unwinding device, that should be treated the same as
// `Err(ErrorGuaranteed)` returns from `link`). // `Err(ErrorGuaranteed)` returns from `link`).
rustc_driver::catch_fatal_errors(|| { rustc_driver::catch_fatal_errors(|| {
let matches = rustc_driver::handle_options(&["".to_string(), "x.rs".to_string()]).unwrap(); let mut early_error_handler = rustc_session::EarlyErrorHandler::new(
let sopts = rustc_session::config::build_session_options(&matches); rustc_session::config::ErrorOutputType::default(),
);
let matches = rustc_driver::handle_options(
&early_error_handler,
&["".to_string(), "x.rs".to_string()],
)
.unwrap();
let sopts =
rustc_session::config::build_session_options(&mut early_error_handler, &matches);
rustc_span::create_session_globals_then(sopts.edition, || { rustc_span::create_session_globals_then(sopts.edition, || {
let mut sess = rustc_session::build_session( let mut sess = rustc_session::build_session(
&early_error_handler,
sopts, sopts,
CompilerIO { CompilerIO {
input: Input::Str { input: Input::Str {

View File

@ -1,7 +1,7 @@
[toolchain] [toolchain]
channel = "nightly-2023-05-27" channel = "nightly-2023-07-08"
components = ["rust-src", "rustc-dev", "llvm-tools-preview"] components = ["rust-src", "rustc-dev", "llvm-tools-preview"]
# commit_hash = 1a5f8bce74ee432f7cc3aa131bc3d6920e06de10 # commit_hash = cb80ff132a0e9aa71529b701427e4e6c243b58df
# Whenever changing the nightly channel, update the commit hash above, and make # 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. # sure to change `REQUIRED_TOOLCHAIN` in `crates/rustc_codegen_spirv/build.rs` also.

View File

@ -11,9 +11,17 @@
#![feature(adt_const_params)] #![feature(adt_const_params)]
#![allow(incomplete_features)] #![allow(incomplete_features)]
use spirv_std::image::Dimensionality;
use spirv_std::spirv; use spirv_std::spirv;
// HACK(eddyb) not using `spirv_std::image::Dimensionality` as that `enum` doesn't
// actually implement `ConstParamTy` (nor do we need *that* `enum`, just any).
#[derive(PartialEq, Eq, PartialOrd, Ord, core::marker::ConstParamTy)]
enum Dimensionality {
OneD,
TwoD,
ThreeD,
}
fn generic<T, const DIM: Dimensionality>() {} fn generic<T, const DIM: Dimensionality>() {}
#[spirv(fragment)] #[spirv(fragment)]

View File

@ -10,6 +10,6 @@ OpEntryPoint Fragment %1 "main"
OpExecutionMode %1 OriginUpperLeft OpExecutionMode %1 OriginUpperLeft
%2 = OpString "$OPSTRING_FILENAME/generic-fn-op-name.rs" %2 = OpString "$OPSTRING_FILENAME/generic-fn-op-name.rs"
OpName %3 "generic_fn_op_name::main" OpName %3 "generic_fn_op_name::main"
OpName %4 "generic_fn_op_name::generic::<f32, {spirv_std_types::image_params::Dimensionality::TwoD}>" OpName %4 "generic_fn_op_name::generic::<f32, {generic_fn_op_name::Dimensionality::TwoD}>"
%5 = OpTypeVoid %5 = OpTypeVoid
%6 = OpTypeFunction %5 %6 = OpTypeFunction %5

View File

@ -1,13 +1,13 @@
error: cannot memcpy dynamically sized data error: cannot memcpy dynamically sized data
--> $CORE_SRC/intrinsics.rs:2760:9 --> $CORE_SRC/intrinsics.rs:2767:9
| |
2760 | copy(src, dst, count) 2767 | copy(src, dst, count)
| ^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^
| |
note: used from within `core::intrinsics::copy::<f32>` note: used from within `core::intrinsics::copy::<f32>`
--> $CORE_SRC/intrinsics.rs:2746:21 --> $CORE_SRC/intrinsics.rs:2753:21
| |
2746 | pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) { 2753 | pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
| ^^^^ | ^^^^
note: called by `ptr_copy::copy_via_raw_ptr` note: called by `ptr_copy::copy_via_raw_ptr`
--> $DIR/ptr_copy.rs:28:18 --> $DIR/ptr_copy.rs:28:18

View File

@ -2,7 +2,7 @@
%4 = OpFunctionParameter %5 %4 = OpFunctionParameter %5
%6 = OpFunctionParameter %5 %6 = OpFunctionParameter %5
%7 = OpLabel %7 = OpLabel
OpLine %8 1178 8 OpLine %8 1179 8
%9 = OpLoad %10 %4 %9 = OpLoad %10 %4
OpLine %11 7 13 OpLine %11 7 13
OpStore %6 %9 OpStore %6 %9

View File

@ -2,7 +2,7 @@
%4 = OpFunctionParameter %5 %4 = OpFunctionParameter %5
%6 = OpFunctionParameter %5 %6 = OpFunctionParameter %5
%7 = OpLabel %7 = OpLabel
OpLine %8 1178 8 OpLine %8 1179 8
%9 = OpLoad %10 %4 %9 = OpLoad %10 %4
OpLine %11 7 13 OpLine %11 7 13
OpStore %6 %9 OpStore %6 %9

View File

@ -4,7 +4,7 @@
%7 = OpLabel %7 = OpLabel
OpLine %8 7 35 OpLine %8 7 35
%9 = OpLoad %10 %4 %9 = OpLoad %10 %4
OpLine %11 1376 8 OpLine %11 1377 8
OpStore %6 %9 OpStore %6 %9
OpNoLine OpNoLine
OpReturn OpReturn

View File

@ -4,7 +4,7 @@
%7 = OpLabel %7 = OpLabel
OpLine %8 7 37 OpLine %8 7 37
%9 = OpLoad %10 %4 %9 = OpLoad %10 %4
OpLine %11 1376 8 OpLine %11 1377 8
OpStore %6 %9 OpStore %6 %9
OpNoLine OpNoLine
OpReturn OpReturn