1use core::slice;
2use slotmap::{DefaultKey, SlotMap};
3use std::{cell::RefCell, cmp::Ordering, collections::HashMap, ops::Range, rc::Rc};
4pub mod bytecode;
5pub mod program;
6mod ringbuffer;
7pub use bytecode::*;
8use ringbuffer::Ringbuffer;
9
10use program::OpenUpValue;
11pub use program::{FuncProto, Program};
12
13use crate::{
14 compiler::bytecodegen::ByteCodeGenerator,
15 interner::Symbol,
16 plugin::{ExtClsInfo, ExtClsType, ExtFunInfo, ExtFunType, MachineFunction},
17 runtime::vm::program::WordSize,
18 types::{Type, TypeSize},
19};
20pub type RawVal = u64;
21pub type ReturnCode = i64;
22
23#[derive(Debug, Default, PartialEq)]
24struct StateStorage {
25 pos: usize,
26 rawdata: Vec<u64>,
27}
28impl StateStorage {
29 fn resize(&mut self, size: usize) {
30 self.rawdata.resize(size, 0)
31 }
32 fn get_state(&self, size: u64) -> &[RawVal] {
33 unsafe {
34 let head = self.rawdata.as_ptr().add(self.pos);
35 slice::from_raw_parts(head, size as _)
36 }
37 }
38 fn get_state_mut(&mut self, size: usize) -> &mut [RawVal] {
39 unsafe {
40 let head = self.rawdata.as_mut_ptr().add(self.pos);
41 slice::from_raw_parts_mut(head, size as _)
42 }
43 }
44 fn get_as_ringbuffer(&mut self, size_in_samples: u64) -> Ringbuffer<'_> {
45 let data_head = unsafe { self.rawdata.as_mut_ptr().add(self.pos) };
46 Ringbuffer::new(data_head, size_in_samples)
47 }
48 fn push_pos(&mut self, offset: StateOffset) {
49 self.pos = (self.pos as u64 + (std::convert::Into::<u64>::into(offset))) as usize;
50 }
51 fn pop_pos(&mut self, offset: StateOffset) {
52 self.pos = (self.pos as u64 - (std::convert::Into::<u64>::into(offset))) as usize;
53 }
54}
55
56#[derive(Debug, Clone, Copy, PartialEq, Eq)]
57pub struct ClosureIdx(pub slotmap::DefaultKey);
58
59#[derive(Debug, Clone, Default)]
60struct StateStorageStack(Vec<ClosureIdx>);
61
62impl StateStorageStack {
63 pub fn push(&mut self, i: ClosureIdx) {
64 self.0.push(i)
65 }
66 pub fn pop(&mut self) {
67 let _ = self.0.pop();
68 }
69}
70
71#[derive(Debug, Clone, Default)]
72pub(crate) struct ArrayHeap {
73 elem_word_size: u64,
74 data: Vec<RawVal>,
75}
76impl ArrayHeap {
77 pub fn get_length_array(&self) -> u64 {
78 self.data.len() as u64 / self.elem_word_size
79 }
80 pub fn get_elem_word_size(&self) -> u64 {
81 self.elem_word_size
82 }
83 pub fn get_data(&self) -> &[RawVal] {
84 &self.data
85 }
86 pub fn get_data_mut(&mut self) -> &mut [RawVal] {
87 &mut self.data
88 }
89}
90#[derive(Debug, Clone, Default)]
91pub(crate) struct ArrayStorage {
92 data: SlotMap<DefaultKey, ArrayHeap>,
93}
94pub(crate) type ArrayIdx = slotmap::DefaultKey;
95impl ArrayStorage {
96 pub fn alloc_array(&mut self, len: u64, elem_size: u64) -> RawVal {
97 let array = ArrayHeap {
98 elem_word_size: elem_size,
99 data: vec![0u64; (len * elem_size) as usize],
100 };
101 let key = self.data.insert(array);
102 debug_assert!(
103 std::mem::size_of::<ArrayIdx>() == 8,
104 "ArrayIdx size must be 8 bytes"
105 );
106 unsafe { std::mem::transmute_copy::<ArrayIdx, RawVal>(&key) }
107 }
108 pub fn get_array(&self, id: RawVal) -> &ArrayHeap {
109 let key: ArrayIdx = unsafe { std::mem::transmute_copy::<RawVal, ArrayIdx>(&id) };
110 self.data.get(key).expect("Invalid ArrayIdx")
111 }
112 pub fn get_array_mut(&mut self, id: RawVal) -> &mut ArrayHeap {
113 let key: ArrayIdx = unsafe { std::mem::transmute_copy::<RawVal, ArrayIdx>(&id) };
114 self.data.get_mut(key).expect("Invalid ArrayIdx")
115 }
116}
117#[derive(Debug, Clone, PartialEq)]
120enum UpValue {
121 Open(OpenUpValue),
122 Closed(Vec<RawVal>, bool),
123}
124type SharedUpValue = Rc<RefCell<UpValue>>;
125impl From<OpenUpValue> for UpValue {
126 fn from(value: OpenUpValue) -> Self {
127 Self::Open(value)
128 }
129}
130
131#[derive(Default)]
132struct LocalUpValueMap(Vec<(Reg, SharedUpValue)>);
133
134impl LocalUpValueMap {
135 pub fn get_or_insert(&mut self, ov: OpenUpValue) -> SharedUpValue {
136 let OpenUpValue { pos, .. } = ov;
137 self.0
138 .iter()
139 .find_map(|(i2, v)| (pos == *i2 as _).then_some(v.clone()))
140 .unwrap_or_else(|| {
141 let v = Rc::new(RefCell::new(UpValue::Open(ov)));
142 self.0.push((pos as Reg, v.clone()));
143 v
144 })
145 }
146}
147
148#[derive(Debug, Default, PartialEq)]
149pub struct Closure {
151 pub fn_proto_pos: usize, pub base_ptr: u64, pub is_closed: bool,
154 pub refcount: u64,
155 pub(self) upvalues: Vec<SharedUpValue>,
156 state_storage: StateStorage,
157}
158impl Closure {
159 pub(self) fn new(
160 program: &Program,
161 base_ptr: u64,
162 fn_i: usize,
163 upv_map: &mut LocalUpValueMap,
164 ) -> Self {
165 let fnproto = &program.global_fn_table[fn_i].1;
166 let upvalues = fnproto
167 .upindexes
168 .iter()
169 .map(|ov| upv_map.get_or_insert(*ov))
170 .collect::<Vec<_>>();
171 let mut state_storage = StateStorage::default();
172 state_storage.resize(fnproto.state_skeleton.total_size() as usize);
173 Self {
174 fn_proto_pos: fn_i,
175 upvalues,
176 is_closed: false,
177 refcount: 1,
178 base_ptr,
179 state_storage,
180 }
181 }
182}
183
184pub type ClosureStorage = SlotMap<DefaultKey, Closure>;
185pub fn drop_closure(storage: &mut ClosureStorage, id: ClosureIdx) {
186 let cls = storage.get_mut(id.0).unwrap();
187 cls.refcount -= 1;
188 if cls.refcount == 0 {
189 let c_cls = storage
190 .get_mut(id.0)
191 .unwrap()
192 .upvalues
193 .iter()
194 .map(|v| {
195 let v = v.borrow();
196 if let UpValue::Closed(v, _) = &v as &UpValue {
197 let cls_i = Machine::get_as::<ClosureIdx>(v[0]);
198 Some(cls_i)
199 } else {
200 None
201 }
202 })
203 .collect::<Vec<_>>();
204 c_cls.iter().filter_map(|i| *i).for_each(|clsi| {
205 drop_closure(storage, clsi);
206 });
207 storage.remove(id.0);
208 }
209}
210
211#[derive(Clone, Copy, Default)]
212enum RawValType {
213 Float,
214 #[default]
215 Int,
216 }
218
219#[derive(Clone, Copy)]
220enum ExtFnIdx {
221 Fun(usize),
222 Cls(usize),
223}
224pub struct Machine {
230 pub prog: Program,
232 stack: Vec<RawVal>,
233 base_pointer: u64,
234 pub closures: ClosureStorage,
235 pub ext_fun_table: Vec<(Symbol, ExtFunType)>,
236 pub ext_cls_table: Vec<(Symbol, ExtClsType)>,
237 pub arrays: ArrayStorage,
238 fn_map: HashMap<usize, ExtFnIdx>, global_states: StateStorage,
241 states_stack: StateStorageStack,
242 delaysizes_pos_stack: Vec<usize>,
243 global_vals: Vec<RawVal>,
244 debug_stacktype: Vec<RawValType>,
245}
246
247macro_rules! binop {
248 ($op:tt,$t:ty, $dst:expr,$src1:expr,$src2:expr,$self:ident) => {
249 {
250 $self.set_stacktype($dst as i64, RawValType::Float);
251 $self.set_stack($dst as i64, Self::to_value::<$t>(
252 Self::get_as::<$t>($self.get_stack($src1 as i64))
253 $op Self::get_as::<$t>($self.get_stack($src2 as i64))))
254 }
255 };
256}
257macro_rules! binop_bool {
258 ($op:tt, $dst:expr,$src1:expr,$src2:expr,$self:ident) => {
259 {
260 $self.set_stacktype($dst as i64, RawValType::Float);
261 let bres:bool =
262 Self::get_as::<f64>($self.get_stack($src1 as i64))
263 $op Self::get_as::<f64>($self.get_stack($src2 as i64));
264 let fres = if bres{
265 1.0f64
266 }else{
267 0.0f64
268 };
269 $self.set_stack($dst as i64,Self::to_value::<f64>(fres))
270 }
271 };
272}
273macro_rules! binop_bool_compose {($op:tt, $dst:expr,$src1:expr,$src2:expr,$self:ident) => {
275 {
276 $self.set_stacktype($dst as i64, RawValType::Float);
277 let bres:bool =
278 Self::get_as::<f64>($self.get_stack($src1 as i64))>0.0
279 $op Self::get_as::<f64>($self.get_stack($src2 as i64))>0.0;
280 let fres = if bres{ 1.0f64 }else{ 0.0f64 };
281 $self.set_stack($dst as i64,Self::to_value::<f64>(fres))
282 }
283 };
284}
285macro_rules! binopmethod {
286 ($op:ident,$t:ty, $dst:expr,$src1:expr,$src2:expr,$self:ident) => {{
287 $self.set_stacktype($dst as i64, RawValType::Float);
288 $self.set_stack(
289 $dst as i64,
290 Self::to_value::<$t>(
291 Self::get_as::<$t>($self.get_stack($src1 as i64))
292 .$op(Self::get_as::<$t>($self.get_stack($src2 as i64))),
293 ),
294 )
295 }};
296}
297macro_rules! uniop {
298 ($op:tt,$t:ty, $dst:expr,$src:expr,$self:ident) => {
299 $self.set_stack($dst as i64,
300 Self::to_value::<$t>(
301 $op Self::get_as::<$t>($self.get_stack($src as i64))))
302 };
303}
304macro_rules! uniop_bool {
305 ($op:tt, $dst:expr,$src:expr,$self:ident) => {{
306 let bres: bool = $op(matches!(
307 Self::get_as::<f64>($self.get_stack($src as i64)).partial_cmp(&0.0),
308 Some(std::cmp::Ordering::Greater)
309 ));
310 let fres = if bres { 1.0f64 } else { 0.0f64 };
311 $self.set_stack($dst as i64, Self::to_value::<f64>(fres))
312 }};
313}
314macro_rules! uniopmethod {
315 ($op:tt,$t:ty, $dst:expr,$src:expr,$self:ident) => {{
316 $self.set_stack(
317 $dst as i64,
318 Self::to_value::<$t>(Self::get_as::<$t>($self.get_stack($src as i64)).$op()),
319 )
320 }};
321}
322
323fn set_vec<T>(vec: &mut Vec<T>, i: usize, value: T)
324where
325 T: Clone + std::default::Default,
326{
327 match i.cmp(&vec.len()) {
328 Ordering::Less => vec[i] = value,
329 Ordering::Equal => vec.push(value),
330 Ordering::Greater => {
331 vec.resize(i, T::default());
332 vec.push(value);
333 }
334 }
335}
336fn set_vec_range<T>(vec: &mut Vec<T>, i: usize, values: &[T])
337where
338 T: std::fmt::Debug + Copy + std::default::Default,
339{
340 let start = i;
344 let end = i + values.len();
345 if end > vec.len() {
346 vec.resize(i, T::default());
347 }
348 match start.cmp(&vec.len()) {
349 Ordering::Less => {
350 let range = i..(i + values.len());
351 for (v, i) in values.iter().zip(range.into_iter()) {
352 vec[i] = *v;
353 }
354 }
355 Ordering::Equal => values.iter().for_each(|v| vec.push(*v)),
356 Ordering::Greater => values.iter().for_each(|v| vec.push(*v)),
357 }
358}
359
360impl Machine {
361 pub fn new(
363 prog: Program,
364 extfns: impl Iterator<Item = ExtFunInfo>,
365 extcls: impl Iterator<Item = Box<dyn MachineFunction>>,
366 ) -> Self {
367 let mut res = Self {
368 prog,
369 stack: vec![],
370 base_pointer: 0,
371 closures: Default::default(),
372 ext_fun_table: vec![],
373 ext_cls_table: vec![],
374 fn_map: HashMap::new(),
375 arrays: ArrayStorage::default(),
377 global_states: Default::default(),
378 states_stack: Default::default(),
379 delaysizes_pos_stack: vec![0],
380 global_vals: vec![],
381 debug_stacktype: vec![RawValType::Int; 255],
382 };
383 extfns.for_each(|ExtFunInfo { name, fun, .. }| {
384 let _ = res.install_extern_fn(name, fun);
385 });
386 extcls.for_each(|machine_function| {
387 let _ = res.install_extern_cls(machine_function.get_name(), machine_function.get_fn());
388 });
389 res.link_functions();
390 res
391 }
392 pub fn new_resume(&self, prog: Program) -> Self {
394 let mut new_vm = Self {
395 prog,
396 stack: vec![],
397 base_pointer: 0,
398 closures: Default::default(),
399 ext_fun_table: vec![],
400 ext_cls_table: vec![],
401 fn_map: HashMap::new(),
402 arrays: ArrayStorage::default(),
404 global_states: Default::default(),
405 states_stack: Default::default(),
406 delaysizes_pos_stack: vec![0],
407 global_vals: vec![],
408 debug_stacktype: vec![RawValType::Int; 255],
409 };
410 new_vm.ext_fun_table = self.ext_fun_table.clone();
413 new_vm.ext_cls_table = self.ext_cls_table.clone();
414 new_vm.global_vals = self.global_vals.clone();
415 new_vm.arrays = self.arrays.clone();
416
417 let new_state = state_tree::update_state_storage(
418 &self.global_states.rawdata,
419 self.prog
420 .get_dsp_state_skeleton()
421 .cloned()
422 .expect("dsp function not found"),
423 new_vm
424 .prog
425 .get_dsp_state_skeleton()
426 .cloned()
427 .expect("dsp function not found"),
428 );
429 match new_state {
430 Ok(Some(s)) => {
431 new_vm.global_states.rawdata = s;
432 }
433 Ok(None) => {
434 log::info!("No state structure change detected. Just copies buffer");
435 new_vm.global_states.rawdata = self.global_states.rawdata.clone();
436 }
437 Err(e) => {
438 log::error!("Failed to migrate global state: {e}");
439 }
440 }
441 new_vm.link_functions();
442 new_vm.execute_main();
443 new_vm
444 }
445 pub fn clear_stack(&mut self) {
446 self.stack.fill(0);
447 }
448 pub fn get_stack(&self, offset: i64) -> RawVal {
449 self.get_stack_range(offset, 1).1[0]
455 }
456 pub fn get_stack_range(&self, offset: i64, word_size: TypeSize) -> (Range<usize>, &[RawVal]) {
457 let addr_start = self.base_pointer as usize + offset as usize;
458 let addr_end = addr_start + word_size as usize;
459 let start = self.stack.as_slice().as_ptr();
460 let slice = unsafe {
461 let vstart = start.add(addr_start);
465 slice::from_raw_parts(vstart, word_size as usize)
466 };
467 (addr_start..addr_end, slice)
468 }
469 pub fn get_stack_range_mut(
470 &mut self,
471 offset: i64,
472 word_size: TypeSize,
473 ) -> (Range<usize>, &mut [RawVal]) {
474 let addr_start = self.base_pointer as usize + offset as usize;
475 let addr_end = addr_start + word_size as usize;
476 let start = self.stack.as_mut_ptr();
477 let slice = unsafe {
478 let vstart = start.add(addr_start);
482 slice::from_raw_parts_mut(vstart, word_size as usize)
483 };
484 (addr_start..addr_end, slice)
485 }
486 pub fn set_stack(&mut self, offset: i64, v: RawVal) {
487 self.set_stack_range(offset, &[v])
488 }
489 pub fn set_stack_range(&mut self, offset: i64, vs: &[RawVal]) {
490 set_vec_range(
494 &mut self.stack,
495 (self.base_pointer as i64 + offset) as usize,
496 vs,
497 )
498 }
499 fn move_stack_range(&mut self, offset: i64, srcrange: Range<usize>) {
500 let dest = (self.base_pointer as i64 + offset) as usize;
501 if srcrange.end > self.stack.len() {
502 self.stack.resize(srcrange.end, 0);
503 }
504 let dest_end = dest + (srcrange.end - srcrange.start);
505 if dest_end > self.stack.len() {
506 self.stack.resize(dest_end, 0);
507 }
508 self.stack.copy_within(srcrange, dest)
509 }
510 fn set_stacktype(&mut self, offset: i64, t: RawValType) {
511 }
517 pub fn get_top_n(&self, n: usize) -> &[RawVal] {
518 let len = self.stack.len();
519 &self.stack[(len - n)..]
520 }
521 fn get_upvalue_offset(upper_base: usize, offset: OpenUpValue) -> usize {
522 upper_base + offset.pos
523 }
524 pub fn get_open_upvalue(
525 &self,
526 upper_base: usize,
527 ov: OpenUpValue,
528 ) -> (Range<usize>, &[RawVal]) {
529 let OpenUpValue { size, .. } = ov;
530 let abs_pos = Self::get_upvalue_offset(upper_base, ov);
532 let end = abs_pos + size as usize;
533 let slice = unsafe {
534 let vstart = self.stack.as_slice().as_ptr().add(abs_pos);
535 slice::from_raw_parts(vstart, size as usize)
536 };
537 (abs_pos..end, slice)
538 }
539 pub fn get_closure(&self, idx: ClosureIdx) -> &Closure {
540 debug_assert!(
541 self.closures.contains_key(idx.0),
542 "Invalid Closure Id referred"
543 );
544 unsafe { self.closures.get_unchecked(idx.0) }
545 }
546 pub(crate) fn get_closure_mut(&mut self, idx: ClosureIdx) -> &mut Closure {
547 debug_assert!(
548 self.closures.contains_key(idx.0),
549 "Invalid Closure Id referred"
550 );
551 unsafe { self.closures.get_unchecked_mut(idx.0) }
552 }
553 fn get_current_state(&mut self) -> &mut StateStorage {
554 if self.states_stack.0.is_empty() {
555 &mut self.global_states
556 } else {
557 let idx = unsafe { self.states_stack.0.last().unwrap_unchecked() };
558 &mut self.get_closure_mut(*idx).state_storage
559 }
560 }
561 fn return_general(&mut self, iret: Reg, nret: Reg) -> &[u64] {
562 let base = self.base_pointer as usize;
563 let iret_abs = base + iret as usize;
564 self.stack
565 .copy_within(iret_abs..(iret_abs + nret as usize), base - 1);
566 self.stack.truncate(base - 1 + nret as usize);
569 let res_slice = self.stack.split_at(base).1;
570 res_slice
571 }
572
573 pub fn get_as<T>(v: RawVal) -> T {
574 unsafe { std::mem::transmute_copy::<RawVal, T>(&v) }
575 }
576 pub fn get_as_array<T>(v: &[RawVal]) -> &[T] {
577 unsafe { std::mem::transmute::<&[RawVal], &[T]>(v) }
578 }
579 pub fn to_value<T>(v: T) -> RawVal {
580 assert_eq!(std::mem::size_of::<T>(), 8);
581 unsafe { std::mem::transmute_copy::<T, RawVal>(&v) }
582 }
583 fn call_function<F>(
584 &mut self,
585 func_pos: u8,
586 _nargs: u8,
587 nret_req: u8,
588 mut action: F,
589 ) -> ReturnCode
590 where
591 F: FnMut(&mut Self) -> ReturnCode,
592 {
593 let offset = (func_pos + 1) as u64;
594 self.delaysizes_pos_stack.push(0);
595 self.base_pointer += offset;
596 let nret = action(self);
597
598 if nret_req > nret as u8 {
599 panic!("invalid number of return value {nret_req} required but accepts only {nret}.");
600 }
601 self.stack
603 .truncate((self.base_pointer as i64 + nret_req as i64) as usize);
604 self.base_pointer -= offset;
605 self.delaysizes_pos_stack.pop();
606 nret
607 }
608 fn allocate_closure(&mut self, fn_i: usize, upv_map: &mut LocalUpValueMap) -> ClosureIdx {
609 let idx = self
610 .closures
611 .insert(Closure::new(&self.prog, self.base_pointer, fn_i, upv_map));
612 ClosureIdx(idx)
613 }
614 pub fn wrap_extern_cls(&mut self, extcls: ExtClsInfo) -> ClosureIdx {
618 let ExtClsInfo { name, fun, ty } = extcls;
619
620 self.prog.ext_fun_table.push((name.to_string(), ty));
621 let prog_funid = self.prog.ext_fun_table.len() - 1;
622 self.ext_cls_table.push((name, fun));
623 let vm_clsid = self.ext_cls_table.len() - 1;
624 self.fn_map.insert(prog_funid, ExtFnIdx::Cls(vm_clsid));
625 let (bytecodes, nargs, nret) = if let Type::Function { arg, ret } = ty.to_type() {
626 let mut wrap_bytecode = Vec::<Instruction>::new();
627 let asize = ByteCodeGenerator::word_size_for_type(arg);
629 let nargs = match arg.to_type() {
631 Type::Tuple(args) => args.len(),
632 Type::Record(fields) => fields.len(),
633 _ => unreachable!("single argument should be 1 element record"),
634 } as u8;
635 let base = nargs as u8;
636 let nret = ByteCodeGenerator::word_size_for_type(ret);
637 wrap_bytecode.push(Instruction::MoveConst(base, 0));
638 wrap_bytecode.push(Instruction::MoveRange(base + 1, 0, asize));
639
640 wrap_bytecode.extend_from_slice(&[
641 Instruction::CallExtFun(base, nargs, nret as _),
642 Instruction::Return(base, nret as _),
643 ]);
644 (wrap_bytecode, nargs, nret)
645 } else {
646 panic!("non-function type called for wrapping external closure");
647 };
648 let newfunc = FuncProto {
649 nparam: nargs as _,
650 nret: nret as _,
651 bytecodes,
652 constants: vec![prog_funid as _],
653 ..Default::default()
654 };
655 self.prog.global_fn_table.push((name.to_string(), newfunc));
656 let fn_i = self.prog.global_fn_table.len() - 1;
657 let mut cls = Closure::new(
658 &self.prog,
659 self.base_pointer,
660 fn_i,
661 &mut LocalUpValueMap(vec![]),
662 );
663 cls.is_closed = true;
665 let idx = self.closures.insert(cls);
666 ClosureIdx(idx)
667 }
668 fn close_upvalues(&mut self, src: Reg) {
669 let clsidx = Self::get_as::<ClosureIdx>(self.get_stack(src as _));
670
671 let clsidxs = self
672 .get_closure(clsidx)
673 .upvalues
674 .iter()
675 .map(|upv| {
676 let upv = &mut *upv.borrow_mut();
677 match upv {
678 UpValue::Open(ov) => {
679 let (_range, ov_raw) =
680 self.get_open_upvalue(self.base_pointer as usize, *ov);
681 let is_closure = ov.is_closure;
682 *upv = UpValue::Closed(ov_raw.to_vec(), is_closure);
683 is_closure.then_some(Self::get_as::<ClosureIdx>(ov_raw[0]))
684 }
685 UpValue::Closed(v, is_closure) => {
686 is_closure.then_some(Self::get_as::<ClosureIdx>(v[0]))
687 }
688 }
689 })
690 .collect::<Vec<_>>();
691 clsidxs.iter().for_each(|i| {
692 if let Some(ci) = i {
693 let cls = self.get_closure_mut(*ci);
694 cls.refcount += 1;
695 }
696 });
697 let cls = self.get_closure_mut(clsidx);
698 cls.is_closed = true;
699 }
700 fn release_open_closures(&mut self, local_closures: &[ClosureIdx]) {
701 for clsidx in local_closures.iter() {
702 let cls = self.get_closure(*clsidx);
703 if !cls.is_closed {
704 drop_closure(&mut self.closures, *clsidx)
706 }
707 }
708 }
709 fn get_fnproto(&self, func_i: usize) -> &FuncProto {
710 &self.prog.global_fn_table[func_i].1
711 }
712 pub fn execute(&mut self, func_i: usize, cls_i: Option<ClosureIdx>) -> ReturnCode {
719 let mut local_closures: Vec<ClosureIdx> = vec![];
720 let mut upv_map = LocalUpValueMap::default();
721 let mut pcounter = 0;
722 loop {
727 let mut increment = 1;
747 match self.get_fnproto(func_i).bytecodes[pcounter] {
748 Instruction::Move(dst, src) => {
749 self.set_stack(dst as i64, self.get_stack(src as i64));
750 }
751 Instruction::MoveConst(dst, pos) => {
752 self.set_stack(dst as i64, self.get_fnproto(func_i).constants[pos as usize]);
753 }
754 Instruction::MoveImmF(dst, v) => {
755 self.set_stack(dst as i64, Self::to_value(Into::<f64>::into(v)));
756 }
757 Instruction::MoveRange(dst, src, n) => {
758 let (range, _slice) = self.get_stack_range(src as _, n);
759 self.move_stack_range(dst as i64, range);
760 }
761 Instruction::CallCls(func, nargs, nret_req) => {
762 let addr = self.get_stack(func as i64);
763 let cls_i = Self::get_as::<ClosureIdx>(addr);
764 let cls = self.get_closure(cls_i);
765 let pos_of_f = cls.fn_proto_pos;
766 self.states_stack.push(cls_i);
767 self.call_function(func, nargs, nret_req, move |machine| {
768 machine.execute(pos_of_f, Some(cls_i))
769 });
770 self.states_stack.pop();
771 }
772 Instruction::Call(func, nargs, nret_req) => {
773 let pos_of_f = Self::get_as::<usize>(self.get_stack(func as i64));
774 self.call_function(func, nargs, nret_req, move |machine| {
775 machine.execute(pos_of_f, None)
776 });
777 }
778 Instruction::CallExtFun(func, nargs, nret_req) => {
779 let ext_fn_idx = self.get_stack(func as i64) as usize;
780 let fidx = self.fn_map.get(&ext_fn_idx).unwrap();
781 let nret = match fidx {
782 ExtFnIdx::Fun(fi) => {
783 let f = self.ext_fun_table[*fi].1;
784 self.call_function(func, nargs, nret_req, f)
785 }
786 ExtFnIdx::Cls(ci) => {
787 let (_name, cls) = &self.ext_cls_table[*ci];
788 let cls = cls.clone();
789 self.call_function(func, nargs, nret_req, move |machine| {
790 cls.borrow_mut()(machine)
791 })
792 }
793 };
794
795 let base = self.base_pointer as usize;
797 let iret = base + func as usize + 1;
798 self.stack
799 .copy_within(iret..(iret + nret as usize), base + func as usize);
800 self.stack.truncate(base + func as usize + nret as usize);
801 }
802 Instruction::Closure(dst, fn_index) => {
803 let fn_proto_pos = self.get_stack(fn_index as i64) as usize;
804 let vaddr = self.allocate_closure(fn_proto_pos, &mut upv_map);
805 local_closures.push(vaddr);
806 self.set_stack(dst as i64, Self::to_value(vaddr));
807 }
808 Instruction::Close(src) => {
809 self.close_upvalues(src);
810 }
811 Instruction::Return0 => {
812 self.stack.truncate((self.base_pointer - 1) as usize);
813 self.release_open_closures(&local_closures);
814 return 0;
815 }
816 Instruction::Return(iret, nret) => {
817 let _ = self.return_general(iret, nret);
818 self.release_open_closures(&local_closures);
819 return nret.into();
820 }
821 Instruction::GetUpValue(dst, index, _size) => {
822 {
823 let up_i = cls_i.unwrap();
824 let cls = self.get_closure(up_i);
825 let upvalues = &cls.upvalues;
826 let rv = &upvalues[index as usize];
827 let vs = match &*rv.borrow() {
828 UpValue::Open(i) => {
829 let upper_base = cls.base_ptr as usize;
830 let (_range, rawv) = self.get_open_upvalue(upper_base, *i);
831 let rawv: &[RawVal] = unsafe { std::mem::transmute(rawv) };
836 rawv
837 }
838 UpValue::Closed(rawval, _) => {
839 let rawv: &[RawVal] =
841 unsafe { std::mem::transmute(rawval.as_slice()) };
842 rawv
843 }
845 };
846 self.set_stack_range(dst as i64, vs);
847 };
848 }
849 Instruction::SetUpValue(index, src, size) => {
850 let up_i = cls_i.unwrap();
851 let cls = self.get_closure(up_i);
852 let upper_base = cls.base_ptr as usize;
853 let upvalues = &cls.upvalues;
854 let (_range, v) = self.get_stack_range(src as i64, size);
855 let rv = &mut *upvalues[index as usize].borrow_mut();
856 match rv {
857 UpValue::Open(OpenUpValue { pos: i, size, .. }) => {
858 let (range, _v) = self.get_stack_range(src as i64, *size);
859 let dest = upper_base + *i;
860 unsafe {
861 let dst = slice::from_raw_parts_mut(
863 std::mem::transmute::<*const RawVal, *mut RawVal>(
864 self.stack.as_ptr(),
865 ),
866 self.stack.len(),
867 );
868 dst.copy_within(range, dest);
869 }
870 }
871 UpValue::Closed(uv, _) => {
872 uv.as_mut_slice().copy_from_slice(v);
873 }
874 };
875 }
876 Instruction::GetGlobal(dst, gid, size) => {
877 let gvs = unsafe {
878 let vstart = self.global_vals.as_ptr().offset(gid as _);
879 debug_assert!(!vstart.is_null());
880 slice::from_raw_parts(vstart, size as _)
882 };
883 self.set_stack_range(dst as i64, gvs)
884 }
885 Instruction::SetGlobal(gid, src, size) => {
886 let gvs = unsafe {
887 let vstart = self.global_vals.as_mut_ptr().offset(gid as _);
888 debug_assert!(!vstart.is_null());
889 slice::from_raw_parts_mut(vstart, size as _)
891 };
892 let (_, slice) = self.get_stack_range(src as i64, size);
893 gvs.copy_from_slice(slice);
894 }
895 Instruction::Jmp(offset) => {
896 increment = offset;
898 }
899 Instruction::JmpIfNeg(cond, offset) => {
900 let cond_v = self.get_stack(cond as i64);
901 if Self::get_as::<f64>(cond_v) <= 0.0 {
902 increment = offset;
903 }
904 }
905 Instruction::AddF(dst, src1, src2) => binop!(+,f64,dst,src1,src2,self),
906 Instruction::SubF(dst, src1, src2) => {
907 binop!(-,f64,dst,src1,src2,self)
908 }
909 Instruction::MulF(dst, src1, src2) => binop!(*,f64,dst,src1,src2,self),
910 Instruction::DivF(dst, src1, src2) => binop!(/,f64,dst,src1,src2,self),
911 Instruction::ModF(dst, src1, src2) => binop!(%,f64,dst,src1,src2,self),
912 Instruction::NegF(dst, src) => uniop!(-,f64,dst,src,self),
913 Instruction::AbsF(dst, src) => uniopmethod!(abs, f64, dst, src, self),
914 Instruction::SqrtF(dst, src) => uniopmethod!(sqrt, f64, dst, src, self),
915 Instruction::SinF(dst, src) => uniopmethod!(sin, f64, dst, src, self),
916 Instruction::CosF(dst, src) => uniopmethod!(cos, f64, dst, src, self),
917 Instruction::PowF(dst, src1, src2) => {
918 binopmethod!(powf, f64, dst, src1, src2, self)
919 }
920 Instruction::LogF(dst, src) => uniopmethod!(ln, f64, dst, src, self),
921 Instruction::AddI(dst, src1, src2) => binop!(+,i64,dst,src1,src2,self),
922 Instruction::SubI(dst, src1, src2) => binop!(-,i64,dst,src1,src2,self),
923 Instruction::MulI(dst, src1, src2) => binop!(*,i64,dst,src1,src2,self),
924 Instruction::DivI(dst, src1, src2) => binop!(/,i64,dst,src1,src2,self),
925 Instruction::ModI(dst, src1, src2) => binop!(%,i64,dst,src1,src2,self),
926 Instruction::NegI(dst, src) => uniop!(-,i64,dst,src,self),
927 Instruction::AbsI(dst, src) => uniopmethod!(abs, i64, dst, src, self),
928 Instruction::PowI(dst, lhs, rhs) => binop!(^,i64,dst,lhs,rhs,self),
929 Instruction::LogI(_, _, _) => todo!(),
930 Instruction::Not(dst, src) => uniop_bool!(!, dst, src, self),
931 Instruction::Eq(dst, src1, src2) => binop_bool!(==,dst,src1,src2,self),
932 Instruction::Ne(dst, src1, src2) => binop_bool!(!=,dst,src1,src2,self),
933 Instruction::Gt(dst, src1, src2) => binop_bool!(>,dst,src1,src2,self),
934 Instruction::Ge(dst, src1, src2) => binop_bool!(>=,dst,src1,src2,self),
935 Instruction::Lt(dst, src1, src2) => binop_bool!(<,dst,src1,src2,self),
936 Instruction::Le(dst, src1, src2) => binop_bool!(<=,dst,src1,src2,self),
937 Instruction::And(dst, src1, src2) => binop_bool_compose!(&&,dst,src1,src2,self),
938 Instruction::Or(dst, src1, src2) => binop_bool_compose!(||,dst,src1,src2,self),
939 Instruction::CastFtoI(dst, src) => self.set_stack(
940 dst as i64,
941 Self::to_value::<i64>(Self::get_as::<f64>(self.get_stack(src as i64)) as i64),
942 ),
943 Instruction::CastItoF(dst, src) => self.set_stack(
944 dst as i64,
945 Self::to_value::<f64>(Self::get_as::<i64>(self.get_stack(src as i64)) as f64),
946 ),
947 Instruction::CastItoB(dst, src) => self.set_stack(
948 dst as i64,
949 Self::to_value::<bool>(Self::get_as::<i64>(self.get_stack(src as i64)) != 0),
950 ),
951 Instruction::AllocArray(dst, len, elem_size) => {
952 let key = self.arrays.alloc_array(len as _, elem_size as _);
954 self.set_stack(dst as i64, key);
956 }
957 Instruction::GetArrayElem(dst, arr, idx) => {
958 let array = self.get_stack(arr as i64);
960 let index = self.get_stack(idx as i64);
961 let index_val = Self::get_as::<f64>(index);
962 let adata = self.arrays.get_array(array);
963 let elem_word_size = adata.elem_word_size as usize;
964 let buffer = unsafe {
965 let address = adata
966 .data
967 .as_ptr()
968 .wrapping_add(index_val as usize * elem_word_size);
969 std::slice::from_raw_parts(address, elem_word_size)
970 };
971 set_vec_range(
972 &mut self.stack,
973 (self.base_pointer + dst as u64) as usize,
974 buffer,
975 );
976 }
978 Instruction::SetArrayElem(arr, idx, val) => {
979 let array = self.get_stack(arr as i64);
981 let index = self.get_stack(idx as i64);
982 let index_val = Self::get_as::<f64>(index);
983 let index_int = index_val as usize;
984 let adata = self.arrays.get_array_mut(array);
985 let elem_word_size = adata.elem_word_size as usize;
986 let buffer = unsafe {
987 let address = adata
988 .data
989 .as_mut_ptr()
990 .wrapping_add(index_int * elem_word_size);
991 std::slice::from_raw_parts_mut(address, elem_word_size)
992 };
993 let (_range, buf_src) = self.get_stack_range(val as _, elem_word_size as _);
994 buffer.copy_from_slice(buf_src);
995 }
996 Instruction::GetState(dst, size) => {
997 let v: &[RawVal] = unsafe {
999 std::mem::transmute(self.get_current_state().get_state(size as _))
1000 };
1001 self.set_stack_range(dst as i64, v);
1002 }
1003 Instruction::SetState(src, size) => {
1004 let vs = {
1005 let (_range, v) = self.get_stack_range(src as i64, size as _);
1006 unsafe { std::mem::transmute::<&[RawVal], &[RawVal]>(v) }
1007 };
1008 let dst = self.get_current_state().get_state_mut(size as _);
1009 dst.copy_from_slice(vs);
1010 }
1011 Instruction::PushStatePos(v) => self.get_current_state().push_pos(v),
1012 Instruction::PopStatePos(v) => self.get_current_state().pop_pos(v),
1013 Instruction::Delay(dst, src, time) => {
1014 let i = self.get_stack(src as i64);
1015 let t = self.get_stack(time as i64);
1016 let delaysize_i =
1017 unsafe { self.delaysizes_pos_stack.last().unwrap_unchecked() };
1018
1019 let size_in_samples = unsafe {
1020 *self
1021 .get_fnproto(func_i)
1022 .delay_sizes
1023 .get_unchecked(*delaysize_i)
1024 };
1025 let mut ringbuf = self.get_current_state().get_as_ringbuffer(size_in_samples);
1026
1027 let res = ringbuf.process(i, t);
1028 self.set_stack(dst as i64, res);
1029 }
1030 Instruction::Mem(dst, src) => {
1031 let s = self.get_stack(src as i64);
1032 let ptr = self.get_current_state().get_state_mut(1);
1033 let v = Self::to_value(ptr[0]);
1034 self.set_stack(dst as i64, v);
1035 let ptr = self.get_current_state().get_state_mut(1);
1036 ptr[0] = s;
1037 }
1038 Instruction::Dummy => {
1039 unreachable!()
1040 }
1041 }
1042 pcounter = (pcounter as i64 + increment as i64) as usize;
1043 }
1044 }
1045 pub fn install_extern_fn(&mut self, name: Symbol, f: ExtFunType) -> usize {
1046 self.ext_fun_table.push((name, f));
1047 self.ext_fun_table.len() - 1
1048 }
1049 pub fn install_extern_cls(&mut self, name: Symbol, f: ExtClsType) -> usize {
1050 self.ext_cls_table.push((name, f));
1051 self.ext_cls_table.len() - 1
1052 }
1053
1054 fn link_functions(&mut self) {
1055 let global_mem_size = self
1057 .prog
1058 .global_vals
1059 .iter()
1060 .map(|WordSize(size)| *size as usize)
1061 .sum();
1062 self.global_vals = vec![0; global_mem_size];
1063 self.prog
1064 .ext_fun_table
1065 .iter_mut()
1066 .enumerate()
1067 .for_each(|(i, (name, _ty))| {
1068 if let Some((j, _)) = self
1069 .ext_fun_table
1070 .iter()
1071 .enumerate()
1072 .find(|(_j, (fname, _fn))| name == fname.as_str())
1073 {
1074 let _ = self.fn_map.insert(i, ExtFnIdx::Fun(j));
1075 } else if let Some((j, _)) = self
1076 .ext_cls_table
1077 .iter()
1078 .enumerate()
1079 .find(|(_j, (fname, _fn))| name == fname.as_str())
1080 {
1081 let _ = self.fn_map.insert(i, ExtFnIdx::Cls(j));
1082 } else {
1083 panic!("external function {} cannot be found", name);
1084 }
1085 });
1086 }
1087 pub fn execute_idx(&mut self, idx: usize) -> ReturnCode {
1088 let (_name, func) = &self.prog.global_fn_table[idx];
1089 if !func.bytecodes.is_empty() {
1090 self.global_states
1091 .resize(func.state_skeleton.total_size() as usize);
1092 if !self.stack.is_empty() {
1094 self.stack[0] = 0;
1095 }
1096 self.base_pointer = 1;
1097 self.execute(idx, None)
1098 } else {
1099 0
1100 }
1101 }
1102 pub fn execute_entry(&mut self, entry: &str) -> ReturnCode {
1103 if let Some(idx) = self.prog.get_fun_index(entry) {
1104 self.execute_idx(idx)
1105 } else {
1106 -1
1107 }
1108 }
1109 pub fn execute_main(&mut self) -> ReturnCode {
1110 self.base_pointer += 1;
1112 self.execute(0, None)
1113 }
1114}
1115
1116#[cfg(test)]
1117mod test;