Earlier quoted context omitted.
It gets even funnier in OCaml where they nominally defined it UB in order to get the freedom to make the only existing implementation always 100% reliably evaluate right-to-left, which reportedly was better for performance or something :) And before somebody wonders about currying and eager evaluation, the problem is not functions but type constructors, which aren't curried.
The functions arguments are pushed onto the stack. From within the function you can think of the stack as an array. void test(a, b, c) stack[0] == a stack[1] == b stack[2] == c But to get the items in the stack in that order you have to... puch c push b push a If you wanted to do that, and still allow for left to right evaluation you could... temp_a = a temp_b = b temp_c = c push c puch b push a That would be 2x inst…
Instead, the stackframe is created in one go with a single change to the stack pointer and then the values are filled in in whatever order the compiler / language desires.
Here is a typical example using GCC:
movq %rsp, %rbp
subq $16, %rsp
movl $12, -4(%rbp)
addl $1, -4(%rbp)
movl -4(%rbp), %eax
movl $14, %edx
movl %eax, %esi
movl $12, %edi
call f
Which moves the parameters using registers (subject to availability) as a further optimization. The 'subq' reserves space for the stackframe with addresses relative to rbp being the parameters.