1use crate::ast::{ArgSep, ExprType};
20use crate::num::{
21 unchecked_u32_as_u8, unchecked_u32_as_u16, unchecked_u32_as_usize, unchecked_u64_as_u8,
22};
23use std::convert::TryFrom;
24use std::fmt;
25
26#[derive(Debug)]
28pub enum RegisterScope {
29 Global,
31
32 Local,
34
35 Temp,
37}
38
39impl fmt::Display for RegisterScope {
40 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
41 match self {
42 Self::Global => write!(f, "global"),
43 Self::Local => write!(f, "local"),
44 Self::Temp => write!(f, "temp"),
45 }
46 }
47}
48
49#[derive(Debug, thiserror::Error)]
51#[error("Exit code must be in the 0..127 range")]
52pub struct InvalidExitCodeError(());
53
54#[derive(Debug, thiserror::Error)]
56#[error("Out of registers")]
57pub(crate) struct OutOfRegistersError(());
58
59#[derive(Debug, thiserror::Error)]
61#[error("Too many dimensions")]
62pub(crate) struct TooManyArrayDimensionsError(());
63
64#[derive(Debug, thiserror::Error)]
66pub(crate) enum ParseError {
67 #[error("{0}: Invalid type tag {0}")]
69 InvalidTypeTag(u64),
70}
71
72pub(crate) type ParseResult<T> = Result<T, ParseError>;
74
75#[derive(Clone, Copy, Debug, Eq, PartialEq)]
77pub struct ExitCode(u8);
78
79impl ExitCode {
80 pub fn is_success(self) -> bool {
82 self.0 == 0
83 }
84
85 pub fn try_new(value: i32) -> Result<Self, InvalidExitCodeError> {
87 if (0..128).contains(&value) {
88 Ok(Self(value as u8))
89 } else {
90 Err(InvalidExitCodeError(()))
91 }
92 }
93
94 pub fn to_i32(self) -> i32 {
96 i32::from(self.0)
97 }
98}
99
100impl TryFrom<i32> for ExitCode {
101 type Error = InvalidExitCodeError;
102
103 fn try_from(value: i32) -> Result<Self, Self::Error> {
104 Self::try_new(value)
105 }
106}
107
108trait RawValue: Sized {
110 fn from_u32(v: u32) -> Self;
115
116 fn to_u32(self) -> u32;
122}
123
124macro_rules! impl_raw_value {
126 ( $ty:ty, $from_u32_conv:ident ) => {
127 impl RawValue for $ty {
128 fn from_u32(v: u32) -> Self {
129 $from_u32_conv(v)
130 }
131
132 fn to_u32(self) -> u32 {
133 u32::from(self)
134 }
135 }
136 };
137}
138
139impl_raw_value!(u8, unchecked_u32_as_u8);
140impl_raw_value!(u16, unchecked_u32_as_u16);
141
142#[derive(Clone, Copy, Debug, Eq, PartialEq)]
152pub(crate) struct Register(pub(crate) u8);
153
154impl fmt::Display for Register {
155 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
156 write!(f, "R{}", self.0)
157 }
158}
159
160impl RawValue for Register {
161 fn from_u32(v: u32) -> Self {
162 Self(unchecked_u32_as_u8(v))
163 }
164
165 fn to_u32(self) -> u32 {
166 u32::from(self.0)
167 }
168}
169
170impl Register {
171 pub(crate) const MAX: u8 = u8::MAX;
173
174 pub(crate) const MAX_GLOBAL: u8 = 64;
176
177 pub(crate) fn global(reg: u8) -> Result<Self, OutOfRegistersError> {
180 if reg < Self::MAX_GLOBAL { Ok(Self(reg)) } else { Err(OutOfRegistersError(())) }
181 }
182
183 pub(crate) fn local(reg: u8) -> Result<Self, OutOfRegistersError> {
186 match reg.checked_add(Self::MAX_GLOBAL) {
187 Some(num) => Ok(Self(num)),
188 None => Err(OutOfRegistersError(())),
189 }
190 }
191
192 pub(crate) fn to_parts(self) -> (bool, u8) {
195 if self.0 < Self::MAX_GLOBAL { (true, self.0) } else { (false, self.0 - Self::MAX_GLOBAL) }
196 }
197}
198
199pub(crate) struct TaggedRegisterRef(u64);
208
209impl TaggedRegisterRef {
210 pub(crate) fn new(reg: Register, fp: usize, vtype: ExprType) -> Self {
212 let (is_global, index) = reg.to_parts();
213 let mut index = usize::from(index);
214 if !is_global {
215 index += fp;
216 }
217
218 let index = u32::try_from(index).expect("Cannot support that many registers");
219 Self(u64::from(vtype as u8) << 32 | u64::from(index))
220 }
221
222 pub(crate) fn parse(self) -> (usize, ExprType) {
227 let vtype: ExprType = {
228 #[allow(unsafe_code)]
229 unsafe {
230 let v = unchecked_u64_as_u8(self.0 >> 32);
231 assert!(v <= ExprType::Text as u8);
232 std::mem::transmute(v)
233 }
234 };
235
236 let index = unchecked_u32_as_usize((self.0 & 0xffffffff) as u32);
237
238 (index, vtype)
239 }
240
241 pub(crate) fn as_u64(&self) -> u64 {
243 self.0
244 }
245
246 pub(crate) fn from_u64(v: u64) -> Self {
248 Self(v)
249 }
250}
251
252#[derive(Clone, Copy, Debug, Eq, PartialEq)]
257pub(crate) struct PackedArrayType(u8);
258
259impl PackedArrayType {
260 pub(crate) fn new(
262 subtype: ExprType,
263 ndims: usize,
264 ) -> Result<Self, TooManyArrayDimensionsError> {
265 if ndims > 15 {
266 return Err(TooManyArrayDimensionsError(()));
267 }
268 let ndims = ndims as u8;
269 Ok(Self(((subtype as u8) << 4) | (ndims & 0x0f)))
270 }
271
272 pub(crate) fn subtype(self) -> ExprType {
274 ExprType::from_u32(u32::from(self.0 >> 4))
275 }
276
277 pub(crate) fn ndims(self) -> u8 {
279 self.0 & 0x0f
280 }
281}
282
283impl fmt::Display for PackedArrayType {
284 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
285 write!(f, "[{}]{}", self.ndims(), self.subtype().annotation())
286 }
287}
288
289impl RawValue for PackedArrayType {
290 fn from_u32(v: u32) -> Self {
291 Self(unchecked_u32_as_u8(v))
292 }
293
294 fn to_u32(self) -> u32 {
295 u32::from(self.0)
296 }
297}
298
299impl RawValue for ExprType {
300 fn from_u32(v: u32) -> Self {
301 #[allow(unsafe_code)]
302 unsafe {
303 let v = unchecked_u32_as_u8(v);
304 assert!(v <= ExprType::Text as u8);
305 std::mem::transmute(v)
306 }
307 }
308
309 fn to_u32(self) -> u32 {
310 u32::from(self as u8)
311 }
312}
313
314#[derive(Clone, Copy, Debug, Eq, PartialEq)]
316pub(crate) enum ErrorHandlerMode {
317 None,
319
320 ResumeNext,
322
323 Jump,
325}
326
327impl RawValue for ErrorHandlerMode {
328 fn from_u32(v: u32) -> Self {
329 #[allow(unsafe_code)]
330 unsafe {
331 let v = unchecked_u32_as_u8(v);
332 assert!(v <= ErrorHandlerMode::Jump as u8);
333 std::mem::transmute(v)
334 }
335 }
336
337 fn to_u32(self) -> u32 {
338 u32::from(self as u8)
339 }
340}
341
342impl fmt::Display for ErrorHandlerMode {
343 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
344 match self {
345 Self::None => write!(f, "NONE"),
346 Self::ResumeNext => write!(f, "RESUME_NEXT"),
347 Self::Jump => write!(f, "JUMP"),
348 }
349 }
350}
351
352macro_rules! instr {
355 ( $opcode:expr, $name:expr,
356 $make:ident, $parse:ident, $format:ident,
357 ) => {
358 pub(crate) fn $make() -> u32 {
359 ($opcode as u32) << 24
360 }
361
362 pub(crate) fn $parse(op: u32) {
363 debug_assert_eq!($opcode as u32, op >> 24);
364 }
365
366 pub(crate) fn $format(op: u32) -> String {
367 $parse(op);
368 $name.to_owned()
369 }
370 };
371
372 ( $opcode:expr, $name: expr,
373 $make:ident, $parse:ident, $format:ident,
374 $type1:ty, $mask1:expr, $offset1:expr,
375 ) => {
376 pub(crate) fn $make(v1: $type1) -> u32 {
377 let v1 = (RawValue::to_u32(v1) & $mask1) << $offset1;
378 (($opcode as u32) << 24) | v1
379 }
380
381 pub(crate) fn $parse(op: u32) -> $type1 {
382 debug_assert_eq!($opcode as u32, op >> 24);
383 let v1 = RawValue::from_u32((op >> $offset1) & $mask1);
384 v1
385 }
386
387 pub(crate) fn $format(op: u32) -> String {
388 let v1 = $parse(op);
389 format!("{:11} {}", $name, v1)
390 }
391 };
392
393 ( $opcode:expr, $name:expr,
394 $make:ident, $parse:ident, $format:ident,
395 $type1:ty, $mask1:expr, $offset1:expr,
396 $type2:ty, $mask2:expr, $offset2:expr,
397 ) => {
398 pub(crate) fn $make(v1: $type1, v2: $type2) -> u32 {
399 let v1 = (RawValue::to_u32(v1) & $mask1) << $offset1;
400 let v2 = (RawValue::to_u32(v2) & $mask2) << $offset2;
401 (($opcode as u32) << 24) | v1 | v2
402 }
403
404 pub(crate) fn $parse(op: u32) -> ($type1, $type2) {
405 debug_assert_eq!($opcode as u32, op >> 24);
406 let v1 = RawValue::from_u32((op >> $offset1) & $mask1);
407 let v2 = RawValue::from_u32((op >> $offset2) & $mask2);
408 (v1, v2)
409 }
410
411 pub(crate) fn $format(op: u32) -> String {
412 let (v1, v2) = $parse(op);
413 format!("{:11} {}, {}", $name, v1, v2)
414 }
415 };
416
417 ( $opcode:expr, $name:expr,
418 $make:ident, $parse:ident, $format:ident,
419 $type1:ty, $mask1:expr, $offset1:expr,
420 $type2:ty, $mask2:expr, $offset2:expr,
421 $type3:ty, $mask3:expr, $offset3:expr,
422 ) => {
423 pub(crate) fn $make(v1: $type1, v2: $type2, v3: $type3) -> u32 {
424 let v1 = (RawValue::to_u32(v1) & $mask1) << $offset1;
425 let v2 = (RawValue::to_u32(v2) & $mask2) << $offset2;
426 let v3 = (RawValue::to_u32(v3) & $mask3) << $offset3;
427 (($opcode as u32) << 24) | v1 | v2 | v3
428 }
429
430 pub(crate) fn $parse(op: u32) -> ($type1, $type2, $type3) {
431 debug_assert_eq!($opcode as u32, op >> 24);
432 let v1 = RawValue::from_u32((op >> $offset1) & $mask1);
433 let v2 = RawValue::from_u32((op >> $offset2) & $mask2);
434 let v3 = RawValue::from_u32((op >> $offset3) & $mask3);
435 (v1, v2, v3)
436 }
437
438 pub(crate) fn $format(op: u32) -> String {
439 let (v1, v2, v3) = $parse(op);
440 format!("{:11} {}, {}, {}", $name, v1, v2, v3)
441 }
442 };
443}
444
445#[repr(u8)]
451pub(crate) enum Opcode {
452 AddDouble,
454
455 AddInteger,
457
458 Alloc,
460
461 AllocArray,
463
464 BitwiseAnd,
466
467 BitwiseNot,
469
470 BitwiseOr,
472
473 BitwiseXor,
475
476 Call,
478
479 Concat,
481
482 DivideDouble,
484
485 DivideInteger,
487
488 DoubleToInteger,
490
491 EqualBoolean,
493
494 EqualDouble,
496
497 EqualInteger,
499
500 EqualText,
502
503 Gosub,
505
506 GreaterDouble,
508
509 GreaterEqualDouble,
511
512 GreaterEqualInteger,
514
515 GreaterEqualText,
517
518 GreaterInteger,
520
521 GreaterText,
523
524 IntegerToDouble,
526
527 Jump,
529
530 JumpIfFalse,
532
533 LessDouble,
535
536 LessEqualDouble,
538
539 LessEqualInteger,
541
542 LessEqualText,
544
545 LessInteger,
547
548 LessText,
550
551 LoadArray,
553
554 LoadConstant,
556
557 LoadInteger,
559
560 LoadRegisterPointer,
562
563 ModuloDouble,
565
566 ModuloInteger,
568
569 Move,
571
572 MultiplyDouble,
574
575 MultiplyInteger,
577
578 NegateDouble,
580
581 NegateInteger,
583
584 NotEqualBoolean,
586
587 NotEqualDouble,
589
590 NotEqualInteger,
592
593 NotEqualText,
595
596 Nop,
598
599 PowerDouble,
601
602 PowerInteger,
604
605 Return,
607
608 SetErrorHandler,
610
611 ShiftLeft,
614
615 ShiftRight,
618
619 StoreArray,
621
622 SubtractDouble,
624
625 SubtractInteger,
627
628 End,
630
631 Upcall,
633
634 UpcallAsync,
636
637 Eof,
640}
641
642#[rustfmt::skip]
643instr!(
644 Opcode::AddDouble, "ADDD",
645 make_add_double, parse_add_double, format_add_double,
646 Register, 0x000000ff, 16, Register, 0x000000ff, 8, Register, 0x000000ff, 0, );
650
651#[rustfmt::skip]
652instr!(
653 Opcode::AddInteger, "ADDI",
654 make_add_integer, parse_add_integer, format_add_integer,
655 Register, 0x000000ff, 16, Register, 0x000000ff, 8, Register, 0x000000ff, 0, );
659
660#[rustfmt::skip]
661instr!(
662 Opcode::Alloc, "ALLOC",
663 make_alloc, parse_alloc, format_alloc,
664 Register, 0x000000ff, 8, ExprType, 0x000000ff, 0, );
667
668#[rustfmt::skip]
669instr!(
670 Opcode::AllocArray, "ALLOCA",
671 make_alloc_array, parse_alloc_array, format_alloc_array,
672 Register, 0x000000ff, 16, PackedArrayType, 0x000000ff, 8, Register, 0x000000ff, 0, );
676
677#[rustfmt::skip]
678instr!(
679 Opcode::BitwiseAnd, "AND",
680 make_bitwise_and, parse_bitwise_and, format_bitwise_and,
681 Register, 0x000000ff, 16, Register, 0x000000ff, 8, Register, 0x000000ff, 0, );
685
686#[rustfmt::skip]
687instr!(
688 Opcode::BitwiseNot, "NOT",
689 make_bitwise_not, parse_bitwise_not, format_bitwise_not,
690 Register, 0x000000ff, 0, );
692
693#[rustfmt::skip]
694instr!(
695 Opcode::BitwiseOr, "OR",
696 make_bitwise_or, parse_bitwise_or, format_bitwise_or,
697 Register, 0x000000ff, 16, Register, 0x000000ff, 8, Register, 0x000000ff, 0, );
701
702#[rustfmt::skip]
703instr!(
704 Opcode::BitwiseXor, "XOR",
705 make_bitwise_xor, parse_bitwise_xor, format_bitwise_xor,
706 Register, 0x000000ff, 16, Register, 0x000000ff, 8, Register, 0x000000ff, 0, );
710
711#[rustfmt::skip]
712instr!(
713 Opcode::Call, "CALL",
714 make_call, parse_call, format_call,
715 Register, 0x000000ff, 16, u16, 0x0000ffff, 0, );
718
719#[rustfmt::skip]
720instr!(
721 Opcode::Concat, "CONCAT",
722 make_concat, parse_concat, format_concat,
723 Register, 0x000000ff, 16, Register, 0x000000ff, 8, Register, 0x000000ff, 0, );
727
728#[rustfmt::skip]
729instr!(
730 Opcode::DivideDouble, "DIVD",
731 make_divide_double, parse_divide_double, format_divide_double,
732 Register, 0x000000ff, 16, Register, 0x000000ff, 8, Register, 0x000000ff, 0, );
736
737#[rustfmt::skip]
738instr!(
739 Opcode::DivideInteger, "DIVI",
740 make_divide_integer, parse_divide_integer, format_divide_integer,
741 Register, 0x000000ff, 16, Register, 0x000000ff, 8, Register, 0x000000ff, 0, );
745
746#[rustfmt::skip]
747instr!(
748 Opcode::DoubleToInteger, "DTOI",
749 make_double_to_integer, parse_double_to_integer, format_double_to_integer,
750 Register, 0x000000ff, 0, );
752
753#[rustfmt::skip]
754instr!(
755 Opcode::EqualBoolean, "CMPEQB",
756 make_equal_boolean, parse_equal_boolean, format_equal_boolean,
757 Register, 0x000000ff, 16, Register, 0x000000ff, 8, Register, 0x000000ff, 0, );
761
762#[rustfmt::skip]
763instr!(
764 Opcode::EqualDouble, "CMPEQD",
765 make_equal_double, parse_equal_double, format_equal_double,
766 Register, 0x000000ff, 16, Register, 0x000000ff, 8, Register, 0x000000ff, 0, );
770
771#[rustfmt::skip]
772instr!(
773 Opcode::EqualInteger, "CMPEQI",
774 make_equal_integer, parse_equal_integer, format_equal_integer,
775 Register, 0x000000ff, 16, Register, 0x000000ff, 8, Register, 0x000000ff, 0, );
779
780#[rustfmt::skip]
781instr!(
782 Opcode::EqualText, "CMPEQS",
783 make_equal_text, parse_equal_text, format_equal_text,
784 Register, 0x000000ff, 16, Register, 0x000000ff, 8, Register, 0x000000ff, 0, );
788
789#[rustfmt::skip]
790instr!(
791 Opcode::End, "END",
792 make_end, parse_end, format_end,
793 Register, 0x000000ff, 0, );
795
796#[rustfmt::skip]
797instr!(
798 Opcode::Eof, "EOF",
799 make_eof, parse_eof, format_eof,
800);
801
802#[rustfmt::skip]
803instr!(
804 Opcode::Gosub, "GOSUB",
805 make_gosub, parse_gosub, format_gosub,
806 u16, 0x0000ffff, 0, );
808
809#[rustfmt::skip]
810instr!(
811 Opcode::GreaterDouble, "CMPGTD",
812 make_greater_double, parse_greater_double, format_greater_double,
813 Register, 0x000000ff, 16, Register, 0x000000ff, 8, Register, 0x000000ff, 0, );
817
818#[rustfmt::skip]
819instr!(
820 Opcode::GreaterEqualDouble, "CMPGED",
821 make_greater_equal_double, parse_greater_equal_double, format_greater_equal_double,
822 Register, 0x000000ff, 16, Register, 0x000000ff, 8, Register, 0x000000ff, 0, );
826
827#[rustfmt::skip]
828instr!(
829 Opcode::GreaterEqualInteger, "CMPGEI",
830 make_greater_equal_integer, parse_greater_equal_integer, format_greater_equal_integer,
831 Register, 0x000000ff, 16, Register, 0x000000ff, 8, Register, 0x000000ff, 0, );
835
836#[rustfmt::skip]
837instr!(
838 Opcode::GreaterEqualText, "CMPGES",
839 make_greater_equal_text, parse_greater_equal_text, format_greater_equal_text,
840 Register, 0x000000ff, 16, Register, 0x000000ff, 8, Register, 0x000000ff, 0, );
844
845#[rustfmt::skip]
846instr!(
847 Opcode::GreaterInteger, "CMPGTI",
848 make_greater_integer, parse_greater_integer, format_greater_integer,
849 Register, 0x000000ff, 16, Register, 0x000000ff, 8, Register, 0x000000ff, 0, );
853
854#[rustfmt::skip]
855instr!(
856 Opcode::GreaterText, "CMPGTS",
857 make_greater_text, parse_greater_text, format_greater_text,
858 Register, 0x000000ff, 16, Register, 0x000000ff, 8, Register, 0x000000ff, 0, );
862
863#[rustfmt::skip]
864instr!(
865 Opcode::IntegerToDouble, "ITOD",
866 make_integer_to_double, parse_integer_to_double, format_integer_to_double,
867 Register, 0x000000ff, 0, );
869
870#[rustfmt::skip]
871instr!(
872 Opcode::Jump, "JUMP",
873 make_jump, parse_jump, format_jump,
874 u16, 0x0000ffff, 0, );
876
877#[rustfmt::skip]
878instr!(
879 Opcode::JumpIfFalse, "JMPF",
880 make_jump_if_false, parse_jump_if_false, format_jump_if_false,
881 Register, 0x000000ff, 16, u16, 0x0000ffff, 0, );
884
885#[rustfmt::skip]
886instr!(
887 Opcode::LessDouble, "CMPLTD",
888 make_less_double, parse_less_double, format_less_double,
889 Register, 0x000000ff, 16, Register, 0x000000ff, 8, Register, 0x000000ff, 0, );
893
894#[rustfmt::skip]
895instr!(
896 Opcode::LessEqualDouble, "CMPLED",
897 make_less_equal_double, parse_less_equal_double, format_less_equal_double,
898 Register, 0x000000ff, 16, Register, 0x000000ff, 8, Register, 0x000000ff, 0, );
902
903#[rustfmt::skip]
904instr!(
905 Opcode::LessEqualInteger, "CMPLEI",
906 make_less_equal_integer, parse_less_equal_integer, format_less_equal_integer,
907 Register, 0x000000ff, 16, Register, 0x000000ff, 8, Register, 0x000000ff, 0, );
911
912#[rustfmt::skip]
913instr!(
914 Opcode::LessEqualText, "CMPLES",
915 make_less_equal_text, parse_less_equal_text, format_less_equal_text,
916 Register, 0x000000ff, 16, Register, 0x000000ff, 8, Register, 0x000000ff, 0, );
920
921#[rustfmt::skip]
922instr!(
923 Opcode::LessInteger, "CMPLTI",
924 make_less_integer, parse_less_integer, format_less_integer,
925 Register, 0x000000ff, 16, Register, 0x000000ff, 8, Register, 0x000000ff, 0, );
929
930#[rustfmt::skip]
931instr!(
932 Opcode::LessText, "CMPLTS",
933 make_less_text, parse_less_text, format_less_text,
934 Register, 0x000000ff, 16, Register, 0x000000ff, 8, Register, 0x000000ff, 0, );
938
939#[rustfmt::skip]
940instr!(
941 Opcode::LoadArray, "LOADA",
942 make_load_array, parse_load_array, format_load_array,
943 Register, 0x000000ff, 16, Register, 0x000000ff, 8, Register, 0x000000ff, 0, );
947
948#[rustfmt::skip]
949instr!(
950 Opcode::LoadConstant, "LOADC",
951 make_load_constant, parse_load_constant, format_load_constant,
952 Register, 0x000000ff, 16, u16, 0x0000ffff, 0, );
955
956#[rustfmt::skip]
957instr!(
958 Opcode::LoadInteger, "LOADI",
959 make_load_integer, parse_load_integer, format_load_integer,
960 Register, 0x000000ff, 16, u16, 0x0000ffff, 0, );
963
964#[rustfmt::skip]
965instr!(
966 Opcode::LoadRegisterPointer, "LOADRP",
967 make_load_register_ptr, parse_load_register_ptr, format_load_register_ptr,
968 Register, 0x000000ff, 16, ExprType, 0x000000ff, 8, Register, 0x000000ff, 0, );
972
973#[rustfmt::skip]
974instr!(
975 Opcode::ModuloDouble, "MODD",
976 make_modulo_double, parse_modulo_double, format_modulo_double,
977 Register, 0x000000ff, 16, Register, 0x000000ff, 8, Register, 0x000000ff, 0, );
981
982#[rustfmt::skip]
983instr!(
984 Opcode::ModuloInteger, "MODI",
985 make_modulo_integer, parse_modulo_integer, format_modulo_integer,
986 Register, 0x000000ff, 16, Register, 0x000000ff, 8, Register, 0x000000ff, 0, );
990
991#[rustfmt::skip]
992instr!(
993 Opcode::Move, "MOVE",
994 make_move, parse_move, format_move,
995 Register, 0x000000ff, 8, Register, 0x000000ff, 0, );
998
999#[rustfmt::skip]
1000instr!(
1001 Opcode::MultiplyDouble, "MULD",
1002 make_multiply_double, parse_multiply_double, format_multiply_double,
1003 Register, 0x000000ff, 16, Register, 0x000000ff, 8, Register, 0x000000ff, 0, );
1007
1008#[rustfmt::skip]
1009instr!(
1010 Opcode::MultiplyInteger, "MULI",
1011 make_multiply_integer, parse_multiply_integer, format_multiply_integer,
1012 Register, 0x000000ff, 16, Register, 0x000000ff, 8, Register, 0x000000ff, 0, );
1016
1017#[rustfmt::skip]
1018instr!(
1019 Opcode::NegateDouble,
1020 "NEGD",
1021 make_negate_double,
1022 parse_negate_double,
1023 format_negate_double,
1024 Register,
1025 0x000000ff,
1026 0, );
1028
1029#[rustfmt::skip]
1030instr!(
1031 Opcode::NegateInteger, "NEGI",
1032 make_negate_integer, parse_negate_integer, format_negate_integer,
1033 Register, 0x000000ff, 0, );
1035
1036#[rustfmt::skip]
1037instr!(
1038 Opcode::NotEqualBoolean, "CMPNEB",
1039 make_not_equal_boolean, parse_not_equal_boolean, format_not_equal_boolean,
1040 Register, 0x000000ff, 16, Register, 0x000000ff, 8, Register, 0x000000ff, 0, );
1044
1045#[rustfmt::skip]
1046instr!(
1047 Opcode::NotEqualDouble, "CMPNED",
1048 make_not_equal_double, parse_not_equal_double, format_not_equal_double,
1049 Register, 0x000000ff, 16, Register, 0x000000ff, 8, Register, 0x000000ff, 0, );
1053
1054#[rustfmt::skip]
1055instr!(
1056 Opcode::NotEqualInteger, "CMPNEI",
1057 make_not_equal_integer, parse_not_equal_integer, format_not_equal_integer,
1058 Register, 0x000000ff, 16, Register, 0x000000ff, 8, Register, 0x000000ff, 0, );
1062
1063#[rustfmt::skip]
1064instr!(
1065 Opcode::NotEqualText, "CMPNES",
1066 make_not_equal_text, parse_not_equal_text, format_not_equal_text,
1067 Register, 0x000000ff, 16, Register, 0x000000ff, 8, Register, 0x000000ff, 0, );
1071
1072#[rustfmt::skip]
1073instr!(
1074 Opcode::Nop, "NOP",
1075 make_nop, parse_nop, format_nop,
1076);
1077
1078#[rustfmt::skip]
1079instr!(
1080 Opcode::PowerDouble, "POWD",
1081 make_power_double, parse_power_double, format_power_double,
1082 Register, 0x000000ff, 16, Register, 0x000000ff, 8, Register, 0x000000ff, 0, );
1086
1087#[rustfmt::skip]
1088instr!(
1089 Opcode::PowerInteger, "POWI",
1090 make_power_integer, parse_power_integer, format_power_integer,
1091 Register, 0x000000ff, 16, Register, 0x000000ff, 8, Register, 0x000000ff, 0, );
1095
1096#[rustfmt::skip]
1097instr!(
1098 Opcode::Return, "RETURN",
1099 make_return, parse_return, format_return,
1100);
1101
1102#[rustfmt::skip]
1103instr!(
1104 Opcode::SetErrorHandler, "SETEH",
1105 make_set_error_handler, parse_set_error_handler, format_set_error_handler,
1106 ErrorHandlerMode, 0x000000ff, 16, u16, 0x0000ffff, 0, );
1109
1110#[rustfmt::skip]
1111instr!(
1112 Opcode::ShiftLeft, "SHL",
1113 make_shift_left, parse_shift_left, format_shift_left,
1114 Register, 0x000000ff, 16, Register, 0x000000ff, 8, Register, 0x000000ff, 0, );
1118
1119#[rustfmt::skip]
1120instr!(
1121 Opcode::ShiftRight, "SHR",
1122 make_shift_right, parse_shift_right, format_shift_right,
1123 Register, 0x000000ff, 16, Register, 0x000000ff, 8, Register, 0x000000ff, 0, );
1127
1128#[rustfmt::skip]
1129instr!(
1130 Opcode::StoreArray, "STOREA",
1131 make_store_array, parse_store_array, format_store_array,
1132 Register, 0x000000ff, 16, Register, 0x000000ff, 8, Register, 0x000000ff, 0, );
1136
1137#[rustfmt::skip]
1138instr!(
1139 Opcode::SubtractDouble, "SUBD",
1140 make_subtract_double, parse_subtract_double, format_subtract_double,
1141 Register, 0x000000ff, 16, Register, 0x000000ff, 8, Register, 0x000000ff, 0, );
1145
1146#[rustfmt::skip]
1147instr!(
1148 Opcode::SubtractInteger, "SUBI",
1149 make_subtract_integer, parse_subtract_integer, format_subtract_integer,
1150 Register, 0x000000ff, 16, Register, 0x000000ff, 8, Register, 0x000000ff, 0, );
1154
1155#[rustfmt::skip]
1156instr!(
1157 Opcode::Upcall, "UPCALL",
1158 make_upcall, parse_upcall, format_upcall,
1159 u16, 0x0000ffff, 8, Register, 0x000000ff, 0, );
1162
1163#[rustfmt::skip]
1164instr!(
1165 Opcode::UpcallAsync, "UPCALLA",
1166 make_upcall_async, parse_upcall_async, format_upcall_async,
1167 u16, 0x0000ffff, 8, Register, 0x000000ff, 0, );
1170
1171pub(crate) fn opcode_of(instr: u32) -> Opcode {
1173 #[allow(unsafe_code)]
1174 unsafe {
1175 let num = unchecked_u32_as_u8(instr >> 24);
1176 debug_assert!(num <= Opcode::Eof as u8);
1177 std::mem::transmute::<u8, Opcode>(num)
1178 }
1179}
1180
1181#[derive(Clone, Copy, Debug, PartialEq)]
1187#[repr(u8)]
1188pub enum VarArgTag {
1189 Missing(ArgSep) = 0,
1191
1192 Immediate(ArgSep, ExprType) = 1,
1194
1195 Pointer(ArgSep) = 2,
1197}
1198
1199impl VarArgTag {
1200 pub(crate) fn parse_u64(value: u64) -> ParseResult<Self> {
1204 if value & !(0x0fff) != 0 {
1205 return Err(ParseError::InvalidTypeTag(value));
1206 };
1207
1208 let key_u8 = ((value & 0x0f00) >> 8) as u8;
1209 let sep_u8 = ((value & 0x00f0) >> 4) as u8;
1210 let other_u8 = (value & 0x000f) as u8;
1211
1212 let Ok(sep) = ArgSep::try_from(sep_u8) else {
1213 return Err(ParseError::InvalidTypeTag(value));
1214 };
1215
1216 match key_u8 {
1217 0 => {
1218 if other_u8 == 0 {
1219 Ok(Self::Missing(sep))
1220 } else {
1221 Err(ParseError::InvalidTypeTag(value))
1222 }
1223 }
1224 1 => match ExprType::try_from(other_u8) {
1225 Ok(etype) => Ok(Self::Immediate(sep, etype)),
1226 Err(_) => Err(ParseError::InvalidTypeTag(value)),
1227 },
1228 2 => {
1229 if other_u8 == 0 {
1230 Ok(Self::Pointer(sep))
1231 } else {
1232 Err(ParseError::InvalidTypeTag(value))
1233 }
1234 }
1235 _ => Err(ParseError::InvalidTypeTag(value)),
1236 }
1237 }
1238
1239 pub(crate) fn make_u16(self) -> u16 {
1241 let (key_u8, sep, other_u8): (u8, ArgSep, u8) = match self {
1242 Self::Missing(sep) => (0, sep, 0),
1243 Self::Immediate(sep, etype) => (1, sep, etype as u8),
1244 Self::Pointer(sep) => (2, sep, 0),
1245 };
1246 u16::from(key_u8) << 8 | u16::from(sep as u8) << 4 | u16::from(other_u8)
1247 }
1248}
1249
1250#[cfg(test)]
1251mod tests {
1252 use super::*;
1253
1254 macro_rules! test_instr {
1255 ( $name:ident, $make:ident, $parse:ident ) => {
1256 #[test]
1257 fn $name() {
1258 let instr = $make();
1259 $parse(instr);
1260 }
1261 };
1262
1263 ( $name:ident, $make:ident, $parse:ident, $v1:expr ) => {
1264 #[test]
1265 fn $name() {
1266 let instr = $make($v1);
1267 assert_eq!($v1, $parse(instr));
1268 }
1269 };
1270
1271 ( $name:ident, $make:ident, $parse:ident, $v1:expr, $v2:expr ) => {
1272 #[test]
1273 fn $name() {
1274 let instr = $make($v1, $v2);
1275 assert_eq!(($v1, $v2), $parse(instr));
1276 }
1277 };
1278
1279 ( $name:ident, $make:ident, $parse:ident, $v1:expr, $v2:expr, $v3:expr ) => {
1280 #[test]
1281 fn $name() {
1282 let instr = $make($v1, $v2, $v3);
1283 assert_eq!(($v1, $v2, $v3), $parse(instr));
1284 }
1285 };
1286 }
1287
1288 test_instr!(
1289 test_add_double,
1290 make_add_double,
1291 parse_add_double,
1292 Register::local(1).unwrap(),
1293 Register::local(2).unwrap(),
1294 Register::local(3).unwrap()
1295 );
1296
1297 test_instr!(
1298 test_add_integer,
1299 make_add_integer,
1300 parse_add_integer,
1301 Register::local(1).unwrap(),
1302 Register::local(2).unwrap(),
1303 Register::local(3).unwrap()
1304 );
1305
1306 test_instr!(
1307 test_alloc,
1308 make_alloc,
1309 parse_alloc,
1310 Register::local(1).unwrap(),
1311 ExprType::Integer
1312 );
1313
1314 test_instr!(
1315 test_alloc_array,
1316 make_alloc_array,
1317 parse_alloc_array,
1318 Register::local(1).unwrap(),
1319 PackedArrayType::new(ExprType::Integer, 3).unwrap(),
1320 Register::local(2).unwrap()
1321 );
1322
1323 test_instr!(
1324 test_bitwise_and,
1325 make_bitwise_and,
1326 parse_bitwise_and,
1327 Register::local(1).unwrap(),
1328 Register::local(2).unwrap(),
1329 Register::local(3).unwrap()
1330 );
1331
1332 test_instr!(test_bitwise_not, make_bitwise_not, parse_bitwise_not, Register::local(1).unwrap());
1333
1334 test_instr!(
1335 test_bitwise_or,
1336 make_bitwise_or,
1337 parse_bitwise_or,
1338 Register::local(1).unwrap(),
1339 Register::local(2).unwrap(),
1340 Register::local(3).unwrap()
1341 );
1342
1343 test_instr!(
1344 test_bitwise_xor,
1345 make_bitwise_xor,
1346 parse_bitwise_xor,
1347 Register::local(1).unwrap(),
1348 Register::local(2).unwrap(),
1349 Register::local(3).unwrap()
1350 );
1351
1352 test_instr!(test_call, make_call, parse_call, Register::local(3).unwrap(), 12345);
1353
1354 test_instr!(
1355 test_concat,
1356 make_concat,
1357 parse_concat,
1358 Register::local(1).unwrap(),
1359 Register::local(2).unwrap(),
1360 Register::local(3).unwrap()
1361 );
1362
1363 test_instr!(
1364 test_divide_double,
1365 make_divide_double,
1366 parse_divide_double,
1367 Register::local(1).unwrap(),
1368 Register::local(2).unwrap(),
1369 Register::local(3).unwrap()
1370 );
1371
1372 test_instr!(
1373 test_divide_integer,
1374 make_divide_integer,
1375 parse_divide_integer,
1376 Register::local(1).unwrap(),
1377 Register::local(2).unwrap(),
1378 Register::local(3).unwrap()
1379 );
1380
1381 test_instr!(
1382 test_double_to_integer,
1383 make_double_to_integer,
1384 parse_double_to_integer,
1385 Register::local(1).unwrap()
1386 );
1387
1388 test_instr!(
1389 test_equal_boolean,
1390 make_equal_boolean,
1391 parse_equal_boolean,
1392 Register::local(1).unwrap(),
1393 Register::local(2).unwrap(),
1394 Register::local(3).unwrap()
1395 );
1396
1397 test_instr!(
1398 test_equal_double,
1399 make_equal_double,
1400 parse_equal_double,
1401 Register::local(1).unwrap(),
1402 Register::local(2).unwrap(),
1403 Register::local(3).unwrap()
1404 );
1405
1406 test_instr!(
1407 test_equal_integer,
1408 make_equal_integer,
1409 parse_equal_integer,
1410 Register::local(1).unwrap(),
1411 Register::local(2).unwrap(),
1412 Register::local(3).unwrap()
1413 );
1414
1415 test_instr!(
1416 test_equal_text,
1417 make_equal_text,
1418 parse_equal_text,
1419 Register::local(1).unwrap(),
1420 Register::local(2).unwrap(),
1421 Register::local(3).unwrap()
1422 );
1423
1424 test_instr!(test_end, make_end, parse_end, Register::local(1).unwrap());
1425
1426 test_instr!(test_eof, make_eof, parse_eof);
1427
1428 test_instr!(test_gosub, make_gosub, parse_gosub, 12345);
1429
1430 test_instr!(
1431 test_greater_double,
1432 make_greater_double,
1433 parse_greater_double,
1434 Register::local(1).unwrap(),
1435 Register::local(2).unwrap(),
1436 Register::local(3).unwrap()
1437 );
1438
1439 test_instr!(
1440 test_greater_equal_double,
1441 make_greater_equal_double,
1442 parse_greater_equal_double,
1443 Register::local(1).unwrap(),
1444 Register::local(2).unwrap(),
1445 Register::local(3).unwrap()
1446 );
1447
1448 test_instr!(
1449 test_greater_equal_integer,
1450 make_greater_equal_integer,
1451 parse_greater_equal_integer,
1452 Register::local(1).unwrap(),
1453 Register::local(2).unwrap(),
1454 Register::local(3).unwrap()
1455 );
1456
1457 test_instr!(
1458 test_greater_equal_text,
1459 make_greater_equal_text,
1460 parse_greater_equal_text,
1461 Register::local(1).unwrap(),
1462 Register::local(2).unwrap(),
1463 Register::local(3).unwrap()
1464 );
1465
1466 test_instr!(
1467 test_greater_integer,
1468 make_greater_integer,
1469 parse_greater_integer,
1470 Register::local(1).unwrap(),
1471 Register::local(2).unwrap(),
1472 Register::local(3).unwrap()
1473 );
1474
1475 test_instr!(
1476 test_greater_text,
1477 make_greater_text,
1478 parse_greater_text,
1479 Register::local(1).unwrap(),
1480 Register::local(2).unwrap(),
1481 Register::local(3).unwrap()
1482 );
1483
1484 test_instr!(
1485 test_integer_to_double,
1486 make_integer_to_double,
1487 parse_integer_to_double,
1488 Register::local(1).unwrap()
1489 );
1490
1491 test_instr!(test_jump, make_jump, parse_jump, 12345);
1492
1493 test_instr!(
1494 test_jump_if_false,
1495 make_jump_if_false,
1496 parse_jump_if_false,
1497 Register::local(1).unwrap(),
1498 12345
1499 );
1500
1501 test_instr!(
1502 test_less_double,
1503 make_less_double,
1504 parse_less_double,
1505 Register::local(1).unwrap(),
1506 Register::local(2).unwrap(),
1507 Register::local(3).unwrap()
1508 );
1509
1510 test_instr!(
1511 test_less_equal_double,
1512 make_less_equal_double,
1513 parse_less_equal_double,
1514 Register::local(1).unwrap(),
1515 Register::local(2).unwrap(),
1516 Register::local(3).unwrap()
1517 );
1518
1519 test_instr!(
1520 test_less_equal_integer,
1521 make_less_equal_integer,
1522 parse_less_equal_integer,
1523 Register::local(1).unwrap(),
1524 Register::local(2).unwrap(),
1525 Register::local(3).unwrap()
1526 );
1527
1528 test_instr!(
1529 test_less_equal_text,
1530 make_less_equal_text,
1531 parse_less_equal_text,
1532 Register::local(1).unwrap(),
1533 Register::local(2).unwrap(),
1534 Register::local(3).unwrap()
1535 );
1536
1537 test_instr!(
1538 test_less_integer,
1539 make_less_integer,
1540 parse_less_integer,
1541 Register::local(1).unwrap(),
1542 Register::local(2).unwrap(),
1543 Register::local(3).unwrap()
1544 );
1545
1546 test_instr!(
1547 test_less_text,
1548 make_less_text,
1549 parse_less_text,
1550 Register::local(1).unwrap(),
1551 Register::local(2).unwrap(),
1552 Register::local(3).unwrap()
1553 );
1554
1555 test_instr!(
1556 test_load_array,
1557 make_load_array,
1558 parse_load_array,
1559 Register::local(1).unwrap(),
1560 Register::local(2).unwrap(),
1561 Register::local(3).unwrap()
1562 );
1563
1564 test_instr!(
1565 test_load_constant,
1566 make_load_constant,
1567 parse_load_constant,
1568 Register::local(1).unwrap(),
1569 12345
1570 );
1571
1572 test_instr!(
1573 test_load_integer,
1574 make_load_integer,
1575 parse_load_integer,
1576 Register::local(1).unwrap(),
1577 12345
1578 );
1579
1580 test_instr!(
1581 test_load_register_ptr,
1582 make_load_register_ptr,
1583 parse_load_register_ptr,
1584 Register::local(1).unwrap(),
1585 ExprType::Double,
1586 Register::local(2).unwrap()
1587 );
1588
1589 test_instr!(
1590 test_modulo_double,
1591 make_modulo_double,
1592 parse_modulo_double,
1593 Register::local(1).unwrap(),
1594 Register::local(2).unwrap(),
1595 Register::local(3).unwrap()
1596 );
1597
1598 test_instr!(
1599 test_modulo_integer,
1600 make_modulo_integer,
1601 parse_modulo_integer,
1602 Register::local(1).unwrap(),
1603 Register::local(2).unwrap(),
1604 Register::local(3).unwrap()
1605 );
1606
1607 test_instr!(
1608 test_move,
1609 make_move,
1610 parse_move,
1611 Register::local(1).unwrap(),
1612 Register::local(2).unwrap()
1613 );
1614
1615 test_instr!(
1616 test_multiply_double,
1617 make_multiply_double,
1618 parse_multiply_double,
1619 Register::local(1).unwrap(),
1620 Register::local(2).unwrap(),
1621 Register::local(3).unwrap()
1622 );
1623
1624 test_instr!(
1625 test_multiply_integer,
1626 make_multiply_integer,
1627 parse_multiply_integer,
1628 Register::local(1).unwrap(),
1629 Register::local(2).unwrap(),
1630 Register::local(3).unwrap()
1631 );
1632
1633 test_instr!(
1634 test_negate_double,
1635 make_negate_double,
1636 parse_negate_double,
1637 Register::local(1).unwrap()
1638 );
1639
1640 test_instr!(
1641 test_negate_integer,
1642 make_negate_integer,
1643 parse_negate_integer,
1644 Register::local(1).unwrap()
1645 );
1646
1647 test_instr!(
1648 test_not_equal_boolean,
1649 make_not_equal_boolean,
1650 parse_not_equal_boolean,
1651 Register::local(1).unwrap(),
1652 Register::local(2).unwrap(),
1653 Register::local(3).unwrap()
1654 );
1655
1656 test_instr!(
1657 test_not_equal_double,
1658 make_not_equal_double,
1659 parse_not_equal_double,
1660 Register::local(1).unwrap(),
1661 Register::local(2).unwrap(),
1662 Register::local(3).unwrap()
1663 );
1664
1665 test_instr!(
1666 test_not_equal_integer,
1667 make_not_equal_integer,
1668 parse_not_equal_integer,
1669 Register::local(1).unwrap(),
1670 Register::local(2).unwrap(),
1671 Register::local(3).unwrap()
1672 );
1673
1674 test_instr!(
1675 test_not_equal_text,
1676 make_not_equal_text,
1677 parse_not_equal_text,
1678 Register::local(1).unwrap(),
1679 Register::local(2).unwrap(),
1680 Register::local(3).unwrap()
1681 );
1682
1683 test_instr!(test_nop, make_nop, parse_nop);
1684
1685 test_instr!(
1686 test_power_double,
1687 make_power_double,
1688 parse_power_double,
1689 Register::local(1).unwrap(),
1690 Register::local(2).unwrap(),
1691 Register::local(3).unwrap()
1692 );
1693
1694 test_instr!(
1695 test_power_integer,
1696 make_power_integer,
1697 parse_power_integer,
1698 Register::local(1).unwrap(),
1699 Register::local(2).unwrap(),
1700 Register::local(3).unwrap()
1701 );
1702
1703 test_instr!(test_return, make_return, parse_return);
1704
1705 test_instr!(
1706 test_shift_left,
1707 make_shift_left,
1708 parse_shift_left,
1709 Register::local(1).unwrap(),
1710 Register::local(2).unwrap(),
1711 Register::local(3).unwrap()
1712 );
1713
1714 test_instr!(
1715 test_shift_right,
1716 make_shift_right,
1717 parse_shift_right,
1718 Register::local(1).unwrap(),
1719 Register::local(2).unwrap(),
1720 Register::local(3).unwrap()
1721 );
1722
1723 test_instr!(
1724 test_store_array,
1725 make_store_array,
1726 parse_store_array,
1727 Register::local(1).unwrap(),
1728 Register::local(2).unwrap(),
1729 Register::local(3).unwrap()
1730 );
1731
1732 test_instr!(
1733 test_subtract_double,
1734 make_subtract_double,
1735 parse_subtract_double,
1736 Register::local(1).unwrap(),
1737 Register::local(2).unwrap(),
1738 Register::local(3).unwrap()
1739 );
1740
1741 test_instr!(
1742 test_subtract_integer,
1743 make_subtract_integer,
1744 parse_subtract_integer,
1745 Register::local(1).unwrap(),
1746 Register::local(2).unwrap(),
1747 Register::local(3).unwrap()
1748 );
1749
1750 test_instr!(test_upcall, make_upcall, parse_upcall, 12345, Register::local(3).unwrap());
1751
1752 test_instr!(
1753 test_upcall_async,
1754 make_upcall_async,
1755 parse_upcall_async,
1756 12345,
1757 Register::local(3).unwrap()
1758 );
1759
1760 #[test]
1761 fn test_exit_code_try_ok() {
1762 assert_eq!(ExitCode(0), ExitCode::try_from(0).unwrap());
1763 assert_eq!(ExitCode(127), ExitCode::try_from(127).unwrap());
1764 assert!(ExitCode::try_from(0).unwrap().is_success());
1765 assert!(!ExitCode::try_from(127).unwrap().is_success());
1766 }
1767
1768 #[test]
1769 fn test_exit_code_try_errors() {
1770 assert!(ExitCode::try_from(-1).is_err());
1771 assert!(ExitCode::try_from(128).is_err());
1772 }
1773
1774 #[test]
1775 fn test_packed_array_type_round_trip() {
1776 for subtype in [ExprType::Boolean, ExprType::Double, ExprType::Integer, ExprType::Text] {
1777 for ndims in [1, 2, 5, 15] {
1778 let packed = PackedArrayType::new(subtype, ndims).unwrap();
1779 assert_eq!(subtype, packed.subtype());
1780 assert_eq!(ndims, usize::from(packed.ndims()));
1781 }
1782 }
1783 }
1784
1785 #[test]
1786 fn test_packed_array_type_display() {
1787 let p = PackedArrayType::new(ExprType::Integer, 2).unwrap();
1788 assert_eq!("[2]%", format!("{}", p));
1789 let p = PackedArrayType::new(ExprType::Text, 1).unwrap();
1790 assert_eq!("[1]$", format!("{}", p));
1791 }
1792
1793 #[test]
1794 fn test_var_arg_tag_ok() {
1795 for sep in [ArgSep::As, ArgSep::End, ArgSep::Long, ArgSep::Short] {
1796 for vat in [
1797 VarArgTag::Missing(sep),
1798 VarArgTag::Pointer(sep),
1799 VarArgTag::Immediate(sep, ExprType::Boolean),
1800 VarArgTag::Immediate(sep, ExprType::Double),
1801 VarArgTag::Immediate(sep, ExprType::Integer),
1802 VarArgTag::Immediate(sep, ExprType::Text),
1803 ] {
1804 assert_eq!(vat, VarArgTag::parse_u64(u64::from(VarArgTag::make_u16(vat))).unwrap());
1805 }
1806 }
1807 }
1808
1809 #[test]
1810 fn test_var_arg_tag_errors() {
1811 VarArgTag::parse_u64(1 << 12).unwrap_err();
1813
1814 VarArgTag::parse_u64(0x00000500).unwrap_err();
1816
1817 VarArgTag::parse_u64(0x00000001).unwrap_err();
1819
1820 VarArgTag::parse_u64(0x00000040).unwrap_err();
1822
1823 VarArgTag::parse_u64(0x00000104).unwrap_err();
1825
1826 VarArgTag::parse_u64(0x00000140).unwrap_err();
1828
1829 VarArgTag::parse_u64(0x00000201).unwrap_err();
1831
1832 VarArgTag::parse_u64(0x00000240).unwrap_err();
1834 }
1835}