en)演算e::=式
c定数
op(e1;:::;en)プリミティブ演算
ife1thene2elsee3条件分岐
letx=e1ine2変数定义
x変数の読み出し
let recxy1:::yn=e1ine2再帰関数定义
e e1: : : en関数呼び出し(e1;:::;en)组の作成
let(x1;:::;xn)=e1ine2组の読み出し
Array:createe1e2配列の作成
e1:(e2)配列の読み出し
e1:(e2)^e3配列への书き込み
図1: MinCamlの抽象构文(型は省略)
1
cは…型の定数
''c:…
''e1:…1: : : ''en:…n
opは…1,:::,…n型の値を受け取って…型の値を返すプリミティブ演算
''op(e1; : : : ; en) :…
''e1:bool ''e2: ''e3:
''ife1thene2elsee3:
''e1: 1 ;x: 1''e2: 2
''letx=e1ine2: 2
(x)=
''x:
; x: 1!:::! n! ; y1: 1;:::;yn: n''e1:
; x: 1!:::! n! ''e2: 0
''let recxy1:::yn=e1ine2: 0
''e: 1!:::! n!
''e1: 1: : : ''en: n
''e e1: : : en:
''e1: 1::: ''en: n
''(e1;:::;en): 1 ::: n
''e1: 1 ::: n ; x1: 1;:::;xn: n''e2:
''let(x1; : : : ; xn) =e1ine2:
''e1:int ''e2:
''Array:createe1e2: array
''e1: array ''e2:int
''e1:(e2) :
''e1: array ''e2:int ''e3:
''e1:(e2)^e3:unit
図3:MinCamlの型つけ规则
e::=
c
op(x1;:::;xn)
ifx=ythene1elsee2
ifx ythene1elsee2
letx=e1ine2
x
letrecx y1: : : yn=e1ine2
x y1: : : yn
(x1;:::;xn)
let(x1; : : : ; xn) =yine
x:(y)
x:(y)^z
図4:MinCamlのK正规形(外部配列 外部関数适用は省略)
2
K:Syntax.t!KNormal.t
K(c)=c
K(not(e))=K(ifethen false else true)
K(e1=e2)=K(ife1=e2thentrueelsefalse)
K(e1 e2)=K(ife1 e2thentrue else false)
K(op(e1; : : : ; en))=letx1=K(e1)in: : :letxn=K(en)inop(x1;:::;xn)
opが论理演算 比较以外の场合
K(if note1thene2elsee3)=K(ife1the3elsee2)
K(ife1=e2thene3elsee4)=letx=K(e1)in lety=K(e2)in
ifx=ythenK(e3)elseK(e4)
K(ife1 e2thene3elsee4)=letx=K(e1)in lety=K(e2)in
ifx ythenK(e3)elseK(e4)
K(ife1thene2elsee3)=K(ife1=false thene3elsee2)
eが论理演算 比较以外の场合
K(letx=e1ine2)=letx=K(e1)inK(e2)
K(x)=x
K(let recxy1:::yn=e1ine2)=let recxy1:::yn=K(e1)inK(e2)
K(e e1: : : en)=letx=K(e)inlety1=K(e1)in:::letyn=K(en)in
x y1: : : yn
K(e1; : : : ; en)=letx1=K(e1)in: : :letxn=K(en)in(x1; : : : ; xn)
K(let(x1;:::;xn)=e1ine2)=lety=K(e1)in let(x1; : : : ; xn) =yinK(e2)
K(Array:createe1e2)=letx=K(e1)in lety=K(e2)in createarrayxy
K(e1:(e2))=letx=K(e1)in lety=K(e2)inx:(y)
K(e1:(e2)^e3)=letx=K(e1)in lety=K(e2)in letz=K(e3)in
x:(y)^z
図5: K正规化(论理値の整数化と,insertletによる最适化は省略).右辺に出现していて左辺に出现
していない変数は,すべて新しい(fresh)とする.
3
fi:Id.t M.t!KNormal.t!KNormal.t
fi"(c)=c
fi"(op(x1;:::;xn))=op("(x1); : : : ; "(xn))
fi"(ifx=ythene1elsee2)=if"(x) ="(y)thenfi"(e1)elsefi"(e2)
fi"(ifx ythene1elsee2)=if"(x) "(y)thenfi"(e1)elsefi"(e2)
fi"(letx=e1ine2)=letx0=fi"(e1)infi";x7!x0(e2)
fi"(x)="(x)
fi"(let recxy1:::yn=e1ine2)=let recx0y0
1: : : y0
n=fi";x7!x0;y17!y0
1;:::;yn7!y0
n
(e1)in
fi";x7!x0(e2)
fi"(xy1:::yn)="(x)"(y1): : : "(yn)
fi"((x1; : : : ; xn))=("(x1);:::;"(xn))
fi"(let(x1;:::;xn)=yine)=let(x0
1; : : : ; x0
n)="(y)infi";x17!x0
1;:::;xn7!x0
n
(e)
fi"(x:(y))="(x):("(y))
fi"(x:(y)^z)="(x):("(y))^"(z)
図6:fi変换."はfi変换前の変数を受け取って,fi変换后の変数を返す写像.右辺に出现していて左辺に
出现していない変数(x0など)は,すべてfreshとする.
:Id.t M.t!KNormal.t!KNormal.t
"(c)=c
"(op(x1;:::;xn))=op("(x1); : : : ; "(xn))
"(ifx=ythene1elsee2)=if"(x) ="(y)then "(e1)else "(e2)
"(ifx ythene1elsee2)=if"(x) "(y)then "(e1)else "(e2)
"(letx=e1ine2)= ";x7!y(e2) "(e1)が変数yの场合
"(letx=e1ine2)=letx= "(e1)in "(e2) "(e1)が変数でない场合
"(x)="(x)
"(letrecx y1: : : yn=e1ine2) =letrecx y1: : : yn= "(e1)in "(e2)
"(xy1:::yn)="(x)"(y1): : : "(yn)
"((x1; : : : ; xn))=("(x1);:::;"(xn))
"(let(x1;:::;xn)=yine)=let(x1;:::;xn)="(y)in "(e)
"(x:(y))="(x):("(y))
"(x:(y)^z)="(x):("(y))^"(z)
図7: 简约."は 简约前の変数を受け取って, 简约后の変数を返す写像."(x)が定义されていない场
合は,"(x)=xとみなす.
4
A:KNormal.t!KNormal.t
A(c)=c
A(op(x1;:::;xn))=op(x1;:::;xn)
A(ifx=ythene1elsee2)=ifx=ythenA(e1)elseA(e2)
A(ifx ythene1elsee2)=ifx ythenA(e1)elseA(e2)
A(letx=e1ine2)=let:::in letx=e0
1inA(e2)
A(e1) =let: : :ine0
1という形で
(let:::inは0个以上のletの列),
e0
1はletでない
A(x)=x
A(let recxy1:::yn=e1ine2)=let recxy1:::yn=A(e1)inA(e2)
A(xy1:::yn)=x y1: : : yn
A((x1; : : : ; xn))=(x1; : : : ; xn)
A(let(x1;:::;xn)=yine)=let(x1;:::;xn)=yinA(e)
A(x:(y))=x:(y)
A(x:(y)^z)=x:(y)^z
図8:ネストしたletの简约
5
I:(Id.t list KNormal.t)M.t!KNormal.t!KNormal.t
I"(c)=c
I"(op(x1;:::;xn))=op(x1;:::;xn)
I"(ifx=ythene1elsee2)=ifx=ythenI"(e1)elseI"(e2)
I"(ifx ythene1elsee2)=ifx ythenI"(e1)elseI"(e2)
I"(letx=e1ine2)=letx=I"(e1)inI"(e2)
I"(x)=x
I"(let recxy1:::yn=e1ine2)="0=";x7!((y1; : : : ; yn);e1)として
letrecx y1: : : yn=I"0(e1)inI"0(e2)
size(e1) thの场合
I"(letrecx y1: : : yn=e1ine2) =letrecx y1: : : yn=I"(e1)inI"(e2)
size(e1)>thの场合
I"(xy1:::yn)=fiy17!z1;:::;yn7!zn(e)"(x) = ((z1;:::;zn); e)の场合
I"(x y1: : : yn)=x y1: : : yn"(x)が定义されていない场合
I"((x1; : : : ; xn))=(x1; : : : ; n)
I"(let(x1; : : : ; xn) =yine)=let(x1; : : : ; xn) =yinI"(e)
I"(x:(y))=x:(y)
I"(x:(y)^z)=x:(y)^z
size(c=1
size(op(x1; : : : ; xn))=1
size(ifx=ythene1elsee2)=1+size(e1) +size(e2)
size(ifx ythene1elsee2)=1+size(e1) +size(e2)
size(letx=e1ine2)= 1 +size(e1)+size(e2)
size(x)=1
size(let recxy1:::yn=e1ine2)=1+size(e1) +size(e2)
size(x y1: : : yn)=1
size((x1; : :: ; xn))=1
size(let(x1; : : : ; xn) =yine)=1+size(e)
size(x:(y))= 1
size(x:(y)^z)= 1
図9:インライン展开."はサイズの小さい関数名を受け取って,仮引数と本体を返す写像.thはインライ
ン展开する関数の最大サイズ(ユーザ指定).
6
F:KNormal.t M.t!KNormal.t!KNormal.t
F"(c)=c
F"(op(x1;:::;xn))=cop("(x1);:::;"(xn))=cの场合
F"(op(x1;:::;xn))=op(x1;:::;x
n)それ以外の场合
F"(ifx=ythene1elsee2)=F"(e1)"(x)と"(y)が等しい定数の场合
F"(ifx=ythene1elsee2)=F"(e2)"(x)と"(y)が异なる定数の场合
F"(ifx=ythene1elsee2)=ifx=ythenF"(e1)elseF"(e2)それ以外の场合
F"(ifx ythene1elsee2)=F"(e1)"(x)と"(y)が定数で,"(x) "(y)の场合
F"(ifx ythene1elsee2)=F"(e2)"(x)と"(y)が定数で,"(x)> "(y)の场合
F"(ifx ythene1elsee2)=ifx ythenF"(e1)elseF"(e2)それ以外の场合
F"(letx=e1ine2)=e0
1=F"(e1)として
letx=e0
1inF";x7!e0
1
(e2)
F"(x)=x
F"(letrecx y1: : : yn=e1ine2) =letrecx y1: : : yn=F"(e1)inF"(e2)
F"(xy1:::yn)=xy1:::yn
F"((x1; : : : ; xn))=(x1; : : : ; xn)
F"(let(x1; : : : ; xn) =yine)=letx1=y1in:::letxn=yninF"(e)
"(y)=(y1; : : : ; yn)の场合
F"(let(x1;:::;xn)=yine)=let(x1;:::;xn)=yinF"(e)
F"(x:(y))=x:(y)
F"(x:(y)^z)=x:(y)^z
図10:定数畳み込み."は変数を受け取って,定数を返す写像.
7
E:KNormal.t!KNormal.t
E(c)=c
E(op(x1;:::;xn))=op(x1;:::;xn)
E(ifx=ythene1elsee2)=ifx=ythenE(e1)elseE(e2)
E(ifx ythene1elsee2)=ifx ythenE(e1)elseE(e2)
E(letx=e1ine2)=E(e2)efiect(E(e1))=falseかつx62FV(E(e2))の场合
E(letx=e1ine2)=letx=E(e1)inE(e2)それ以外の场合
E(x)=x
E(letrecx y1: : : yn=e1ine2) =E(e2)x62FV(E(e2))の场合
E(let recx y1: : : yn=e1ine2) =letrecx y1: : : yn=E(e1)inE(e2)それ以外の场合
E(xy1:::yn)=xy1:::yn
E((x1;:::;xn))= (x1;:::;xn)
E(let(x1; : : : ; xn) =yine)=E(e)fx1;:::;xng\FV(E(e))=;の场合
E(let(x1; : : : ; xn) =yine)=let(x1; : : : ; xn) =yinE(e)それ以外の场合
E(x:(y))=x:(y)
E(x:(y)^z)=x:(y)^z
efiect:KNormal.t!bool
efiect(c)=false
efiect(op(x1; : : : ; xn))=false
efiect(ifx=ythene1elsee2)=efiect(e1)_efiect(e2)
efiect(ifx ythene1elsee2)=efiect(e1)_efiect(e2)
efiect(letx=e1ine2)=efiect(e1)_efiect(e2)
efiect(x)=false
efiect(letrecx y: : : yn=e1ine2) =efiect(e2)
efiect(x y1: : : yn)=true
efiect((x1;:::;xn))=false
efiect(let(x1; : : : ; xn) =yine)=efiect(e)
efiect(x:(y))=false
efiect(x:(y)^z)=true
図11:不要定义削除(1/2)
8
FV:KNormal.t!S.t
FV(c)=;
FV(op(x1;:::;xn))=fx1; : : : ; xng
FV(ifx=ythene1elsee2)=fx; yg[FV(e1)[FV(e2)
FV(ifxythene1elsee2)=fx; yg[FV(e1)[FV(e2)
FV(letx=e1ine2)=FV(e1)[(FV(e2)nfxg)
FV(x)=fxg
FV(letrecx y1: : : n=e1ine2) = ((FV(e1)n fy1;:::;yng)[FV(e2))nfxg
FV(x y1: : : yn)=fx;y1;:::;yng
FV((x1; : : : ; xn))=fx1;:::;xng
FV(let(x1;:::;xn)=yine)=fyg[(FV(e)nfx1; : : : ; xng)
FV(x:(y))=fx; yg
FV(x:(y)^z)=fx;y;zg
図12:不要定义削除(2/2)
P::=プログラム全体
(fD1;:::;Dng; e)トップレベル関数定义の集合とメインルーチンの式
D::=トップレベル関数定义
Lx(y1;:::;ym)(z1; : : : ; zn) =e関数のラベルと仮引数,自由変数,および本体
e::=
c
op(x1; : : : ; xn)
ifx=ythene1elsee2
ifxythene1elsee2
letx=e1ine2
x
makeclosurex= (Lx;(y1;:::;yn))ineクロージャ生成
applyclosure(x; y1; : : : ; yn)クロージャを用いた関数呼び出し
applydirect(Lx; y1; : : : ; yn)クロージャを用いない関数呼び出し(knownfunctioncall)
(x1;:::;xn)
let(x1; : : : ; xn) =yine
x:(y)
x:(y)^z
図13:クロージャ変换后の构文
9
C:KNormal.t!Closure.t
C(c)=c
C(op(x1;:::;xn))=op(x1;:::;xn)
C(ifx=ythene1elsee2)=ifx=ythenC(e1)elseC(e2)
C(ifx ythene1elsee2)=ifx ythenC(e1)elseC(e2)
C(letx=e1ine2)=letx=C(e1)inC(e2)
C(x)=x
C(let recxy1:::yn=e1ine2)=DにLx(y1;:::;yn)(z1; : : : ; zm) =e0
1を加え,
makeclosurex= (Lx;(z1;:::;zm))ine0
2を返す
ただしe0
1=C(e1),e0
2=C(e2),
FV(e0
1)n fx;y1;:::;yng=fz1; : : : ; zmg
C(xy1:::yn)=applyclosure(x; y1; : : : ; yn)
C((x1;:::;xn))= (x1;:::;xn)
C(let(x1; : : : ; xn) =yine)=let(x1; : : : ; xn) =yinC(e)
C(x:(y))=x:(y)
C(x:(y)^z)=x:(y)^z
FV:Closure.t!S.t
FV(c)=;
FV(op(x1; : : : ; xn))=fx1;:::;xng
FV(ifx=ythene1elsee2)=fx;yg [FV(e1)[FV(e2)
FV(ifx ythene1elsee2)=fx;yg [FV(e1)[FV(e2)
FV(letx=e1ine2)=FV(e1)[(FV(e2)nfxg)
FV(x)=fxg
FV(makeclosurex= (Lx;(y1;:::;yn))ine) =fy1;:::;yng[(FV(e)nfxg)
FV(applyclosure(x; y1; : : : ; yn))=fx;y1;:::;yng
FV(applydirect(Lx; y1; : : : ; yn))=fy1;:::;yng
FV((x1; : :: ; xn))=fx1;:::;xng
FV(let(x1; : : : ; xn) =yine)=fyg [(FV(e)n fx1;:::;xng)
FV(x:(y))=fx;yg
FV(x:(y)^z)=fx; y; zg
図14:贤くないClosure変换C(e).Dはトップレベル関数定义の集合を记忆しておくためのグローバル
変数.
10
C:S.t!KNormal.t!Closure.t
Cs(let recxy1:::yn=e1ine2)=DにLx(y1;:::;yn)()=e0
1を加え,
makeclosurex= (Lx;())ine0
2を返す
ただしe0
1=Cs0(e1),e0
2=Cs0(e2),s0=s[fxg,
FV(e0
1)nfy1; : : : ; yng=;の场合
Cs(letrecx y1: : : yn=e1ine2) =DにLx(y1; : : : ; yn)(z1;:::;zm)=e0
1を加え,
makeclosurex= (Lx;(z1;:::;zm))ine0
2を返す
ただしe0
1=Cs(e1),e0
2=Cs(e2),
FV(e0
1)n fy1;:::;yng6=;,
FV(e0
1)nfx; y1; : : : ; yng=fz1;:::;zmgの场合
Cs(x y1: : : yn)=applyclosure(x; y1; : : : ; yn)x62sの场合
Cs(x y1n)=applydirect(Lx; y1; : : : ; yn)x2sの场合
図15:やや贤いClosure変换Cs(e).sは自由変数がないとわかっている関数の名前の集合.
C:S.t!KNormal.t!Closure.t
Cs(let recxy1:::yn=e1ine2) =DにLx(y1; : : : ; yn)() =e0
1を加え,
makeclosurex= (Lx;())ine0
2を返す
ただしe0
1=Cs0(e1),e0
2=Cs0(e2),s0=s[fxg,
FV(e0
1)n fy1;:::;yng=;かつx2FV(e0
2)の场合
Cs(letrecx y1: : : yn=e1ine2) =DにLx(y1; : : : ; yn)() =e0
1を加え,e0
2を返す
ただしe0
1=Cs0(e1),e0
2=Cs0(e2),s0=s[fxg,
FV(e0
1)nfy1; : : : ; yng=;かつx62FV(e0
2)の场合
Cs(let recxy1:::yn=e1ie2)=DにLx(y1;:::;yn)(z1; : : : ; zm) =e0
1を加え,
makeclosurex= (Lx;(z1;:::;zm))ine0
2を返す
ただしe0
1=Cs(e1),e0
2=Cs
(e2),
FV(e0
1)n fy1;:::;yng6=;,
FV(e0
1)nfx; y1; : : : ; yng=fz1;:::;zmgの场合
Cs(x y1: : : yn)=apply
closure(x; y1; : : : ; yn)x62sの场合
Cs(xy1:::yn)=applydirect(Lx; y1; : : : ; yn)x2sの场合
図16:もっと贤いClosure変换Cs(e)
11
P::=
(fD1; : : : ; Dng;E)
D::=
Lx(y1; : : : ; yn) =E
E::=命令の列
x^e;E代入
e返値
e::=式
c即値
Lxラベル
op(x1;:::;xn)算术演算
ifx=ythenE1elseE2比较&分岐
ifx ythenE1elseE2比较&分岐
xmov命令
applyclosure(x; y1; : : : ; yn)クロージャを用いた関数呼び出し
applydirect(Lx; y1; : : : ; yn)クロージャを用いない関数呼び出し
x:(y)ロード
x:(y)^zストア
save(x; y)変数xの値をスタック位置yに退避する
restore(y)スタック位置yから値を复元する
図17:仮想マシンコードの构文
12
V:Closure.prog!SparcAsm.prog
V((fD1; : : : ; Dng;e))=(fV(D1);:::;V(Dn)g;V(e))
V:Closure.fundef!SparcAsm.fundef
V(Lx(y1;:::;yn)(z1; : : : ; zn) =e)=Lx(y1;:::;yn)=z1^R0:(4);:::;zn^R0:(4n);V(e)
V:Closure.t!SparcAsm.t
V(c)=c
V(op(x1;:::;xn))=op(x1;:::;xn)
V(ifx=ythene1elsee2)=ifx=ythenV(e1)elseV(e2)
V(ifx ythene1elsee2)=ifx ythenV(e1)elseV(e2)
V(letx=e1ine2)=x^ V(e1);V(e2)
V(x)=x
V(makeclosurex= (Lx;(y1;:::;yn))ine) =x^Rhp;Rhp^Rhp+4(n+1);z^Lx;x:(0)^z;
x:(4)^y1;:::;x:(4n)^yn;V(e)
V(applyclosure(x; y1; : : : ; yn))=applyclosure(x; y1; : : : ; yn)
V(applydirect(Lx; y1; : : : ; yn))=applydirect(Lx;y1;:::;yn)
V((x1; : : : ; xn))=y^Rhp;Rhp^Rhp+ 4n;
y:(0)^x1;:::;y:(4(n 1))^xn;y
V(let(x1;:::;xn)=yine)fx1; : : : ; xng \FV(e) =fxi1;:::;ximgとして
xi1^y:(4(i1 1));: : :;xim^y:(4(im 1));V(e)
V(x:(y))=y0^4 y;x:(y0)
V(x:(y)^z)=y0^4 y;x:(y0)^z
図18:仮想マシンコード生成V(P),V(D)およびV(e).右辺に出现して左辺に出现しない変数はfresh
とする.Rhpはヒープポインタ(専用レジスタ).e1;e2はダミーの変数xについてx^e1;e2の略记.
x^E1;E2は,E1=(x1^e1;: : :;xn^en;e)として,x1^e1;:::;xn^en;x^e;E2の略记.
13
FV:S.t!SparcAsm.t!S.t
FVs(x^e;E)=s0=FVs(E)nfxgとしてFVs0(e)
FVs(e)=FVs(e)
FV:S.t!SparcAsm.exp!S.t
FVs(c)=s
FVs(Lx)=s
FVs(op(x1; : : : ; xn))=fx1;:::;xng[s
FVs(ifx=ythenE1elseE2) =fx; yg[FVs(E1)[FVs(E2)
FVs(ifx ythenE1elseE2) =fx; yg[FVs(E1)[FVs(E2)
FVs(x)=fxg[s
FVs(applyclosure(x; y1; : : : ; yn)) =fx; y1; : : : ; yng [s
FVs(applydirectLx; y1; : : : ; yn)) =fy1; : : : ; yng [s
FVs(x:(y))=fx;yg [s
FVs(x:(y)^z)=fx; y; zg[s
FVs(save(x; y))=fxg[s
FVs(restore(y))=s
図19:命令の列Eおよび式eにおいて生きている変数の集合FVs(E)およびFVs(e).sはEやeの后で
使われる変数の集合.以后のFV(E)はFV;(E)の略记.
14
R:SparcAsm.prog!SparcAsm.prog
R((fD1; : : : ; Dng;E))=(fR(D1);:::;R(Dn)g;R;(E; x;()))xはダミーのfreshな変数
R:SparcAsm.fundef!SparcAsm.fundef
R(Lx(y1; : : : ; yn) =E)=Lx(R1; : : : ;Rn)=Rx7!R0;y17!R1;:::;yn7!Rn(E;R0;R0)
R:Id.tM.t!SparcAsm.t Id.t SparcAsm.t!SparcAsm.t Id.tM.t
R"((x^e;E);zdest;Econt)=E0
cont=(zdest^E;Econt);
R"(e; x; E0
cont)=(E0; "0);
r62f"0(y)jy2FV(E0
cont)g;
R"0;x7!r(E;zdest;Econt)=(E00; "00)として
((r^E0;E00);"00)xがレジスタでない场合
R"((r^e;E);zdest;Econt)=E0
cont=(zdest^E;Econt);
R"(e; r; E0
cont)=(E0; "0);
R"0(E; zde; Econt) = (E00;"00)として
((r^E0;E00); "00)
R"(e; x; Econt)=R"(e;x;Econt)(次図参照)
図20:単纯なレジスタ割り当てR(P),R(D)およびR"(E; zdest; Econt)."は変数からレジスタへの写
像,zdestはEの结果をセットする変数,EcontはEの后に実行される命令の列.R"(E; x; Econt)の返り
値はレジスタ割り当てされた命令の列E0と,Eの后のレジスタ割り当てを表す写像"0の组.[ファイル
regAlloc.notarget-nospill.ml参照]
15
R:Id.t M.t!SparcAsm.exp Id.t SparcAsm.t!SparcAsm.t Id.t M.t
R"(c; zdest; Econt)=(c; ")
R"(Lx;zdest;Econt)= (Lx;")
R"(op(x1; : : : ; xn);zdest;Econt)= (op("(x1);:::;"(xn)); ")
R"(ifx=ythenE1elseE2;zdest;Econt)=R"(E1;zdest;Econt)=(E0
1;"1);
R"(E2; zdest; Econt) = (E0
2; "2);
"0=fz7!rj"1(z) ="2(z)=rg;
fz1; : : : ; zng=
(FV(Econt)n fzdestgndom("0))\dom(")として
((save("(z1);z1);: : :;save("(zn);zn);
if"(x) "(y)thenE0
1elseE0
2);"0)
R"(ifx ythenE1elseE2;zdest;Econt)=同様
R"(x; zdest; Econt)= ("(x);")
R"(applyclosure(x; y1; : : : ; yn);zdest;Econt)=fz1;:::;zng= (FV(Econt)n fzdestg)\dom(")として
((save("(z1);z1: : :;save("(zn);zn);
applyclosure("(x); "(y1);:::;"(yn)));;)
R"(applydirect(Lx; y1; : : : ; yn);zdest;Econt)=同様
R"(x:(y); zdest; Econt)=("(x):("(y)); ")
R"(x:(y)^z; zdest; Econt)=("(x):("(y))^"(z);")
R"(save(x; y); zdest; Econt)=(save("(x); y); ")
R"(restore(y);zdest;Econt)= (restore(y);")
図21:単纯なレジスタ割り当てR"(e;zdest;Econt).R"(e)の右辺で変数xのレジスタ"(x)が定义されて
いない场合は,R"(e) =R"(x^restore(x);e)とする.ただしレジスタrについては"(r) =rとする.
[ファイルregAlloc.notarget-nospill.ml参照]
16
T:Id.t!SparcAsm.t Id.t!bool S.t
Tx((y^e;E); zdest)=Tx(e;y) = (c1;s1)として,もしc1ならば(true; s1)
そうでなければTx(E;zdest)=(c2; s2)として(c2; s1[s2)
Tx(e;zdest)=Tx(e; zdest)
T:Id.t!SparcAsm.exp Id.t!bool S.t
Tx(x;zdest)= (false;fzdestg)
Tx(ify=zthenE1elseE2;zdest)=Tx(E1;zdest)=(c1; s1);
Tx(E2;zdest)=(c2; s2)として
(c1^c2; s1[s2)
Tx(ify zthenE1elseE2;zdest)=同上
Tx(applyclosure(y0; y1; : : : ; yn);zdest)=(true;fRijx=yig)
Tx(applydirect(Ly; y1; : : : ; yn);zdest)=同上
Tx(e; zdest)=(false;;)それ以外の场合
図22:変数xに割り当てるレジスタrを选ぶときに使うtargetingTx(E;zdest)およびTx(e; zdest).Eやe
で関数呼び出しがあったかどうかを表す论理値cと,xを割り当てると良いレジスタの集合sの组を返す.
前々図の「xがレジスタでない场合」において,Tx(E0
cont;zdest)=(c; s)として,できればr2sとする.
[ファイルregAlloc.target-nospill.ml参照]
R:Id.t M.t!SparcAsm.t Id.t SparcAsm.t!SparcAsm.t Id.t M.t
R"((x^e;E); zdest; Econt) =E0
cont= (zdest^E;Econt);
R"(e;x;E0
cont) = (E0;"0);
y2FV(E0
cont);
R"0nfy7!"0(y)g;x7!"0(y)(E; zdest; Econt) = (E00;"00)として(
((save("(y);y);"0(y)^E0;E00); "00)y2dom(")のとき
(("0(y)^E0;E00);"00)y62dom(")のとき
xがレジスタでなく,
r62 f"0(y)jy2FV(E0
cont)gなるrがない场合
図23:spillingをするレジスタ割り当てR"(E; zdest; Econt) [ファイルregAlloc.target-latespill.ml
参照]
17
S:SparcAsm.prog!string
S((fD1; : : : ; Dng;E)) =.section".text"
S(D1)
:::
S(Dn)
.globalmin_caml_start
min_caml_start:
save%sp,-112,%sp
S(E;%g0)
ret
restore
S:SparcAsm.fundef!string
S(Lx(y1;:::;yn)=E)=x:
S(E;R0)
retl
nop
S:SparcAsm.t Id.t!string
S((x^e;E);zdest)=S(e; x)
S(E; zdest)
S(e;zdest)=S(e;zdest)
図24:単纯なアセンブリ生成S(P),S(D)およびS(E;zdest)
18
S:SparcAsm.exp Id.t!string
S(c;zdest)=setc; zdest
S(Lx; zdest)=set Lx; zdest
S(op(x1; : : : ; xn);zdest)=opx1; : : : ; xn; zdest
S(ifx=ythenE1elseE2;zdest)=cmpx;y
bneb1
nop
S(E1; zdest)
bb2
nop
b1:
S(E2; zdest)
b2:
S(ifx ythenE1elseE2; zdest) =同様
S(x; zdest)=movx;zdest
S(applyclosure(x; y1; : : : ; yn);zdest)=shu e((x; y1; : : : ; yn);(R0;R1; : : : ;Rn))
st Rra;[Rst+ 4#"]
ld[R0];Rn+1
call Rn+1
addRst;4(#"+1);Rst!delay slot
subRst;4(#"+ 1);Rst
ld[Rst+ 4#"];Rra
mov R0; zdest
S(applydirect(Lx; y1; : : : ; yn);zdest)=shu e((y1; : : : ; yn);(R1;:::;Rn))
stRra;[Rst+4#"]
callx
add Rst;4(#"+1);Rst!delay slot
subRst;4(#"+ 1);Rst
ld[Rst+ 4#"];Rra
mov R0; zdest
S(x:(y); zdest)=ld[x+y];zdest
S(x:(y)^z; zdest)=stz;[x+y]
S(save(x;y);zdest)=もしy62dom(")なら"にy7!4#"を加えて
stx;[Rst+"(y)]
S(restore(y);zdest)=ld[Rst+"(y)];zdest
図25:単纯なアセンブリ生成S(e; zdest)."はスタック位置を记忆するグローバル変数.#"は"の要素の
个数.shu e((x1; : : : ; xn);(r1;:::;rn))はx1,...,xnをr1, . . . ,rnに适切な顺序で移动する命令.
19
S:S.t!SparcAsm.t Id.t!S.t string
Ss((x^e;E); zdest)=Ss(e;x) = (s0;S);
Ss0(E; zdest) = (s00;S0)として
(s00; SS0)
Ss(e; zdest)=Ss(e; zdest)
S:S.t!SparcAsm.exp Id.t!S.t string
Ss(ifx=ythenE1elseE2;zdest)=Ss(E1;zdest)=(s1; S1);
Ss(E2;zdest)=(s2; S2)として
(s1\s2;
cmpx;y
bneb1
nop
S1
bb2
nop
b1:
S2
b2:)
Ss(ifx ythenE1elseE2; zdest) =同様
Ss(save(x;y);zdest)= (s;nop)y2sの场合
Ss(save(x; y); zdest)=もしy62dom(")なら"にy7!4#"を加えて
(s[fyg;stx;[Rst+"(y)])y62sの场合
Ss(e; zdest)=(s;以前と同様)上述以外の场合
図26:无駄なsaveを省略するアセンブリ生成Ss(E;zdest)およびSs(e; zdest).sはすでにsaveされた変
数の名前の集合.以前のS(E;zdest)はS;(E; zdest) = (s;S)としてSの略记とする.
20
S:SparcAsm.fundef!string
S(Lx(y1; : : : ; yn) =E)=S;(E;tail)=(s; S)として
x:
S
S:S.t!SparcAsm.exp Id.t!S.t string
Ss(ifx=ythenE1elseE2;tail) =Ss(E1;tail) = (s1;S1);
Ss(E2;tail) = (s2;S2)として
(;;
cmpx;y
bneb
nop
S1
b:
S2)
Ss(ifx ythenE1elseE2;tail)=同様
Ss(applyclosure(x; y1; : : : ; yn);tail)=(;;
shu e((x; y1; : : : ; yn);(R0;R1; : : : ;Rn))
ld[R0];Rn+1
jmpRn+1
nop)
Ss(applydirect(Lx; y1;:::;yn);tail) = (;;
shu e((y1;:::;yn);(R1; : : : ;Rn))
bx
nop)
Ss(e;tail)=Ss(e;R0)=(s0; S)として
(;;
S
retl
nop)上述以外の场合
図27:末尾呼び出し最适化をするアセンブリ生成Ss(D)およびSs(e;zdest).zdest=tailの场合が末尾.
21
c定数
op(e1;:::;en)プリミティブ演算
ife1thene2elsee3条件分岐
letx=e1ine2変数定义
x変数の読み出し
let recxy1:::yn=e1ine2再帰関数定义
e e1: : : en関数呼び出し(e1;:::;en)组の作成
let(x1;:::;xn)=e1ine2组の読み出し
Array:createe1e2配列の作成
e1:(e2)配列の読み出し
e1:(e2)^e3配列への书き込み
図1: MinCamlの抽象构文(型は省略)
1
cは…型の定数
''c:…
''e1:…1: : : ''en:…n
opは…1,:::,…n型の値を受け取って…型の値を返すプリミティブ演算
''op(e1; : : : ; en) :…
''e1:bool ''e2: ''e3:
''ife1thene2elsee3:
''e1: 1 ;x: 1''e2: 2
''letx=e1ine2: 2
(x)=
''x:
; x: 1!:::! n! ; y1: 1;:::;yn: n''e1:
; x: 1!:::! n! ''e2: 0
''let recxy1:::yn=e1ine2: 0
''e: 1!:::! n!
''e1: 1: : : ''en: n
''e e1: : : en:
''e1: 1::: ''en: n
''(e1;:::;en): 1 ::: n
''e1: 1 ::: n ; x1: 1;:::;xn: n''e2:
''let(x1; : : : ; xn) =e1ine2:
''e1:int ''e2:
''Array:createe1e2: array
''e1: array ''e2:int
''e1:(e2) :
''e1: array ''e2:int ''e3:
''e1:(e2)^e3:unit
図3:MinCamlの型つけ规则
e::=
c
op(x1;:::;xn)
ifx=ythene1elsee2
ifx ythene1elsee2
letx=e1ine2
x
letrecx y1: : : yn=e1ine2
x y1: : : yn
(x1;:::;xn)
let(x1; : : : ; xn) =yine
x:(y)
x:(y)^z
図4:MinCamlのK正规形(外部配列 外部関数适用は省略)
2
K:Syntax.t!KNormal.t
K(c)=c
K(not(e))=K(ifethen false else true)
K(e1=e2)=K(ife1=e2thentrueelsefalse)
K(e1 e2)=K(ife1 e2thentrue else false)
K(op(e1; : : : ; en))=letx1=K(e1)in: : :letxn=K(en)inop(x1;:::;xn)
opが论理演算 比较以外の场合
K(if note1thene2elsee3)=K(ife1the3elsee2)
K(ife1=e2thene3elsee4)=letx=K(e1)in lety=K(e2)in
ifx=ythenK(e3)elseK(e4)
K(ife1 e2thene3elsee4)=letx=K(e1)in lety=K(e2)in
ifx ythenK(e3)elseK(e4)
K(ife1thene2elsee3)=K(ife1=false thene3elsee2)
eが论理演算 比较以外の场合
K(letx=e1ine2)=letx=K(e1)inK(e2)
K(x)=x
K(let recxy1:::yn=e1ine2)=let recxy1:::yn=K(e1)inK(e2)
K(e e1: : : en)=letx=K(e)inlety1=K(e1)in:::letyn=K(en)in
x y1: : : yn
K(e1; : : : ; en)=letx1=K(e1)in: : :letxn=K(en)in(x1; : : : ; xn)
K(let(x1;:::;xn)=e1ine2)=lety=K(e1)in let(x1; : : : ; xn) =yinK(e2)
K(Array:createe1e2)=letx=K(e1)in lety=K(e2)in createarrayxy
K(e1:(e2))=letx=K(e1)in lety=K(e2)inx:(y)
K(e1:(e2)^e3)=letx=K(e1)in lety=K(e2)in letz=K(e3)in
x:(y)^z
図5: K正规化(论理値の整数化と,insertletによる最适化は省略).右辺に出现していて左辺に出现
していない変数は,すべて新しい(fresh)とする.
3
fi:Id.t M.t!KNormal.t!KNormal.t
fi"(c)=c
fi"(op(x1;:::;xn))=op("(x1); : : : ; "(xn))
fi"(ifx=ythene1elsee2)=if"(x) ="(y)thenfi"(e1)elsefi"(e2)
fi"(ifx ythene1elsee2)=if"(x) "(y)thenfi"(e1)elsefi"(e2)
fi"(letx=e1ine2)=letx0=fi"(e1)infi";x7!x0(e2)
fi"(x)="(x)
fi"(let recxy1:::yn=e1ine2)=let recx0y0
1: : : y0
n=fi";x7!x0;y17!y0
1;:::;yn7!y0
n
(e1)in
fi";x7!x0(e2)
fi"(xy1:::yn)="(x)"(y1): : : "(yn)
fi"((x1; : : : ; xn))=("(x1);:::;"(xn))
fi"(let(x1;:::;xn)=yine)=let(x0
1; : : : ; x0
n)="(y)infi";x17!x0
1;:::;xn7!x0
n
(e)
fi"(x:(y))="(x):("(y))
fi"(x:(y)^z)="(x):("(y))^"(z)
図6:fi変换."はfi変换前の変数を受け取って,fi変换后の変数を返す写像.右辺に出现していて左辺に
出现していない変数(x0など)は,すべてfreshとする.
:Id.t M.t!KNormal.t!KNormal.t
"(c)=c
"(op(x1;:::;xn))=op("(x1); : : : ; "(xn))
"(ifx=ythene1elsee2)=if"(x) ="(y)then "(e1)else "(e2)
"(ifx ythene1elsee2)=if"(x) "(y)then "(e1)else "(e2)
"(letx=e1ine2)= ";x7!y(e2) "(e1)が変数yの场合
"(letx=e1ine2)=letx= "(e1)in "(e2) "(e1)が変数でない场合
"(x)="(x)
"(letrecx y1: : : yn=e1ine2) =letrecx y1: : : yn= "(e1)in "(e2)
"(xy1:::yn)="(x)"(y1): : : "(yn)
"((x1; : : : ; xn))=("(x1);:::;"(xn))
"(let(x1;:::;xn)=yine)=let(x1;:::;xn)="(y)in "(e)
"(x:(y))="(x):("(y))
"(x:(y)^z)="(x):("(y))^"(z)
図7: 简约."は 简约前の変数を受け取って, 简约后の変数を返す写像."(x)が定义されていない场
合は,"(x)=xとみなす.
4
A:KNormal.t!KNormal.t
A(c)=c
A(op(x1;:::;xn))=op(x1;:::;xn)
A(ifx=ythene1elsee2)=ifx=ythenA(e1)elseA(e2)
A(ifx ythene1elsee2)=ifx ythenA(e1)elseA(e2)
A(letx=e1ine2)=let:::in letx=e0
1inA(e2)
A(e1) =let: : :ine0
1という形で
(let:::inは0个以上のletの列),
e0
1はletでない
A(x)=x
A(let recxy1:::yn=e1ine2)=let recxy1:::yn=A(e1)inA(e2)
A(xy1:::yn)=x y1: : : yn
A((x1; : : : ; xn))=(x1; : : : ; xn)
A(let(x1;:::;xn)=yine)=let(x1;:::;xn)=yinA(e)
A(x:(y))=x:(y)
A(x:(y)^z)=x:(y)^z
図8:ネストしたletの简约
5
I:(Id.t list KNormal.t)M.t!KNormal.t!KNormal.t
I"(c)=c
I"(op(x1;:::;xn))=op(x1;:::;xn)
I"(ifx=ythene1elsee2)=ifx=ythenI"(e1)elseI"(e2)
I"(ifx ythene1elsee2)=ifx ythenI"(e1)elseI"(e2)
I"(letx=e1ine2)=letx=I"(e1)inI"(e2)
I"(x)=x
I"(let recxy1:::yn=e1ine2)="0=";x7!((y1; : : : ; yn);e1)として
letrecx y1: : : yn=I"0(e1)inI"0(e2)
size(e1) thの场合
I"(letrecx y1: : : yn=e1ine2) =letrecx y1: : : yn=I"(e1)inI"(e2)
size(e1)>thの场合
I"(xy1:::yn)=fiy17!z1;:::;yn7!zn(e)"(x) = ((z1;:::;zn); e)の场合
I"(x y1: : : yn)=x y1: : : yn"(x)が定义されていない场合
I"((x1; : : : ; xn))=(x1; : : : ; n)
I"(let(x1; : : : ; xn) =yine)=let(x1; : : : ; xn) =yinI"(e)
I"(x:(y))=x:(y)
I"(x:(y)^z)=x:(y)^z
size(c=1
size(op(x1; : : : ; xn))=1
size(ifx=ythene1elsee2)=1+size(e1) +size(e2)
size(ifx ythene1elsee2)=1+size(e1) +size(e2)
size(letx=e1ine2)= 1 +size(e1)+size(e2)
size(x)=1
size(let recxy1:::yn=e1ine2)=1+size(e1) +size(e2)
size(x y1: : : yn)=1
size((x1; : :: ; xn))=1
size(let(x1; : : : ; xn) =yine)=1+size(e)
size(x:(y))= 1
size(x:(y)^z)= 1
図9:インライン展开."はサイズの小さい関数名を受け取って,仮引数と本体を返す写像.thはインライ
ン展开する関数の最大サイズ(ユーザ指定).
6
F:KNormal.t M.t!KNormal.t!KNormal.t
F"(c)=c
F"(op(x1;:::;xn))=cop("(x1);:::;"(xn))=cの场合
F"(op(x1;:::;xn))=op(x1;:::;x
n)それ以外の场合
F"(ifx=ythene1elsee2)=F"(e1)"(x)と"(y)が等しい定数の场合
F"(ifx=ythene1elsee2)=F"(e2)"(x)と"(y)が异なる定数の场合
F"(ifx=ythene1elsee2)=ifx=ythenF"(e1)elseF"(e2)それ以外の场合
F"(ifx ythene1elsee2)=F"(e1)"(x)と"(y)が定数で,"(x) "(y)の场合
F"(ifx ythene1elsee2)=F"(e2)"(x)と"(y)が定数で,"(x)> "(y)の场合
F"(ifx ythene1elsee2)=ifx ythenF"(e1)elseF"(e2)それ以外の场合
F"(letx=e1ine2)=e0
1=F"(e1)として
letx=e0
1inF";x7!e0
1
(e2)
F"(x)=x
F"(letrecx y1: : : yn=e1ine2) =letrecx y1: : : yn=F"(e1)inF"(e2)
F"(xy1:::yn)=xy1:::yn
F"((x1; : : : ; xn))=(x1; : : : ; xn)
F"(let(x1; : : : ; xn) =yine)=letx1=y1in:::letxn=yninF"(e)
"(y)=(y1; : : : ; yn)の场合
F"(let(x1;:::;xn)=yine)=let(x1;:::;xn)=yinF"(e)
F"(x:(y))=x:(y)
F"(x:(y)^z)=x:(y)^z
図10:定数畳み込み."は変数を受け取って,定数を返す写像.
7
E:KNormal.t!KNormal.t
E(c)=c
E(op(x1;:::;xn))=op(x1;:::;xn)
E(ifx=ythene1elsee2)=ifx=ythenE(e1)elseE(e2)
E(ifx ythene1elsee2)=ifx ythenE(e1)elseE(e2)
E(letx=e1ine2)=E(e2)efiect(E(e1))=falseかつx62FV(E(e2))の场合
E(letx=e1ine2)=letx=E(e1)inE(e2)それ以外の场合
E(x)=x
E(letrecx y1: : : yn=e1ine2) =E(e2)x62FV(E(e2))の场合
E(let recx y1: : : yn=e1ine2) =letrecx y1: : : yn=E(e1)inE(e2)それ以外の场合
E(xy1:::yn)=xy1:::yn
E((x1;:::;xn))= (x1;:::;xn)
E(let(x1; : : : ; xn) =yine)=E(e)fx1;:::;xng\FV(E(e))=;の场合
E(let(x1; : : : ; xn) =yine)=let(x1; : : : ; xn) =yinE(e)それ以外の场合
E(x:(y))=x:(y)
E(x:(y)^z)=x:(y)^z
efiect:KNormal.t!bool
efiect(c)=false
efiect(op(x1; : : : ; xn))=false
efiect(ifx=ythene1elsee2)=efiect(e1)_efiect(e2)
efiect(ifx ythene1elsee2)=efiect(e1)_efiect(e2)
efiect(letx=e1ine2)=efiect(e1)_efiect(e2)
efiect(x)=false
efiect(letrecx y: : : yn=e1ine2) =efiect(e2)
efiect(x y1: : : yn)=true
efiect((x1;:::;xn))=false
efiect(let(x1; : : : ; xn) =yine)=efiect(e)
efiect(x:(y))=false
efiect(x:(y)^z)=true
図11:不要定义削除(1/2)
8
FV:KNormal.t!S.t
FV(c)=;
FV(op(x1;:::;xn))=fx1; : : : ; xng
FV(ifx=ythene1elsee2)=fx; yg[FV(e1)[FV(e2)
FV(ifxythene1elsee2)=fx; yg[FV(e1)[FV(e2)
FV(letx=e1ine2)=FV(e1)[(FV(e2)nfxg)
FV(x)=fxg
FV(letrecx y1: : : n=e1ine2) = ((FV(e1)n fy1;:::;yng)[FV(e2))nfxg
FV(x y1: : : yn)=fx;y1;:::;yng
FV((x1; : : : ; xn))=fx1;:::;xng
FV(let(x1;:::;xn)=yine)=fyg[(FV(e)nfx1; : : : ; xng)
FV(x:(y))=fx; yg
FV(x:(y)^z)=fx;y;zg
図12:不要定义削除(2/2)
P::=プログラム全体
(fD1;:::;Dng; e)トップレベル関数定义の集合とメインルーチンの式
D::=トップレベル関数定义
Lx(y1;:::;ym)(z1; : : : ; zn) =e関数のラベルと仮引数,自由変数,および本体
e::=
c
op(x1; : : : ; xn)
ifx=ythene1elsee2
ifxythene1elsee2
letx=e1ine2
x
makeclosurex= (Lx;(y1;:::;yn))ineクロージャ生成
applyclosure(x; y1; : : : ; yn)クロージャを用いた関数呼び出し
applydirect(Lx; y1; : : : ; yn)クロージャを用いない関数呼び出し(knownfunctioncall)
(x1;:::;xn)
let(x1; : : : ; xn) =yine
x:(y)
x:(y)^z
図13:クロージャ変换后の构文
9
C:KNormal.t!Closure.t
C(c)=c
C(op(x1;:::;xn))=op(x1;:::;xn)
C(ifx=ythene1elsee2)=ifx=ythenC(e1)elseC(e2)
C(ifx ythene1elsee2)=ifx ythenC(e1)elseC(e2)
C(letx=e1ine2)=letx=C(e1)inC(e2)
C(x)=x
C(let recxy1:::yn=e1ine2)=DにLx(y1;:::;yn)(z1; : : : ; zm) =e0
1を加え,
makeclosurex= (Lx;(z1;:::;zm))ine0
2を返す
ただしe0
1=C(e1),e0
2=C(e2),
FV(e0
1)n fx;y1;:::;yng=fz1; : : : ; zmg
C(xy1:::yn)=applyclosure(x; y1; : : : ; yn)
C((x1;:::;xn))= (x1;:::;xn)
C(let(x1; : : : ; xn) =yine)=let(x1; : : : ; xn) =yinC(e)
C(x:(y))=x:(y)
C(x:(y)^z)=x:(y)^z
FV:Closure.t!S.t
FV(c)=;
FV(op(x1; : : : ; xn))=fx1;:::;xng
FV(ifx=ythene1elsee2)=fx;yg [FV(e1)[FV(e2)
FV(ifx ythene1elsee2)=fx;yg [FV(e1)[FV(e2)
FV(letx=e1ine2)=FV(e1)[(FV(e2)nfxg)
FV(x)=fxg
FV(makeclosurex= (Lx;(y1;:::;yn))ine) =fy1;:::;yng[(FV(e)nfxg)
FV(applyclosure(x; y1; : : : ; yn))=fx;y1;:::;yng
FV(applydirect(Lx; y1; : : : ; yn))=fy1;:::;yng
FV((x1; : :: ; xn))=fx1;:::;xng
FV(let(x1; : : : ; xn) =yine)=fyg [(FV(e)n fx1;:::;xng)
FV(x:(y))=fx;yg
FV(x:(y)^z)=fx; y; zg
図14:贤くないClosure変换C(e).Dはトップレベル関数定义の集合を记忆しておくためのグローバル
変数.
10
C:S.t!KNormal.t!Closure.t
Cs(let recxy1:::yn=e1ine2)=DにLx(y1;:::;yn)()=e0
1を加え,
makeclosurex= (Lx;())ine0
2を返す
ただしe0
1=Cs0(e1),e0
2=Cs0(e2),s0=s[fxg,
FV(e0
1)nfy1; : : : ; yng=;の场合
Cs(letrecx y1: : : yn=e1ine2) =DにLx(y1; : : : ; yn)(z1;:::;zm)=e0
1を加え,
makeclosurex= (Lx;(z1;:::;zm))ine0
2を返す
ただしe0
1=Cs(e1),e0
2=Cs(e2),
FV(e0
1)n fy1;:::;yng6=;,
FV(e0
1)nfx; y1; : : : ; yng=fz1;:::;zmgの场合
Cs(x y1: : : yn)=applyclosure(x; y1; : : : ; yn)x62sの场合
Cs(x y1n)=applydirect(Lx; y1; : : : ; yn)x2sの场合
図15:やや贤いClosure変换Cs(e).sは自由変数がないとわかっている関数の名前の集合.
C:S.t!KNormal.t!Closure.t
Cs(let recxy1:::yn=e1ine2) =DにLx(y1; : : : ; yn)() =e0
1を加え,
makeclosurex= (Lx;())ine0
2を返す
ただしe0
1=Cs0(e1),e0
2=Cs0(e2),s0=s[fxg,
FV(e0
1)n fy1;:::;yng=;かつx2FV(e0
2)の场合
Cs(letrecx y1: : : yn=e1ine2) =DにLx(y1; : : : ; yn)() =e0
1を加え,e0
2を返す
ただしe0
1=Cs0(e1),e0
2=Cs0(e2),s0=s[fxg,
FV(e0
1)nfy1; : : : ; yng=;かつx62FV(e0
2)の场合
Cs(let recxy1:::yn=e1ie2)=DにLx(y1;:::;yn)(z1; : : : ; zm) =e0
1を加え,
makeclosurex= (Lx;(z1;:::;zm))ine0
2を返す
ただしe0
1=Cs(e1),e0
2=Cs
(e2),
FV(e0
1)n fy1;:::;yng6=;,
FV(e0
1)nfx; y1; : : : ; yng=fz1;:::;zmgの场合
Cs(x y1: : : yn)=apply
closure(x; y1; : : : ; yn)x62sの场合
Cs(xy1:::yn)=applydirect(Lx; y1; : : : ; yn)x2sの场合
図16:もっと贤いClosure変换Cs(e)
11
P::=
(fD1; : : : ; Dng;E)
D::=
Lx(y1; : : : ; yn) =E
E::=命令の列
x^e;E代入
e返値
e::=式
c即値
Lxラベル
op(x1;:::;xn)算术演算
ifx=ythenE1elseE2比较&分岐
ifx ythenE1elseE2比较&分岐
xmov命令
applyclosure(x; y1; : : : ; yn)クロージャを用いた関数呼び出し
applydirect(Lx; y1; : : : ; yn)クロージャを用いない関数呼び出し
x:(y)ロード
x:(y)^zストア
save(x; y)変数xの値をスタック位置yに退避する
restore(y)スタック位置yから値を复元する
図17:仮想マシンコードの构文
12
V:Closure.prog!SparcAsm.prog
V((fD1; : : : ; Dng;e))=(fV(D1);:::;V(Dn)g;V(e))
V:Closure.fundef!SparcAsm.fundef
V(Lx(y1;:::;yn)(z1; : : : ; zn) =e)=Lx(y1;:::;yn)=z1^R0:(4);:::;zn^R0:(4n);V(e)
V:Closure.t!SparcAsm.t
V(c)=c
V(op(x1;:::;xn))=op(x1;:::;xn)
V(ifx=ythene1elsee2)=ifx=ythenV(e1)elseV(e2)
V(ifx ythene1elsee2)=ifx ythenV(e1)elseV(e2)
V(letx=e1ine2)=x^ V(e1);V(e2)
V(x)=x
V(makeclosurex= (Lx;(y1;:::;yn))ine) =x^Rhp;Rhp^Rhp+4(n+1);z^Lx;x:(0)^z;
x:(4)^y1;:::;x:(4n)^yn;V(e)
V(applyclosure(x; y1; : : : ; yn))=applyclosure(x; y1; : : : ; yn)
V(applydirect(Lx; y1; : : : ; yn))=applydirect(Lx;y1;:::;yn)
V((x1; : : : ; xn))=y^Rhp;Rhp^Rhp+ 4n;
y:(0)^x1;:::;y:(4(n 1))^xn;y
V(let(x1;:::;xn)=yine)fx1; : : : ; xng \FV(e) =fxi1;:::;ximgとして
xi1^y:(4(i1 1));: : :;xim^y:(4(im 1));V(e)
V(x:(y))=y0^4 y;x:(y0)
V(x:(y)^z)=y0^4 y;x:(y0)^z
図18:仮想マシンコード生成V(P),V(D)およびV(e).右辺に出现して左辺に出现しない変数はfresh
とする.Rhpはヒープポインタ(専用レジスタ).e1;e2はダミーの変数xについてx^e1;e2の略记.
x^E1;E2は,E1=(x1^e1;: : :;xn^en;e)として,x1^e1;:::;xn^en;x^e;E2の略记.
13
FV:S.t!SparcAsm.t!S.t
FVs(x^e;E)=s0=FVs(E)nfxgとしてFVs0(e)
FVs(e)=FVs(e)
FV:S.t!SparcAsm.exp!S.t
FVs(c)=s
FVs(Lx)=s
FVs(op(x1; : : : ; xn))=fx1;:::;xng[s
FVs(ifx=ythenE1elseE2) =fx; yg[FVs(E1)[FVs(E2)
FVs(ifx ythenE1elseE2) =fx; yg[FVs(E1)[FVs(E2)
FVs(x)=fxg[s
FVs(applyclosure(x; y1; : : : ; yn)) =fx; y1; : : : ; yng [s
FVs(applydirectLx; y1; : : : ; yn)) =fy1; : : : ; yng [s
FVs(x:(y))=fx;yg [s
FVs(x:(y)^z)=fx; y; zg[s
FVs(save(x; y))=fxg[s
FVs(restore(y))=s
図19:命令の列Eおよび式eにおいて生きている変数の集合FVs(E)およびFVs(e).sはEやeの后で
使われる変数の集合.以后のFV(E)はFV;(E)の略记.
14
R:SparcAsm.prog!SparcAsm.prog
R((fD1; : : : ; Dng;E))=(fR(D1);:::;R(Dn)g;R;(E; x;()))xはダミーのfreshな変数
R:SparcAsm.fundef!SparcAsm.fundef
R(Lx(y1; : : : ; yn) =E)=Lx(R1; : : : ;Rn)=Rx7!R0;y17!R1;:::;yn7!Rn(E;R0;R0)
R:Id.tM.t!SparcAsm.t Id.t SparcAsm.t!SparcAsm.t Id.tM.t
R"((x^e;E);zdest;Econt)=E0
cont=(zdest^E;Econt);
R"(e; x; E0
cont)=(E0; "0);
r62f"0(y)jy2FV(E0
cont)g;
R"0;x7!r(E;zdest;Econt)=(E00; "00)として
((r^E0;E00);"00)xがレジスタでない场合
R"((r^e;E);zdest;Econt)=E0
cont=(zdest^E;Econt);
R"(e; r; E0
cont)=(E0; "0);
R"0(E; zde; Econt) = (E00;"00)として
((r^E0;E00); "00)
R"(e; x; Econt)=R"(e;x;Econt)(次図参照)
図20:単纯なレジスタ割り当てR(P),R(D)およびR"(E; zdest; Econt)."は変数からレジスタへの写
像,zdestはEの结果をセットする変数,EcontはEの后に実行される命令の列.R"(E; x; Econt)の返り
値はレジスタ割り当てされた命令の列E0と,Eの后のレジスタ割り当てを表す写像"0の组.[ファイル
regAlloc.notarget-nospill.ml参照]
15
R:Id.t M.t!SparcAsm.exp Id.t SparcAsm.t!SparcAsm.t Id.t M.t
R"(c; zdest; Econt)=(c; ")
R"(Lx;zdest;Econt)= (Lx;")
R"(op(x1; : : : ; xn);zdest;Econt)= (op("(x1);:::;"(xn)); ")
R"(ifx=ythenE1elseE2;zdest;Econt)=R"(E1;zdest;Econt)=(E0
1;"1);
R"(E2; zdest; Econt) = (E0
2; "2);
"0=fz7!rj"1(z) ="2(z)=rg;
fz1; : : : ; zng=
(FV(Econt)n fzdestgndom("0))\dom(")として
((save("(z1);z1);: : :;save("(zn);zn);
if"(x) "(y)thenE0
1elseE0
2);"0)
R"(ifx ythenE1elseE2;zdest;Econt)=同様
R"(x; zdest; Econt)= ("(x);")
R"(applyclosure(x; y1; : : : ; yn);zdest;Econt)=fz1;:::;zng= (FV(Econt)n fzdestg)\dom(")として
((save("(z1);z1: : :;save("(zn);zn);
applyclosure("(x); "(y1);:::;"(yn)));;)
R"(applydirect(Lx; y1; : : : ; yn);zdest;Econt)=同様
R"(x:(y); zdest; Econt)=("(x):("(y)); ")
R"(x:(y)^z; zdest; Econt)=("(x):("(y))^"(z);")
R"(save(x; y); zdest; Econt)=(save("(x); y); ")
R"(restore(y);zdest;Econt)= (restore(y);")
図21:単纯なレジスタ割り当てR"(e;zdest;Econt).R"(e)の右辺で変数xのレジスタ"(x)が定义されて
いない场合は,R"(e) =R"(x^restore(x);e)とする.ただしレジスタrについては"(r) =rとする.
[ファイルregAlloc.notarget-nospill.ml参照]
16
T:Id.t!SparcAsm.t Id.t!bool S.t
Tx((y^e;E); zdest)=Tx(e;y) = (c1;s1)として,もしc1ならば(true; s1)
そうでなければTx(E;zdest)=(c2; s2)として(c2; s1[s2)
Tx(e;zdest)=Tx(e; zdest)
T:Id.t!SparcAsm.exp Id.t!bool S.t
Tx(x;zdest)= (false;fzdestg)
Tx(ify=zthenE1elseE2;zdest)=Tx(E1;zdest)=(c1; s1);
Tx(E2;zdest)=(c2; s2)として
(c1^c2; s1[s2)
Tx(ify zthenE1elseE2;zdest)=同上
Tx(applyclosure(y0; y1; : : : ; yn);zdest)=(true;fRijx=yig)
Tx(applydirect(Ly; y1; : : : ; yn);zdest)=同上
Tx(e; zdest)=(false;;)それ以外の场合
図22:変数xに割り当てるレジスタrを选ぶときに使うtargetingTx(E;zdest)およびTx(e; zdest).Eやe
で関数呼び出しがあったかどうかを表す论理値cと,xを割り当てると良いレジスタの集合sの组を返す.
前々図の「xがレジスタでない场合」において,Tx(E0
cont;zdest)=(c; s)として,できればr2sとする.
[ファイルregAlloc.target-nospill.ml参照]
R:Id.t M.t!SparcAsm.t Id.t SparcAsm.t!SparcAsm.t Id.t M.t
R"((x^e;E); zdest; Econt) =E0
cont= (zdest^E;Econt);
R"(e;x;E0
cont) = (E0;"0);
y2FV(E0
cont);
R"0nfy7!"0(y)g;x7!"0(y)(E; zdest; Econt) = (E00;"00)として(
((save("(y);y);"0(y)^E0;E00); "00)y2dom(")のとき
(("0(y)^E0;E00);"00)y62dom(")のとき
xがレジスタでなく,
r62 f"0(y)jy2FV(E0
cont)gなるrがない场合
図23:spillingをするレジスタ割り当てR"(E; zdest; Econt) [ファイルregAlloc.target-latespill.ml
参照]
17
S:SparcAsm.prog!string
S((fD1; : : : ; Dng;E)) =.section".text"
S(D1)
:::
S(Dn)
.globalmin_caml_start
min_caml_start:
save%sp,-112,%sp
S(E;%g0)
ret
restore
S:SparcAsm.fundef!string
S(Lx(y1;:::;yn)=E)=x:
S(E;R0)
retl
nop
S:SparcAsm.t Id.t!string
S((x^e;E);zdest)=S(e; x)
S(E; zdest)
S(e;zdest)=S(e;zdest)
図24:単纯なアセンブリ生成S(P),S(D)およびS(E;zdest)
18
S:SparcAsm.exp Id.t!string
S(c;zdest)=setc; zdest
S(Lx; zdest)=set Lx; zdest
S(op(x1; : : : ; xn);zdest)=opx1; : : : ; xn; zdest
S(ifx=ythenE1elseE2;zdest)=cmpx;y
bneb1
nop
S(E1; zdest)
bb2
nop
b1:
S(E2; zdest)
b2:
S(ifx ythenE1elseE2; zdest) =同様
S(x; zdest)=movx;zdest
S(applyclosure(x; y1; : : : ; yn);zdest)=shu e((x; y1; : : : ; yn);(R0;R1; : : : ;Rn))
st Rra;[Rst+ 4#"]
ld[R0];Rn+1
call Rn+1
addRst;4(#"+1);Rst!delay slot
subRst;4(#"+ 1);Rst
ld[Rst+ 4#"];Rra
mov R0; zdest
S(applydirect(Lx; y1; : : : ; yn);zdest)=shu e((y1; : : : ; yn);(R1;:::;Rn))
stRra;[Rst+4#"]
callx
add Rst;4(#"+1);Rst!delay slot
subRst;4(#"+ 1);Rst
ld[Rst+ 4#"];Rra
mov R0; zdest
S(x:(y); zdest)=ld[x+y];zdest
S(x:(y)^z; zdest)=stz;[x+y]
S(save(x;y);zdest)=もしy62dom(")なら"にy7!4#"を加えて
stx;[Rst+"(y)]
S(restore(y);zdest)=ld[Rst+"(y)];zdest
図25:単纯なアセンブリ生成S(e; zdest)."はスタック位置を记忆するグローバル変数.#"は"の要素の
个数.shu e((x1; : : : ; xn);(r1;:::;rn))はx1,...,xnをr1, . . . ,rnに适切な顺序で移动する命令.
19
S:S.t!SparcAsm.t Id.t!S.t string
Ss((x^e;E); zdest)=Ss(e;x) = (s0;S);
Ss0(E; zdest) = (s00;S0)として
(s00; SS0)
Ss(e; zdest)=Ss(e; zdest)
S:S.t!SparcAsm.exp Id.t!S.t string
Ss(ifx=ythenE1elseE2;zdest)=Ss(E1;zdest)=(s1; S1);
Ss(E2;zdest)=(s2; S2)として
(s1\s2;
cmpx;y
bneb1
nop
S1
bb2
nop
b1:
S2
b2:)
Ss(ifx ythenE1elseE2; zdest) =同様
Ss(save(x;y);zdest)= (s;nop)y2sの场合
Ss(save(x; y); zdest)=もしy62dom(")なら"にy7!4#"を加えて
(s[fyg;stx;[Rst+"(y)])y62sの场合
Ss(e; zdest)=(s;以前と同様)上述以外の场合
図26:无駄なsaveを省略するアセンブリ生成Ss(E;zdest)およびSs(e; zdest).sはすでにsaveされた変
数の名前の集合.以前のS(E;zdest)はS;(E; zdest) = (s;S)としてSの略记とする.
20
S:SparcAsm.fundef!string
S(Lx(y1; : : : ; yn) =E)=S;(E;tail)=(s; S)として
x:
S
S:S.t!SparcAsm.exp Id.t!S.t string
Ss(ifx=ythenE1elseE2;tail) =Ss(E1;tail) = (s1;S1);
Ss(E2;tail) = (s2;S2)として
(;;
cmpx;y
bneb
nop
S1
b:
S2)
Ss(ifx ythenE1elseE2;tail)=同様
Ss(applyclosure(x; y1; : : : ; yn);tail)=(;;
shu e((x; y1; : : : ; yn);(R0;R1; : : : ;Rn))
ld[R0];Rn+1
jmpRn+1
nop)
Ss(applydirect(Lx; y1;:::;yn);tail) = (;;
shu e((y1;:::;yn);(R1; : : : ;Rn))
bx
nop)
Ss(e;tail)=Ss(e;R0)=(s0; S)として
(;;
S
retl
nop)上述以外の场合
図27:末尾呼び出し最适化をするアセンブリ生成Ss(D)およびSs(e;zdest).zdest=tailの场合が末尾.
21
·上一篇:关于元组关系演算安全性的讨论
·下一篇:Python多倍长整数演算改良

文件类型:PDF/Adobe Acrobat 文件大小:字节