[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Tinycc-devel] Bug in _Bool return values

From: Christian Jullien
Subject: Re: [Tinycc-devel] Bug in _Bool return values
Date: Tue, 5 Feb 2019 08:58:00 +0100

Thanks for the sample. On ARM nothing has to be done as it returns the expected result.

I let other maintainers to see if your patch for Intel 32/64 is Ok.


From: Tinycc-devel [mailto:address@hidden On Behalf Of Louis Botha
Sent: lundi 4 février 2019 23:32
To: address@hidden
Subject: Re: [Tinycc-devel] Bug in _Bool return values


As requested by Christian here is a code-sample to replicate the bug

This borrows heavily from libtcc_test.c, so if you are able to run that you can run this, which requires passing in the path to where tcclib.h and libtcc1.a lies via a -B option, for example:  -Bc:/git/tcc/win32).


With out the fix the program prints:  1000 > 2000 : true

With this fix described below the program prints:  1000 > 2000 : false


#include <stdlib.h>

#include <stdio.h>

#include <stdbool.h>

#include "libtcc.h"


bool greater(int a, int b)


       return a > b;



char my_program[] =

"#include <tcclib.h>\n"

"#include <stdbool.h>\n\n"

"extern bool greater(int a, int b);\n\n"

"void foo(void)\n"


"    printf(\"%d > %d : %s\", 1000, 2000, greater(1000,2000) ? \"true\" : \"false\");\n"



int main(int argc, char **argv)


    TCCState *s;

    int i;

    void (*func)(void);


    s = tcc_new();

    if (!s) {

        fprintf(stderr, "Could not create tcc state\n");




    /* if tcclib.h and libtcc1.a are not installed, where can we find them */

    for (i = 1; i < argc; ++i) {

        char *a = argv[i];

        if (a[0] == '-') {

            if (a[1] == 'B')

                tcc_set_lib_path(s, a+2);

            else if (a[1] == 'I')

                tcc_add_include_path(s, a+2);

            else if (a[1] == 'L')

                tcc_add_library_path(s, a+2);




    tcc_set_output_type(s, TCC_OUTPUT_MEMORY);


    if (tcc_compile_string(s, my_program) == -1)

        return 1;


              tcc_add_symbol(s, "greater", greater);


    if (tcc_relocate(s, TCC_RELOCATE_AUTO) < 0)

        return 1;


    func = tcc_get_symbol(s, "foo");

    if (!func)

        return 1;






    return 0;





From: Louis Botha
Sent: Sunday, February 3, 2019 4:54 PM
To: 'address@hidden' <address@hidden>
Subject: Bug in _Bool return values


Hi TCC-fans,


Think I found a bug in the implementation of _Bool in return values in version 0.9.27, found on i386, probably applies to x86_64, and possibly others as well:

Since sizeof(_Bool) == 1 as implemented in TCC, I believe this comment in i386-gen.c applies:

extend the return value to the whole register if necessary

visual studio and gcc do not always set the whole eax register

when assigning the return value of a function


The scenario that broke for me was calling a function that only set the AL register on return, leaving the rest of EAX undefined, yet TCC checked the whole of EAX for the _Bool return value (true came out correct, but false tested as true when the undefined-bits were non-0)


Assigning the _Bool return value to a _Bool variable and then checking that variable instead of the return value is one confirmed workaround (the emitted TCC code then uses just AL to generate a full EAX before checking EAX), but I think I have found the proper fix:


Add “case VT_BOOL:” as shown here, just after line 365 of i386-gen.c:


switch (rt & VT_BTYPE) {

    case VT_BYTE:

    case VT_BOOL:


This modification fixed the problem I was having, I *think* the line in x86_64-gen.c that needs to change for the equivalent there is this (@ line 934):


else if (bt == VT_BYTE || bt == VT_BOOL)


Sorry, I don’t know the other architectures or TCC in general well enough to comment on other places that may also need this fix.


Best regards,



reply via email to

[Prev in Thread] Current Thread [Next in Thread]