steel_gen/
opcode.rs

1use serde::{Deserialize, Serialize};
2
3macro_rules! declare_opcodes {
4
5    ( { $($variant:tt);* } { $( [ $super:tt => $(($k:path, $v:expr),)* ] );* } ) => {
6        #[repr(u8)]
7        #[derive(Copy, Clone, Debug, Hash, PartialEq, Serialize, Deserialize, Eq, PartialOrd, Ord)]
8        pub enum OpCode {
9            $($variant),*
10
11            ,
12
13            $($super),*
14        }
15
16        // $( const $super: &'static [(TestOpCode, usize)] = &[ $($v),* ]; )*
17
18        pub const fn op_code_to_super_instruction_pattern(op_code: OpCode) -> Option<&'static [(OpCode, usize)]> {
19            match op_code {
20                $(OpCode::$super => Some( &[ $(($k, $v)),* ]) ),* ,
21                _ => None
22            }
23        }
24
25        pub const fn sequence_to_opcode(pattern: &[(OpCode, usize)]) -> Option<OpCode> {
26            match pattern {
27                $(&[ $(($k, _)),* ] => Some(OpCode::$super) ),* ,
28                _ => None
29            }
30        }
31
32        pub static PATTERNS: &'static [&'static [(OpCode, usize)]] = &[
33                $( &[ $(($k, $v)),* ] ),* ,
34        ];
35    }
36
37}
38
39declare_opcodes! {
40    {
41        VOID;
42        PUSH;
43        IF;
44        JMP;
45        FUNC;
46        SCLOSURE;
47        ECLOSURE;
48        BIND;
49        SDEF;
50        EDEF;
51        POPPURE;
52        POPN;
53        POPSINGLE;
54        PASS;
55        PUSHCONST;
56        NDEFS;
57        PANIC;
58        TAILCALL;
59        SET;
60        READLOCAL;
61        READLOCAL0;
62        READLOCAL1;
63        READLOCAL2;
64        READLOCAL3;
65        SETLOCAL;
66        COPYCAPTURESTACK;
67        COPYCAPTURECLOSURE;
68        COPYHEAPCAPTURECLOSURE;
69        FIRSTCOPYHEAPCAPTURECLOSURE;
70        TCOJMP;
71        CALLGLOBAL;
72        CALLGLOBALTAIL;
73        LOADINT0; // Load const 0
74        LOADINT1;
75        LOADINT2;
76        CGLOCALCONST;
77        MOVEREADLOCAL;
78        MOVEREADLOCAL0;
79        MOVEREADLOCAL1;
80        MOVEREADLOCAL2;
81        MOVEREADLOCAL3;
82        READCAPTURED;
83        BEGINSCOPE;
84        LETENDSCOPE;
85        PUREFUNC;
86        ADD;
87        SUB;
88        MUL;
89        DIV;
90        EQUAL;
91        NUMEQUAL;
92        NULL;
93        LTE;
94        CONS; // Cons should be... probably specialized
95        LIST;
96        CAR;
97        CDR;
98        NEWBOX;
99        SETBOX;
100        UNBOX;
101        NEWSCLOSURE;
102        ADDREGISTER;
103        SUBREGISTER;
104        LTEREGISTER;
105        SUBREGISTER1;
106        ALLOC;
107        READALLOC;
108        SETALLOC;
109        DynSuperInstruction;
110        Arity;
111        LetVar;
112        ADDIMMEDIATE;
113        SUBIMMEDIATE;
114        LTEIMMEDIATE;
115        BINOPADD;
116        BINOPSUB;
117        LTEIMMEDIATEIF;
118        NOT;
119        VEC;
120        Apply;
121        POPJMP;
122        CALLGLOBALTAILPOP;
123        BINOPADDTAIL;
124        LOADINT0POP; // Load const 0
125        LOADINT1POP;
126        LOADINT2POP
127    }
128
129    // Super instructions
130    {
131
132
133        [
134            CaseLambdaDispatch =>
135                                  (OpCode::BEGINSCOPE, 0),
136                                  (OpCode::READLOCAL0, 0),
137                                  (OpCode::CALLGLOBAL, 75),
138                                  (OpCode::FUNC, 1),
139                                  (OpCode::READLOCAL1, 1),
140                                  (OpCode::PUSHCONST, 565),
141                                  (OpCode::CALLGLOBAL, 75),
142                                  (OpCode::FUNC, 1),
143                                  (OpCode::NUMEQUAL, 2),
144                                  (OpCode::PASS, 2),
145                                  (OpCode::IF, 22),
146        ]
147
148        // [
149        //     ReadLocal1PushConstEqualIf => (OpCode::READLOCAL1, 1),
150        //                                   (OpCode::PUSHCONST, 335),
151        //                                   (OpCode::EQUAL, 2),
152        //                                   (OpCode::PASS, 0),
153        //                                   (OpCode::IF, 8),
154        // ];
155
156        // [
157        //     ReadLocal2CallGlobalIf => (OpCode::READLOCAL2, 2),
158        //                               (OpCode::CALLGLOBAL, 1),
159        //                               (OpCode::FUNC, 1),
160        //                               (OpCode::IF, 8),
161        // ]
162
163        // 16    READLOCAL0         : 0      ##args
164        // 17    CALLGLOBAL         : 1      length
165        // 18    Arity              : 82     length
166        // 19    READLOCAL1         : 1      l
167        // 20    LOADINT0           : 274    0
168        // 21    CALLGLOBAL         : 2      =
169        // 22    Arity              : 180    =
170        // 23    IF                 : 22
171
172        // [
173        //     CaseLambdaDispatch => (OpCode::READLOCAL0, 0),
174        //                           (OpCode::CALLGLOBAL, 1),
175        //                           (OpCode::Arity, 92),
176        //                           (OpCode::READLOCAL1, 1),
177        //                           (OpCode::LOADINT0, 0),
178        //                           (OpCode::CALLGLOBAL, 2),
179        //                           (OpCode::Arity, 181),
180        //                           (OpCode::IF, 22),
181        // ]
182
183        // [ MOVERLLIS2CG => (OpCode::MOVEREADLOCAL, 0), (OpCode::LOADINT2, 225), (OpCode::SUB, 2), (OpCode::CALLGLOBAL, 1), ];
184
185        // [ MOVERLLIS2CGFOO => (OpCode::MOVEREADLOCAL, 1), (OpCode::LOADINT2, 225), (OpCode::SUB, 2), (OpCode::CALLGLOBAL, 1), ]
186
187
188        //         (MOVEREADLOCAL0, 0),
189        //         (LOADINT2, 225),
190        //         (SUB, 2),
191        //         (CALLGLOBAL, 1),
192
193    }
194}
195
196// // expansion
197// enum EntryPoints {
198//     SomeLibCallback(u64),
199
200//     A(),
201//     B(),
202// }
203
204impl OpCode {
205    /// Is this op code created as part of the aggregation of multiple op codes?
206    pub fn is_super_instruction(&self) -> bool {
207        // TODO: Check where super instructions start!
208        *self as u32 > Self::LTEIMMEDIATEIF as u32
209    }
210
211    /// Statically create the mapping we need for super instruction. Also, as part of the op code map generating,
212    /// the macro used for calling super instructions should also be generated.
213    pub fn super_instructions(&self) -> &'static [&'static [(OpCode, usize)]] {
214        todo!()
215    }
216
217    pub fn is_ephemeral_opcode(&self) -> bool {
218        use OpCode::*;
219
220        matches!(
221            self,
222            ECLOSURE
223                | PASS
224                | Arity
225                | NDEFS
226                | COPYCAPTURECLOSURE
227                | COPYCAPTURESTACK
228                | COPYHEAPCAPTURECLOSURE,
229        )
230    }
231
232    // TODO better error handling here
233    pub fn from(s: &str) -> Self {
234        use OpCode::*;
235        match s {
236            "VOID" => VOID,
237            "PUSH" => PUSH,
238            "IF" => IF,
239            "JMP" => JMP,
240            "FUNC" => FUNC,
241            "SCLOSURE" => SCLOSURE,
242            "ECLOSURE" => ECLOSURE,
243            // "STRUCT" => STRUCT,
244            "BIND" => BIND,
245            "SDEF" => SDEF,
246            "EDEF" => EDEF,
247            "PASS" => PASS,
248            "PUSHCONST" => PUSHCONST,
249            "NDEFS" => NDEFS,
250            "PANIC" => PANIC,
251            "TAILCALL" => TAILCALL,
252            "SET" => SET,
253            "READLOCAL" => READLOCAL,
254            "SETLOCAL" => SETLOCAL,
255            "TCOJMP" => TCOJMP,
256            "CALLGLOBAL" => CALLGLOBAL,
257            "CALLGLOBALTAIL" => CALLGLOBALTAIL,
258            "LOADINT0" => LOADINT0, // Load const 0
259            "LOADINT1" => LOADINT1,
260            "LOADINT2" => LOADINT2,
261            "CGLOCALCONST" => CGLOCALCONST,
262            "MOVEREADLOCAL" => MOVEREADLOCAL,
263            "BEGINSCOPE" => BEGINSCOPE,
264            "ADD" => ADD,
265            "SUB" => SUB,
266            "MUL" => MUL,
267            "DIV" => DIV,
268            "EQUAL" => EQUAL,
269            "LTE" => LTE,
270            "LETENDSCOPE" => LETENDSCOPE,
271            "PUREFUNC" => PUREFUNC,
272            "POP_PURE" => POPPURE,
273            "READCAPTURED" => READCAPTURED,
274            "COPYCAPTURESTACK" => COPYCAPTURESTACK,
275            "COPYCAPTURECLOSURE" => COPYCAPTURECLOSURE,
276            "COPYHEAPCAPTURECLOSURE" => COPYHEAPCAPTURECLOSURE,
277            "NEWSCLOSURE" => NEWSCLOSURE,
278            "ADDREGISTER" => ADDREGISTER,
279            "SUBREGISTER" => SUBREGISTER,
280            "LTEREGISTER" => LTEREGISTER,
281            "SUBREGISTER1" => SUBREGISTER1,
282            "ALLOC" => ALLOC,
283            "READALLOC" => READALLOC,
284            "SETALLOC" => SETALLOC,
285            _ => panic!("Unable to map string to opcode"),
286        }
287    }
288
289    pub fn width(&self) -> usize {
290        match self {
291            OpCode::VOID => todo!(),
292            OpCode::PUSH => todo!(),
293            OpCode::IF => todo!(),
294            OpCode::JMP => todo!(),
295            OpCode::FUNC => todo!(),
296            OpCode::SCLOSURE => todo!(),
297            OpCode::ECLOSURE => todo!(),
298            // OpCode::STRUCT => todo!(),
299            OpCode::BIND => todo!(),
300            OpCode::SDEF => todo!(),
301            OpCode::EDEF => todo!(),
302            OpCode::POPPURE => todo!(),
303            OpCode::PASS => todo!(),
304            OpCode::PUSHCONST => todo!(),
305            OpCode::NDEFS => todo!(),
306            OpCode::PANIC => todo!(),
307            OpCode::TAILCALL => todo!(),
308            OpCode::SET => todo!(),
309            OpCode::READLOCAL => todo!(),
310            OpCode::SETLOCAL => todo!(),
311            OpCode::COPYCAPTURESTACK => todo!(),
312            OpCode::COPYCAPTURECLOSURE => todo!(),
313            OpCode::TCOJMP => todo!(),
314            OpCode::CALLGLOBAL => 2,
315            OpCode::CALLGLOBALTAIL => todo!(),
316            OpCode::LOADINT0 => todo!(),
317            OpCode::LOADINT1 => todo!(),
318            OpCode::LOADINT2 => todo!(),
319            OpCode::CGLOCALCONST => todo!(),
320            OpCode::MOVEREADLOCAL => todo!(),
321            OpCode::READCAPTURED => todo!(),
322            OpCode::BEGINSCOPE => todo!(),
323            OpCode::LETENDSCOPE => todo!(),
324            OpCode::PUREFUNC => todo!(),
325            OpCode::ADD => 2,
326            OpCode::SUB => todo!(),
327            OpCode::MUL => todo!(),
328            OpCode::DIV => todo!(),
329            OpCode::EQUAL => todo!(),
330            OpCode::LTE => todo!(),
331            OpCode::NEWSCLOSURE => todo!(),
332            OpCode::ADDREGISTER => 2,
333            OpCode::SUBREGISTER => 2,
334            OpCode::LTEREGISTER => 2,
335            OpCode::SUBREGISTER1 => todo!(),
336            OpCode::ALLOC => todo!(),
337            _ => todo!(),
338        }
339    }
340}