All asm codes are compiled in https://godbolt.org/, by x86-64 ocamlopt 5.2.0.
let declaration
Let’s start from a simple example. A whole file is written with only two lines:
| |
Compiled:
| |
The value of the list is stored in segment.
The immediate value $21 is the value of a 10, I guess that may bring some benefit for arithmetic (And 21 >> 1 == 10).
The 3 in camlExample.3 is the 1, and the 5 in camlExample.2 is the 2.
I can see the linked list structure that there’s an address right after the integer data(and there’s a 1 as zero standing for the tail).
After get the address of the variables, it calls the function caml_initialize, the 1st is caml_initialize(camlExample, 10) and the 2nd is caml_initialize(camlExample+8, camlExample.3).
So I know the data in camlExample stores the pointer of the variables.
The official doc also mentioned it.
I also see that it mov a strange value %r14 + 64 to %rsp to take place of previous %rsp. This is not easy to explain. In short, OCaml compiler use Emulating Thread Local Storage tech in gcc to let the OCaml processes run as threads of C process, which causes the variable declaration caml_initialize should use the main thread process stack address %r14 + 0x40. It doesn’t matter and I can just ignore it(although I takes hours to make it up).
curry
Source code
| |
Assembly
| |
Because the interger in OCaml is OCamlnum == realnum * 2 + 1, The leaq -1(%rax,%rbx), %rax in camlExample.fun_342 is doing a plus operation. It’s my (fun acc x -> acc + x).
At here the official doc said %r15 is used as a heap pointer in my case:OCaml on x86_64 architectures caches the location of the minor heap in the %r15 register since it's so frequently referenced in OCaml functions.
It’s amazing that there’s two ways to curry a function. The first is the camlExample.4, use a built-in function to curry my lambda function. Another is to build a sequence for a expression, and evaluate it.