tomoyanonymous / mimium-rs

minimal musical medium- an infrastructural language for sound and music.
Mozilla Public License 2.0
9 stars 1 forks source link

Conditional stateful function call will not handle shiftstate position properly #71

Open tomoyanonymous opened 1 month ago

tomoyanonymous commented 1 month ago

Continued from #63 .

I found the reason for the bug of the segfault. Function that calls stateful function only on the one side of the if-else branch generate bytecodes that may shift different amount of state position depending on the branch path.

The function bar is compiled to

fn some_self_fun() {
  self + 1.0
}
fn foo() {
  0.0
}
fn bar(){
  let _ = some_self_fun()

  if (1.0) {
    0.0
  } else {
    foo()
  }
}

fn dsp(){
  bar()
}

like this.

fn bar []
upindexes:[]upper:0 state_size: 1(=[number])
  block 0
  reg(9)  := alloc number
  reg(7)  := uint 1
  reg(8)  := call reg(7) [] ->number
  reg(10) := store reg(9), reg(8), number
  reg(11) := float 1
  reg(12) := jmpif reg(11) 1 2 3

  block 1
  reg(13) := float 0

  block 2
             pushstateidx 1(=[number])
  reg(14) := uint 2
  reg(15) := call reg(14) [] ->number

  block 3
  reg(16) := phi reg(13) reg(15)
             popstateidx  1(=[number])
  reg(17) := ret reg(16) number

If the condition was true, pushstate(1) and popstate(1) will be called but only popstate(1) is called when the condition was false.

tomoyanonymous commented 1 month ago

In the current implementation, popstate is inserted at the end of the function with the sum of the statesize within the function, but is should be inserted right after the non-closure function call. Or, maybe new instruction like callstatefulfn address [arguments] statesize should be introduced at the MIR level and push/popstate instruction should be removed.

tomoyanonymous commented 1 month ago

Hmm, I'm thinking a bit more subtle cases like this.

fn dsp(){
 if (random()){
   gen_a() 
 }else{
   gen_b()
}
}

gen_a and gen_b are stateful functions which have a different state size, 4 and 5 respectively for instance.

The state size of the dsp function should be 9 and shiftstate(4) should be inserted at the beginning of else block.

Also, it maybe problematic because only one side of branches are evaluated and then samplerate becomes inconsistent...