1#![allow(dead_code)]
2#![allow(non_camel_case_types)]
3use std::fmt;
4
5pub type OpIndex = i32;
6
7#[repr(u8)]
8#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
9pub enum Opcode {
10 ZERO = 0, PUSH_CONST,
13 PUSH_NIL,
14 PUSH_FALSE,
15 PUSH_TRUE,
16 PUSH_IMM,
17 POP,
18 LOAD_LOCAL,
19 STORE_LOCAL, LOAD_UPVALUE,
21 STORE_UPVALUE,
22 LOAD_INDEX,
23 STORE_INDEX,
24 LOAD_INDEX_IMM,
25 STORE_INDEX_IMM,
26 LOAD_STRUCT_FIELD,
27 STORE_STRUCT_FIELD,
28 LOAD_PKG_FIELD,
29 STORE_PKG_FIELD,
30 LOAD_FIELD,
31 STORE_FIELD,
32 STORE_DEREF,
33 BIND_METHOD,
34 BIND_INTERFACE_METHOD,
35 CAST,
36 ADD, SUB, MUL, QUO, REM, AND, OR, XOR, SHL, SHR, AND_NOT, UNARY_ADD, UNARY_SUB, UNARY_XOR, REF_LOCAL,
53 REF_UPVALUE,
54 REF_SLICE_MEMBER,
55 REF_STRUCT_FIELD,
56 REF_PKG_MEMBER,
57 REF_LITERAL,
58 DEREF, SEND, RECV, NOT, EQL, LSS, GTR, NEQ, LEQ, GEQ, PRE_CALL,
71 CALL,
72 RETURN,
73
74 JUMP,
76 JUMP_IF,
77 JUMP_IF_NOT,
78 SWITCH, SELECT,
80 LOOP,
81 RANGE_INIT,
82 RANGE, TYPE_ASSERT,
86 TYPE,
87
88 IMPORT, SLICE, SLICE_FULL, LITERAL, NEW, MAKE, LEN, CAP, APPEND, CLOSE, PANIC, RECOVER, ASSERT, FFI, }
104
105impl Opcode {
106 #[inline]
107 pub fn offset(&self, base: Opcode) -> OpIndex {
108 (*self as i16 - base as i16) as OpIndex
109 }
110
111 pub fn property(&self) -> (&str, i8) {
112 match self {
113 Opcode::ZERO => ("ZERO (place holder)", 0),
114 Opcode::PUSH_CONST => ("PUSH_CONST", 1),
115 Opcode::PUSH_NIL => ("PUSH_NIL", 1),
116 Opcode::PUSH_FALSE => ("PUSH_FALSE", 1),
117 Opcode::PUSH_TRUE => ("PUSH_TRUE", 1),
118 Opcode::PUSH_IMM => ("PUSH_IMM", 1),
119 Opcode::POP => ("POP", -1),
120 Opcode::LOAD_LOCAL => ("LOAD_LOCAL", 1),
121 Opcode::STORE_LOCAL => ("STORE_LOCAL", 0),
122 Opcode::LOAD_UPVALUE => ("LOAD_LOCAL", 1),
123 Opcode::STORE_UPVALUE => ("STORE_UPVALUE", 0),
124 Opcode::LOAD_INDEX => ("LOAD_INDEX", -1),
125 Opcode::STORE_INDEX => ("STORE_INDEX", 0),
126 Opcode::LOAD_INDEX_IMM => ("LOAD_INDEX_IMM", 0),
127 Opcode::STORE_INDEX_IMM => ("STORE_INDEX_IMM", 0),
128 Opcode::LOAD_STRUCT_FIELD => ("LOAD_STRUCT_FIELD", 0),
129 Opcode::STORE_STRUCT_FIELD => ("STORE_STRUCT_FIELD", 0),
130 Opcode::LOAD_PKG_FIELD => ("LOAD_PKG_FIELD", 1),
131 Opcode::STORE_PKG_FIELD => ("STORE_PKG_FIELD", 0),
132 Opcode::LOAD_FIELD => ("LOAD_FIELD", -1),
133 Opcode::STORE_FIELD => ("STORE_FIELD", 0),
134 Opcode::STORE_DEREF => ("STORE_DEREF", 0),
135 Opcode::BIND_METHOD => ("BIND_METHOD", 0),
136 Opcode::BIND_INTERFACE_METHOD => ("BIND_INTERFACE_METHOD", 0),
137 Opcode::CAST => ("CAST", 0),
138
139 Opcode::ADD => ("ADD", -1),
140 Opcode::SUB => ("SUB", -1),
141 Opcode::MUL => ("MUL", -1),
142 Opcode::QUO => ("QUO", -1),
143 Opcode::REM => ("REM", -1),
144 Opcode::AND => ("AND", -1),
145 Opcode::OR => ("OR", -1),
146 Opcode::XOR => ("XOR", -1),
147 Opcode::SHL => ("SHL", -1),
148 Opcode::SHR => ("SHR", -1),
149 Opcode::AND_NOT => ("AND_NOT", -1),
150 Opcode::UNARY_ADD => ("UNARY_ADD", 0),
151 Opcode::UNARY_SUB => ("UNARY_SUB", 0),
152 Opcode::UNARY_XOR => ("UNARY_XOR", 0),
153 Opcode::REF_LOCAL => ("REF_LOCAL", 0),
154 Opcode::REF_UPVALUE => ("REF_UPVALUE", 0),
155 Opcode::REF_SLICE_MEMBER => ("REF_SLICE_MEMBER", 0),
156 Opcode::REF_STRUCT_FIELD => ("REF_STRUCT_FIELD", 0),
157 Opcode::REF_PKG_MEMBER => ("REF_PKG_MEMBER", 0),
158 Opcode::REF_LITERAL => ("REF_LITERAL", 0),
159 Opcode::DEREF => ("DEREF", 0),
160 Opcode::SEND => ("SEND", -1),
161 Opcode::RECV => ("RECV", 1),
162 Opcode::NOT => ("LNOT", 0),
163 Opcode::EQL => ("EQL", -1),
164 Opcode::LSS => ("LSS", -1),
165 Opcode::GTR => ("GTR", -1),
166 Opcode::NEQ => ("NEQ", -1),
167 Opcode::LEQ => ("LEQ", -1),
168 Opcode::GEQ => ("GEQ", -1),
169
170 Opcode::PRE_CALL => ("PRE_CALL", -128),
171 Opcode::CALL => ("CALL", -128),
172 Opcode::RETURN => ("RETURN", -128),
173
174 Opcode::JUMP => ("JUMP", 0),
175 Opcode::LOOP => ("LOOP", 0),
176 Opcode::JUMP_IF => ("JUMP_IF", -1),
177 Opcode::JUMP_IF_NOT => ("JUMP_IF_NOT", -1),
178 Opcode::SWITCH => ("SWITCH", -1),
179 Opcode::SELECT => ("SELECT", -128),
180 Opcode::RANGE_INIT => ("RANGE_INIT", 0),
181 Opcode::RANGE => ("RANGE", 1),
182
183 Opcode::TYPE_ASSERT => ("TYPE_ASSERT", 0),
184 Opcode::TYPE => ("TYPE", 1),
185
186 Opcode::IMPORT => ("IMPORT", 0),
187 Opcode::SLICE => ("SLICE", -2),
188 Opcode::SLICE_FULL => ("SLICE_FULL", -3),
189 Opcode::LITERAL => ("LITERAL", 0),
190 Opcode::NEW => ("NEW", 0),
191 Opcode::MAKE => ("MAKE", 0),
192 Opcode::LEN => ("LEN", 0),
193 Opcode::CAP => ("CAP", 0),
194 Opcode::APPEND => ("APPEND", -128),
195 Opcode::CLOSE => ("CLOSE", -1),
196 Opcode::PANIC => ("PANIC", -1),
197 Opcode::RECOVER => ("RECOVER", 1),
198 Opcode::ASSERT => ("ASSERT", 0),
199 Opcode::FFI => ("FFI", 0),
200 }
201 }
202
203 pub fn text(&self) -> &str {
204 let (t, _) = self.property();
205 t
206 }
207}
208
209impl fmt::Display for Opcode {
210 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
211 let (t, _) = self.property();
212 write!(f, "OPCODE: {}", t)
213 }
214}
215
216pub const COPYABLE_END: ValueType = ValueType::Package;
217
218#[derive(Copy, Clone, Eq, PartialEq, Debug, Ord, PartialOrd)]
219#[repr(u8)]
220pub enum ValueType {
221 Zero, Bool = 1,
223 Int,
224 Int8,
225 Int16,
226 Int32,
227 Int64,
228 Uint,
229 Uint8,
230 Uint16,
231 Uint32,
232 Uint64,
233 Float32,
234 Float64,
235 Complex64,
236 Function,
237 Package,
238 Metadata,
239
240 Nil,
243 Pointer,
244 Closure,
245 Slice,
246 Map,
247 Interface,
248 Channel,
249
250 Complex128,
251 Str,
252 Array,
253 Struct,
254
255 Named,
256
257 FfiClosure,
258
259 FlagA, FlagB,
261 FlagC,
262 FlagD,
263 FlagE,
264}
265
266impl ValueType {
267 #[inline]
268 pub fn copyable(&self) -> bool {
269 self <= ©ABLE_END
270 }
271}
272
273#[derive(Clone, Copy)]
285pub struct Instruction {
286 val: u64,
287}
288
289impl Instruction {
290 pub fn new(
291 op: Opcode,
292 type0: Option<ValueType>,
293 type1: Option<ValueType>,
294 type2: Option<ValueType>,
295 imm: Option<OpIndex>,
296 ) -> Instruction {
297 let val = (op as u64) << (8 * 3 + 32);
298 let mut inst = Instruction { val: val };
299 if let Some(v) = type0 {
300 inst.val |= (v as u64) << (8 * 2 + 32);
301 }
302 if let Some(v) = type1 {
303 inst.val |= (v as u64) << (8 + 32);
304 }
305 if let Some(v) = type2 {
306 inst.val |= (v as u64) << 32;
307 }
308 if let Some(v) = imm {
309 inst.set_imm(v);
310 }
311 inst
312 }
313
314 #[inline]
315 pub fn from_u64(v: u64) -> Instruction {
316 Instruction { val: v }
317 }
318
319 #[inline]
320 pub fn set_imm(&mut self, imm: OpIndex) {
321 let uv: u32 = unsafe { std::mem::transmute(imm) };
322 self.val = (self.val & 0xffff_ffff_0000_0000) | uv as u64;
323 }
324
325 #[inline]
327 pub fn set_imm824(&mut self, imm0: OpIndex, imm1: OpIndex) {
328 assert!(Instruction::in_8bit_range(imm0));
329 assert!(Instruction::in_24bit_range(imm1));
330 let u0: u8 = unsafe { std::mem::transmute(imm0 as i8) };
331 let u0 = (u0 as u32) << 24;
332 let u1: u32 = unsafe { std::mem::transmute(imm1) };
333 let u1 = u1 & 0x00ff_ffff;
334 self.val = (self.val & 0xffff_ffff_0000_0000) | (u0 | u1) as u64;
335 }
336
337 #[inline]
341 pub fn set_t2_with_index(&mut self, index: i8) {
342 let val8: u8 = unsafe { std::mem::transmute(index) };
343 let val64 = (val8 as u64) << 32;
344 self.val = (self.val & 0xffff_ff00_ffff_ffff) | val64;
345 }
346
347 #[inline]
348 pub fn get_u64(&self) -> u64 {
349 self.val
350 }
351
352 #[inline]
353 pub fn op(&self) -> Opcode {
354 unsafe { std::mem::transmute((self.val >> (8 * 3 + 32)) as u8) }
355 }
356
357 #[inline]
358 pub fn t0(&self) -> ValueType {
359 let v = ((self.val >> (8 * 2 + 32)) as u16) & 0xff;
360 unsafe { std::mem::transmute(v as u8) }
361 }
362
363 #[inline]
364 pub fn t1(&self) -> ValueType {
365 let v = ((self.val >> (8 + 32)) as u32) & 0xff;
366 unsafe { std::mem::transmute(v as u8) }
367 }
368
369 #[inline]
370 pub fn t2(&self) -> ValueType {
371 let v = ((self.val >> 32) as u32) & 0xff;
372 unsafe { std::mem::transmute(v as u8) }
373 }
374
375 #[inline]
376 pub fn t2_as_index(&self) -> OpIndex {
377 let v = ((self.val & 0x0000_00ff_0000_0000) >> 32) as u8;
378 let ival: i8 = unsafe { std::mem::transmute(v) };
379 ival as OpIndex
380 }
381
382 #[inline]
383 pub fn imm(&self) -> OpIndex {
384 unsafe { std::mem::transmute((self.val & 0xffff_ffff) as u32) }
385 }
386
387 #[inline]
388 pub fn imm824(&self) -> (OpIndex, OpIndex) {
389 let all = (self.val & 0xffff_ffff) as u32;
390 let i0: i8 = unsafe { std::mem::transmute((all >> 24) as u8) };
391 let all = all & 0x00ff_ffff;
392 let sign = all >> 23;
393 let all = ((sign * 0xff) << 24) | all;
394 let i1 = unsafe { std::mem::transmute(all) };
395 (i0 as OpIndex, i1)
396 }
397
398 #[inline]
399 pub fn code2index(op: Opcode) -> OpIndex {
400 op as OpIndex
401 }
402
403 #[inline]
404 pub fn index2code(i: OpIndex) -> Opcode {
405 unsafe { std::mem::transmute(i as u8) }
406 }
407
408 #[inline]
409 pub fn in_8bit_range(i: OpIndex) -> bool {
410 -(1 << 7) <= i && i < (1 << 7)
411 }
412
413 #[inline]
414 pub fn in_24bit_range(i: OpIndex) -> bool {
415 -(1 << 23) <= i && i < (1 << 23)
416 }
417}
418
419impl fmt::Debug for Instruction {
420 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
421 let op = self.op();
422 match op {
423 Opcode::STORE_LOCAL
424 | Opcode::STORE_UPVALUE
425 | Opcode::STORE_FIELD
426 | Opcode::STORE_STRUCT_FIELD
427 | Opcode::STORE_PKG_FIELD
428 | Opcode::STORE_DEREF => {
429 let (i0, i1) = self.imm824();
430 if i0 < 0 {
431 write!(f, "{}, IMM0: {}, IMM1: {}", op, i0, i1)
432 } else {
433 let op_ex = Instruction::index2code(i0);
434 write!(f, "{}, EX: {}, IMM0: {}, IMM1: {}", op, op_ex, i0, i1)
435 }
436 }
437 _ => {
438 let imm = self.imm();
439 write!(f, "{}, IMM: {}", op, imm)
440 }
441 }
442 }
443}
444
445#[cfg(test)]
446mod test {
447 use super::*;
448
449 #[test]
450 fn test_opcode() {
451 println!("opcode {} \n", Opcode::POP);
452 }
453
454 #[test]
455 fn test_instruction() {
456 let mut i = Instruction::new(
457 Opcode::ADD,
458 Some(ValueType::Str),
459 Some(ValueType::Closure),
460 Some(ValueType::Int),
461 Some(-99),
462 );
463 assert_eq!(i.op(), Opcode::ADD);
464 assert_eq!(i.t0(), ValueType::Str);
465 assert_eq!(i.t1(), ValueType::Closure);
466 assert_eq!(i.t2(), ValueType::Int);
467 assert_eq!(i.imm(), -99);
468
469 dbg!(1 << 8);
470 i.set_imm824(-128, -(1 << 23));
471 assert_eq!(i.imm824().0, -128);
472 assert_eq!(i.imm824().1, -(1 << 23));
473 i.set_imm824(127, 1 << 23 - 1);
474 assert_eq!(i.imm824().0, 127);
475 assert_eq!(i.imm824().1, 1 << 23 - 1);
476
477 assert!(!Instruction::in_8bit_range(128));
478 i.set_t2_with_index(-128);
479 assert_eq!(i.t2_as_index(), -128);
480 let _ = i.set_t2_with_index(90);
481 assert_eq!(i.t2_as_index(), 90);
482 assert_eq!(i.t0(), ValueType::Str);
483 assert_eq!(i.t1(), ValueType::Closure);
484 assert_ne!(i.t2(), ValueType::Int);
485 assert_eq!(i.imm824().0, 127);
486 assert_eq!(i.imm824().1, 1 << 23 - 1);
487 }
488}