Hi,
This seems to be the issue causing SQLite compilation to fail (or at least
part of it/related to it).

When a function pointer is declared in a particular way, it seems that
__stdcall (and presumably other attributes?) are ignored. As a result, TCC
thinks the function is caller-cleanup when it is not, and the stack gets
"cleaned" twice.

See the full test case attached. As a quick summary,

This works:
((int __stdcall (*)(int, int, int))some_stdcall_func) (2, 0, 0);

And so does this:
((int(*__stdcall)(int, int, int))some_stdcall_func) (3, 0, 0);

But this fails:
((int(__stdcall*)(int, int, int))some_stdcall_func) (4, 0, 0);

This is mostly relevant on 32-bit Windows (where the stdcall convention is
common).
// tcc -m32 minimal.c

#include <stdio.h>

void printf_stack_pointer(int ln) {
    unsigned int i;
    asm("\t movl %%esp,%0" : "=r"(i));
    printf("At line %i, SP is %u\n", ln, i);
}

#define PRINTF_STACK_POINTER printf_stack_pointer(__LINE__);


__stdcall int some_stdcall_func(int foo, int bar, int baz) {
        printf("Hello from stdcall: %i\n", foo);
        return 12;
}


int main() {

        PRINTF_STACK_POINTER
        // Baseline stack pointer for comparison.

        some_stdcall_func(1, 0, 0);
        PRINTF_STACK_POINTER
        // No problem. Stack pointer is unchanged, as it should be.


        ((int __stdcall (*)(int, int, int))some_stdcall_func) (2, 0, 0);
        PRINTF_STACK_POINTER
        // Still no problem.


        ((int(*__stdcall)(int, int, int))some_stdcall_func) (3, 0, 0);
        PRINTF_STACK_POINTER
        // Still no problem.


        ((int(__stdcall*)(int, int, int))some_stdcall_func) (4, 0, 0);
        PRINTF_STACK_POINTER
        // Problem! Notice that SP is now 12 ( e.g. sizeof(int)*3 ) bytes 
higher.

        // My guess: For whatever reason TCC thinks this is a cdecl function
        // (caller-cleanup) and has generated code to recover the stack.

        // Of course, since the function is actually callee-cleanup, it has 
already
        // did that. The stack has been "cleaned" twice and is now sizeof(args) 
too high.

        // Seems to happen when the calling convention attribute is inside the 
brackets
        // AND before the asterisk.
        
}
_______________________________________________
Tinycc-devel mailing list
[email protected]
https://lists.nongnu.org/mailman/listinfo/tinycc-devel

Reply via email to