MinCamlのバグ修正 ( test/inprod-rec )
MLソース
code:test/inprod-rec.ml
let rec inprod v1 v2 i =
if i < 0 then 0.0 else
v1.(i) *. v2.(i) +. inprod v1 v2 (i - 1) in
let v1 = Array.make 3 1.23 in
let v2 = Array.make 3 4.56 in
print_int (truncate (1000000. *. inprod v1 v2 2))
アセンブリソース
code:asm
.data
.literal8
.align 3
l.44: # 1000000.000000
.long 0
.long 1093567616
.align 3
l.43: # 4.560000
.long -1546188227
.long 1074937200
.align 3
l.42: # 1.230000
.long 2061584302
.long 1072934420
.align 3
l.39: # 0.000000
.long 0
.long 0
.text
.globl _min_caml_start
.align 2
inprod.17:
cmp x2, 0
blt bge_else.49
lsl x3, x2, 3
ldr d0, x0, x3
lsl x3, x2, 3
ldr d1, x1, x3
fmul d0, d0, d1
sub x2, x2, 1
mov x26, lr
add x28, x28, 24
bl inprod.17
sub x28, x28, 24
mov lr, x26
fadd d0, d1, d0
ret
bge_else.49:
adrp x26, l.39@PAGE
ret
_min_caml_start: # main entry point
add x28, x0, 0
add x27, x1, 0
add x28, x28, 16
# main program starts
mov x0, 3
adrp x26, l.42@PAGE
mov x26, lr
add x28, x28, 8
bl _min_caml_create_float_array
sub x28, x28, 8
mov lr, x26
mov x1, 3
adrp x26, l.43@PAGE
mov x0, x1
mov x26, lr
add x28, x28, 16
bl _min_caml_create_float_array
sub x28, x28, 16
mov x1, x0
mov lr, x26
adrp x26, l.44@PAGE
mov x2, 2
mov x26, lr
add x28, x28, 40
bl inprod.17
sub x28, x28, 40
mov lr, x26
fmul d0, d1, d0
mov x26, lr
add x28, x28, 40
bl _min_caml_truncate
sub x28, x28, 40
mov lr, x26
mov x26, lr
add x28, x28, 40
bl _min_caml_print_int
sub x28, x28, 40
mov lr, x26
# main program ends
sub x28, x28, 16
ret
実行結果
code:sh
$ ocaml test/inprod-rec.ml
16826400
中間コード
code:ml
- : Asm.prog =
Asm.Prog
([(Id.L "l.92", 1000000.); (Id.L "l.91", 4.56); (Id.L "l.90", 1.23);
(Id.L "l.87", 0.)],
body =
Asm.Let (("%x3", Type.Int), Asm.Li 0,
Asm.Ans
(Asm.IfLE ("%x3", Asm.V "%x2",
Asm.Let (("%x3", Type.Int), Asm.Slw ("%x2", Asm.C 3),
Asm.Let (("%d0", Type.Float), Asm.Lfd ("%x0", Asm.V "%x3"),
Asm.Let (("%x3", Type.Int), Asm.Slw ("%x2", Asm.C 3),
Asm.Let (("%d1", Type.Float), Asm.Lfd ("%x1", Asm.V "%x3"),
Asm.Let (("%d0", Type.Float), Asm.FMul ("%d0", "%d1"),
Asm.Let (("%x3", Type.Int), Asm.Li 1,
Asm.Let (("%x2", Type.Int), Asm.Sub ("%x2", Asm.V "%x3"),
Asm.Let (("Tu93", Type.Unit), Asm.Save ("%d0", "Td61.81"),
Asm.Let (("%d0", Type.Float),
Asm.Let (("%d1", Type.Float), Asm.Restore "Td61.81",
Asm.Ans (Asm.FAdd ("%d1", "%d0")))))))))))),
Asm.Ans (Asm.FLi (Id.L "l.87")))));
ret = Type.Float}],
Asm.Let (("%x0", Type.Int), Asm.Li 3,
Asm.Let (("%d0", Type.Float), Asm.FLi (Id.L "l.90"),
Asm.Let (("%x0", Type.Array Type.Float),
Asm.CallDir (Id.L "_min_caml_create_float_array", "%x0", "%d0"), Asm.Let (("%x1", Type.Int), Asm.Li 3,
Asm.Let (("%d0", Type.Float), Asm.FLi (Id.L "l.91"),
Asm.Let (("Tu95", Type.Unit), Asm.Save ("%x0", "v1.69"),
Asm.Let (("%x1", Type.Array Type.Float),
Asm.CallDir (Id.L "_min_caml_create_float_array", "%x1", "%d0"), Asm.Let (("%d0", Type.Float), Asm.FLi (Id.L "l.92"),
Asm.Let (("%x2", Type.Int), Asm.Li 2,
Asm.Let (("%x0", Type.Int), Asm.Restore "v1.69",
Asm.Let (("Tu96", Type.Unit), Asm.Save ("%d0", "Td53.73"),
Asm.Let (("%d0", Type.Float),
Asm.Let (("%d1", Type.Float), Asm.Restore "Td53.73",
Asm.Let (("%d0", Type.Float), Asm.FMul ("%d1", "%d0"),
Asm.Let (("%x0", ...), ...))))))))))))))))
直った!
ldr x0, x1, x2 を ldr x0, [x1, x2] のように修正したら動いた
code:diff
diff --git a/AArch64/emit.ml b/AArch64/emit.ml
index 6cb9c92..8cb1c8b 100644
--- a/AArch64/emit.ml
+++ b/AArch64/emit.ml
@@ -106,9 +106,9 @@ and g' oc = function (* 各命令のアセンブリ生成 (caml2html: emit_gprim
| NonTail(x), FSub(y, z) -> Printf.fprintf oc "\tfsub\t%s, %s, %s\n" (reg x) (reg y) (reg z)
| NonTail(x), FMul(y, z) -> Printf.fprintf oc "\tfmul\t%s, %s, %s\n" (reg x) (reg y) (reg z)
| NonTail(x), FDiv(y, z) -> Printf.fprintf oc "\tfdiv\t%s, %s, %s\n" (reg x) (reg y) (reg z)
- | NonTail(x), Lfd(y, V(z)) -> Printf.fprintf oc "\tldr %s, %s, %s\n" (reg x) (reg y) (reg z)
+ | NonTail(x), Lfd(y, V(z)) -> Printf.fprintf oc "\tldr %s, %s, %s\n" (reg x) (reg y) (reg z) | NonTail(x), Lfd(y, C(z)) -> Printf.fprintf oc "\tldr %s, %s, %d\n" (reg x) (reg y) z - | NonTail(_), Stfd(x, y, V(z)) -> Printf.fprintf oc "\tstr %s, %s, %s\n" (reg x) (reg y) (reg z)
+ | NonTail(_), Stfd(x, y, V(z)) -> Printf.fprintf oc "\tstr %s, %s, %s\n" (reg x) (reg y) (reg z) | NonTail(_), Stfd(x, y, C(z)) -> Printf.fprintf oc "\tstr %s, %s, %d\n" (reg x) (reg y) z | NonTail(_), Comment(s) -> Printf.fprintf oc "#\t%s\n" s
(* 退避の仮想命令の実装 (caml2html: emit_save) *)