/src/wasmtime/cranelift/codegen/src/ir/entities.rs
Line | Count | Source |
1 | | //! Cranelift IR entity references. |
2 | | //! |
3 | | //! Instructions in Cranelift IR need to reference other entities in the function. This can be other |
4 | | //! parts of the function like basic blocks or stack slots, or it can be external entities |
5 | | //! that are declared in the function preamble in the text format. |
6 | | //! |
7 | | //! These entity references in instruction operands are not implemented as Rust references both |
8 | | //! because Rust's ownership and mutability rules make it difficult, and because 64-bit pointers |
9 | | //! take up a lot of space, and we want a compact in-memory representation. Instead, entity |
10 | | //! references are structs wrapping a `u32` index into a table in the `Function` main data |
11 | | //! structure. There is a separate index type for each entity type, so we don't lose type safety. |
12 | | //! |
13 | | //! The `entities` module defines public types for the entity references along with constants |
14 | | //! representing an invalid reference. We prefer to use `Option<EntityRef>` whenever possible, but |
15 | | //! unfortunately that type is twice as large as the 32-bit index type on its own. Thus, compact |
16 | | //! data structures use the `PackedOption<EntityRef>` representation, while function arguments and |
17 | | //! return values prefer the more Rust-like `Option<EntityRef>` variant. |
18 | | //! |
19 | | //! The entity references all implement the `Display` trait in a way that matches the textual IR |
20 | | //! format. |
21 | | |
22 | | use crate::entity::entity_impl; |
23 | | use crate::ir::AliasRegion; |
24 | | use core::fmt; |
25 | | use core::u32; |
26 | | #[cfg(feature = "enable-serde")] |
27 | | use serde_derive::{Deserialize, Serialize}; |
28 | | |
29 | | /// An opaque reference to a [basic block](https://en.wikipedia.org/wiki/Basic_block) in a |
30 | | /// [`Function`](super::function::Function). |
31 | | /// |
32 | | /// You can get a `Block` using |
33 | | /// [`FunctionBuilder::create_block`](https://docs.rs/cranelift-frontend/*/cranelift_frontend/struct.FunctionBuilder.html#method.create_block) |
34 | | /// |
35 | | /// While the order is stable, it is arbitrary and does not necessarily resemble the layout order. |
36 | | #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] |
37 | | #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] |
38 | | pub struct Block(u32); |
39 | | entity_impl!(Block, "block"); |
40 | | |
41 | | impl Block { |
42 | | /// Create a new block reference from its number. This corresponds to the `blockNN` representation. |
43 | | /// |
44 | | /// This method is for use by the parser. |
45 | 186k | pub fn with_number(n: u32) -> Option<Self> { |
46 | 186k | if n < u32::MAX { Some(Self(n)) } else { None } |
47 | 186k | } |
48 | | } |
49 | | |
50 | | /// An opaque reference to an SSA value. |
51 | | /// |
52 | | /// You can get a constant `Value` from the following |
53 | | /// [`InstBuilder`](super::InstBuilder) instructions: |
54 | | /// |
55 | | /// - [`iconst`](super::InstBuilder::iconst) for integer constants |
56 | | /// - [`f16const`](super::InstBuilder::f16const) for 16-bit float constants |
57 | | /// - [`f32const`](super::InstBuilder::f32const) for 32-bit float constants |
58 | | /// - [`f64const`](super::InstBuilder::f64const) for 64-bit float constants |
59 | | /// - [`f128const`](super::InstBuilder::f128const) for 128-bit float constants |
60 | | /// - [`vconst`](super::InstBuilder::vconst) for vector constants |
61 | | /// |
62 | | /// Any `InstBuilder` instruction that has an output will also return a `Value`. |
63 | | /// |
64 | | /// While the order is stable, it is arbitrary. |
65 | | #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] |
66 | | #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] |
67 | | pub struct Value(u32); |
68 | | entity_impl!(Value, "v"); |
69 | | |
70 | | impl Value { |
71 | | /// Create a value from its number representation. |
72 | | /// This is the number in the `vNN` notation. |
73 | | /// |
74 | | /// This method is for use by the parser. |
75 | 0 | pub fn with_number(n: u32) -> Option<Self> { |
76 | 0 | if n < u32::MAX / 2 { |
77 | 0 | Some(Self(n)) |
78 | | } else { |
79 | 0 | None |
80 | | } |
81 | 0 | } |
82 | | } |
83 | | |
84 | | /// An opaque reference to an instruction in a [`Function`](super::Function). |
85 | | /// |
86 | | /// Most usage of `Inst` is internal. `Inst`ructions are returned by |
87 | | /// [`InstBuilder`](super::InstBuilder) instructions that do not return a |
88 | | /// [`Value`], such as control flow and trap instructions, as well as instructions that return a |
89 | | /// variable (potentially zero!) number of values, like call or call-indirect instructions. To get |
90 | | /// the `Value` of such instructions, use [`inst_results`](super::DataFlowGraph::inst_results) or |
91 | | /// its analogue in `cranelift_frontend::FuncBuilder`. |
92 | | /// |
93 | | /// [inst_comment]: https://github.com/bjorn3/rustc_codegen_cranelift/blob/0f8814fd6da3d436a90549d4bb19b94034f2b19c/src/pretty_clif.rs |
94 | | /// |
95 | | /// While the order is stable, it is arbitrary and does not necessarily resemble the layout order. |
96 | | #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] |
97 | | #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] |
98 | | pub struct Inst(u32); |
99 | | entity_impl!(Inst, "inst"); |
100 | | |
101 | | /// An opaque reference to a stack slot. |
102 | | /// |
103 | | /// Stack slots represent an address on the |
104 | | /// [call stack](https://en.wikipedia.org/wiki/Call_stack). |
105 | | /// |
106 | | /// `StackSlot`s can be created with |
107 | | /// [`FunctionBuilder::create_sized_stack_slot`](https://docs.rs/cranelift-frontend/*/cranelift_frontend/struct.FunctionBuilder.html#method.create_sized_stack_slot) |
108 | | /// or |
109 | | /// [`FunctionBuilder::create_dynamic_stack_slot`](https://docs.rs/cranelift-frontend/*/cranelift_frontend/struct.FunctionBuilder.html#method.create_dynamic_stack_slot). |
110 | | /// |
111 | | /// `StackSlot`s are most often used with |
112 | | /// [`stack_addr`](super::InstBuilder::stack_addr), |
113 | | /// [`stack_load`](super::InstBuilder::stack_load), and |
114 | | /// [`stack_store`](super::InstBuilder::stack_store). |
115 | | /// |
116 | | /// While the order is stable, it is arbitrary and does not necessarily resemble the stack order. |
117 | | #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] |
118 | | #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] |
119 | | pub struct StackSlot(u32); |
120 | | entity_impl!(StackSlot, "ss"); |
121 | | |
122 | | impl StackSlot { |
123 | | /// Create a new stack slot reference from its number. |
124 | | /// |
125 | | /// This method is for use by the parser. |
126 | 0 | pub fn with_number(n: u32) -> Option<Self> { |
127 | 0 | if n < u32::MAX { Some(Self(n)) } else { None } |
128 | 0 | } |
129 | | } |
130 | | |
131 | | /// An opaque reference to a dynamic stack slot. |
132 | | #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] |
133 | | #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] |
134 | | pub struct DynamicStackSlot(u32); |
135 | | entity_impl!(DynamicStackSlot, "dss"); |
136 | | |
137 | | impl DynamicStackSlot { |
138 | | /// Create a new stack slot reference from its number. |
139 | | /// |
140 | | /// This method is for use by the parser. |
141 | 0 | pub fn with_number(n: u32) -> Option<Self> { |
142 | 0 | if n < u32::MAX { Some(Self(n)) } else { None } |
143 | 0 | } |
144 | | } |
145 | | |
146 | | /// An opaque reference to a dynamic type. |
147 | | #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] |
148 | | #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] |
149 | | pub struct DynamicType(u32); |
150 | | entity_impl!(DynamicType, "dt"); |
151 | | |
152 | | impl DynamicType { |
153 | | /// Create a new dynamic type reference from its number. |
154 | | /// |
155 | | /// This method is for use by the parser. |
156 | 0 | pub fn with_number(n: u32) -> Option<Self> { |
157 | 0 | if n < u32::MAX { Some(Self(n)) } else { None } |
158 | 0 | } |
159 | | } |
160 | | |
161 | | /// An opaque reference to a global value. |
162 | | /// |
163 | | /// A `GlobalValue` is a [`Value`] that will be live across the entire |
164 | | /// function lifetime. It can be preloaded from other global values. |
165 | | /// |
166 | | /// You can create a `GlobalValue` in the following ways: |
167 | | /// |
168 | | /// - When compiling to native code, you can use it for objects in static memory with |
169 | | /// [`Module::declare_data_in_func`](https://docs.rs/cranelift-module/*/cranelift_module/trait.Module.html#method.declare_data_in_func). |
170 | | /// - For any compilation target, it can be registered with |
171 | | /// [`FunctionBuilder::create_global_value`](https://docs.rs/cranelift-frontend/*/cranelift_frontend/struct.FunctionBuilder.html#method.create_global_value). |
172 | | /// |
173 | | /// `GlobalValue`s can be referenced from a function's body with |
174 | | /// [`InstBuilder::symbol_value`](super::InstBuilder::symbol_value) and |
175 | | /// [`InstBuilder::tls_value`](super::InstBuilder::tls_value). |
176 | | /// |
177 | | /// While the order is stable, it is arbitrary. |
178 | | #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] |
179 | | #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] |
180 | | pub struct GlobalValue(u32); |
181 | | entity_impl!(GlobalValue, "gv"); |
182 | | |
183 | | impl GlobalValue { |
184 | | /// Create a new global value reference from its number. |
185 | | /// |
186 | | /// This method is for use by the parser. |
187 | 0 | pub fn with_number(n: u32) -> Option<Self> { |
188 | 0 | if n < u32::MAX { Some(Self(n)) } else { None } |
189 | 0 | } |
190 | | } |
191 | | |
192 | | /// An opaque reference to a constant. |
193 | | /// |
194 | | /// You can store [`ConstantData`](super::ConstantData) in a |
195 | | /// [`ConstantPool`](super::ConstantPool) for efficient storage and retrieval. |
196 | | /// See [`ConstantPool::insert`](super::ConstantPool::insert). |
197 | | /// |
198 | | /// While the order is stable, it is arbitrary and does not necessarily resemble the order in which |
199 | | /// the constants are written in the constant pool. |
200 | | #[derive(Copy, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)] |
201 | | #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] |
202 | | pub struct Constant(u32); |
203 | | entity_impl!(Constant, "const"); |
204 | | |
205 | | impl Constant { |
206 | | /// Create a const reference from its number. |
207 | | /// |
208 | | /// This method is for use by the parser. |
209 | 0 | pub fn with_number(n: u32) -> Option<Self> { |
210 | 0 | if n < u32::MAX { Some(Self(n)) } else { None } |
211 | 0 | } |
212 | | } |
213 | | |
214 | | /// An opaque reference to an immediate. |
215 | | /// |
216 | | /// Some immediates (e.g. SIMD shuffle masks) are too large to store in the |
217 | | /// [`InstructionData`](super::instructions::InstructionData) struct and therefore must be |
218 | | /// tracked separately in [`DataFlowGraph::immediates`](super::dfg::DataFlowGraph). `Immediate` |
219 | | /// provides a way to reference values stored there. |
220 | | /// |
221 | | /// While the order is stable, it is arbitrary. |
222 | | #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] |
223 | | #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] |
224 | | pub struct Immediate(u32); |
225 | | entity_impl!(Immediate, "imm"); |
226 | | |
227 | | impl Immediate { |
228 | | /// Create an immediate reference from its number. |
229 | | /// |
230 | | /// This method is for use by the parser. |
231 | 0 | pub fn with_number(n: u32) -> Option<Self> { |
232 | 0 | if n < u32::MAX { Some(Self(n)) } else { None } |
233 | 0 | } |
234 | | } |
235 | | |
236 | | /// An opaque reference to a [jump table](https://en.wikipedia.org/wiki/Branch_table). |
237 | | /// |
238 | | /// `JumpTable`s are used for indirect branching and are specialized for dense, |
239 | | /// 0-based jump offsets. If you want a jump table which doesn't start at 0, |
240 | | /// or is not contiguous, consider using a [`Switch`](https://docs.rs/cranelift-frontend/*/cranelift_frontend/struct.Switch.html) instead. |
241 | | /// |
242 | | /// `JumpTable` are used with [`br_table`](super::InstBuilder::br_table). |
243 | | /// |
244 | | /// `JumpTable`s can be created with |
245 | | /// [`create_jump_table`](https://docs.rs/cranelift-frontend/*/cranelift_frontend/struct.FunctionBuilder.html#method.create_jump_table). |
246 | | /// |
247 | | /// While the order is stable, it is arbitrary. |
248 | | #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] |
249 | | #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] |
250 | | pub struct JumpTable(u32); |
251 | | entity_impl!(JumpTable, "jt"); |
252 | | |
253 | | impl JumpTable { |
254 | | /// Create a new jump table reference from its number. |
255 | | /// |
256 | | /// This method is for use by the parser. |
257 | 0 | pub fn with_number(n: u32) -> Option<Self> { |
258 | 0 | if n < u32::MAX { Some(Self(n)) } else { None } |
259 | 0 | } |
260 | | } |
261 | | |
262 | | /// An opaque reference to another [`Function`](super::Function). |
263 | | /// |
264 | | /// `FuncRef`s are used for [direct](super::InstBuilder::call) function calls |
265 | | /// and by [`func_addr`](super::InstBuilder::func_addr) for use in |
266 | | /// [indirect](super::InstBuilder::call_indirect) function calls. |
267 | | /// |
268 | | /// `FuncRef`s can be created with |
269 | | /// |
270 | | /// - [`FunctionBuilder::import_function`](https://docs.rs/cranelift-frontend/*/cranelift_frontend/struct.FunctionBuilder.html#method.import_function) |
271 | | /// for external functions |
272 | | /// - [`Module::declare_func_in_func`](https://docs.rs/cranelift-module/*/cranelift_module/trait.Module.html#method.declare_func_in_func) |
273 | | /// for functions declared elsewhere in the same native |
274 | | /// [`Module`](https://docs.rs/cranelift-module/*/cranelift_module/trait.Module.html) |
275 | | /// |
276 | | /// While the order is stable, it is arbitrary. |
277 | | #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] |
278 | | #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] |
279 | | pub struct FuncRef(u32); |
280 | | entity_impl!(FuncRef, "fn"); |
281 | | |
282 | | impl FuncRef { |
283 | | /// Create a new external function reference from its number. |
284 | | /// |
285 | | /// This method is for use by the parser. |
286 | 0 | pub fn with_number(n: u32) -> Option<Self> { |
287 | 0 | if n < u32::MAX { Some(Self(n)) } else { None } |
288 | 0 | } |
289 | | } |
290 | | |
291 | | /// A reference to an `UserExternalName`, declared with `Function::declare_imported_user_function`. |
292 | | #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Default)] |
293 | | #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] |
294 | | pub struct UserExternalNameRef(u32); |
295 | | entity_impl!(UserExternalNameRef, "userextname"); |
296 | | |
297 | | /// An opaque reference to a function [`Signature`](super::Signature). |
298 | | /// |
299 | | /// `SigRef`s are used to declare a function with |
300 | | /// [`FunctionBuilder::import_function`](https://docs.rs/cranelift-frontend/*/cranelift_frontend/struct.FunctionBuilder.html#method.import_function) |
301 | | /// as well as to make an [indirect function call](super::InstBuilder::call_indirect). |
302 | | /// |
303 | | /// `SigRef`s can be created with |
304 | | /// [`FunctionBuilder::import_signature`](https://docs.rs/cranelift-frontend/*/cranelift_frontend/struct.FunctionBuilder.html#method.import_signature). |
305 | | /// |
306 | | /// You can retrieve the [`Signature`](super::Signature) that was used to create a `SigRef` with |
307 | | /// [`FunctionBuilder::signature`](https://docs.rs/cranelift-frontend/*/cranelift_frontend/struct.FunctionBuilder.html#method.signature) or |
308 | | /// [`func.dfg.signatures`](super::dfg::DataFlowGraph::signatures). |
309 | | /// |
310 | | /// While the order is stable, it is arbitrary. |
311 | | #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] |
312 | | #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] |
313 | | pub struct SigRef(u32); |
314 | | entity_impl!(SigRef, "sig"); |
315 | | |
316 | | impl SigRef { |
317 | | /// Create a new function signature reference from its number. |
318 | | /// |
319 | | /// This method is for use by the parser. |
320 | 0 | pub fn with_number(n: u32) -> Option<Self> { |
321 | 0 | if n < u32::MAX { Some(Self(n)) } else { None } |
322 | 0 | } |
323 | | } |
324 | | |
325 | | /// An opaque exception tag. |
326 | | /// |
327 | | /// Exception tags are used to denote the identity of an exception for |
328 | | /// matching by catch-handlers in exception tables. |
329 | | /// |
330 | | /// The index space is arbitrary and is given meaning only by the |
331 | | /// embedder of Cranelift. Cranelift will carry through these tags |
332 | | /// from exception tables to the handler metadata produced as output |
333 | | /// (for use by the embedder's unwinder). |
334 | | #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] |
335 | | #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] |
336 | | pub struct ExceptionTag(u32); |
337 | | entity_impl!(ExceptionTag, "tag"); |
338 | | |
339 | | impl ExceptionTag { |
340 | | /// Create a new exception tag from its arbitrary index. |
341 | | /// |
342 | | /// This method is for use by the parser. |
343 | 0 | pub fn with_number(n: u32) -> Option<Self> { |
344 | 0 | if n < u32::MAX { Some(Self(n)) } else { None } |
345 | 0 | } |
346 | | } |
347 | | |
348 | | /// An opaque reference to an exception table. |
349 | | /// |
350 | | /// `ExceptionTable`s are used for describing exception catch handlers on |
351 | | /// `try_call` and `try_call_indirect` instructions. |
352 | | #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] |
353 | | #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] |
354 | | pub struct ExceptionTable(u32); |
355 | | entity_impl!(ExceptionTable, "extable"); |
356 | | |
357 | | impl ExceptionTable { |
358 | | /// Create a new exception table reference from its number. |
359 | | /// |
360 | | /// This method is for use by the parser. |
361 | 0 | pub fn with_number(n: u32) -> Option<Self> { |
362 | 0 | if n < u32::MAX { Some(Self(n)) } else { None } |
363 | 0 | } |
364 | | } |
365 | | |
366 | | /// An opaque reference to any of the entities defined in this module that can appear in CLIF IR. |
367 | | #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] |
368 | | #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] |
369 | | pub enum AnyEntity { |
370 | | /// The whole function. |
371 | | Function, |
372 | | /// a basic block. |
373 | | Block(Block), |
374 | | /// An instruction. |
375 | | Inst(Inst), |
376 | | /// An SSA value. |
377 | | Value(Value), |
378 | | /// A stack slot. |
379 | | StackSlot(StackSlot), |
380 | | /// A dynamic stack slot. |
381 | | DynamicStackSlot(DynamicStackSlot), |
382 | | /// A dynamic type |
383 | | DynamicType(DynamicType), |
384 | | /// A Global value. |
385 | | GlobalValue(GlobalValue), |
386 | | /// A jump table. |
387 | | JumpTable(JumpTable), |
388 | | /// A constant. |
389 | | Constant(Constant), |
390 | | /// An external function. |
391 | | FuncRef(FuncRef), |
392 | | /// A function call signature. |
393 | | SigRef(SigRef), |
394 | | /// An exception table. |
395 | | ExceptionTable(ExceptionTable), |
396 | | /// An alias region. |
397 | | AliasRegion(AliasRegion), |
398 | | /// A function's stack limit |
399 | | StackLimit, |
400 | | } |
401 | | |
402 | | impl fmt::Display for AnyEntity { |
403 | 0 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
404 | 0 | match *self { |
405 | 0 | Self::Function => write!(f, "function"), |
406 | 0 | Self::Block(r) => r.fmt(f), |
407 | 0 | Self::Inst(r) => r.fmt(f), |
408 | 0 | Self::Value(r) => r.fmt(f), |
409 | 0 | Self::StackSlot(r) => r.fmt(f), |
410 | 0 | Self::DynamicStackSlot(r) => r.fmt(f), |
411 | 0 | Self::DynamicType(r) => r.fmt(f), |
412 | 0 | Self::GlobalValue(r) => r.fmt(f), |
413 | 0 | Self::JumpTable(r) => r.fmt(f), |
414 | 0 | Self::Constant(r) => r.fmt(f), |
415 | 0 | Self::FuncRef(r) => r.fmt(f), |
416 | 0 | Self::SigRef(r) => r.fmt(f), |
417 | 0 | Self::ExceptionTable(r) => r.fmt(f), |
418 | 0 | Self::AliasRegion(r) => r.fmt(f), |
419 | 0 | Self::StackLimit => write!(f, "stack_limit"), |
420 | | } |
421 | 0 | } |
422 | | } |
423 | | |
424 | | impl fmt::Debug for AnyEntity { |
425 | 0 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
426 | 0 | (self as &dyn fmt::Display).fmt(f) |
427 | 0 | } |
428 | | } |
429 | | |
430 | | impl From<Block> for AnyEntity { |
431 | 0 | fn from(r: Block) -> Self { |
432 | 0 | Self::Block(r) |
433 | 0 | } |
434 | | } |
435 | | |
436 | | impl From<Inst> for AnyEntity { |
437 | 0 | fn from(r: Inst) -> Self { |
438 | 0 | Self::Inst(r) |
439 | 0 | } |
440 | | } |
441 | | |
442 | | impl From<Value> for AnyEntity { |
443 | 0 | fn from(r: Value) -> Self { |
444 | 0 | Self::Value(r) |
445 | 0 | } |
446 | | } |
447 | | |
448 | | impl From<StackSlot> for AnyEntity { |
449 | 0 | fn from(r: StackSlot) -> Self { |
450 | 0 | Self::StackSlot(r) |
451 | 0 | } |
452 | | } |
453 | | |
454 | | impl From<DynamicStackSlot> for AnyEntity { |
455 | 0 | fn from(r: DynamicStackSlot) -> Self { |
456 | 0 | Self::DynamicStackSlot(r) |
457 | 0 | } |
458 | | } |
459 | | |
460 | | impl From<DynamicType> for AnyEntity { |
461 | 0 | fn from(r: DynamicType) -> Self { |
462 | 0 | Self::DynamicType(r) |
463 | 0 | } |
464 | | } |
465 | | |
466 | | impl From<GlobalValue> for AnyEntity { |
467 | 0 | fn from(r: GlobalValue) -> Self { |
468 | 0 | Self::GlobalValue(r) |
469 | 0 | } |
470 | | } |
471 | | |
472 | | impl From<JumpTable> for AnyEntity { |
473 | 0 | fn from(r: JumpTable) -> Self { |
474 | 0 | Self::JumpTable(r) |
475 | 0 | } |
476 | | } |
477 | | |
478 | | impl From<Constant> for AnyEntity { |
479 | 0 | fn from(r: Constant) -> Self { |
480 | 0 | Self::Constant(r) |
481 | 0 | } |
482 | | } |
483 | | |
484 | | impl From<FuncRef> for AnyEntity { |
485 | 0 | fn from(r: FuncRef) -> Self { |
486 | 0 | Self::FuncRef(r) |
487 | 0 | } |
488 | | } |
489 | | |
490 | | impl From<SigRef> for AnyEntity { |
491 | 0 | fn from(r: SigRef) -> Self { |
492 | 0 | Self::SigRef(r) |
493 | 0 | } |
494 | | } |
495 | | |
496 | | impl From<ExceptionTable> for AnyEntity { |
497 | 0 | fn from(r: ExceptionTable) -> Self { |
498 | 0 | Self::ExceptionTable(r) |
499 | 0 | } |
500 | | } |
501 | | |
502 | | impl From<AliasRegion> for AnyEntity { |
503 | 0 | fn from(r: AliasRegion) -> Self { |
504 | 0 | Self::AliasRegion(r) |
505 | 0 | } |
506 | | } |
507 | | |
508 | | #[cfg(test)] |
509 | | mod tests { |
510 | | use super::*; |
511 | | use alloc::string::ToString; |
512 | | |
513 | | #[test] |
514 | | fn value_with_number() { |
515 | | assert_eq!(Value::with_number(0).unwrap().to_string(), "v0"); |
516 | | assert_eq!(Value::with_number(1).unwrap().to_string(), "v1"); |
517 | | |
518 | | assert_eq!(Value::with_number(u32::MAX / 2), None); |
519 | | assert!(Value::with_number(u32::MAX / 2 - 1).is_some()); |
520 | | } |
521 | | |
522 | | #[test] |
523 | | fn memory() { |
524 | | use crate::packed_option::PackedOption; |
525 | | use core::mem; |
526 | | // This is the whole point of `PackedOption`. |
527 | | assert_eq!( |
528 | | mem::size_of::<Value>(), |
529 | | mem::size_of::<PackedOption<Value>>() |
530 | | ); |
531 | | } |
532 | | |
533 | | #[test] |
534 | | fn memory_option() { |
535 | | use core::mem; |
536 | | // PackedOption is used because Option<EntityRef> is twice as large |
537 | | // as EntityRef. If this ever fails to be the case, this test will fail. |
538 | | assert_eq!(mem::size_of::<Value>() * 2, mem::size_of::<Option<Value>>()); |
539 | | } |
540 | | |
541 | | #[test] |
542 | | fn constant_with_number() { |
543 | | assert_eq!(Constant::with_number(0).unwrap().to_string(), "const0"); |
544 | | assert_eq!(Constant::with_number(1).unwrap().to_string(), "const1"); |
545 | | } |
546 | | } |