Skip to main content

bytecode_lang/
ids.rs

1//! Dense index types.
2//!
3//! Every cross-reference in a module is a plain integer index into a table,
4//! never a pointer or a name lookup, so a decoded module is usable as is and a
5//! VM resolves each reference with one bounds-checked load. Each kind of index
6//! has its own newtype so a function index can never be passed where a
7//! constant index is expected.
8//!
9//! The decoder checks only that indices are well-formed numbers; whether an
10//! index is *in range* for its table is the verifier's job (see
11//! `docs/API.md`), and every accessor that follows an index returns `Option`.
12
13index_type! {
14    /// A register in the running function's frame.
15    ///
16    /// Registers are numbered from zero. The first registers hold the
17    /// function's parameters, in order; the rest are locals. Every register
18    /// has a declared [`ValType`](crate::ValType). The 16-bit width allows
19    /// 65,536 registers per function.
20    ///
21    /// # Examples
22    ///
23    /// ```
24    /// use bytecode_lang::Reg;
25    ///
26    /// assert_eq!(Reg(3).to_string(), "r3");
27    /// assert_eq!(Reg(3).index(), 3);
28    /// ```
29    Reg(u16) => "r"
30}
31
32index_type! {
33    /// An instruction index within one function: the destination of a branch.
34    ///
35    /// Targets are absolute, already resolved positions in the function's
36    /// code. They are never symbolic labels, so the encoded form can be
37    /// executed without a fix-up table (the defect class of family issue H02).
38    /// Every instruction is one slot wide, so every target is an instruction
39    /// boundary.
40    ///
41    /// # Examples
42    ///
43    /// ```
44    /// use bytecode_lang::Target;
45    ///
46    /// assert_eq!(Target(12).to_string(), "@12");
47    /// ```
48    Target(u32) => "@"
49}
50
51index_type! {
52    /// An index into the module's constant pool.
53    ///
54    /// # Examples
55    ///
56    /// ```
57    /// use bytecode_lang::ConstId;
58    ///
59    /// assert_eq!(ConstId(0).to_string(), "k0");
60    /// ```
61    ConstId(u32) => "k"
62}
63
64index_type! {
65    /// An index into the module's function table.
66    ///
67    /// # Examples
68    ///
69    /// ```
70    /// use bytecode_lang::FuncId;
71    ///
72    /// assert_eq!(FuncId(2).to_string(), "f2");
73    /// ```
74    FuncId(u32) => "f"
75}
76
77index_type! {
78    /// An index into the module's import table (host functions).
79    ///
80    /// # Examples
81    ///
82    /// ```
83    /// use bytecode_lang::ImportId;
84    ///
85    /// assert_eq!(ImportId(1).to_string(), "imp1");
86    /// ```
87    ImportId(u32) => "imp"
88}
89
90index_type! {
91    /// An index into the module's global table.
92    ///
93    /// # Examples
94    ///
95    /// ```
96    /// use bytecode_lang::GlobalId;
97    ///
98    /// assert_eq!(GlobalId(4).to_string(), "g4");
99    /// ```
100    GlobalId(u32) => "g"
101}
102
103index_type! {
104    /// An index into the module's type table.
105    ///
106    /// # Examples
107    ///
108    /// ```
109    /// use bytecode_lang::TypeId;
110    ///
111    /// assert_eq!(TypeId(7).to_string(), "t7");
112    /// ```
113    TypeId(u32) => "t"
114}
115
116index_type! {
117    /// An index into the module's string table.
118    ///
119    /// # Examples
120    ///
121    /// ```
122    /// use bytecode_lang::StrId;
123    ///
124    /// assert_eq!(StrId(5).to_string(), "s5");
125    /// ```
126    StrId(u32) => "s"
127}
128
129index_type! {
130    /// An index into the running function's name list, which maps it to a
131    /// [`StrId`].
132    ///
133    /// Property instructions need two registers and a name in one eight-byte
134    /// instruction, which leaves 16 bits for the name. Routing names through a
135    /// per-function list (as Lua and V8 do with their per-function constant
136    /// pools) keeps the module's string table unbounded while each function
137    /// may still name 65,536 distinct properties.
138    ///
139    /// # Examples
140    ///
141    /// ```
142    /// use bytecode_lang::NameRef;
143    ///
144    /// assert_eq!(NameRef(0).to_string(), "n0");
145    /// ```
146    NameRef(u16) => "n"
147}
148
149index_type! {
150    /// An index into the running function's type list, which maps it to a
151    /// [`TypeId`].
152    ///
153    /// Used by the instructions that need a type next to two or three
154    /// registers ([`Inst::IsType`](crate::Inst::IsType),
155    /// [`Inst::NewArray`](crate::Inst::NewArray), ...), for the same reason as
156    /// [`NameRef`].
157    ///
158    /// # Examples
159    ///
160    /// ```
161    /// use bytecode_lang::TypeRef;
162    ///
163    /// assert_eq!(TypeRef(1).to_string(), "ty1");
164    /// ```
165    TypeRef(u16) => "ty"
166}
167
168index_type! {
169    /// An index into the running function's jump tables (see
170    /// [`Inst::Switch`](crate::Inst::Switch)).
171    ///
172    /// # Examples
173    ///
174    /// ```
175    /// use bytecode_lang::TableId;
176    ///
177    /// assert_eq!(TableId(0).to_string(), "jt0");
178    /// ```
179    TableId(u32) => "jt"
180}
181
182index_type! {
183    /// An index into the running function's call shapes (see
184    /// [`Inst::DCallShape`](crate::Inst::DCallShape) and
185    /// [`CallShape`](crate::CallShape)): which window arguments are positional,
186    /// named, or spread. 16-bit, like [`NameRef`], so a function may use 65,536
187    /// distinct shapes.
188    ///
189    /// # Examples
190    ///
191    /// ```
192    /// use bytecode_lang::ShapeId;
193    ///
194    /// assert_eq!(ShapeId(2).to_string(), "cs2");
195    /// ```
196    ShapeId(u16) => "cs"
197}
198
199index_type! {
200    /// A field slot of a struct type, counted across the whole parent chain
201    /// (a struct's fields start with its parent's).
202    ///
203    /// # Examples
204    ///
205    /// ```
206    /// use bytecode_lang::FieldIdx;
207    ///
208    /// assert_eq!(FieldIdx(2).to_string(), "#2");
209    /// ```
210    FieldIdx(u16) => "#"
211}
212
213index_type! {
214    /// A captured value of the running closure (see
215    /// [`Inst::GetUpval`](crate::Inst::GetUpval)).
216    ///
217    /// # Examples
218    ///
219    /// ```
220    /// use bytecode_lang::UpvalIdx;
221    ///
222    /// assert_eq!(UpvalIdx(0).to_string(), "u0");
223    /// ```
224    UpvalIdx(u16) => "u"
225}