mir icon indicating copy to clipboard operation
mir copied to clipboard

Problem with an optimization for VA_STACK_ARG.

Open Kray-G opened this issue 5 years ago • 2 comments

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.

Kray-G avatar Nov 17 '20 10:11 Kray-G

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.

vnmakarov avatar Nov 17 '20 22:11 vnmakarov

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.

Kray-G avatar Nov 18 '20 00:11 Kray-G