Problem with an optimization for VA_STACK_ARG.
This is an optimization issue. This happens both Windows and Linux. By the way, as for Linux, you will face this problem after fixing the problem of #136. Currently this code does not correctly work on Linux because of the problem of #136.
Look at the following source code, for example, it is test.c.
int prinft(char*, ...);
#include <stdarg.h>
struct car {
char a, b, c;
};
int foo(int n, ...)
{
struct car c1, c2;
va_list args;
va_start(args, n);
c1 = va_arg(args, struct car);
int n1 = c1.a + c1.b + c1.c;
c2 = va_arg(args, struct car);
int n2 = c2.a + c2.b + c2.c;
va_end(args);
return n1 + n2;
}
int main(void)
{
struct car c1 = {1, 2, 3};
struct car c2 = {4, 5, 6};
printf("%d\n", foo(1, c2, c1));
return 0;
}
The MIR for the above code is here.
M0: module
proto0: proto i32, ...
proto1: proto i32, i32:i0_n, ...
import printf
foo: func i32, i32:i0_n, ...
local i64:fp, i64:I_0, i64:i_1, i64:I_2, i64:I_3, i64:I_4, i64:I_5, i64:i0_n1
local i64:i_6, i64:i_7, i64:i_8, i64:I_9, i64:I_10, i64:I_11, i64:I_12, i64:i0_n2
local i64:i_13, i64:i_14, i64:i_15
# 1 arg, 19 locals
alloca fp, 48
add I_0, fp, 16
va_start I_0
add I_2, fp, 48
add I_4, fp, 16
va_stack_arg I_3, I_4, 3
mov I_5, 3
L1:
sub I_5, I_5, 1
mov i8:3(fp, I_5), i8:(I_3, I_5)
bgt L1, I_5, 0
adds i_6, i8:3(fp), i8:4(fp)
adds i_7, i_6, i8:5(fp)
mov i0_n1, i_7
add I_9, fp, 48
add I_11, fp, 16
va_stack_arg I_10, I_11, 3
mov I_12, 3
L2:
sub I_12, I_12, 1
mov i8:(fp, I_12), i8:(I_10, I_12)
bgt L2, I_12, 0
adds i_13, i8:(fp), i8:1(fp)
adds i_14, i_13, i8:2(fp)
mov i0_n2, i_14
adds i_15, i0_n1, i0_n2
ret i_15
endfunc
export foo
main: func i32
local i64:fp, i64:I_0, i64:I_1, i64:I_2, i64:I_3, i64:I_4, i64:I_5, i64:i_6
local i64:i_7, i64:I_8, i64:i_9, i64:I_10, i64:i_11
# 0 args, 13 locals
alloca fp, 16
ext8 I_0, 1
mov i8:9(fp), I_0
ext8 I_1, 2
mov i8:10(fp), I_1
ext8 I_2, 3
mov i8:11(fp), I_2
ext8 I_3, 4
mov i8:6(fp), I_3
ext8 I_4, 5
mov i8:7(fp), I_4
ext8 I_5, 6
mov i8:8(fp), I_5
add I_8, fp, 6
mov i_9, i32:(I_8)
add I_10, fp, 9
mov i_11, i32:(I_10)
call proto1, foo, i_7, 1, i_9, i_11
call proto0, printf, i_6, "%d\n\000", i_7
ret 0
endfunc
export main
endmodule
You will see 2 of va_stack_arg instruction above, but you will see the incorrect result only with -O2 below when you execute it.
$ ./c2m -O0 test.c -eg
21
$ ./c2m -O1 test.c -eg
21
$ ./c2m -O2 test.c -eg
30
Thanks in advance.
Thank you a lot for reporting this problem. I did not reproduce exactly your results but I am getting rather random results which are wrong too.
I'll look and try to fix this problem this week.
Thanks for your comment.
Your random results will be caused by the problem of #136, if it is on Linux. After you fix the problem of #136, you will face this problem also on Linux.
Thanks in advance.