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]
### Changed 🛠
- [PR#1085](https://github.com/EmbarkStudios/rust-gpu/pull/1085) updated toolchain to `nightly-2023-07-08`
## [0.9.0]
### Added ⭐

4
Cargo.lock generated
View File

@ -1837,9 +1837,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.47"
version = "1.0.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725"
checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9"
dependencies = [
"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 :/
//const REQUIRED_RUST_TOOLCHAIN: &str = include_str!("../../rust-toolchain.toml");
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"]
# commit_hash = 1a5f8bce74ee432f7cc3aa131bc3d6920e06de10"#;
# commit_hash = cb80ff132a0e9aa71529b701427e4e6c243b58df"#;
fn get_rustc_commit_hash() -> Result<String, Box<dyn Error>> {
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
.constant_u64(self.span(), memset_fill_u64(fill_byte))
.def(self),
_ => self.fatal(&format!(
_ => self.fatal(format!(
"memset on integer width {width} not implemented yet"
)),
},
@ -212,9 +212,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
64 => self
.constant_f64(self.span(), f64::from_bits(memset_fill_u64(fill_byte)))
.def(self),
_ => self.fatal(&format!(
"memset on float width {width} not implemented yet"
)),
_ => self.fatal(format!("memset on float width {width} not implemented yet")),
},
SpirvType::Adt { .. } => self.fatal("memset on structs not implemented yet"),
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),
32 => memset_dynamic_scalar(self, fill_var, 4, false),
64 => memset_dynamic_scalar(self, fill_var, 8, false),
_ => self.fatal(&format!(
_ => self.fatal(format!(
"memset on integer width {width} not implemented yet"
)),
},
SpirvType::Float(width) => match width {
32 => memset_dynamic_scalar(self, fill_var, 4, true),
64 => memset_dynamic_scalar(self, fill_var, 8, true),
_ => self.fatal(&format!(
"memset on float width {width} not implemented yet"
)),
_ => self.fatal(format!("memset on float width {width} not implemented yet")),
},
SpirvType::Adt { .. } => self.fatal("memset on structs not implemented yet"),
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 {
if v > u8::MAX as u128 {
self_.fatal(&format!(
self_.fatal(format!(
"Switches to values above u8::MAX not supported: {v:?}"
))
} 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 {
if v > u16::MAX as u128 {
self_.fatal(&format!(
self_.fatal(format!(
"Switches to values above u16::MAX not supported: {v:?}"
))
} 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 {
if v > u32::MAX as u128 {
self_.fatal(&format!(
self_.fatal(format!(
"Switches to values above u32::MAX not supported: {v:?}"
))
} 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 {
if v > u64::MAX as u128 {
self_.fatal(&format!(
self_.fatal(format!(
"Switches to values above u64::MAX not supported: {v:?}"
))
} else {
@ -852,13 +848,13 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
16 => construct_16,
32 => construct_32,
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)"
)),
};
(signed, construct_case)
}
other => self.fatal(&format!(
other => self.fatal(format!(
"switch selector cannot have non-integer type {}",
other.debug(v.ty, self)
)),
@ -947,7 +943,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
SpirvType::Bool => self
.emit()
.logical_and(ty, None, lhs.def(self), rhs.def(self)),
o => self.fatal(&format!(
o => self.fatal(format!(
"and() not implemented for type {}",
o.debug(ty, self)
)),
@ -966,7 +962,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
SpirvType::Bool => self
.emit()
.logical_or(ty, None, lhs.def(self), rhs.def(self)),
o => self.fatal(&format!(
o => self.fatal(format!(
"or() not implemented for type {}",
o.debug(ty, self)
)),
@ -986,7 +982,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
self.emit()
.logical_not_equal(ty, None, lhs.def(self), rhs.def(self))
}
o => self.fatal(&format!(
o => self.fatal(format!(
"xor() not implemented for type {}",
o.debug(ty, self)
)),
@ -1003,7 +999,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
self.emit()
.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 {}",
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);
pointee
}
ty => self.fatal(&format!(
ty => self.fatal(format!(
"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);
pointee
}
ty => self.fatal(&format!(
ty => self.fatal(format!(
"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>,
) -> OperandRef<'tcx, Self::Value> {
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 {
@ -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 {
let ptr_elem_ty = match self.lookup_type(ptr.ty) {
SpirvType::Pointer { pointee } => pointee,
ty => self.fatal(&format!(
ty => self.fatal(format!(
"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,
) -> Self::Value {
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)
}
@ -1282,7 +1278,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
) {
let ptr_elem_ty = match self.lookup_type(ptr.ty) {
SpirvType::Pointer { pointee } => pointee,
ty => self.fatal(&format!(
ty => self.fatal(format!(
"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);
pointee
}
other => self.fatal(&format!(
other => self.fatal(format!(
"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);
inner_type
}
other => self.fatal(&format!(
other => self.fatal(format!(
"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 {
match self.lookup_type(val.ty) {
SpirvType::Pointer { .. } => (),
other => self.fatal(&format!(
other => self.fatal(format!(
"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 {
match self.lookup_type(dest_ty) {
SpirvType::Pointer { .. } => (),
other => self.fatal(&format!(
other => self.fatal(format!(
"inttoptr called on non-pointer dest type: {other:?}"
)),
}
@ -1603,7 +1599,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
.unwrap()
.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}"
)),
}
@ -1628,14 +1624,14 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
_ => match self.lookup_type(val.ty) {
SpirvType::Pointer { pointee } => (val, pointee),
other => self.fatal(&format!(
other => self.fatal(format!(
"pointercast called on non-pointer source type: {other:?}"
)),
},
};
let dest_pointee = match self.lookup_type(dest_ty) {
SpirvType::Pointer { pointee } => pointee,
other => self.fatal(&format!(
other => self.fatal(format!(
"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"),
IntSLE => self.fatal("TODO: boolean operator IntSLE not implemented yet"),
},
other => self.fatal(&format!(
other => self.fatal(format!(
"Int comparison not implemented on {}",
other.debug(lhs.ty, self)
)),
@ -1930,7 +1926,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
flags: MemFlags,
) {
if flags != MemFlags::empty() {
self.err(&format!(
self.err(format!(
"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,
) {
if flags != MemFlags::empty() {
self.err(&format!(
self.err(format!(
"memset with mem flags is not supported yet: {flags:?}"
));
}
let elem_ty = match self.lookup_type(ptr.ty) {
SpirvType::Pointer { pointee } => pointee,
_ => self.fatal(&format!(
_ => self.fatal(format!(
"memset called on non-pointer type: {}",
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 {
let result_type = match self.lookup_type(vec.ty) {
SpirvType::Vector { element, .. } => element,
other => self.fatal(&format!(
"extract_element not implemented on type {other:?}"
)),
other => self.fatal(format!("extract_element not implemented on type {other:?}")),
};
match self.builder.lookup_const_u64(idx) {
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::Vector { element, .. }
| SpirvType::Matrix { element, .. } => element,
other => self.fatal(&format!(
other => self.fatal(format!(
"extract_value not implemented on type {}",
other.debug(agg_val.ty, self)
)),
@ -2105,7 +2099,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
SpirvType::Adt { field_types, .. } => {
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()
.composite_insert(
@ -2173,7 +2167,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
) -> Self::Value {
let dst_pointee_ty = match self.lookup_type(dst.ty) {
SpirvType::Pointer { pointee } => pointee,
ty => self.fatal(&format!(
ty => self.fatal(format!(
"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 {
let dst_pointee_ty = match self.lookup_type(dst.ty) {
SpirvType::Pointer { pointee } => pointee,
ty => self.fatal(&format!(
ty => self.fatal(format!(
"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> {
Bitcast(ID, ID),
CompositeExtract(ID, ID, u32),
AccessChain(ID, ID, SpirvConst<'tcx>),
InBoundsAccessChain(ID, ID, SpirvConst<'tcx>),
AccessChain(ID, ID, SpirvConst<'tcx, 'tcx>),
InBoundsAccessChain(ID, ID, SpirvConst<'tcx, 'tcx>),
Store(ID, ID),
Load(ID, ID),
Call(ID, ID, SmallVec<[ID; 4]>),

View File

@ -10,7 +10,7 @@ use rustc_target::abi::{Align, Size};
impl<'a, 'tcx> Builder<'a, 'tcx> {
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",
self.debug_type(original_type)
));
@ -191,7 +191,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// Signature: fn load<T>(array: &[u32], index: u32) -> T;
if args.len() != 3 {
self.fatal(&format!(
self.fatal(format!(
"buffer_load_intrinsic should have 3 args, it has {}",
args.len()
));
@ -205,7 +205,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
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",
self.debug_type(original_type)
));
@ -358,7 +358,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
};
let expected_args = if is_pair { 5 } else { 4 };
if args.len() != expected_args {
self.fatal(&format!(
self.fatal(format!(
"buffer_store_intrinsic should have {} args, it has {}",
expected_args,
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())
}
TyKind::Float(_) => self.fadd(args[0].immediate(), args[1].immediate()),
other => self.fatal(&format!(
other => self.fatal(format!(
"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())
}
TyKind::Float(_) => self.fsub(args[0].immediate(), args[1].immediate()),
other => self.fatal(&format!(
other => self.fatal(format!(
"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() {

View File

@ -20,10 +20,8 @@ use rustc_codegen_ssa::traits::{
AbiBuilderMethods, ArgAbiMethods, BackendTypes, BuilderMethods, CoverageInfoBuilderMethods,
DebugInfoBuilderMethods, HasCodegen, StaticBuilderMethods, TypeMembershipMethods,
};
use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed};
use rustc_middle::mir::coverage::{
CodeRegion, CounterValueReference, ExpressionOperandId, InjectedExpressionId, Op,
};
use rustc_errors::{DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed};
use rustc_middle::mir::Coverage;
use rustc_middle::span_bug;
use rustc_middle::ty::layout::{
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 {
self.tcx.sess.struct_span_err(current_span, msg)
} 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 {
self.tcx.sess.span_err(current_span, msg);
} 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 {
self.tcx.sess.span_fatal(current_span, msg)
} else {
@ -136,7 +140,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
assert_ty_eq!(self, ty, pointee);
pointee
}
other_type => self.fatal(&format!(
other_type => self.fatal(format!(
"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_pointee_type = match self.lookup_type(result_pointee_type) {
SpirvType::Array { element, .. } | SpirvType::RuntimeArray { element } => element,
_ => self.fatal(&format!(
_ => self.fatal(format!(
"GEP not implemented for 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 {
let width = match self.lookup_type(shift.ty) {
SpirvType::Integer(width, _) => width,
other => self.fatal(&format!(
other => self.fatal(format!(
"cannot rotate non-integer type: {}",
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> {
fn set_function_source_hash(&mut self, _: rustc_middle::ty::Instance<'tcx>, _: u64) -> bool {
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!()
}
fn add_coverage(&mut self, _instance: Instance<'tcx>, _coverage: &Coverage) {}
}
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;
let unsupported_options = options & !SUPPORTED_OPTIONS;
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
let mut tokens = vec![vec![]];
@ -162,14 +162,14 @@ impl<'a, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'tcx> {
}
(false, AsmBlock::Open) => (),
(false, AsmBlock::End(terminator)) => {
self.err(&format!(
self.err(format!(
"trailing terminator `Op{terminator:?}` requires `options(noreturn)`"
));
}
}
for (id, num) in id_map {
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(escape) => {
self.err(&format!("invalid escape '\\{escape}'"));
self.err(format!("invalid escape '\\{escape}'"));
return None;
}
};
@ -359,7 +359,7 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> {
// NOTE(eddyb) allowing the instruction to be added below avoids
// spurious "`noreturn` requires a terminator at the end" errors.
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"
))
.note(
@ -383,7 +383,7 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> {
}
AsmBlock::End(terminator) => {
if op != Op::Label {
self.err(&format!(
self.err(format!(
"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 {
inst
} else {
self.err(&format!("unknown spirv instruction {inst_name}"));
self.err(format!("unknown spirv instruction {inst_name}"));
return;
};
let result_id = match out_register {
@ -521,7 +521,7 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> {
if kind == OperandKind::IdResult {
assert_eq!(quantifier, OperandQuantifier::One);
if instruction.result_id.is_none() {
self.err(&format!(
self.err(format!(
"instruction {} expects a result id",
instruction.class.opname
));
@ -539,7 +539,7 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> {
instruction.result_type = Some(id);
}
} else {
self.err(&format!(
self.err(format!(
"instruction {} expects a result type",
instruction.class.opname
));
@ -552,7 +552,7 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> {
match quantifier {
OperandQuantifier::One => {
if !self.parse_one_operand(id_map, instruction, kind, &mut tokens) {
self.err(&format!(
self.err(format!(
"expected operand after instruction: {}",
instruction.class.opname
));
@ -576,7 +576,7 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> {
}
if !saw_id_result && instruction.result_id.is_some() {
self.err(&format!(
self.err(format!(
"instruction {} does not expect a result id",
instruction.class.opname
));
@ -593,7 +593,7 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> {
match self.infer_result_type(id_to_type_map, instruction) {
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.class.opname
)),
@ -816,7 +816,7 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> {
Some(OutRegister::Regular({
let num = *id_map.entry(id).or_insert_with(|| self.emit().id());
if !defined_ids.insert(num) {
self.err(&format!("%{id} is defined more than once"));
self.err(format!("%{id} is defined more than once"));
}
num
}))
@ -1078,7 +1078,7 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> {
(OperandKind::LiteralInteger, Some(word)) => match word.parse() {
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, _) => {
if let Token::String(value) = token {
@ -1128,12 +1128,12 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> {
}
match parse(self.lookup_type(ty), word) {
Ok(op) => inst.operands.push(op),
Err(err) => self.err(&err),
Err(err) => self.err(err),
}
}
(OperandKind::LiteralExtInstInteger, Some(word)) => match word.parse() {
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)) => {
match self.instruction_table.table.get(word) {
@ -1154,11 +1154,11 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> {
Some(Token::Word(word)) => match word.parse() {
Ok(v) => inst.operands.push(dr::Operand::LiteralInt32(v)),
Err(e) => {
self.err(&format!("invalid integer: {e}"));
self.err(format!("invalid integer: {e}"));
}
},
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)) => {
self.tcx.sess.span_err(
@ -1195,172 +1195,172 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> {
(OperandKind::ImageOperands, Some(word)) => {
match parse_bitflags_operand(IMAGE_OPERANDS, word) {
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)) => {
match parse_bitflags_operand(FP_FAST_MATH_MODE, word) {
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)) => {
match parse_bitflags_operand(SELECTION_CONTROL, word) {
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)) => {
match parse_bitflags_operand(LOOP_CONTROL, word) {
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)) => {
match parse_bitflags_operand(FUNCTION_CONTROL, word) {
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)) => {
match parse_bitflags_operand(MEMORY_SEMANTICS, word) {
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)) => {
match parse_bitflags_operand(MEMORY_ACCESS, word) {
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)) => {
match parse_bitflags_operand(KERNEL_PROFILING_INFO, word) {
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) {
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)) => {
match parse_bitflags_operand(FRAGMENT_SHADING_RATE, word) {
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() {
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() {
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() {
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() {
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() {
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() {
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() {
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() {
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() {
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() {
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() {
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() {
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() {
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() {
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() {
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() {
Ok(x) => inst
.operands
.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() {
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() {
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() {
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() {
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() {
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() {
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() {
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() {
Ok(x) => inst
.operands
.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() {
Ok(x) => inst
.operands
.push(dr::Operand::RayQueryCandidateIntersectionType(x)),
Err(()) => self.err(&format!("unknown RayQueryCandidateIntersectionType {word}")),
Err(()) => self.err(format!("unknown RayQueryCandidateIntersectionType {word}")),
},
(kind, None) => match token {
Token::Word(_) => bug!(),
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) => {
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::sync::Lrc;
use rustc_middle::bug;
use rustc_middle::mir::interpret::ConstAllocation;
use rustc_middle::ty::TyCtxt;
use rustc_span::source_map::SourceMap;
use rustc_span::symbol::Symbol;
@ -206,8 +207,8 @@ impl SpirvValueExt for Word {
}
}
#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
pub enum SpirvConst<'tcx> {
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum SpirvConst<'a, 'tcx> {
U32(u32),
U64(u64),
/// 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.
ZombieUndefForFnAddr,
Composite(&'tcx [Word]),
Composite(&'a [Word]),
/// Pointer to constant data, i.e. `&pointee`, represented as an `OpVariable`
/// in the `Private` storage class, and with `pointee` as its initializer.
PtrTo {
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
/// `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,
@ -242,7 +250,7 @@ impl SpirvConst<'_> {
/// (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
/// 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] {
if xs.is_empty() {
&[]
@ -264,6 +272,8 @@ impl SpirvConst<'_> {
SpirvConst::PtrTo { pointee } => SpirvConst::PtrTo { pointee },
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.
// FIXME(eddyb) figure out if this is an accidental omission in SPIR-V.
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 {
@ -290,6 +306,10 @@ impl LeafIllegalConst {
Self::CompositeContainsPtrTo => {
"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.
// NOTE(eddyb) both maps have `WithConstLegality` around their keys, which
// allows getting that legality information without additional lookups.
const_to_id: RefCell<FxHashMap<WithType<SpirvConst<'tcx>>, WithConstLegality<Word>>>,
id_to_const: RefCell<FxHashMap<Word, WithConstLegality<SpirvConst<'tcx>>>>,
const_to_id: RefCell<FxHashMap<WithType<SpirvConst<'tcx, 'tcx>>, WithConstLegality<Word>>>,
id_to_const: RefCell<FxHashMap<Word, WithConstLegality<SpirvConst<'tcx, 'tcx>>>>,
debug_file_cache: RefCell<FxHashMap<DebugFileKey, DebugFileSpirv<'tcx>>>,
@ -535,7 +555,7 @@ impl<'tcx> BuilderSpirv<'tcx> {
pub(crate) fn def_constant_cx(
&self,
ty: Word,
val: SpirvConst<'_>,
val: SpirvConst<'_, 'tcx>,
cx: &CodegenCx<'tcx>,
) -> SpirvValue {
let val_with_type = WithType { ty, val };
@ -564,7 +584,9 @@ impl<'tcx> BuilderSpirv<'tcx> {
}
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()),
@ -635,6 +657,10 @@ impl<'tcx> BuilderSpirv<'tcx> {
Err(IllegalConst::Indirect(cause))
}
},
SpirvConst::ConstDataFromAlloc(_) => Err(IllegalConst::Shallow(
LeafIllegalConst::UntypedConstDataFromAlloc,
)),
};
let val = val.tcx_arena_alloc_slices(cx);
assert_matches!(
@ -658,11 +684,11 @@ impl<'tcx> BuilderSpirv<'tcx> {
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)
}
pub fn lookup_const(&self, def: SpirvValue) -> Option<SpirvConst<'tcx>> {
pub fn lookup_const(&self, def: SpirvValue) -> Option<SpirvConst<'tcx, 'tcx>> {
match def.kind {
SpirvValueKind::Def(id) | SpirvValueKind::IllegalConst(id) => {
self.lookup_const_by_id(id)

View File

@ -1,18 +1,17 @@
use super::CodegenCx;
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 rspirv::spirv::Word;
use rustc_codegen_ssa::mir::place::PlaceRef;
use rustc_codegen_ssa::traits::{BaseTypeMethods, ConstMethods, MiscMethods, StaticMethods};
use rustc_middle::bug;
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_target::abi::{self, AddressSpace, HasDataLayout, Integer, Primitive, Size};
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)
}
@ -137,8 +136,22 @@ impl<'tcx> ConstMethods<'tcx> for CodegenCx<'tcx> {
fn const_uint(&self, t: Self::Type, i: u64) -> Self::Value {
self.constant_int(t, i)
}
fn const_uint_big(&self, t: Self::Type, u: u128) -> Self::Value {
self.constant_int(t, u as u64)
// FIXME(eddyb) support `u128`.
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 {
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 {
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 {
let ptr_size = self.tcx.data_layout.pointer_size.bits() as u32;
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,
// see https://github.com/rust-lang/rust/pull/86475#discussion_r680792727.
fn const_data_from_alloc(&self, _alloc: ConstAllocation<'tcx>) -> Self::Value {
let undef = self.undef(SpirvType::Void.def(DUMMY_SP, self));
self.zombie_no_span(undef.def_cx(self), "const_data_from_alloc");
undef
}
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)
// HACK(eddyb) this uses a symbolic `ConstDataFromAlloc`, 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.
fn const_data_from_alloc(&self, alloc: ConstAllocation<'tcx>) -> Self::Value {
let void_type = SpirvType::Void.def(DUMMY_SP, self);
self.def_constant(void_type, SpirvConst::ConstDataFromAlloc(alloc))
}
// FIXME(eddyb) is this just redundant with `const_bitcast`?!
fn const_ptrcast(&self, val: Self::Value, ty: Self::Type) -> Self::Value {
if val.ty == ty {
val
} 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);
self.zombie_no_span(result.def_cx(self), "const_ptrcast");
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> {

View File

@ -15,8 +15,7 @@ use rspirv::spirv::{Decoration, LinkageType, Op, Word};
use rustc_ast::ast::{InlineAsmOptions, InlineAsmTemplatePiece};
use rustc_codegen_ssa::mir::debuginfo::{FunctionDebugContext, VariableKind};
use rustc_codegen_ssa::traits::{
AsmMethods, BackendTypes, CoverageInfoMethods, DebugInfoMethods, GlobalAsmOperandRef,
MiscMethods,
AsmMethods, BackendTypes, DebugInfoMethods, GlobalAsmOperandRef, MiscMethods,
};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
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::{Instance, ParamEnv, PolyExistentialTraitRef, Ty, TyCtxt};
use rustc_session::Session;
use rustc_span::def_id::DefId;
use rustc_span::symbol::Symbol;
use rustc_span::{SourceFile, Span, DUMMY_SP};
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> {
fn codegen_global_asm(
&self,

View File

@ -9,7 +9,7 @@ use rustc_middle::ty::layout::{
};
use rustc_middle::ty::Ty;
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::{Abi, AddressSpace, FieldsShape};
@ -37,16 +37,13 @@ impl<'tcx> FnAbiOfHelpers<'tcx> for CodegenCx<'tcx> {
fn_abi_request: FnAbiRequest<'tcx>,
) -> ! {
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 {
match fn_abi_request {
FnAbiRequest::OfFnPtr { sig, extra_args } => {
span_bug!(
span,
"`fn_abi_of_fn_ptr({}, {:?})` failed: {}",
sig,
extra_args,
err
"`fn_abi_of_fn_ptr({sig}, {extra_args:?})` failed: {err:?}",
);
}
FnAbiRequest::OfInstance {
@ -55,10 +52,7 @@ impl<'tcx> FnAbiOfHelpers<'tcx> for CodegenCx<'tcx> {
} => {
span_bug!(
span,
"`fn_abi_of_instance({}, {:?})` failed: {}",
instance,
extra_args,
err
"`fn_abi_of_instance({instance}, {extra_args:?})` failed: {err:?}",
);
}
}

View File

@ -97,7 +97,7 @@ use rustc_codegen_ssa::traits::{
WriteBackendMethods,
};
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_metadata::EncodedMetadata;
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
@ -257,7 +257,7 @@ impl CodegenBackend for SpirvCodegenBackend {
ongoing_codegen: Box<dyn Any>,
sess: &Session,
_outputs: &OutputFilenames,
) -> Result<(CodegenResults, FxHashMap<WorkProductId, WorkProduct>), ErrorGuaranteed> {
) -> Result<(CodegenResults, FxIndexMap<WorkProductId, WorkProduct>), ErrorGuaranteed> {
let (codegen_results, work_products) = ongoing_codegen
.downcast::<OngoingCodegen<Self>>()
.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::dep_graph::WorkProduct;
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::utils::NativeLibKind;
use rustc_session::Session;
@ -60,9 +62,11 @@ pub fn link(
if outputs.outputs.should_codegen() {
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 {
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 => {
// HACK(eddyb) there's no way way to access `outputs.filestem`,
@ -76,7 +80,7 @@ pub fn link(
link_exe(
sess,
crate_type,
&out_filename,
&out_filename_file_for_writing,
codegen_results,
outputs,
&disambiguated_crate_name_for_dumps,
@ -86,6 +90,21 @@ pub fn link(
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
// `Err(ErrorGuaranteed)` returns from `link`).
rustc_driver::catch_fatal_errors(|| {
let matches = rustc_driver::handle_options(&["".to_string(), "x.rs".to_string()]).unwrap();
let sopts = rustc_session::config::build_session_options(&matches);
let mut early_error_handler = rustc_session::EarlyErrorHandler::new(
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, || {
let mut sess = rustc_session::build_session(
&early_error_handler,
sopts,
CompilerIO {
input: Input::Str {

View File

@ -1,7 +1,7 @@
[toolchain]
channel = "nightly-2023-05-27"
channel = "nightly-2023-07-08"
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
# sure to change `REQUIRED_TOOLCHAIN` in `crates/rustc_codegen_spirv/build.rs` also.

View File

@ -11,9 +11,17 @@
#![feature(adt_const_params)]
#![allow(incomplete_features)]
use spirv_std::image::Dimensionality;
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>() {}
#[spirv(fragment)]

View File

@ -10,6 +10,6 @@ OpEntryPoint Fragment %1 "main"
OpExecutionMode %1 OriginUpperLeft
%2 = OpString "$OPSTRING_FILENAME/generic-fn-op-name.rs"
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
%6 = OpTypeFunction %5

View File

@ -1,13 +1,13 @@
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>`
--> $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`
--> $DIR/ptr_copy.rs:28:18

View File

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

View File

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

View File

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

View File

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