-
Notifications
You must be signed in to change notification settings - Fork 250
/
Copy pathruntime_array.rs
130 lines (125 loc) · 4.98 KB
/
runtime_array.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
use crate::builder::Builder;
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_target::abi::call::PassMode;
impl<'a, 'tcx> Builder<'a, 'tcx> {
/// Note: DOES NOT do bounds checking! Bounds checking is expected to be done in the caller.
pub fn codegen_runtime_array_index_intrinsic(
&mut self,
result_type: Word,
args: &[SpirvValue],
pass_mode: &PassMode,
) -> SpirvValue {
match pass_mode {
PassMode::Ignore => {
return SpirvValue {
kind: SpirvValueKind::IllegalTypeUsed(result_type),
ty: result_type,
};
}
// PassMode::Pair is identical to PassMode::Direct - it's returned as a struct
PassMode::Direct(_) | PassMode::Pair(_, _) => (),
PassMode::Cast { .. } => {
self.fatal("PassMode::Cast not supported in codegen_runtime_array_index_intrinsic")
}
PassMode::Indirect { .. } => self
.fatal("PassMode::Indirect not supported in codegen_runtime_array_index_intrinsic"),
}
// Signatures:
// fn <T: ?Sized>(runtime_array: &RuntimeArray<T>, index: usize) -> &T
// fn <T: ?Sized>(runtime_array: &mut RuntimeArray<T>, index: usize) -> &mut T
if args.len() != 2 {
self.fatal(format!(
"runtime_array_index_intrinsic should have 3 args, it has {}",
args.len()
));
}
let runtime_array = args[0];
let index = args[1];
let runtime_array_type = self.lookup_type(runtime_array.ty);
let element_ty = match runtime_array_type {
SpirvType::Pointer { pointee } => {
match self.lookup_type(pointee) {
SpirvType::RuntimeArray { element } => {
element
}
_ => self.fatal(format!(
"runtime_array_index_intrinsic args[0] is {:?} and not a Pointer to a RuntimeArray!",
runtime_array_type
)),
}
}
_ => self.fatal(format!(
"runtime_array_index_intrinsic args[0] is {:?} and not a Pointer!",
runtime_array_type
)),
};
let ptr_element = self.type_ptr_to(element_ty);
let element = self
.emit()
.access_chain(
ptr_element,
None,
runtime_array.def(self),
[index.def(self)],
)
.unwrap()
.with_type(ptr_element);
match self.lookup_type(element_ty) {
SpirvType::InterfaceBlock { .. } => {
// array of buffer descriptors
let inner = self.struct_gep(element_ty, element, 0);
match pass_mode {
PassMode::Direct(_) => {
// element is sized
if inner.ty == result_type {
inner
} else {
self.fatal(format!(
"runtime_array_index_intrinsic expected result_type to equal RuntimeArray's InterfaceBlock's inner_type: {:?} == {:?}",
self.lookup_type(result_type).debug(result_type, self),
self.lookup_type(inner.ty).debug(inner.ty, self)
))
}
}
PassMode::Pair(_, _) => {
// element is a slice
match self.lookup_type(result_type) {
SpirvType::Adt { field_types, .. } if field_types.len() == 2
&& matches!(self.lookup_type(field_types[0]), SpirvType::Pointer {..})
&& field_types[1] == self.type_isize() => {
}
_ => self.fatal(format!(
"Expected element of RuntimeArray to be a plain slice, like `&RuntimeArray<[u32]>`, but got {:?}!",
self.lookup_type(result_type).debug(result_type, self)
))
};
let len = self
.emit()
.array_length(self.type_isize(), None, element.def(self), 0)
.unwrap();
self.emit()
.composite_construct(result_type, None, [inner.def(self), len])
.unwrap()
.with_type(result_type)
}
_ => unreachable!(),
}
}
_ => {
// array of UniformConstant (image, sampler, etc.) descriptors
if ptr_element == result_type {
element
} else {
self.fatal(format!(
"runtime_array_index_intrinsic expected result_type to equal RuntimeArray's element_ty: {:?} == {:?}",
self.lookup_type(result_type).debug(result_type, self),
self.lookup_type(ptr_element).debug(ptr_element, self)
))
}
}
}
}
}