cranelift_codegen/ir/
trapcode.rs1use core::fmt::{self, Display, Formatter};
4use core::str::FromStr;
5#[cfg(feature = "enable-serde")]
6use serde_derive::{Deserialize, Serialize};
7
8#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
12#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
13pub enum TrapCode {
14 StackOverflow,
16
17 HeapOutOfBounds,
23
24 HeapMisaligned,
26
27 TableOutOfBounds,
29
30 IndirectCallToNull,
32
33 BadSignature,
35
36 IntegerOverflow,
38
39 IntegerDivisionByZero,
41
42 BadConversionToInteger,
44
45 UnreachableCodeReached,
47
48 Interrupt,
50
51 User(u16),
53
54 NullReference,
56
57 NullI31Ref,
59}
60
61impl TrapCode {
62 pub const fn non_user_traps() -> &'static [TrapCode] {
64 &[
65 TrapCode::StackOverflow,
66 TrapCode::HeapOutOfBounds,
67 TrapCode::HeapMisaligned,
68 TrapCode::TableOutOfBounds,
69 TrapCode::IndirectCallToNull,
70 TrapCode::BadSignature,
71 TrapCode::IntegerOverflow,
72 TrapCode::IntegerDivisionByZero,
73 TrapCode::BadConversionToInteger,
74 TrapCode::UnreachableCodeReached,
75 TrapCode::Interrupt,
76 TrapCode::NullReference,
77 ]
78 }
79}
80
81impl Display for TrapCode {
82 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
83 use self::TrapCode::*;
84 let identifier = match *self {
85 StackOverflow => "stk_ovf",
86 HeapOutOfBounds => "heap_oob",
87 HeapMisaligned => "heap_misaligned",
88 TableOutOfBounds => "table_oob",
89 IndirectCallToNull => "icall_null",
90 BadSignature => "bad_sig",
91 IntegerOverflow => "int_ovf",
92 IntegerDivisionByZero => "int_divz",
93 BadConversionToInteger => "bad_toint",
94 UnreachableCodeReached => "unreachable",
95 Interrupt => "interrupt",
96 User(x) => return write!(f, "user{x}"),
97 NullReference => "null_reference",
98 NullI31Ref => "null_i31ref",
99 };
100 f.write_str(identifier)
101 }
102}
103
104impl FromStr for TrapCode {
105 type Err = ();
106
107 fn from_str(s: &str) -> Result<Self, Self::Err> {
108 use self::TrapCode::*;
109 match s {
110 "stk_ovf" => Ok(StackOverflow),
111 "heap_oob" => Ok(HeapOutOfBounds),
112 "heap_misaligned" => Ok(HeapMisaligned),
113 "table_oob" => Ok(TableOutOfBounds),
114 "icall_null" => Ok(IndirectCallToNull),
115 "bad_sig" => Ok(BadSignature),
116 "int_ovf" => Ok(IntegerOverflow),
117 "int_divz" => Ok(IntegerDivisionByZero),
118 "bad_toint" => Ok(BadConversionToInteger),
119 "unreachable" => Ok(UnreachableCodeReached),
120 "interrupt" => Ok(Interrupt),
121 "null_reference" => Ok(NullReference),
122 "null_i31ref" => Ok(NullI31Ref),
123 _ if s.starts_with("user") => s[4..].parse().map(User).map_err(|_| ()),
124 _ => Err(()),
125 }
126 }
127}
128
129#[cfg(test)]
130mod tests {
131 use super::*;
132 use alloc::string::ToString;
133
134 #[test]
135 fn display() {
136 for r in TrapCode::non_user_traps() {
137 let tc = *r;
138 assert_eq!(tc.to_string().parse(), Ok(tc));
139 }
140 assert_eq!("bogus".parse::<TrapCode>(), Err(()));
141
142 assert_eq!(TrapCode::User(17).to_string(), "user17");
143 assert_eq!("user22".parse(), Ok(TrapCode::User(22)));
144 assert_eq!("user".parse::<TrapCode>(), Err(()));
145 assert_eq!("user-1".parse::<TrapCode>(), Err(()));
146 assert_eq!("users".parse::<TrapCode>(), Err(()));
147 }
148}