mirror of
https://github.com/EmbarkStudios/rust-gpu.git
synced 2024-11-21 22:34:34 +00:00
rustup: update to nightly-2023-07-08
.
This commit is contained in:
parent
c2f98b612a
commit
50ebb52619
@ -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
4
Cargo.lock
generated
@ -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",
|
||||||
]
|
]
|
||||||
|
@ -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"));
|
||||||
|
@ -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]>),
|
||||||
|
@ -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()
|
||||||
|
@ -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() {
|
||||||
|
@ -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> {
|
||||||
|
@ -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(
|
||||||
|
@ -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)
|
||||||
|
@ -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> {
|
||||||
|
@ -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,
|
||||||
|
@ -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
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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>")
|
||||||
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
@ -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.
|
||||||
|
@ -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)]
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user