mirror of
https://github.com/EmbarkStudios/rust-gpu.git
synced 2024-11-22 06:45:13 +00:00
Zombies are errors in user code
This commit is contained in:
parent
e56c35aaf3
commit
01ccf5cf39
@ -305,6 +305,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
|
||||
cursor: Default::default(),
|
||||
current_fn: Default::default(),
|
||||
basic_block: Default::default(),
|
||||
current_span: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -336,6 +337,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
|
||||
cursor,
|
||||
current_fn: llfn,
|
||||
basic_block: label,
|
||||
current_span: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -354,6 +356,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
|
||||
cursor: new_cursor,
|
||||
current_fn: self.current_fn,
|
||||
basic_block: new_bb,
|
||||
current_span: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -365,8 +368,8 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
|
||||
self.basic_block
|
||||
}
|
||||
|
||||
fn set_span(&self, _span: Span) {
|
||||
// TODO
|
||||
fn set_span(&self, span: Span) {
|
||||
*self.current_span.borrow_mut() = Some(span);
|
||||
}
|
||||
|
||||
fn ret_void(&mut self) {
|
||||
@ -380,7 +383,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
|
||||
fn br(&mut self, dest: Self::BasicBlock) {
|
||||
if !self.kernel_mode && self.basic_block == dest {
|
||||
// TODO: Remove once structurizer is done.
|
||||
self.zombie(dest, "Infinite loop before structurizer is done");
|
||||
self.zombie_even_in_user_code(dest, "Infinite loop before structurizer is done");
|
||||
}
|
||||
self.emit().branch(dest).unwrap()
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ use crate::abi::ConvSpirvType;
|
||||
use crate::builder_spirv::{BuilderCursor, SpirvValue, SpirvValueExt};
|
||||
use crate::codegen_cx::CodegenCx;
|
||||
use crate::spirv_type::SpirvType;
|
||||
use rspirv::spirv::StorageClass;
|
||||
use rspirv::spirv::{StorageClass, Word};
|
||||
use rustc_ast::ast::{InlineAsmOptions, InlineAsmTemplatePiece};
|
||||
use rustc_codegen_ssa::mir::operand::OperandValue;
|
||||
use rustc_codegen_ssa::mir::place::PlaceRef;
|
||||
@ -28,6 +28,7 @@ use rustc_span::source_map::Span;
|
||||
use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode};
|
||||
use rustc_target::abi::{HasDataLayout, LayoutOf, Size, TargetDataLayout};
|
||||
use rustc_target::spec::{HasTargetSpec, Target};
|
||||
use std::cell::RefCell;
|
||||
use std::ops::Deref;
|
||||
|
||||
pub struct Builder<'a, 'tcx> {
|
||||
@ -35,6 +36,7 @@ pub struct Builder<'a, 'tcx> {
|
||||
cursor: BuilderCursor,
|
||||
current_fn: <Self as BackendTypes>::Function,
|
||||
basic_block: <Self as BackendTypes>::BasicBlock,
|
||||
current_span: RefCell<Option<Span>>,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
@ -43,6 +45,25 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
self.emit_with_cursor(self.cursor)
|
||||
}
|
||||
|
||||
pub fn zombie(&self, word: Word, reason: &'static str) {
|
||||
if let Some(current_span) = *self.current_span.borrow() {
|
||||
self.zombie_with_span(word, current_span, reason);
|
||||
} else {
|
||||
self.zombie_no_span(word, reason);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn validate_atomic(&self, ty: Word, to_zombie: Word) {
|
||||
if !self.i8_i16_atomics_allowed {
|
||||
match self.lookup_type(ty) {
|
||||
SpirvType::Integer(width, _) if width < 32 => {
|
||||
self.zombie(to_zombie, "atomic on i8 or i16 when disallowed by runtime");
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn gep_help(
|
||||
&self,
|
||||
ptr: SpirvValue,
|
||||
|
@ -67,7 +67,7 @@ impl<'tcx> CodegenCx<'tcx> {
|
||||
},
|
||||
SpirvType::Integer(128, _) => {
|
||||
let result = self.undef(ty);
|
||||
self.zombie(result.def, "u128 constant");
|
||||
self.zombie_no_span(result.def, "u128 constant");
|
||||
result
|
||||
}
|
||||
other => panic!("constant_int invalid on type {}", other.debug(ty, self)),
|
||||
@ -160,7 +160,7 @@ impl<'tcx> ConstMethods<'tcx> for CodegenCx<'tcx> {
|
||||
let len = s.as_str().len();
|
||||
let ty = self.type_ptr_to(self.layout_of(self.tcx.types.str_).spirv_type(self));
|
||||
let result = self.undef(ty);
|
||||
self.zombie(result.def, "constant string");
|
||||
self.zombie_no_span(result.def, "constant string");
|
||||
(result, self.const_usize(len as u64))
|
||||
}
|
||||
fn const_struct(&self, elts: &[Self::Value], _packed: bool) -> Self::Value {
|
||||
@ -283,7 +283,7 @@ impl<'tcx> ConstMethods<'tcx> for CodegenCx<'tcx> {
|
||||
) => {
|
||||
if a_space != b_space {
|
||||
// TODO: Emit the correct type that is passed into this function.
|
||||
self.zombie(value.def, "invalid pointer space in constant");
|
||||
self.zombie_no_span(value.def, "invalid pointer space in constant");
|
||||
}
|
||||
assert_ty_eq!(self, a, b);
|
||||
}
|
||||
@ -313,7 +313,7 @@ impl<'tcx> ConstMethods<'tcx> for CodegenCx<'tcx> {
|
||||
} else {
|
||||
// constant ptrcast is not supported in spir-v
|
||||
let result = val.def.with_type(ty);
|
||||
self.zombie(result.def, "const_ptrcast");
|
||||
self.zombie_no_span(result.def, "const_ptrcast");
|
||||
result
|
||||
}
|
||||
}
|
||||
@ -421,7 +421,7 @@ impl<'tcx> CodegenCx<'tcx> {
|
||||
*data = *c + asdf->y[*c];
|
||||
}
|
||||
*/
|
||||
self.zombie(result.def, "constant runtime array value");
|
||||
self.zombie_no_span(result.def, "constant runtime array value");
|
||||
result
|
||||
}
|
||||
SpirvType::Pointer { .. } => {
|
||||
|
@ -14,6 +14,7 @@ use rustc_middle::mir::mono::{Linkage, MonoItem, Visibility};
|
||||
use rustc_middle::ty::layout::FnAbiExt;
|
||||
use rustc_middle::ty::{Instance, ParamEnv, Ty, TypeFoldable};
|
||||
use rustc_span::def_id::DefId;
|
||||
use rustc_span::Span;
|
||||
use rustc_target::abi::call::FnAbi;
|
||||
use rustc_target::abi::{Align, LayoutOf};
|
||||
use std::collections::HashMap;
|
||||
@ -83,7 +84,8 @@ impl<'tcx> CodegenCx<'tcx> {
|
||||
if crate::is_blocklisted_fn(name) {
|
||||
// This can happen if we call a blocklisted function in another crate.
|
||||
let result = self.undef(function_type);
|
||||
self.zombie(result.def, "called blocklisted fn");
|
||||
// TODO: Span info here
|
||||
self.zombie_no_span(result.def, "called blocklisted fn");
|
||||
return result;
|
||||
}
|
||||
let mut emit = self.emit_global();
|
||||
@ -130,13 +132,14 @@ impl<'tcx> CodegenCx<'tcx> {
|
||||
|
||||
let ty = instance.ty(self.tcx, ParamEnv::reveal_all());
|
||||
let sym = self.tcx.symbol_name(instance).name;
|
||||
let g = self.declare_global(self.layout_of(ty).spirv_type(self));
|
||||
let span = self.tcx.def_span(def_id);
|
||||
let g = self.declare_global(span, self.layout_of(ty).spirv_type(self));
|
||||
self.instances.borrow_mut().insert(instance, g);
|
||||
self.set_linkage(g.def, sym.to_string(), LinkageType::Import);
|
||||
g
|
||||
}
|
||||
|
||||
fn declare_global(&self, ty: Word) -> SpirvValue {
|
||||
fn declare_global(&self, span: Span, ty: Word) -> SpirvValue {
|
||||
let ptr_ty = SpirvType::Pointer {
|
||||
storage_class: StorageClass::Function,
|
||||
pointee: ty,
|
||||
@ -147,7 +150,7 @@ impl<'tcx> CodegenCx<'tcx> {
|
||||
.variable(ptr_ty, None, StorageClass::Function, None)
|
||||
.with_type(ptr_ty);
|
||||
// TODO: These should be StorageClass::Private, so just zombie for now.
|
||||
self.zombie(result.def, "declare_global");
|
||||
self.zombie_with_span(result.def, span, "Globals are not supported yet");
|
||||
result
|
||||
}
|
||||
|
||||
@ -292,7 +295,8 @@ impl<'tcx> PreDefineMethods<'tcx> for CodegenCx<'tcx> {
|
||||
other => panic!("TODO: Linkage type not supported yet: {:?}", other),
|
||||
};
|
||||
|
||||
let g = self.declare_global(spvty);
|
||||
let span = self.tcx.def_span(def_id);
|
||||
let g = self.declare_global(span, spvty);
|
||||
|
||||
// unsafe {
|
||||
// llvm::LLVMRustSetLinkage(g, base::linkage_to_llvm(linkage));
|
||||
@ -356,7 +360,7 @@ impl<'tcx> StaticMethods for CodegenCx<'tcx> {
|
||||
}
|
||||
.def(self);
|
||||
let result = self.undef(ty);
|
||||
self.zombie(result.def, "static_addr_of");
|
||||
self.zombie_no_span(result.def, "static_addr_of");
|
||||
result
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,7 @@ use rustc_middle::ty::{Instance, ParamEnv, PolyExistentialTraitRef, Ty, TyCtxt};
|
||||
use rustc_session::Session;
|
||||
use rustc_span::def_id::CrateNum;
|
||||
use rustc_span::source_map::Span;
|
||||
use rustc_span::symbol::Symbol;
|
||||
use rustc_span::symbol::{sym, Symbol};
|
||||
use rustc_span::SourceFile;
|
||||
use rustc_target::abi::call::FnAbi;
|
||||
use rustc_target::abi::{HasDataLayout, TargetDataLayout};
|
||||
@ -116,8 +116,30 @@ impl<'tcx> CodegenCx<'tcx> {
|
||||
///
|
||||
/// Finally, if *user* code is marked as zombie, then this means that the user tried to do something that isn't
|
||||
/// supported, and should be an error.
|
||||
pub fn zombie(&self, word: Word, reason: &'static str) {
|
||||
pub fn zombie_with_span(&self, word: Word, span: Span, reason: &'static str) {
|
||||
if self.is_system_crate() {
|
||||
self.zombie_values.borrow_mut().insert(word, reason);
|
||||
} else {
|
||||
self.tcx.sess.span_err(span, reason);
|
||||
}
|
||||
}
|
||||
pub fn zombie_no_span(&self, word: Word, reason: &'static str) {
|
||||
if self.is_system_crate() {
|
||||
self.zombie_values.borrow_mut().insert(word, reason);
|
||||
} else {
|
||||
self.tcx.sess.err(reason);
|
||||
}
|
||||
}
|
||||
pub fn zombie_even_in_user_code(&self, word: Word, reason: &'static str) {
|
||||
self.zombie_values.borrow_mut().insert(word, reason);
|
||||
}
|
||||
|
||||
fn is_system_crate(&self) -> bool {
|
||||
let krate_attrs = self.tcx.hir().krate_attrs();
|
||||
self.tcx
|
||||
.sess
|
||||
.contains_name(krate_attrs, sym::compiler_builtins)
|
||||
|| self.tcx.sess.contains_name(krate_attrs, sym::core)
|
||||
}
|
||||
|
||||
pub fn finalize_module(self) -> Module {
|
||||
@ -152,8 +174,8 @@ impl<'tcx> CodegenCx<'tcx> {
|
||||
.def(self);
|
||||
// We want a unique ID for these undefs, so don't use the caching system.
|
||||
let result = self.emit_global().undef(ty, None).with_type(ty);
|
||||
// It's obviously invalid, so zombie it.
|
||||
self.zombie(result.def, "get_fn_addr");
|
||||
// It's obviously invalid, so zombie it. Zombie it in user code as well, because it's valid there too.
|
||||
self.zombie_even_in_user_code(result.def, "get_fn_addr");
|
||||
self.function_pointers
|
||||
.borrow_mut()
|
||||
.insert_no_overwrite(result, function)
|
||||
@ -168,17 +190,6 @@ impl<'tcx> CodegenCx<'tcx> {
|
||||
.get_by_left(&pointer)
|
||||
.cloned()
|
||||
}
|
||||
|
||||
pub fn validate_atomic(&self, ty: Word, to_zombie: Word) {
|
||||
if !self.i8_i16_atomics_allowed {
|
||||
match self.lookup_type(ty) {
|
||||
SpirvType::Integer(width, _) if width < 32 => {
|
||||
self.zombie(to_zombie, "atomic on i8 or i16 when disallowed by runtime");
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> BackendTypes for CodegenCx<'tcx> {
|
||||
|
@ -72,16 +72,16 @@ impl SpirvType {
|
||||
.type_int(width, if signedness { 1 } else { 0 });
|
||||
match width {
|
||||
8 if !cx.builder.has_capability(Capability::Int8) => {
|
||||
cx.zombie(result, "u8 without OpCapability Int8")
|
||||
cx.zombie_no_span(result, "u8 without OpCapability Int8")
|
||||
}
|
||||
16 if !cx.builder.has_capability(Capability::Int16) => {
|
||||
cx.zombie(result, "u16 without OpCapability Int16")
|
||||
cx.zombie_no_span(result, "u16 without OpCapability Int16")
|
||||
}
|
||||
64 if !cx.builder.has_capability(Capability::Int64) => {
|
||||
cx.zombie(result, "u64 without OpCapability Int64")
|
||||
cx.zombie_no_span(result, "u64 without OpCapability Int64")
|
||||
}
|
||||
8 | 16 | 32 | 64 => (),
|
||||
128 => cx.zombie(result, "u128"),
|
||||
128 => cx.zombie_no_span(result, "u128"),
|
||||
other => panic!("Integer width {} invalid for spir-v", other),
|
||||
};
|
||||
result
|
||||
@ -90,7 +90,7 @@ impl SpirvType {
|
||||
let result = cx.emit_global().type_float(width);
|
||||
match width {
|
||||
64 if !cx.builder.has_capability(Capability::Float64) => {
|
||||
cx.zombie(result, "f64 without OpCapability Float64")
|
||||
cx.zombie_no_span(result, "f64 without OpCapability Float64")
|
||||
}
|
||||
32 | 64 => (),
|
||||
other => panic!("Float width {} invalid for spir-v", other),
|
||||
@ -154,7 +154,7 @@ impl SpirvType {
|
||||
SpirvType::RuntimeArray { element } => {
|
||||
let result = cx.emit_global().type_runtime_array(element);
|
||||
if cx.kernel_mode {
|
||||
cx.zombie(result, "RuntimeArray in kernel mode");
|
||||
cx.zombie_no_span(result, "RuntimeArray in kernel mode");
|
||||
}
|
||||
result
|
||||
}
|
||||
@ -165,7 +165,7 @@ impl SpirvType {
|
||||
let result = cx.emit_global().type_pointer(None, storage_class, pointee);
|
||||
// no pointers to functions
|
||||
if let SpirvType::Function { .. } = cx.lookup_type(pointee) {
|
||||
cx.zombie(result, "pointer to function")
|
||||
cx.zombie_even_in_user_code(result, "pointer to function")
|
||||
}
|
||||
result
|
||||
}
|
||||
@ -197,7 +197,7 @@ impl SpirvType {
|
||||
.type_pointer(Some(id), storage_class, pointee);
|
||||
// no pointers to functions
|
||||
if let SpirvType::Function { .. } = cx.lookup_type(pointee) {
|
||||
cx.zombie(result, "pointer to function")
|
||||
cx.zombie_even_in_user_code(result, "pointer to function")
|
||||
}
|
||||
result
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user