|
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 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" "{\n" " printf(\"%d > %d : %s\", 1000, 2000, greater(1000,2000) ? \"true\" : \"false\");\n" "}\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"); exit(1); } /* 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; func(); tcc_delete(s); return 0; } From: Louis Botha 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, Louis |
[Prev in Thread] | Current Thread | [Next in Thread] |