1use core::{
3 fmt::{self, Display, Debug},
4 slice,
5};
6use crate::{
7 core::*,
8 stream::*,
9 module::*,
10};
11use super::*;
12#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
14pub struct IdResultType(pub(crate) u32);
15impl Display for IdResultType {
16
17 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
18 write!(f, "%{}", self.0)
19 }
20}
21impl Word for IdResultType {
22
23 #[inline]
24 fn from_word(word: u32) -> Self {
25 Self(word)
26 }
27}
28#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
30pub struct IdResult(pub(crate) u32);
31impl Display for IdResult {
32
33 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
34 write!(f, "%{}", self.0)
35 }
36}
37impl Word for IdResult {
38
39 #[inline]
40 fn from_word(word: u32) -> Self {
41 Self(word)
42 }
43}
44#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
47pub struct IdMemorySemantics(pub(crate) u32);
48impl Display for IdMemorySemantics {
49
50 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
51 write!(f, "%{}", self.0)
52 }
53}
54impl Word for IdMemorySemantics {
55
56 #[inline]
57 fn from_word(word: u32) -> Self {
58 Self(word)
59 }
60}
61#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
63pub struct IdScope(pub(crate) u32);
64impl Display for IdScope {
65
66 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
67 write!(f, "%{}", self.0)
68 }
69}
70impl Word for IdScope {
71
72 #[inline]
73 fn from_word(word: u32) -> Self {
74 Self(word)
75 }
76}
77#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
79pub struct IdRef(pub(crate) u32);
80impl Display for IdRef {
81
82 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
83 write!(f, "%{}", self.0)
84 }
85}
86impl Word for IdRef {
87
88 #[inline]
89 fn from_word(word: u32) -> Self {
90 Self(word)
91 }
92}
93impl From<IdResultType> for IdRef {
94
95 #[inline]
96 fn from(value: IdResultType) -> Self {
97 Self(value.0)
98 }
99}
100impl From<IdResult> for IdRef {
101
102 #[inline]
103 fn from(value: IdResult) -> Self {
104 Self(value.0)
105 }
106}
107pub type LiteralInteger = u32;
109pub type LiteralString<'a> = CompilerStr<'a>;
111pub type LiteralFloat = f32;
113impl Word for LiteralFloat {
114
115 #[inline]
116 fn from_word(word: u32) -> Self {
117 Self::from_bits(word)
118 }
119}
120pub type LiteralContextDependentNumber = Literal;
123impl<'a> LiteralContextDependentNumber {
124
125 pub fn parse_one(
126 module: &Module<'a>,
127 stream: &mut InstructionStream<'a>,
128 ctx: &mut ParseContext,
129 ) -> ParseResult<Self> {
130 let Some(result_type) = ctx.result_type else {
131 return Err(ParseError::ExpectedContextResultType)
132 };
133 let mut ty_stream = module
134 .get_result(result_type.into())
135 .ok_or(ParseError::InvalidIdResult(result_type.into()))?;
136 match ty_stream.code() {
137 Code::TYPE_INT => {
138 let int = InstTypeInt {
139 id_result: IdResult::parse_one(&mut ty_stream)?,
140 width: ty_stream.read()?,
141 signedness: ty_stream.read()?,
142 };
143 Ok(if int.signedness == 1 {
144 match int.width {
145 8 => Literal::I8(u8::cast_signed(
146 stream.read()? as u8
147 )),
148 16 => Literal::I16(u16::cast_signed(
149 stream.read()? as u16,
150 )),
151 32 => Literal::I32(u32::cast_signed(
152 stream.read()?,
153 )),
154 64 => Literal::I64(u64::cast_signed(
155 stream.read()? as u64 |
156 ((stream.read()? as u64) << 32)
157 )),
158 x => return Err(ParseError
159 ::InvalidIntLiteralWidth(x)
160 )
161 }
162 } else {
163 match int.width {
164 8 => Literal::U8(stream.read()? as u8),
165 16 => Literal::U16(stream.read()? as u16),
166 32 => Literal::U32(stream.read()?),
167 64 => Literal::U64(
168 stream.read()? as u64 |
169 ((stream.read()? as u64) << 32)
170 ),
171 x => return Err(ParseError
172 ::InvalidIntLiteralWidth(x)
173 )
174 }
175 })
176 },
177 Code::TYPE_FLOAT => {
178 let float = InstTypeFloat {
179 id_result: IdResult::parse_one(&mut ty_stream)?,
180 width: ty_stream.read()?,
181 floating_point_encoding: FPEncoding::parse_optional(&mut ty_stream)?,
182 };
183 Ok(match float.width {
184 16 => Literal::F16(stream.read()? as u16),
185 32 => Literal::F32(f32::from_bits(stream.read()?)),
186 64 => Literal::F64(f64::from_bits(
187 stream.read()? as u64 |
188 ((stream.read()? as u64) << 32)
189 )),
190 x => return Err(ParseError
191 ::InvalidFloatLiteralWidth(x)
192 )
193 })
194 },
195 x => Err(ParseError::InvalidType {
196 expected: "float or int type",
197 found: x,
198 })
199 }
200 }
201}
202pub type LiteralExtInstInteger = u32;
205#[derive(Clone, Copy, Debug)]
208pub struct LiteralSpecConstantOpInteger<'a> {
209 pub code: Code,
210 pub operands: &'a [IdRef],
211}
212impl<'a> LiteralSpecConstantOpInteger<'a> {
213
214 pub fn parse_one(
215 stream: &mut InstructionStream<'a>,
216 ) -> ParseResult<Self>
217 {
218 Ok(Self {
219 code: Code::from_word(stream.read()?),
220 operands: IdRef::parse_eos(stream)?,
221 })
222 }
223}
224impl<'a> Display for LiteralSpecConstantOpInteger<'a> {
225
226 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
227 write!(f, "{}", self.code)?;
228 for operand in self.operands {
229 write!(f, " {operand}")?;
230 }
231 Ok(())
232 }
233}
234#[repr(C)]
235#[derive(Clone, Copy, Debug)]
236pub struct Pair<T, U>(T, U)
237 where
238 T: Word + Debug + Display,
239 U: Word + Debug + Display;
240impl<T, U> Display for Pair<T, U>
241 where
242 T: Word + Debug + Display,
243 U: Word + Debug + Display,
244{
245
246 #[inline]
247 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
248 write!(f, "{} {}", self.0, self.1)
249 }
250}
251impl<'a, T, U> Pair<T, U>
252 where
253 T: Word + Debug + Display,
254 U: Word + Debug + Display,
255{
256
257 #[inline]
258 pub fn parse_one(
259 stream: &mut InstructionStream<'a>,
260 ) -> ParseResult<Self> {
261 Ok(Self(T::from_word(stream.read()?), U::from_word(stream.read()?)))
262 }
263
264 #[inline]
265 pub fn parse_eos(
266 stream: &mut InstructionStream<'a>,
267 ) -> ParseResult<&'a [Self]> {
268 let words = stream.read_words(None)?;
269 if !words.len().is_multiple_of(2) {
270 return Err(ParseError::InvalidPairWordCount(words.len() as u32))
271 }
272 unsafe {
273 Ok(slice::from_raw_parts(
274 words.as_ptr().cast(),
275 words.len() / 2
276 ))
277 }
278 }
279}
280pub type PairLiteralIntegerIdRef = Pair<LiteralInteger, IdRef>;
281pub type PairIdRefLiteralInteger = Pair<IdRef, LiteralInteger>;
282pub type PairIdRefIdRef = Pair<IdRef, IdRef>;
283#[derive(Default, Clone, Copy)]
284pub struct InstInfo {
285 pub name: &'static str,
286 pub has_id_result_type: bool,
287 pub has_id_result: bool,
288}