条件分岐を行うAArch64コードを出力
現状のアセンブリコード
code:ml
# let src = "let rec double x = x + x in let x = double 5 in let y = if x > 10 then 1 else 0 in print_int y; print_newline ()" in Emit.f stdout (RegAlloc.f (Simm.f (Virtual.f (Closure.f (Alpha.f (KNormal.f (Typing.f (Parser.exp Lexer.token (Lexing.from_string src)))))))));;
.text
.globl _min_caml_start
.align 2
double.5:
add x0, x0, x0
blr
_min_caml_start: # main entry point
# main program starts
mov x0, 5
bl double.5
cmpwi cr7, x0, 10
bgt cr7, ble_else.14
mov x0, 0
b ble_cont.15
ble_else.14:
mov x0, 1
ble_cont.15:
bl _min_caml_print_int
bl _min_caml_print_newline
# main program ends
ret
現状の仮想マシンコード
code:ml
# let src = "let rec double x = x + x in let x = double 5 in let y = if x > 10 then 1 else 0 in print_int y; print_newline ()" in (RegAlloc.f (Simm.f (Virtual.f (Closure.f (Alpha.f (KNormal.f (Typing.f (Parser.exp Lexer.token (Lexing.from_string src)))))))));;
- : Asm.prog =
Asm.Prog ([],
[{Asm.name = Id.L "double.5"; args = "%x0"; fargs = []; body = Asm.Ans (Asm.Add ("%x0", Asm.V "%x0")); ret = Type.Int}],
Asm.Let (("%x0", Type.Int), Asm.Li 5,
Asm.Let (("%x0", Type.Int), Asm.CallDir (Id.L "double.5", "%x0", []), Asm.Let (("%x0", Type.Int),
Asm.IfLE ("%x0", Asm.C 10, Asm.Ans (Asm.Li 0), Asm.Ans (Asm.Li 1)),
Asm.Let (("%x0", Type.Unit),
Asm.CallDir (Id.L "_min_caml_print_int", "%x0", []), Asm.Let (("%x0", Type.Unit), Asm.Nop,
Asm.Ans (Asm.CallDir (Id.L "_min_caml_print_newline", [], []))))))))
現状のクロージャ変換
code:ml
# let src = "let rec f x y = x + y in print_int (f 10 20)" in (Closure.f (Alpha.f (KNormal.f (Typing.f (Parser.exp Lexer.token (Lexing.from_string src))))));;
- : Closure.prog =
Closure.Prog
body = Closure.Add ("x.33", "y.34")}],
Closure.Let (("Ti31.35", Type.Int),
Closure.Let (("Ti29.36", Type.Int), Closure.Int 10,
Closure.Let (("Ti30.37", Type.Int), Closure.Int 20,
Closure.AppDir (Id.L "_min_caml_print_int", "Ti31.35"))) 現状のK正規形
code:ocaml
# let src = "let rec f x y = x + y in print_int (f 10 20)" in (Alpha.f (KNormal.f (Typing.f (Parser.exp Lexer.token (Lexing.from_string src)))));;
- : KNormal.t =
KNormal.LetRec
body = KNormal.Add ("x.52", "y.53")},
KNormal.Let (("Ti50.54", Type.Int),
KNormal.Let (("Ti48.55", Type.Int), KNormal.Int 10,
KNormal.Let (("Ti49.56", Type.Int), KNormal.Int 20,
修正箇所
blr の代わりに ret を利用する
cmpwi cr7, x0, 10 の代わりに cmp x0, 10 を利用する
bgt cr7, ble_else.14 の代わりに bgt ble_else.14 を利用する
code:asm
double.5:
add x0, x0, x0
blr ← (ここを修正)
_min_caml_start: # main entry point
# main program starts
mov x0, 5
bl double.5
# (ここを修正)
cmpwi cr7, x0, 10
bgt cr7, ble_else.14
mov x0, 0
b ble_cont.15
code:diff
diff --git a/AArch64/emit.ml b/AArch64/emit.ml
index 1d2ace3..81c9ac2 100644
--- a/AArch64/emit.ml
+++ b/AArch64/emit.ml
@@ -116,36 +116,36 @@ and g' oc = function (* 各命令のアセンブリ生成 (caml2html: emit_gprim
(* 末尾だったら計算結果を第一レジスタにセットしてリターン (caml2html: emit_tailret) *)
| Tail, (Nop | Stw _ | Stfd _ | Comment _ | Save _ as exp) ->
g' oc (NonTail(Id.gentmp Type.Unit), exp);
- Printf.fprintf oc "\tblr\n";
+ Printf.fprintf oc "\tret\n";
| Tail, (Li _ | SetL _ | Mr _ | Neg _ | Add _ | Sub _ | Slw _ | Lwz _ as exp) ->
g' oc (NonTail(regs.(0)), exp);
- Printf.fprintf oc "\tblr\n";
+ Printf.fprintf oc "\tret\n";
| Tail, (FLi _ | FMr _ | FNeg _ | FAdd _ | FSub _ | FMul _ | FDiv _ | Lfd _ as exp) ->
g' oc (NonTail(fregs.(0)), exp);
- Printf.fprintf oc "\tblr\n";
+ Printf.fprintf oc "\tret\n";
| Tail, (Restore(x) as exp) ->
(match locate x with
| i -> g' oc (NonTail(regs.(0)), exp) | i; j when i + 1 = j -> g' oc (NonTail(fregs.(0)), exp) | _ -> assert false);
- Printf.fprintf oc "\tblr\n";
+ Printf.fprintf oc "\tret\n";
| Tail, IfEq(x, V(y), e1, e2) ->
- Printf.fprintf oc "\tcmpw\tcr7, %s, %s\n" (reg x) (reg y);
+ Printf.fprintf oc "\tcmp %s, %s\n" (reg x) (reg y);
g'_tail_if oc e1 e2 "beq" "bne"
| Tail, IfEq(x, C(y), e1, e2) ->
- Printf.fprintf oc "\tcmpwi\tcr7, %s, %d\n" (reg x) y;
+ Printf.fprintf oc "\tcmp %s, %d\n" (reg x) y;
g'_tail_if oc e1 e2 "beq" "bne"
| Tail, IfLE(x, V(y), e1, e2) ->
- Printf.fprintf oc "\tcmpw\tcr7, %s, %s\n" (reg x) (reg y);
+ Printf.fprintf oc "\tcmp %s, %s\n" (reg x) (reg y);
g'_tail_if oc e1 e2 "ble" "bgt"
| Tail, IfLE(x, C(y), e1, e2) ->
- Printf.fprintf oc "\tcmpwi\tcr7, %s, %d\n" (reg x) y;
+ Printf.fprintf oc "\tcmp %s, %d\n" (reg x) y;
g'_tail_if oc e1 e2 "ble" "bgt"
| Tail, IfGE(x, V(y), e1, e2) ->
- Printf.fprintf oc "\tcmpw\tcr7, %s, %s\n" (reg x) (reg y);
+ Printf.fprintf oc "\tcmp %s, %s\n" (reg x) (reg y);
g'_tail_if oc e1 e2 "bge" "blt"
| Tail, IfGE(x, C(y), e1, e2) ->
- Printf.fprintf oc "\tcmpwi\tcr7, %s, %d\n" (reg x) y;
+ Printf.fprintf oc "\tcmp %s, %d\n" (reg x) y;
g'_tail_if oc e1 e2 "bge" "blt"
| Tail, IfFEq(x, y, e1, e2) ->
Printf.fprintf oc "\tfcmpu\tcr7, %s, %s\n" (reg x) (reg y);
@@ -157,19 +157,19 @@ and g' oc = function (* 各命令のアセンブリ生成 (caml2html: emit_gprim
Printf.fprintf oc "\tcmpw\tcr7, %s, %s\n" (reg x) (reg y);
g'_non_tail_if oc (NonTail(z)) e1 e2 "beq" "bne"
| NonTail(z), IfEq(x, C(y), e1, e2) ->
- Printf.fprintf oc "\tcmpwi\tcr7, %s, %d\n" (reg x) y;
+ Printf.fprintf oc "\tcmp %s, %d\n" (reg x) y;
g'_non_tail_if oc (NonTail(z)) e1 e2 "beq" "bne"
| NonTail(z), IfLE(x, V(y), e1, e2) ->
Printf.fprintf oc "\tcmpw\tcr7, %s, %s\n" (reg x) (reg y);
g'_non_tail_if oc (NonTail(z)) e1 e2 "ble" "bgt"
| NonTail(z), IfLE(x, C(y), e1, e2) ->
- Printf.fprintf oc "\tcmpwi\tcr7, %s, %d\n" (reg x) y;
+ Printf.fprintf oc "\tcmp %s, %d\n" (reg x) y;
g'_non_tail_if oc (NonTail(z)) e1 e2 "ble" "bgt"
| NonTail(z), IfGE(x, V(y), e1, e2) ->
Printf.fprintf oc "\tcmpw\tcr7, %s, %s\n" (reg x) (reg y);
g'_non_tail_if oc (NonTail(z)) e1 e2 "bge" "blt"
| NonTail(z), IfGE(x, C(y), e1, e2) ->
- Printf.fprintf oc "\tcmpwi\tcr7, %s, %d\n" (reg x) y;
+ Printf.fprintf oc "\tcmp %s, %d\n" (reg x) y;
g'_non_tail_if oc (NonTail(z)) e1 e2 "bge" "blt"
| NonTail(z), IfFEq(x, y, e1, e2) ->
Printf.fprintf oc "\tfcmpu\tcr7, %s, %s\n" (reg x) (reg y);
@@ -213,7 +213,7 @@ and g' oc = function (* 各命令のアセンブリ生成 (caml2html: emit_gprim
Printf.fprintf oc "\tldp fp, lr, sp, 16\n" and g'_tail_if oc e1 e2 b bn =
let b_else = Id.genid (b ^ "_else") in
- Printf.fprintf oc "\t%s\tcr7, %s\n" bn b_else;
+ Printf.fprintf oc "\t%s %s\n" bn b_else;
let stackset_back = !stackset in
g oc (Tail, e1);
Printf.fprintf oc "%s:\n" b_else;
@@ -222,7 +222,7 @@ and g'_tail_if oc e1 e2 b bn =
and g'_non_tail_if oc dest e1 e2 b bn =
let b_else = Id.genid (b ^ "_else") in
let b_cont = Id.genid (b ^ "_cont") in
- Printf.fprintf oc "\t%s\tcr7, %s\n" bn b_else;
+ Printf.fprintf oc "\t%s %s\n" bn b_else;
let stackset_back = !stackset in
g oc (dest, e1);
let stackset1 = !stackset in
動作確認
以下のコードをビルドして、5963が表示されればOK
code:iftest.ml
let rec double x = x + x in
let x = double 5 in
let y = if x >= 10 then 5963 else 4649 in
print_int y; print_newline ()
ビルド & 実行。5963 が表示されたので大丈夫そう。
code:sh
$ make clean && ./to_aarch64 && make min-caml && ./min-caml samples/iftest && gcc samples/iftest.s samples/stub.c -o samples/iftest && ./samples/iftest
(省略)
5963