MinCamlのバグ修正 ( test/inprod-rec )
#MinCaml #AArch64
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
str d0, x28, 0
mov x26, lr
str x26, x28, 16
add x28, x28, 24
bl inprod.17
sub x28, x28, 24
ldr x26, x28, 16
mov lr, x26
ldr d1, x28, 0
fadd d0, d1, d0
ret
bge_else.49:
adrp x26, l.39@PAGE
ldr d0, x26, l.39@PAGEOFF
ret
_min_caml_start: # main entry point
add x28, x0, 0
add x27, x1, 0
str fp, x28, 0
str lr, x28, 8
add x28, x28, 16
# main program starts
mov x0, 3
adrp x26, l.42@PAGE
ldr d0, x26, l.42@PAGEOFF
mov x26, lr
str x26, x28, 0
add x28, x28, 8
bl _min_caml_create_float_array
sub x28, x28, 8
ldr x26, x28, 0
mov lr, x26
mov x1, 3
adrp x26, l.43@PAGE
ldr d0, x26, l.43@PAGEOFF
str x0, x28, 0
mov x0, x1
mov x26, lr
str x26, x28, 8
add x28, x28, 16
bl _min_caml_create_float_array
sub x28, x28, 16
ldr x26, x28, 8
mov x1, x0
mov lr, x26
adrp x26, l.44@PAGE
ldr d0, x26, l.44@PAGEOFF
mov x2, 2
ldr x0, x28, 0
str d0, x28, 16
mov x26, lr
str x26, x28, 32
add x28, x28, 40
bl inprod.17
sub x28, x28, 40
ldr x26, x28, 32
mov lr, x26
ldr d1, x28, 16
fmul d0, d1, d0
mov x26, lr
str x26, x28, 32
add x28, x28, 40
bl _min_caml_truncate
sub x28, x28, 40
ldr x26, x28, 32
mov lr, x26
mov x26, lr
str x26, x28, 32
add x28, x28, 40
bl _min_caml_print_int
sub x28, x28, 40
ldr x26, x28, 32
mov lr, x26
# main program ends
sub x28, x28, 16
ldr fp, x28, 0
str lr, x28, 8
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.)],
[{Asm.name = Id.L "inprod.65"; args = "%x0"; "%x1"; "%x2"; fargs = [];
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.CallDir (Id.L "inprod.65", "%x0"; "%x1"; "%x2", []),
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.CallDir (Id.L "inprod.65", "%x0"; "%x1"; "%x2", []),
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) *)