Merge remote-tracking branch 'home/v4' into v4
All checks were successful
Build / build (push) Successful in 3m9s
All checks were successful
Build / build (push) Successful in 3m9s
This commit is contained in:
commit
43d2f365b9
113
content/mimiumの中間表現を考える.md
Normal file
113
content/mimiumの中間表現を考える.md
Normal file
@ -0,0 +1,113 @@
|
||||
---
|
||||
date: 2024-06-08 22:40
|
||||
---
|
||||
#memo #mimium
|
||||
|
||||
まあいつものサンプルを考える
|
||||
|
||||
```rust
|
||||
fn fbdelay(input:float,fb:float,dtime:float)->float{
|
||||
return input + delay(self,dtime)*fb
|
||||
}
|
||||
|
||||
fn twodelay (input:float,dtime:float)->float{
|
||||
return fbdelay(input,dtime,0.7)+fbdelay(input,dtime*2,0.8)
|
||||
}
|
||||
|
||||
fn dsp (input:float)->float{
|
||||
return twodelay(input,400)+twodelay(input,800)
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
コールツリーとしては
|
||||
```
|
||||
dsp
|
||||
| |
|
||||
twodelay(1) twodelay(2)
|
||||
| | | |
|
||||
fbdelay(1) fbdelay(2) fbdelay(3) fbdelay(4)
|
||||
| | | |
|
||||
delay,feed, delay,feed delay,feed delay,feed
|
||||
|
||||
```
|
||||
|
||||
- 実行中のVMから見れば、簡約されたあとにfeedの項が置き換えられて出てくるわけではない
|
||||
- 関数の定義にジャンプしてみて初めてfeedが現れる
|
||||
- しかし、そのfeedがどこの情報を保持しているかは呼び出し元の情報が必要
|
||||
- コール元の情報を関数の引数として渡す、というのが前とったやり方
|
||||
- feedのコールツリーを持つやり方はポインタを辿ってく形になるのであんまやりたくない
|
||||
- VMがクロージャをsetUpvalue/getUpvalueで解決してるような感じで解決できないか
|
||||
- callの命令は今call、callCls、callExtの3種類存在
|
||||
- これはVM上の参照するテーブルが違うので必要
|
||||
|
||||
- 例えば、VMマシン側に、`feed_baseptr`みたいな情報を持っておく
|
||||
- callのオペランドの中にこのbaseptrからのオフセットバイト数を含めるようにする
|
||||
- いや、コンパイル時、call命令の前にsetFeedAddressみたいな命令を差し込めばそれでいいのか
|
||||
- で、delay命令が来たときは現在のアドレスから必要な長さをリングバッファとして使用する
|
||||
- getfeed命令が来たときは現在のアドレスからその型分のバイト数を取り出して、、、どうする?
|
||||
- 即値用の、getfeedfloatと、それ以外のgetfeedptrは分けたほうがいいな
|
||||
- call命令、delay、getfeed命令が終わるたびにbaseptrの場所は戻される
|
||||
- いや、最後にsetfeedしなきゃいけないからself用のbaseptrに戻す必要があるのかな
|
||||
- 場合によってはdelayの結構長いタイム分をオフセットしないといけないわけだから、命令長が足りなくならんかこれ
|
||||
- オフセットの値を即値でやるのと、レジスタからロードする2パターンの命令持っておけば良い
|
||||
|
||||
|
||||
まあこんな感じで行けそう
|
||||
|
||||
```
|
||||
fn fbdelay(input,fb,dtime){
|
||||
// reg: input,fb,dtime
|
||||
getfeedfloat // load feed to reg3
|
||||
pushfeedoffset 8 // shift feed_base by 64bit
|
||||
delay 3 2 4// write feed and pop head from dtime address offset, push to reg4
|
||||
mulF 4 2 5// multiplay result of delay(reg4) and fb(reg2)
|
||||
addF 0 5 6
|
||||
popfeedoffset 8 // shift feed_base by 64bit
|
||||
setfeed 6
|
||||
return 6
|
||||
}
|
||||
|
||||
fn twodelay (input,dtime){
|
||||
// reg:input,dtime
|
||||
movConst 'fbdelay' 2
|
||||
mov 0 3
|
||||
mov 1 4
|
||||
movConst '0.7' 5
|
||||
call 2 3 1 //reg2 is result of fbdelay
|
||||
mov 1 3
|
||||
movConst '2.0' 4
|
||||
mulF 3 4 5
|
||||
mov 5 3
|
||||
movConst 'fbdelay' 4
|
||||
mov 0 5
|
||||
mov 3 6
|
||||
movConst '0.8' 7
|
||||
pushfeedoffset 8
|
||||
call 4 3 1 //reg4 is result of second fbdelay
|
||||
popfeedoffset
|
||||
addF 2 4 5
|
||||
return 5
|
||||
}
|
||||
|
||||
fn dsp (input){
|
||||
movConst 'twodelay' 1
|
||||
mov 0 2
|
||||
movConst '400' 3
|
||||
call 1 2 1 //reg1 is result of twodelay
|
||||
movConst 'twodelay' 2
|
||||
mov 0 3
|
||||
movConst '800' 4
|
||||
pushfeedoffset 8
|
||||
call 2 2 1
|
||||
addf 1 2 3
|
||||
return 3
|
||||
}
|
||||
```
|
||||
|
||||
delayはどうしておくかというと、最初の8バイトは現在のリングバッファの位置、残りをメモリという扱いにすれば良い。ただメモリのサイズを決定すんのがなあ〜
|
||||
|
||||
|
||||
中間表現では関数呼び出し、即値の読み込みはラベル使ってやるので十分かあ
|
||||
そうなるとローカルの名前リネームは必要
|
||||
|
@ -378,4 +378,6 @@ fn doubleosc(freq)->freq{
|
||||
let res = cascade_f(3,0.9,input)+doubleosc(440)
|
||||
```
|
||||
|
||||
なんかこんな感じだとして、レキシカルに何番目の関数呼び出しか、
|
||||
なんかこんな感じだとして、レキシカルに何番目の関数呼び出しか、
|
||||
|
||||
[[mimiumの中間表現を考える]]
|
Loading…
Reference in New Issue
Block a user