mirror of
https://github.com/EmbarkStudios/rust-gpu.git
synced 2024-11-22 06:45:13 +00:00
rustup: update to nightly-2022-04-01.
This commit is contained in:
parent
f0baf78ade
commit
3e04f62ede
@ -6,7 +6,7 @@ use crate::codegen_cx::CodegenCx;
|
||||
use crate::spirv_type::SpirvType;
|
||||
use rspirv::spirv::{StorageClass, Word};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_errors::ErrorReported;
|
||||
use rustc_errors::ErrorGuaranteed;
|
||||
use rustc_index::vec::Idx;
|
||||
use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, TyAndLayout};
|
||||
use rustc_middle::ty::query::{ExternProviders, Providers};
|
||||
@ -21,7 +21,7 @@ use rustc_span::Span;
|
||||
use rustc_span::DUMMY_SP;
|
||||
use rustc_target::abi::call::{ArgAbi, ArgAttributes, FnAbi, PassMode};
|
||||
use rustc_target::abi::{
|
||||
Abi, Align, FieldsShape, Layout, Primitive, Scalar, Size, TagEncoding, VariantIdx, Variants,
|
||||
Abi, Align, FieldsShape, LayoutS, Primitive, Scalar, Size, TagEncoding, VariantIdx, Variants,
|
||||
};
|
||||
use rustc_target::spec::abi::Abi as SpecAbi;
|
||||
use std::cell::RefCell;
|
||||
@ -92,9 +92,10 @@ pub(crate) fn provide(providers: &mut Providers) {
|
||||
Ok(readjust_fn_abi(tcx, result?))
|
||||
};
|
||||
|
||||
// FIXME(eddyb) remove this by deriving `Clone` for `Layout` upstream.
|
||||
fn clone_layout(layout: &Layout) -> Layout {
|
||||
let Layout {
|
||||
// FIXME(eddyb) remove this by deriving `Clone` for `LayoutS` upstream.
|
||||
// FIXME(eddyb) the `S` suffix is a naming antipattern, rename upstream.
|
||||
fn clone_layout<'a>(layout: &LayoutS<'a>) -> LayoutS<'a> {
|
||||
let LayoutS {
|
||||
ref fields,
|
||||
ref variants,
|
||||
abi,
|
||||
@ -102,7 +103,7 @@ pub(crate) fn provide(providers: &mut Providers) {
|
||||
align,
|
||||
size,
|
||||
} = *layout;
|
||||
Layout {
|
||||
LayoutS {
|
||||
fields: match *fields {
|
||||
FieldsShape::Primitive => FieldsShape::Primitive,
|
||||
FieldsShape::Union(count) => FieldsShape::Union(count),
|
||||
@ -137,7 +138,7 @@ pub(crate) fn provide(providers: &mut Providers) {
|
||||
},
|
||||
},
|
||||
tag_field,
|
||||
variants: variants.iter().map(clone_layout).collect(),
|
||||
variants: variants.clone(),
|
||||
},
|
||||
},
|
||||
abi,
|
||||
@ -157,9 +158,9 @@ pub(crate) fn provide(providers: &mut Providers) {
|
||||
};
|
||||
|
||||
if hide_niche {
|
||||
layout = tcx.arena.alloc(Layout {
|
||||
layout = tcx.intern_layout(LayoutS {
|
||||
largest_niche: None,
|
||||
..clone_layout(layout)
|
||||
..clone_layout(layout.0 .0)
|
||||
});
|
||||
}
|
||||
|
||||
@ -341,10 +342,10 @@ impl<'tcx> ConvSpirvType<'tcx> for TyAndLayout<'tcx> {
|
||||
fn spirv_type(&self, mut span: Span, cx: &CodegenCx<'tcx>) -> Word {
|
||||
if let TyKind::Adt(adt, substs) = *self.ty.kind() {
|
||||
if span == DUMMY_SP {
|
||||
span = cx.tcx.def_span(adt.did);
|
||||
span = cx.tcx.def_span(adt.did());
|
||||
}
|
||||
|
||||
let attrs = AggregatedSpirvAttributes::parse(cx, cx.tcx.get_attrs(adt.did));
|
||||
let attrs = AggregatedSpirvAttributes::parse(cx, cx.tcx.get_attrs(adt.did()));
|
||||
|
||||
if let Some(intrinsic_type_attr) = attrs.intrinsic_type.map(|attr| attr.value) {
|
||||
if let Ok(spirv_type) =
|
||||
@ -368,8 +369,8 @@ impl<'tcx> ConvSpirvType<'tcx> for TyAndLayout<'tcx> {
|
||||
field_names: None,
|
||||
}
|
||||
.def_with_name(cx, span, TyLayoutNameKey::from(*self)),
|
||||
Abi::Scalar(ref scalar) => trans_scalar(cx, span, *self, scalar, Size::ZERO),
|
||||
Abi::ScalarPair(ref a, ref b) => {
|
||||
Abi::Scalar(scalar) => trans_scalar(cx, span, *self, scalar, Size::ZERO),
|
||||
Abi::ScalarPair(a, b) => {
|
||||
// NOTE(eddyb) unlike `Abi::Scalar`'s simpler newtype-unpacking
|
||||
// behavior, `Abi::ScalarPair` can be composed in two ways:
|
||||
// * two `Abi::Scalar` fields (and any number of ZST fields),
|
||||
@ -419,7 +420,7 @@ impl<'tcx> ConvSpirvType<'tcx> for TyAndLayout<'tcx> {
|
||||
if let TyKind::Adt(adt, _) = self.ty.kind() {
|
||||
if let Variants::Single { index } = self.variants {
|
||||
for i in self.fields.index_by_increasing_offset() {
|
||||
let field = &adt.variants[index].fields[i];
|
||||
let field = &adt.variants()[index].fields[i];
|
||||
field_names.push(field.name.to_ident_string());
|
||||
}
|
||||
}
|
||||
@ -438,7 +439,7 @@ impl<'tcx> ConvSpirvType<'tcx> for TyAndLayout<'tcx> {
|
||||
}
|
||||
.def_with_name(cx, span, TyLayoutNameKey::from(*self))
|
||||
}
|
||||
Abi::Vector { ref element, count } => {
|
||||
Abi::Vector { element, count } => {
|
||||
let elem_spirv = trans_scalar(cx, span, *self, element, Size::ZERO);
|
||||
SpirvType::Vector {
|
||||
element: elem_spirv,
|
||||
@ -459,7 +460,7 @@ pub fn scalar_pair_element_backend_type<'tcx>(
|
||||
ty: TyAndLayout<'tcx>,
|
||||
index: usize,
|
||||
) -> Word {
|
||||
let [a, b] = match &ty.layout.abi {
|
||||
let [a, b] = match ty.layout.abi() {
|
||||
Abi::ScalarPair(a, b) => [a, b],
|
||||
other => span_bug!(
|
||||
span,
|
||||
@ -486,7 +487,7 @@ fn trans_scalar<'tcx>(
|
||||
cx: &CodegenCx<'tcx>,
|
||||
span: Span,
|
||||
ty: TyAndLayout<'tcx>,
|
||||
scalar: &Scalar,
|
||||
scalar: Scalar,
|
||||
offset: Size,
|
||||
) -> Word {
|
||||
if scalar.is_bool() {
|
||||
@ -697,7 +698,7 @@ fn trans_struct<'tcx>(cx: &CodegenCx<'tcx>, span: Span, ty: TyAndLayout<'tcx>) -
|
||||
field_offsets.push(offset);
|
||||
if let Variants::Single { index } = ty.variants {
|
||||
if let TyKind::Adt(adt, _) = ty.ty.kind() {
|
||||
let field = &adt.variants[index].fields[i];
|
||||
let field = &adt.variants()[index].fields[i];
|
||||
field_names.push(field.name.to_ident_string());
|
||||
} else {
|
||||
field_names.push(format!("{}", i));
|
||||
@ -730,7 +731,7 @@ fn trans_struct<'tcx>(cx: &CodegenCx<'tcx>, span: Span, ty: TyAndLayout<'tcx>) -
|
||||
/// (not in itself an issue, but it makes error reporting harder).
|
||||
fn def_id_for_spirv_type_adt(layout: TyAndLayout<'_>) -> Option<DefId> {
|
||||
match *layout.ty.kind() {
|
||||
TyKind::Adt(def, _) => Some(def.did),
|
||||
TyKind::Adt(def, _) => Some(def.did()),
|
||||
TyKind::Foreign(def_id) | TyKind::Closure(def_id, _) | TyKind::Generator(def_id, ..) => {
|
||||
Some(def_id)
|
||||
}
|
||||
@ -762,8 +763,8 @@ impl fmt::Display for TyLayoutNameKey<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}", self.ty)?;
|
||||
if let (TyKind::Adt(def, _), Some(index)) = (self.ty.kind(), self.variant) {
|
||||
if def.is_enum() && !def.variants.is_empty() {
|
||||
write!(f, "::{}", def.variants[index].name)?;
|
||||
if def.is_enum() && !def.variants().is_empty() {
|
||||
write!(f, "::{}", def.variants()[index].name)?;
|
||||
}
|
||||
}
|
||||
if let (TyKind::Generator(_, _, _), Some(index)) = (self.ty.kind(), self.variant) {
|
||||
@ -779,15 +780,15 @@ fn trans_intrinsic_type<'tcx>(
|
||||
ty: TyAndLayout<'tcx>,
|
||||
substs: SubstsRef<'tcx>,
|
||||
intrinsic_type_attr: IntrinsicType,
|
||||
) -> Result<Word, ErrorReported> {
|
||||
) -> Result<Word, ErrorGuaranteed> {
|
||||
match intrinsic_type_attr {
|
||||
IntrinsicType::GenericImageType => {
|
||||
// see SpirvType::sizeof
|
||||
if ty.size != Size::from_bytes(4) {
|
||||
cx.tcx
|
||||
return Err(cx
|
||||
.tcx
|
||||
.sess
|
||||
.err("#[spirv(generic_image)] type must have size 4");
|
||||
return Err(ErrorReported);
|
||||
.err("#[spirv(generic_image)] type must have size 4"));
|
||||
}
|
||||
|
||||
// fn type_from_variant_discriminant<'tcx, P: FromPrimitive>(
|
||||
@ -828,10 +829,10 @@ fn trans_intrinsic_type<'tcx>(
|
||||
TyKind::Float(FloatTy::F32) => SpirvType::Float(32).def(span, cx),
|
||||
TyKind::Float(FloatTy::F64) => SpirvType::Float(64).def(span, cx),
|
||||
_ => {
|
||||
cx.tcx
|
||||
return Err(cx
|
||||
.tcx
|
||||
.sess
|
||||
.span_err(span, "Invalid sampled type to `Image`.");
|
||||
return Err(ErrorReported);
|
||||
.span_err(span, "Invalid sampled type to `Image`."));
|
||||
}
|
||||
};
|
||||
|
||||
@ -846,17 +847,15 @@ fn trans_intrinsic_type<'tcx>(
|
||||
fn const_int_value<'tcx, P: FromPrimitive>(
|
||||
cx: &CodegenCx<'tcx>,
|
||||
const_: Const<'tcx>,
|
||||
) -> Result<P, ErrorReported> {
|
||||
) -> Result<P, ErrorGuaranteed> {
|
||||
assert!(const_.ty().is_integral());
|
||||
let value = const_.eval_bits(cx.tcx, ParamEnv::reveal_all(), const_.ty());
|
||||
match P::from_u128(value) {
|
||||
Some(v) => Ok(v),
|
||||
None => {
|
||||
cx.tcx
|
||||
None => Err(cx
|
||||
.tcx
|
||||
.sess
|
||||
.err(&format!("Invalid value for Image const generic: {}", value));
|
||||
Err(ErrorReported)
|
||||
}
|
||||
.err(&format!("Invalid value for Image const generic: {}", value))),
|
||||
}
|
||||
}
|
||||
|
||||
@ -881,8 +880,7 @@ fn trans_intrinsic_type<'tcx>(
|
||||
IntrinsicType::Sampler => {
|
||||
// see SpirvType::sizeof
|
||||
if ty.size != Size::from_bytes(4) {
|
||||
cx.tcx.sess.err("#[spirv(sampler)] type must have size 4");
|
||||
return Err(ErrorReported);
|
||||
return Err(cx.tcx.sess.err("#[spirv(sampler)] type must have size 4"));
|
||||
}
|
||||
Ok(SpirvType::Sampler.def(span, cx))
|
||||
}
|
||||
@ -893,10 +891,10 @@ fn trans_intrinsic_type<'tcx>(
|
||||
IntrinsicType::SampledImage => {
|
||||
// see SpirvType::sizeof
|
||||
if ty.size != Size::from_bytes(4) {
|
||||
cx.tcx
|
||||
return Err(cx
|
||||
.tcx
|
||||
.sess
|
||||
.err("#[spirv(sampled_image)] type must have size 4");
|
||||
return Err(ErrorReported);
|
||||
.err("#[spirv(sampled_image)] type must have size 4"));
|
||||
}
|
||||
|
||||
// We use a generic to indicate the underlying image type of the sampled image.
|
||||
@ -906,18 +904,18 @@ fn trans_intrinsic_type<'tcx>(
|
||||
let image_type = cx.layout_of(image_ty).spirv_type(span, cx);
|
||||
Ok(SpirvType::SampledImage { image_type }.def(span, cx))
|
||||
} else {
|
||||
cx.tcx
|
||||
Err(cx
|
||||
.tcx
|
||||
.sess
|
||||
.err("#[spirv(sampled_image)] type must have a generic image type");
|
||||
Err(ErrorReported)
|
||||
.err("#[spirv(sampled_image)] type must have a generic image type"))
|
||||
}
|
||||
}
|
||||
IntrinsicType::RuntimeArray => {
|
||||
if ty.size != Size::from_bytes(4) {
|
||||
cx.tcx
|
||||
return Err(cx
|
||||
.tcx
|
||||
.sess
|
||||
.err("#[spirv(runtime_array)] type must have size 4");
|
||||
return Err(ErrorReported);
|
||||
.err("#[spirv(runtime_array)] type must have size 4"));
|
||||
}
|
||||
|
||||
// We use a generic to indicate the underlying element type.
|
||||
@ -926,10 +924,10 @@ fn trans_intrinsic_type<'tcx>(
|
||||
let element = cx.layout_of(elem_ty).spirv_type(span, cx);
|
||||
Ok(SpirvType::RuntimeArray { element }.def(span, cx))
|
||||
} else {
|
||||
cx.tcx
|
||||
Err(cx
|
||||
.tcx
|
||||
.sess
|
||||
.err("#[spirv(runtime_array)] type must have a generic element type");
|
||||
Err(ErrorReported)
|
||||
.err("#[spirv(runtime_array)] type must have a generic element type"))
|
||||
}
|
||||
}
|
||||
IntrinsicType::Matrix => {
|
||||
@ -941,28 +939,27 @@ fn trans_intrinsic_type<'tcx>(
|
||||
.map(|i| ty.field(cx, i).spirv_type(span, cx))
|
||||
.collect::<Vec<_>>();
|
||||
if field_types.len() < 2 {
|
||||
cx.tcx
|
||||
return Err(cx
|
||||
.tcx
|
||||
.sess
|
||||
.span_err(span, "#[spirv(matrix)] type must have at least two fields");
|
||||
return Err(ErrorReported);
|
||||
.span_err(span, "#[spirv(matrix)] type must have at least two fields"));
|
||||
}
|
||||
let elem_type = field_types[0];
|
||||
if !field_types.iter().all(|&ty| ty == elem_type) {
|
||||
cx.tcx.sess.span_err(
|
||||
return Err(cx.tcx.sess.span_err(
|
||||
span,
|
||||
"#[spirv(matrix)] type fields must all be the same type",
|
||||
);
|
||||
return Err(ErrorReported);
|
||||
));
|
||||
}
|
||||
match cx.lookup_type(elem_type) {
|
||||
SpirvType::Vector { .. } => (),
|
||||
ty => {
|
||||
cx.tcx
|
||||
return Err(cx
|
||||
.tcx
|
||||
.sess
|
||||
.struct_span_err(span, "#[spirv(matrix)] type fields must all be vectors")
|
||||
.note(&format!("field type is {}", ty.debug(elem_type, cx)))
|
||||
.emit();
|
||||
return Err(ErrorReported);
|
||||
.emit());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -363,13 +363,15 @@ impl CheckSpirvAttrVisitor<'_> {
|
||||
}
|
||||
};
|
||||
match valid_target {
|
||||
Err(Expected(expected_target)) => self.tcx.sess.span_err(
|
||||
Err(Expected(expected_target)) => {
|
||||
self.tcx.sess.span_err(
|
||||
span,
|
||||
&format!(
|
||||
"attribute is only valid on a {}, not on a {}",
|
||||
expected_target, target
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
Ok(()) => match aggregated_attrs.try_insert_attr(parsed_attr, span) {
|
||||
Ok(()) => {}
|
||||
Err(MultipleAttrs {
|
||||
|
@ -917,18 +917,18 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
|
||||
place.align,
|
||||
);
|
||||
OperandValue::Immediate(self.to_immediate(llval, place.layout))
|
||||
} else if let Abi::ScalarPair(ref a, ref b) = place.layout.abi {
|
||||
} else if let Abi::ScalarPair(a, b) = place.layout.abi {
|
||||
let b_offset = a.value.size(self).align_to(b.value.align(self).abi);
|
||||
|
||||
let pair_ty = place.layout.spirv_type(self.span(), self);
|
||||
let mut load = |i, scalar: &Scalar, align| {
|
||||
let mut load = |i, scalar: Scalar, align| {
|
||||
let llptr = self.struct_gep(pair_ty, place.llval, i as u64);
|
||||
let load = self.load(
|
||||
self.scalar_pair_element_backend_type(place.layout, i, false),
|
||||
llptr,
|
||||
align,
|
||||
);
|
||||
self.to_immediate_scalar(load, *scalar)
|
||||
self.to_immediate_scalar(load, scalar)
|
||||
};
|
||||
|
||||
OperandValue::Pair(
|
||||
@ -2214,7 +2214,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
|
||||
self.intcast(val, dest_ty, false)
|
||||
}
|
||||
|
||||
fn apply_attrs_to_cleanup_callsite(&mut self, _llret: Self::Value) {
|
||||
fn do_not_inline(&mut self, _llret: Self::Value) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ use crate::builder_spirv::{SpirvValue, SpirvValueExt, SpirvValueKind};
|
||||
use crate::spirv_type::SpirvType;
|
||||
use rspirv::spirv::Word;
|
||||
use rustc_codegen_ssa::traits::{BaseTypeMethods, BuilderMethods};
|
||||
use rustc_errors::ErrorReported;
|
||||
use rustc_errors::ErrorGuaranteed;
|
||||
use rustc_span::DUMMY_SP;
|
||||
use rustc_target::abi::call::PassMode;
|
||||
use rustc_target::abi::{Align, Size};
|
||||
@ -204,7 +204,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
self.recurse_load_type(result_type, result_type, array, word_index, 0)
|
||||
}
|
||||
|
||||
fn store_err(&mut self, original_type: Word, value: SpirvValue) -> Result<(), ErrorReported> {
|
||||
fn store_err(&mut self, original_type: Word, value: SpirvValue) -> Result<(), ErrorGuaranteed> {
|
||||
let mut err = self.struct_err(&format!(
|
||||
"Cannot store type {} in an untyped buffer store",
|
||||
self.debug_type(original_type)
|
||||
@ -212,8 +212,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
if original_type != value.ty {
|
||||
err.note(&format!("due to containing type {}", value.ty));
|
||||
}
|
||||
err.emit();
|
||||
Err(ErrorReported)
|
||||
Err(err.emit())
|
||||
}
|
||||
|
||||
fn store_u32(
|
||||
@ -222,7 +221,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
dynamic_index: SpirvValue,
|
||||
constant_offset: u32,
|
||||
value: SpirvValue,
|
||||
) -> Result<(), ErrorReported> {
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
let actual_index = if constant_offset != 0 {
|
||||
let const_offset_val = self.constant_u32(DUMMY_SP, constant_offset);
|
||||
self.add(dynamic_index, const_offset_val)
|
||||
@ -250,7 +249,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
constant_word_offset: u32,
|
||||
element: Word,
|
||||
count: u32,
|
||||
) -> Result<(), ErrorReported> {
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
let element_size_bytes = match self.lookup_type(element).sizeof(self) {
|
||||
Some(size) => size,
|
||||
None => return self.store_err(original_type, value),
|
||||
@ -279,7 +278,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
array: SpirvValue,
|
||||
dynamic_word_index: SpirvValue,
|
||||
constant_word_offset: u32,
|
||||
) -> Result<(), ErrorReported> {
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
match self.lookup_type(value.ty) {
|
||||
SpirvType::Integer(32, signed) => {
|
||||
let u32_ty = SpirvType::Integer(32, false).def(DUMMY_SP, self);
|
||||
|
@ -20,7 +20,7 @@ use rustc_codegen_ssa::traits::{
|
||||
AbiBuilderMethods, ArgAbiMethods, BackendTypes, BuilderMethods, CoverageInfoBuilderMethods,
|
||||
DebugInfoBuilderMethods, HasCodegen, StaticBuilderMethods,
|
||||
};
|
||||
use rustc_errors::{DiagnosticBuilder, ErrorReported};
|
||||
use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed};
|
||||
use rustc_middle::mir::coverage::{
|
||||
CodeRegion, CounterValueReference, ExpressionOperandId, InjectedExpressionId, Op,
|
||||
};
|
||||
@ -70,7 +70,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn struct_err(&self, msg: &str) -> DiagnosticBuilder<'_, ErrorReported> {
|
||||
pub fn struct_err(&self, msg: &str) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
|
||||
if let Some(current_span) = self.current_span {
|
||||
self.tcx.sess.struct_span_err(current_span, msg)
|
||||
} else {
|
||||
|
@ -793,10 +793,11 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> {
|
||||
InlineAsmRegOrRegClass::RegClass(InlineAsmRegClass::SpirV(
|
||||
SpirVInlineAsmRegClass::reg,
|
||||
)) => {}
|
||||
_ => self
|
||||
.tcx
|
||||
_ => {
|
||||
self.tcx
|
||||
.sess
|
||||
.span_err(span, &format!("invalid register: {}", reg)),
|
||||
.span_err(span, &format!("invalid register: {}", reg));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1147,21 +1148,34 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> {
|
||||
match tokens.next() {
|
||||
Some(Token::Word(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));
|
||||
}
|
||||
},
|
||||
Some(Token::String(_)) => self.err(&format!(
|
||||
Some(Token::String(_)) => {
|
||||
self.err(&format!(
|
||||
"expected a literal, not a string for a {:?}",
|
||||
kind
|
||||
)),
|
||||
Some(Token::Placeholder(_, span)) => self.tcx.sess.span_err(
|
||||
));
|
||||
}
|
||||
Some(Token::Placeholder(_, span)) => {
|
||||
self.tcx.sess.span_err(
|
||||
span,
|
||||
&format!("expected a literal, not a dynamic value for a {:?}", kind),
|
||||
&format!(
|
||||
"expected a literal, not a dynamic value for a {:?}",
|
||||
kind
|
||||
),
|
||||
Some(Token::Typeof(_, span, _)) => self.tcx.sess.span_err(
|
||||
);
|
||||
}
|
||||
Some(Token::Typeof(_, span, _)) => {
|
||||
self.tcx.sess.span_err(
|
||||
span,
|
||||
&format!("expected a literal, not a type for a {:?}", kind),
|
||||
),
|
||||
None => self.err("expected operand after instruction"),
|
||||
);
|
||||
}
|
||||
None => {
|
||||
self.err("expected operand after instruction");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ 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, Allocation, GlobalAlloc, Scalar, ScalarMaybeUninit,
|
||||
alloc_range, ConstAllocation, GlobalAlloc, Scalar, ScalarMaybeUninit,
|
||||
};
|
||||
use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
|
||||
use rustc_span::symbol::Symbol;
|
||||
@ -275,7 +275,7 @@ impl<'tcx> ConstMethods<'tcx> for CodegenCx<'tcx> {
|
||||
)),
|
||||
};
|
||||
let init = self.create_const_alloc(alloc, pointee);
|
||||
let value = self.static_addr_of(init, alloc.align, None);
|
||||
let value = self.static_addr_of(init, alloc.inner().align, None);
|
||||
(value, AddressSpace::DATA)
|
||||
}
|
||||
GlobalAlloc::Function(fn_instance) => (
|
||||
@ -311,7 +311,7 @@ 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: &Allocation) -> Self::Value {
|
||||
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
|
||||
@ -319,13 +319,13 @@ impl<'tcx> ConstMethods<'tcx> for CodegenCx<'tcx> {
|
||||
fn from_const_alloc(
|
||||
&self,
|
||||
layout: TyAndLayout<'tcx>,
|
||||
alloc: &Allocation,
|
||||
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.align, None);
|
||||
let result = self.static_addr_of(init, alloc.inner().align, None);
|
||||
PlaceRef::new_sized(result, layout)
|
||||
}
|
||||
|
||||
@ -356,7 +356,7 @@ impl<'tcx> CodegenCx<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_const_alloc(&self, alloc: &Allocation, ty: Word) -> SpirvValue {
|
||||
pub fn create_const_alloc(&self, alloc: ConstAllocation<'tcx>, ty: Word) -> SpirvValue {
|
||||
// println!(
|
||||
// "Creating const alloc of type {} with {} bytes",
|
||||
// self.debug_type(ty),
|
||||
@ -366,14 +366,19 @@ impl<'tcx> CodegenCx<'tcx> {
|
||||
let result = self.create_const_alloc2(alloc, &mut offset, ty);
|
||||
assert_eq!(
|
||||
offset.bytes_usize(),
|
||||
alloc.len(),
|
||||
alloc.inner().len(),
|
||||
"create_const_alloc must consume all bytes of an Allocation"
|
||||
);
|
||||
// println!("Done creating alloc of type {}", self.debug_type(ty));
|
||||
result
|
||||
}
|
||||
|
||||
fn create_const_alloc2(&self, alloc: &Allocation, offset: &mut Size, ty: Word) -> SpirvValue {
|
||||
fn create_const_alloc2(
|
||||
&self,
|
||||
alloc: ConstAllocation<'tcx>,
|
||||
offset: &mut Size,
|
||||
ty: Word,
|
||||
) -> SpirvValue {
|
||||
let ty_concrete = self.lookup_type(ty);
|
||||
*offset = offset.align_to(ty_concrete.alignof(self));
|
||||
// these print statements are really useful for debugging, so leave them easily available
|
||||
@ -425,7 +430,11 @@ impl<'tcx> CodegenCx<'tcx> {
|
||||
// only uses the input alloc_id in the case that the scalar is uninitilized
|
||||
// as part of the error output
|
||||
// tldr, the pointer here is only needed for the offset
|
||||
let value = match alloc.read_scalar(self, alloc_range(*offset, size)).unwrap() {
|
||||
let value = match alloc
|
||||
.inner()
|
||||
.read_scalar(self, alloc_range(*offset, size))
|
||||
.unwrap()
|
||||
{
|
||||
ScalarMaybeUninit::Scalar(scalar) => {
|
||||
self.scalar_to_backend(scalar, self.primitive_to_scalar(primitive), ty)
|
||||
}
|
||||
@ -457,7 +466,7 @@ impl<'tcx> CodegenCx<'tcx> {
|
||||
} else {
|
||||
assert_eq!(
|
||||
offset.bytes_usize(),
|
||||
alloc.len(),
|
||||
alloc.inner().len(),
|
||||
"create_const_alloc must consume all bytes of an Allocation after an unsized struct"
|
||||
);
|
||||
}
|
||||
@ -503,7 +512,7 @@ impl<'tcx> CodegenCx<'tcx> {
|
||||
}
|
||||
SpirvType::RuntimeArray { element } => {
|
||||
let mut values = Vec::new();
|
||||
while offset.bytes_usize() != alloc.len() {
|
||||
while offset.bytes_usize() != alloc.inner().len() {
|
||||
values.push(
|
||||
self.create_const_alloc2(alloc, offset, element)
|
||||
.def_cx(self),
|
||||
|
@ -142,10 +142,12 @@ impl<'tcx> CodegenCx<'tcx> {
|
||||
Some(&intrinsic) => {
|
||||
self.libm_intrinsics.borrow_mut().insert(fn_id, intrinsic);
|
||||
}
|
||||
None => self.tcx.sess.err(&format!(
|
||||
None => {
|
||||
self.tcx.sess.err(&format!(
|
||||
"missing libm intrinsic {}, which is {}",
|
||||
symbol_name, instance
|
||||
)),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -328,10 +328,12 @@ impl<'tcx> CodegenCx<'tcx> {
|
||||
let value_len = if is_unsized_with_len {
|
||||
match self.lookup_type(value_spirv_type) {
|
||||
SpirvType::RuntimeArray { .. } => {}
|
||||
_ => self.tcx.sess.span_err(
|
||||
_ => {
|
||||
self.tcx.sess.span_err(
|
||||
hir_param.ty_span,
|
||||
"only plain slices are supported as unsized types",
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME(eddyb) shouldn't this be `usize`?
|
||||
|
@ -602,7 +602,7 @@ impl<'tcx> MiscMethods<'tcx> for CodegenCx<'tcx> {
|
||||
}
|
||||
|
||||
impl<'tcx> DebugInfoMethods<'tcx> for CodegenCx<'tcx> {
|
||||
fn create_vtable_metadata(
|
||||
fn create_vtable_debuginfo(
|
||||
&self,
|
||||
_ty: Ty<'tcx>,
|
||||
_trait_ref: Option<PolyExistentialTraitRef<'tcx>>,
|
||||
|
@ -162,14 +162,14 @@ use rustc_codegen_ssa::traits::{
|
||||
};
|
||||
use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleCodegen, ModuleKind};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_errors::{ErrorReported, FatalError, Handler};
|
||||
use rustc_errors::{ErrorGuaranteed, FatalError, Handler};
|
||||
use rustc_metadata::EncodedMetadata;
|
||||
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
|
||||
use rustc_middle::mir::mono::{Linkage, MonoItem, Visibility};
|
||||
use rustc_middle::mir::pretty::write_mir_pretty;
|
||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||
use rustc_middle::ty::{self, query, DefIdTree, Instance, InstanceDef, TyCtxt};
|
||||
use rustc_session::config::{self, OptLevel, OutputFilenames, OutputType};
|
||||
use rustc_session::config::{self, OutputFilenames, OutputType};
|
||||
use rustc_session::Session;
|
||||
use rustc_span::symbol::{sym, Symbol};
|
||||
use rustc_target::spec::{Target, TargetTriple};
|
||||
@ -281,6 +281,11 @@ impl CodegenBackend for SpirvCodegenBackend {
|
||||
}
|
||||
|
||||
fn provide(&self, providers: &mut query::Providers) {
|
||||
// FIXME(eddyb) this is currently only passed back to us, specifically
|
||||
// into `target_machine_factory` (which is a noop), but it might make
|
||||
// sense to move some of the target feature parsing into here.
|
||||
providers.global_backend_features = |_tcx, ()| vec![];
|
||||
|
||||
crate::abi::provide(providers);
|
||||
crate::attr::provide(providers);
|
||||
}
|
||||
@ -314,7 +319,7 @@ impl CodegenBackend for SpirvCodegenBackend {
|
||||
ongoing_codegen: Box<dyn Any>,
|
||||
sess: &Session,
|
||||
_outputs: &OutputFilenames,
|
||||
) -> Result<(CodegenResults, FxHashMap<WorkProductId, WorkProduct>), ErrorReported> {
|
||||
) -> Result<(CodegenResults, FxHashMap<WorkProductId, WorkProduct>), ErrorGuaranteed> {
|
||||
let (codegen_results, work_products) = ongoing_codegen
|
||||
.downcast::<OngoingCodegen<Self>>()
|
||||
.expect("Expected OngoingCodegen, found Box<Any>")
|
||||
@ -330,7 +335,7 @@ impl CodegenBackend for SpirvCodegenBackend {
|
||||
sess: &Session,
|
||||
codegen_results: CodegenResults,
|
||||
outputs: &OutputFilenames,
|
||||
) -> Result<(), ErrorReported> {
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
let timer = sess.timer("link_crate");
|
||||
link::link(
|
||||
sess,
|
||||
@ -528,8 +533,9 @@ impl ExtraBackendMethods for SpirvCodegenBackend {
|
||||
|
||||
fn target_machine_factory(
|
||||
&self,
|
||||
_: &Session,
|
||||
_: OptLevel,
|
||||
_sess: &Session,
|
||||
_opt_level: config::OptLevel,
|
||||
_target_features: &[String],
|
||||
) -> Arc<(dyn Fn(TargetMachineFactoryConfig) -> Result<(), String> + Send + Sync + 'static)>
|
||||
{
|
||||
Arc::new(|_| Ok(()))
|
||||
|
@ -2,6 +2,7 @@ use crate::codegen_cx::{CodegenArgs, ModuleOutputType, SpirvMetadata};
|
||||
use crate::{linker, SpirvCodegenBackend, SpirvModuleBuffer, SpirvThinBuffer};
|
||||
use ar::{Archive, GnuBuilder, Header};
|
||||
use rspirv::binary::Assemble;
|
||||
use rustc_ast::CRATE_NODE_ID;
|
||||
use rustc_codegen_spirv_types::{CompileResult, ModuleResult};
|
||||
use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule, ThinShared};
|
||||
use rustc_codegen_ssa::back::write::CodegenContext;
|
||||
@ -63,7 +64,9 @@ pub fn link<'a>(
|
||||
CrateType::Executable | CrateType::Cdylib | CrateType::Dylib => {
|
||||
link_exe(sess, crate_type, &out_filename, codegen_results);
|
||||
}
|
||||
other => sess.err(&format!("CrateType {:?} not supported yet", other)),
|
||||
other => {
|
||||
sess.err(&format!("CrateType {:?} not supported yet", other));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -298,7 +301,9 @@ fn do_spirv_opt(
|
||||
|
||||
let mut err = match msg.level {
|
||||
Level::Fatal | Level::InternalError => {
|
||||
sess.struct_fatal(&msg.message).forget_guarantee()
|
||||
// FIXME(eddyb) this was `struct_fatal` but that doesn't seem
|
||||
// necessary and also lacks `.forget_guarantee()`.
|
||||
sess.struct_err(&msg.message).forget_guarantee()
|
||||
}
|
||||
Level::Error => sess.struct_err(&msg.message).forget_guarantee(),
|
||||
Level::Warning => sess.struct_warn(&msg.message),
|
||||
@ -312,7 +317,10 @@ fn do_spirv_opt(
|
||||
);
|
||||
|
||||
match result {
|
||||
Ok(binary) => Vec::from(binary.as_ref()),
|
||||
Ok(binary) => match binary {
|
||||
spirv_tools::binary::Binary::OwnedU32(words) => words,
|
||||
_ => binary.as_words().to_vec(),
|
||||
},
|
||||
Err(e) => {
|
||||
let mut err = sess.struct_warn(&e.to_string());
|
||||
err.note("spirv-opt failed, leaving as unoptimized");
|
||||
@ -383,7 +391,9 @@ fn add_upstream_rust_crates(
|
||||
Linkage::NotLinked | Linkage::IncludedFromDylib => {}
|
||||
Linkage::Static => rlibs.push(src.rlib.as_ref().unwrap().0.clone()),
|
||||
//Linkage::Dynamic => rlibs.push(src.dylib.as_ref().unwrap().0.clone()),
|
||||
Linkage::Dynamic => sess.err("TODO: Linkage::Dynamic not supported yet"),
|
||||
Linkage::Dynamic => {
|
||||
sess.err("TODO: Linkage::Dynamic not supported yet");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -441,9 +451,11 @@ fn add_upstream_native_libraries(
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME(eddyb) upstream has code like this already, maybe we can reuse most of it?
|
||||
// (see `compiler/rustc_codegen_ssa/src/back/link.rs`)
|
||||
fn relevant_lib(sess: &Session, lib: &NativeLib) -> bool {
|
||||
match lib.cfg {
|
||||
Some(ref cfg) => rustc_attr::cfg_matches(cfg, &sess.parse_sess, None),
|
||||
Some(ref cfg) => rustc_attr::cfg_matches(cfg, &sess.parse_sess, CRATE_NODE_ID, None),
|
||||
None => true,
|
||||
}
|
||||
}
|
||||
@ -547,7 +559,7 @@ fn do_link(
|
||||
|
||||
match link_result {
|
||||
Ok(v) => v,
|
||||
Err(rustc_errors::ErrorReported) => {
|
||||
Err(rustc_errors::ErrorGuaranteed { .. }) => {
|
||||
sess.abort_if_errors();
|
||||
bug!("Linker errored, but no error reported")
|
||||
}
|
||||
|
@ -2,7 +2,6 @@ use super::Result;
|
||||
use rspirv::dr::{Instruction, Module};
|
||||
use rspirv::spirv::{Capability, Decoration, LinkageType, Op, Word};
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_errors::ErrorReported;
|
||||
use rustc_session::Session;
|
||||
|
||||
pub fn run(sess: &Session, module: &mut Module) -> Result<()> {
|
||||
@ -35,11 +34,10 @@ fn find_import_export_pairs_and_killed_params(
|
||||
};
|
||||
let type_id = *type_map.get(&id).expect("Unexpected op");
|
||||
if exports.insert(name, (id, type_id)).is_some() {
|
||||
sess.err(&format!("Multiple exports found for {:?}", name));
|
||||
return Err(ErrorReported);
|
||||
return Err(sess.err(&format!("Multiple exports found for {:?}", name)));
|
||||
}
|
||||
}
|
||||
let mut has_err = false;
|
||||
let mut any_err = None;
|
||||
// Then, collect all the imports, and create the rewrite rules.
|
||||
for annotation in &module.annotations {
|
||||
let (import_id, name) = match get_linkage_inst(annotation) {
|
||||
@ -48,8 +46,7 @@ fn find_import_export_pairs_and_killed_params(
|
||||
};
|
||||
let (export_id, export_type) = match exports.get(name) {
|
||||
None => {
|
||||
sess.err(&format!("Unresolved symbol {:?}", name));
|
||||
has_err = true;
|
||||
any_err = Some(sess.err(&format!("Unresolved symbol {:?}", name)));
|
||||
continue;
|
||||
}
|
||||
Some(&x) => x,
|
||||
@ -64,11 +61,11 @@ fn find_import_export_pairs_and_killed_params(
|
||||
}
|
||||
}
|
||||
}
|
||||
if has_err {
|
||||
return Err(ErrorReported);
|
||||
}
|
||||
|
||||
Ok((rewrite_rules, killed_parameters))
|
||||
match any_err {
|
||||
Some(err) => Err(err),
|
||||
None => Ok((rewrite_rules, killed_parameters)),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_linkage_inst(inst: &Instruction) -> Option<(Word, &str, LinkageType)> {
|
||||
@ -148,7 +145,8 @@ fn check_tys_equal(
|
||||
format_ty(ty_defs, ty, &mut result);
|
||||
result
|
||||
}
|
||||
sess.struct_err(&format!("Types mismatch for {:?}", name))
|
||||
Err(sess
|
||||
.struct_err(&format!("Types mismatch for {:?}", name))
|
||||
.note(&format!(
|
||||
"import type: {}",
|
||||
format_ty_(&ty_defs, import_type)
|
||||
@ -157,8 +155,7 @@ fn check_tys_equal(
|
||||
"export type: {}",
|
||||
format_ty_(&ty_defs, export_type)
|
||||
))
|
||||
.emit();
|
||||
Err(ErrorReported)
|
||||
.emit())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,7 @@ use super::{get_name, get_names};
|
||||
use rspirv::dr::{Block, Function, Instruction, Module, ModuleHeader, Operand};
|
||||
use rspirv::spirv::{FunctionControl, Op, StorageClass, Word};
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_errors::ErrorGuaranteed;
|
||||
use rustc_session::Session;
|
||||
use std::mem::take;
|
||||
|
||||
@ -17,9 +18,8 @@ type FunctionMap = FxHashMap<Word, Function>;
|
||||
|
||||
pub fn inline(sess: &Session, module: &mut Module) -> super::Result<()> {
|
||||
// This algorithm gets real sad if there's recursion - but, good news, SPIR-V bans recursion
|
||||
if module_has_recursion(sess, module) {
|
||||
return Err(rustc_errors::ErrorReported);
|
||||
}
|
||||
deny_recursion_in_module(sess, module)?;
|
||||
|
||||
let functions = module
|
||||
.functions
|
||||
.iter()
|
||||
@ -67,7 +67,7 @@ pub fn inline(sess: &Session, module: &mut Module) -> super::Result<()> {
|
||||
}
|
||||
|
||||
// https://stackoverflow.com/a/53995651
|
||||
fn module_has_recursion(sess: &Session, module: &Module) -> bool {
|
||||
fn deny_recursion_in_module(sess: &Session, module: &Module) -> super::Result<()> {
|
||||
let func_to_index: FxHashMap<Word, usize> = module
|
||||
.functions
|
||||
.iter()
|
||||
@ -76,7 +76,7 @@ fn module_has_recursion(sess: &Session, module: &Module) -> bool {
|
||||
.collect();
|
||||
let mut discovered = vec![false; module.functions.len()];
|
||||
let mut finished = vec![false; module.functions.len()];
|
||||
let mut has_recursion = false;
|
||||
let mut has_recursion = None;
|
||||
for index in 0..module.functions.len() {
|
||||
if !discovered[index] && !finished[index] {
|
||||
visit(
|
||||
@ -97,7 +97,7 @@ fn module_has_recursion(sess: &Session, module: &Module) -> bool {
|
||||
current: usize,
|
||||
discovered: &mut Vec<bool>,
|
||||
finished: &mut Vec<bool>,
|
||||
has_recursion: &mut bool,
|
||||
has_recursion: &mut Option<ErrorGuaranteed>,
|
||||
func_to_index: &FxHashMap<Word, usize>,
|
||||
) {
|
||||
discovered[current] = true;
|
||||
@ -107,11 +107,10 @@ fn module_has_recursion(sess: &Session, module: &Module) -> bool {
|
||||
let names = get_names(module);
|
||||
let current_name = get_name(&names, module.functions[current].def_id().unwrap());
|
||||
let next_name = get_name(&names, module.functions[next].def_id().unwrap());
|
||||
sess.err(&format!(
|
||||
*has_recursion = Some(sess.err(&format!(
|
||||
"module has recursion, which is not allowed: `{}` calls `{}`",
|
||||
current_name, next_name
|
||||
));
|
||||
*has_recursion = true;
|
||||
)));
|
||||
break;
|
||||
}
|
||||
|
||||
@ -145,7 +144,10 @@ fn module_has_recursion(sess: &Session, module: &Module) -> bool {
|
||||
})
|
||||
}
|
||||
|
||||
has_recursion
|
||||
match has_recursion {
|
||||
Some(err) => Err(err),
|
||||
None => Ok(()),
|
||||
}
|
||||
}
|
||||
|
||||
fn compute_disallowed_argument_and_return_types(
|
||||
|
@ -24,10 +24,10 @@ use rspirv::binary::{Assemble, Consumer};
|
||||
use rspirv::dr::{Block, Instruction, Loader, Module, ModuleHeader, Operand};
|
||||
use rspirv::spirv::{Op, StorageClass, Word};
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_errors::ErrorReported;
|
||||
use rustc_errors::ErrorGuaranteed;
|
||||
use rustc_session::Session;
|
||||
|
||||
pub type Result<T> = std::result::Result<T, ErrorReported>;
|
||||
pub type Result<T> = std::result::Result<T, ErrorGuaranteed>;
|
||||
|
||||
pub struct Options {
|
||||
pub compact_ids: bool,
|
||||
|
@ -2,7 +2,6 @@ use super::{get_name, get_names, Result};
|
||||
use rspirv::dr::{Block, Function, Module};
|
||||
use rspirv::spirv::{ExecutionModel, Op, Word};
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_errors::ErrorReported;
|
||||
use rustc_session::Session;
|
||||
use std::iter::once;
|
||||
use std::mem::take;
|
||||
@ -172,9 +171,9 @@ pub fn check_fragment_insts(sess: &Session, module: &Module) -> Result<()> {
|
||||
.iter()
|
||||
.filter(|i| i.operands[0].unwrap_execution_model() != ExecutionModel::Fragment)
|
||||
.map(|i| func_id_to_idx[&i.operands[1].unwrap_id_ref()]);
|
||||
let mut okay = true;
|
||||
let mut any_err = None;
|
||||
for entry in entries {
|
||||
okay &= visit(
|
||||
any_err = any_err.or(visit(
|
||||
sess,
|
||||
module,
|
||||
&mut visited,
|
||||
@ -182,11 +181,14 @@ pub fn check_fragment_insts(sess: &Session, module: &Module) -> Result<()> {
|
||||
&mut names,
|
||||
entry,
|
||||
&func_id_to_idx,
|
||||
);
|
||||
)
|
||||
.err());
|
||||
}
|
||||
return if okay { Ok(()) } else { Err(ErrorReported) };
|
||||
return match any_err {
|
||||
Some(err) => Err(err),
|
||||
None => Ok(()),
|
||||
};
|
||||
|
||||
// returns false if error
|
||||
fn visit<'m>(
|
||||
sess: &Session,
|
||||
module: &'m Module,
|
||||
@ -195,17 +197,17 @@ pub fn check_fragment_insts(sess: &Session, module: &Module) -> Result<()> {
|
||||
names: &mut Option<FxHashMap<Word, &'m str>>,
|
||||
index: usize,
|
||||
func_id_to_idx: &FxHashMap<Word, usize>,
|
||||
) -> bool {
|
||||
) -> Result<()> {
|
||||
if visited[index] {
|
||||
return true;
|
||||
return Ok(());
|
||||
}
|
||||
visited[index] = true;
|
||||
stack.push(module.functions[index].def_id().unwrap());
|
||||
let mut okay = true;
|
||||
let mut any_err = None;
|
||||
for inst in module.functions[index].all_inst_iter() {
|
||||
if inst.class.opcode == Op::FunctionCall {
|
||||
let called_func = func_id_to_idx[&inst.operands[0].unwrap_id_ref()];
|
||||
okay &= visit(
|
||||
any_err = any_err.or(visit(
|
||||
sess,
|
||||
module,
|
||||
visited,
|
||||
@ -213,7 +215,8 @@ pub fn check_fragment_insts(sess: &Session, module: &Module) -> Result<()> {
|
||||
names,
|
||||
called_func,
|
||||
func_id_to_idx,
|
||||
);
|
||||
)
|
||||
.err());
|
||||
}
|
||||
if matches!(
|
||||
inst.class.opcode,
|
||||
@ -246,16 +249,21 @@ pub fn check_fragment_insts(sess: &Session, module: &Module) -> Result<()> {
|
||||
.chain(stack)
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n");
|
||||
any_err = Some(
|
||||
sess.struct_err(&format!(
|
||||
"{} cannot be used outside a fragment shader",
|
||||
inst.class.opname
|
||||
))
|
||||
.note(¬e)
|
||||
.emit();
|
||||
okay = false;
|
||||
.emit(),
|
||||
);
|
||||
}
|
||||
}
|
||||
stack.pop();
|
||||
okay
|
||||
|
||||
match any_err {
|
||||
Some(err) => Err(err),
|
||||
None => Ok(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -97,7 +97,7 @@ fn assemble_and_link(binaries: &[&[u8]]) -> Result<Module, String> {
|
||||
spirv_metadata: SpirvMetadata::None,
|
||||
},
|
||||
);
|
||||
assert_eq!(compiler.session().has_errors(), res.is_err());
|
||||
assert_eq!(compiler.session().has_errors(), res.as_ref().err().copied());
|
||||
res.map(|res| match res {
|
||||
LinkResult::SingleModule(m) => *m,
|
||||
LinkResult::MultipleModules(_) => unreachable!(),
|
||||
|
@ -5,5 +5,5 @@
|
||||
# to the user in the error, instead of "error: invalid channel name '[toolchain]'".
|
||||
|
||||
[toolchain]
|
||||
channel = "nightly-2022-03-01"
|
||||
channel = "nightly-2022-04-01"
|
||||
components = ["rust-src", "rustc-dev", "llvm-tools-preview"]
|
||||
|
@ -2,7 +2,7 @@
|
||||
%4 = OpFunctionParameter %5
|
||||
%6 = OpFunctionParameter %5
|
||||
%7 = OpLabel
|
||||
OpLine %8 660 8
|
||||
OpLine %8 971 8
|
||||
%9 = OpLoad %10 %4
|
||||
OpLine %11 7 13
|
||||
OpStore %6 %9
|
||||
|
@ -2,7 +2,7 @@
|
||||
%4 = OpFunctionParameter %5
|
||||
%6 = OpFunctionParameter %5
|
||||
%7 = OpLabel
|
||||
OpLine %8 660 8
|
||||
OpLine %8 971 8
|
||||
%9 = OpLoad %10 %4
|
||||
OpLine %11 7 13
|
||||
OpStore %6 %9
|
||||
|
@ -4,7 +4,7 @@
|
||||
%7 = OpLabel
|
||||
OpLine %8 7 35
|
||||
%9 = OpLoad %10 %4
|
||||
OpLine %11 851 8
|
||||
OpLine %11 1162 8
|
||||
OpStore %6 %9
|
||||
OpLine %8 8 1
|
||||
OpReturn
|
||||
|
@ -4,7 +4,7 @@
|
||||
%7 = OpLabel
|
||||
OpLine %8 7 37
|
||||
%9 = OpLoad %10 %4
|
||||
OpLine %11 851 8
|
||||
OpLine %11 1162 8
|
||||
OpStore %6 %9
|
||||
OpLine %8 8 1
|
||||
OpReturn
|
||||
|
@ -4,30 +4,30 @@ OpLine %5 11 11
|
||||
%6 = OpCompositeInsert %7 %8 %9 0
|
||||
OpLine %5 11 11
|
||||
%10 = OpCompositeExtract %11 %6 1
|
||||
OpLine %12 777 14
|
||||
OpLine %12 781 14
|
||||
%13 = OpBitcast %14 %8
|
||||
OpLine %12 777 8
|
||||
OpLine %12 781 8
|
||||
OpSelectionMerge %15 None
|
||||
OpSwitch %13 %16 0 %17 1 %18
|
||||
%16 = OpLabel
|
||||
OpLine %12 777 14
|
||||
OpLine %12 781 14
|
||||
OpUnreachable
|
||||
%17 = OpLabel
|
||||
OpLine %12 779 20
|
||||
OpLine %12 783 20
|
||||
OpBranch %15
|
||||
%18 = OpLabel
|
||||
OpLine %12 778 23
|
||||
OpLine %12 782 23
|
||||
OpBranch %15
|
||||
%15 = OpLabel
|
||||
%19 = OpPhi %20 %21 %17 %22 %18
|
||||
%23 = OpPhi %11 %24 %17 %10 %18
|
||||
OpBranch %25
|
||||
%25 = OpLabel
|
||||
OpLine %12 781 4
|
||||
OpLine %12 785 4
|
||||
OpSelectionMerge %26 None
|
||||
OpBranchConditional %19 %27 %28
|
||||
%27 = OpLabel
|
||||
OpLine %12 781 4
|
||||
OpLine %12 785 4
|
||||
OpBranch %26
|
||||
%28 = OpLabel
|
||||
OpBranch %26
|
||||
|
@ -2152,133 +2152,133 @@ error: attribute is only valid on a function or closure, not on a associated con
|
||||
239 | unroll_loops, // fn/closure-only
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: attribute is only valid on a struct, not on a method
|
||||
error: attribute is only valid on a struct, not on a required trait method
|
||||
--> $DIR/invalid-target.rs:244:9
|
||||
|
|
||||
244 | sampler, block, sampled_image, generic_image_type, // struct-only
|
||||
| ^^^^^^^
|
||||
|
||||
error: attribute is only valid on a struct, not on a method
|
||||
error: attribute is only valid on a struct, not on a required trait method
|
||||
--> $DIR/invalid-target.rs:244:18
|
||||
|
|
||||
244 | sampler, block, sampled_image, generic_image_type, // struct-only
|
||||
| ^^^^^
|
||||
|
||||
error: attribute is only valid on a struct, not on a method
|
||||
error: attribute is only valid on a struct, not on a required trait method
|
||||
--> $DIR/invalid-target.rs:244:25
|
||||
|
|
||||
244 | sampler, block, sampled_image, generic_image_type, // struct-only
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error: attribute is only valid on a struct, not on a method
|
||||
error: attribute is only valid on a struct, not on a required trait method
|
||||
--> $DIR/invalid-target.rs:244:40
|
||||
|
|
||||
244 | sampler, block, sampled_image, generic_image_type, // struct-only
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: attribute is only valid on a function, not on a method
|
||||
error: attribute is only valid on a function, not on a required trait method
|
||||
--> $DIR/invalid-target.rs:245:9
|
||||
|
|
||||
245 | vertex, // fn-only
|
||||
| ^^^^^^
|
||||
|
||||
error: attribute is only valid on a function parameter, not on a method
|
||||
error: attribute is only valid on a function parameter, not on a required trait method
|
||||
--> $DIR/invalid-target.rs:246:9
|
||||
|
|
||||
246 | uniform, position, descriptor_set = 0, binding = 0, flat, invariant, // param-only
|
||||
| ^^^^^^^
|
||||
|
||||
error: attribute is only valid on a function parameter, not on a method
|
||||
error: attribute is only valid on a function parameter, not on a required trait method
|
||||
--> $DIR/invalid-target.rs:246:18
|
||||
|
|
||||
246 | uniform, position, descriptor_set = 0, binding = 0, flat, invariant, // param-only
|
||||
| ^^^^^^^^
|
||||
|
||||
error: attribute is only valid on a function parameter, not on a method
|
||||
error: attribute is only valid on a function parameter, not on a required trait method
|
||||
--> $DIR/invalid-target.rs:246:28
|
||||
|
|
||||
246 | uniform, position, descriptor_set = 0, binding = 0, flat, invariant, // param-only
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: attribute is only valid on a function parameter, not on a method
|
||||
error: attribute is only valid on a function parameter, not on a required trait method
|
||||
--> $DIR/invalid-target.rs:246:48
|
||||
|
|
||||
246 | uniform, position, descriptor_set = 0, binding = 0, flat, invariant, // param-only
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: attribute is only valid on a function parameter, not on a method
|
||||
error: attribute is only valid on a function parameter, not on a required trait method
|
||||
--> $DIR/invalid-target.rs:246:61
|
||||
|
|
||||
246 | uniform, position, descriptor_set = 0, binding = 0, flat, invariant, // param-only
|
||||
| ^^^^
|
||||
|
||||
error: attribute is only valid on a function parameter, not on a method
|
||||
error: attribute is only valid on a function parameter, not on a required trait method
|
||||
--> $DIR/invalid-target.rs:246:67
|
||||
|
|
||||
246 | uniform, position, descriptor_set = 0, binding = 0, flat, invariant, // param-only
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: attribute is only valid on a function or closure, not on a method
|
||||
error: attribute is only valid on a function or closure, not on a required trait method
|
||||
--> $DIR/invalid-target.rs:247:9
|
||||
|
|
||||
247 | unroll_loops, // fn/closure-only
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: attribute is only valid on a struct, not on a method
|
||||
error: attribute is only valid on a struct, not on a provided trait method
|
||||
--> $DIR/invalid-target.rs:252:9
|
||||
|
|
||||
252 | sampler, block, sampled_image, generic_image_type, // struct-only
|
||||
| ^^^^^^^
|
||||
|
||||
error: attribute is only valid on a struct, not on a method
|
||||
error: attribute is only valid on a struct, not on a provided trait method
|
||||
--> $DIR/invalid-target.rs:252:18
|
||||
|
|
||||
252 | sampler, block, sampled_image, generic_image_type, // struct-only
|
||||
| ^^^^^
|
||||
|
||||
error: attribute is only valid on a struct, not on a method
|
||||
error: attribute is only valid on a struct, not on a provided trait method
|
||||
--> $DIR/invalid-target.rs:252:25
|
||||
|
|
||||
252 | sampler, block, sampled_image, generic_image_type, // struct-only
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error: attribute is only valid on a struct, not on a method
|
||||
error: attribute is only valid on a struct, not on a provided trait method
|
||||
--> $DIR/invalid-target.rs:252:40
|
||||
|
|
||||
252 | sampler, block, sampled_image, generic_image_type, // struct-only
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: attribute is only valid on a function parameter, not on a method
|
||||
error: attribute is only valid on a function parameter, not on a provided trait method
|
||||
--> $DIR/invalid-target.rs:253:9
|
||||
|
|
||||
253 | uniform, position, descriptor_set = 0, binding = 0, flat, invariant, // param-only
|
||||
| ^^^^^^^
|
||||
|
||||
error: attribute is only valid on a function parameter, not on a method
|
||||
error: attribute is only valid on a function parameter, not on a provided trait method
|
||||
--> $DIR/invalid-target.rs:253:18
|
||||
|
|
||||
253 | uniform, position, descriptor_set = 0, binding = 0, flat, invariant, // param-only
|
||||
| ^^^^^^^^
|
||||
|
||||
error: attribute is only valid on a function parameter, not on a method
|
||||
error: attribute is only valid on a function parameter, not on a provided trait method
|
||||
--> $DIR/invalid-target.rs:253:28
|
||||
|
|
||||
253 | uniform, position, descriptor_set = 0, binding = 0, flat, invariant, // param-only
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: attribute is only valid on a function parameter, not on a method
|
||||
error: attribute is only valid on a function parameter, not on a provided trait method
|
||||
--> $DIR/invalid-target.rs:253:48
|
||||
|
|
||||
253 | uniform, position, descriptor_set = 0, binding = 0, flat, invariant, // param-only
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: attribute is only valid on a function parameter, not on a method
|
||||
error: attribute is only valid on a function parameter, not on a provided trait method
|
||||
--> $DIR/invalid-target.rs:253:61
|
||||
|
|
||||
253 | uniform, position, descriptor_set = 0, binding = 0, flat, invariant, // param-only
|
||||
| ^^^^
|
||||
|
||||
error: attribute is only valid on a function parameter, not on a method
|
||||
error: attribute is only valid on a function parameter, not on a provided trait method
|
||||
--> $DIR/invalid-target.rs:253:67
|
||||
|
|
||||
253 | uniform, position, descriptor_set = 0, binding = 0, flat, invariant, // param-only
|
||||
@ -2356,61 +2356,61 @@ error: attribute is only valid on a function or closure, not on a associated con
|
||||
201 | unroll_loops, // fn/closure-only
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: attribute is only valid on a struct, not on a method
|
||||
error: attribute is only valid on a struct, not on a inherent method
|
||||
--> $DIR/invalid-target.rs:206:9
|
||||
|
|
||||
206 | sampler, block, sampled_image, generic_image_type, // struct-only
|
||||
| ^^^^^^^
|
||||
|
||||
error: attribute is only valid on a struct, not on a method
|
||||
error: attribute is only valid on a struct, not on a inherent method
|
||||
--> $DIR/invalid-target.rs:206:18
|
||||
|
|
||||
206 | sampler, block, sampled_image, generic_image_type, // struct-only
|
||||
| ^^^^^
|
||||
|
||||
error: attribute is only valid on a struct, not on a method
|
||||
error: attribute is only valid on a struct, not on a inherent method
|
||||
--> $DIR/invalid-target.rs:206:25
|
||||
|
|
||||
206 | sampler, block, sampled_image, generic_image_type, // struct-only
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error: attribute is only valid on a struct, not on a method
|
||||
error: attribute is only valid on a struct, not on a inherent method
|
||||
--> $DIR/invalid-target.rs:206:40
|
||||
|
|
||||
206 | sampler, block, sampled_image, generic_image_type, // struct-only
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: attribute is only valid on a function parameter, not on a method
|
||||
error: attribute is only valid on a function parameter, not on a inherent method
|
||||
--> $DIR/invalid-target.rs:207:9
|
||||
|
|
||||
207 | uniform, position, descriptor_set = 0, binding = 0, flat, invariant, // param-only
|
||||
| ^^^^^^^
|
||||
|
||||
error: attribute is only valid on a function parameter, not on a method
|
||||
error: attribute is only valid on a function parameter, not on a inherent method
|
||||
--> $DIR/invalid-target.rs:207:18
|
||||
|
|
||||
207 | uniform, position, descriptor_set = 0, binding = 0, flat, invariant, // param-only
|
||||
| ^^^^^^^^
|
||||
|
||||
error: attribute is only valid on a function parameter, not on a method
|
||||
error: attribute is only valid on a function parameter, not on a inherent method
|
||||
--> $DIR/invalid-target.rs:207:28
|
||||
|
|
||||
207 | uniform, position, descriptor_set = 0, binding = 0, flat, invariant, // param-only
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: attribute is only valid on a function parameter, not on a method
|
||||
error: attribute is only valid on a function parameter, not on a inherent method
|
||||
--> $DIR/invalid-target.rs:207:48
|
||||
|
|
||||
207 | uniform, position, descriptor_set = 0, binding = 0, flat, invariant, // param-only
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: attribute is only valid on a function parameter, not on a method
|
||||
error: attribute is only valid on a function parameter, not on a inherent method
|
||||
--> $DIR/invalid-target.rs:207:61
|
||||
|
|
||||
207 | uniform, position, descriptor_set = 0, binding = 0, flat, invariant, // param-only
|
||||
| ^^^^
|
||||
|
||||
error: attribute is only valid on a function parameter, not on a method
|
||||
error: attribute is only valid on a function parameter, not on a inherent method
|
||||
--> $DIR/invalid-target.rs:207:67
|
||||
|
|
||||
207 | uniform, position, descriptor_set = 0, binding = 0, flat, invariant, // param-only
|
||||
@ -2560,61 +2560,61 @@ error: attribute is only valid on a function or closure, not on a associated con
|
||||
277 | unroll_loops, // fn/closure-only
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: attribute is only valid on a struct, not on a method
|
||||
error: attribute is only valid on a struct, not on a provided trait method
|
||||
--> $DIR/invalid-target.rs:282:9
|
||||
|
|
||||
282 | sampler, block, sampled_image, generic_image_type, // struct-only
|
||||
| ^^^^^^^
|
||||
|
||||
error: attribute is only valid on a struct, not on a method
|
||||
error: attribute is only valid on a struct, not on a provided trait method
|
||||
--> $DIR/invalid-target.rs:282:18
|
||||
|
|
||||
282 | sampler, block, sampled_image, generic_image_type, // struct-only
|
||||
| ^^^^^
|
||||
|
||||
error: attribute is only valid on a struct, not on a method
|
||||
error: attribute is only valid on a struct, not on a provided trait method
|
||||
--> $DIR/invalid-target.rs:282:25
|
||||
|
|
||||
282 | sampler, block, sampled_image, generic_image_type, // struct-only
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error: attribute is only valid on a struct, not on a method
|
||||
error: attribute is only valid on a struct, not on a provided trait method
|
||||
--> $DIR/invalid-target.rs:282:40
|
||||
|
|
||||
282 | sampler, block, sampled_image, generic_image_type, // struct-only
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: attribute is only valid on a function parameter, not on a method
|
||||
error: attribute is only valid on a function parameter, not on a provided trait method
|
||||
--> $DIR/invalid-target.rs:283:9
|
||||
|
|
||||
283 | uniform, position, descriptor_set = 0, binding = 0, flat, invariant, // param-only
|
||||
| ^^^^^^^
|
||||
|
||||
error: attribute is only valid on a function parameter, not on a method
|
||||
error: attribute is only valid on a function parameter, not on a provided trait method
|
||||
--> $DIR/invalid-target.rs:283:18
|
||||
|
|
||||
283 | uniform, position, descriptor_set = 0, binding = 0, flat, invariant, // param-only
|
||||
| ^^^^^^^^
|
||||
|
||||
error: attribute is only valid on a function parameter, not on a method
|
||||
error: attribute is only valid on a function parameter, not on a provided trait method
|
||||
--> $DIR/invalid-target.rs:283:28
|
||||
|
|
||||
283 | uniform, position, descriptor_set = 0, binding = 0, flat, invariant, // param-only
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: attribute is only valid on a function parameter, not on a method
|
||||
error: attribute is only valid on a function parameter, not on a provided trait method
|
||||
--> $DIR/invalid-target.rs:283:48
|
||||
|
|
||||
283 | uniform, position, descriptor_set = 0, binding = 0, flat, invariant, // param-only
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: attribute is only valid on a function parameter, not on a method
|
||||
error: attribute is only valid on a function parameter, not on a provided trait method
|
||||
--> $DIR/invalid-target.rs:283:61
|
||||
|
|
||||
283 | uniform, position, descriptor_set = 0, binding = 0, flat, invariant, // param-only
|
||||
| ^^^^
|
||||
|
||||
error: attribute is only valid on a function parameter, not on a method
|
||||
error: attribute is only valid on a function parameter, not on a provided trait method
|
||||
--> $DIR/invalid-target.rs:283:67
|
||||
|
|
||||
283 | uniform, position, descriptor_set = 0, binding = 0, flat, invariant, // param-only
|
||||
|
Loading…
Reference in New Issue
Block a user