aboutsummaryrefslogtreecommitdiff
path: root/tccgen.c
Commit message (Collapse)AuthorAgeFilesLines
...
* Revert "* and #pragma pop_macro("macro_name")"grischka2015-04-231-0/+1
| | | | | | | | | | | | - pop_macro incorrect with initially undefined macro - horrible implementation (tcc_open_bf) - crashes eventually (abuse of Sym->prev_tok) - the (unrelated) asm_label part is the opposite of a fix (Despite of its name this variable has nothing to do with the built-in assembler) This reverts commit 0c8447db7970813292a8be74ee50e49091be5d15.
* * and #pragma pop_macro("macro_name")seyko2015-04-211-1/+0
| | | | | | | | | | * give warning if pragma is unknown for tcc * don't free asm_label in sym_free(), it's a job of the asm_free_labels(). The above pragmas are used in the mingw headers. Thise pragmas are implemented in gcc-4.5+ and current clang.
* option to use an old algorithm of the array in struct initializationseyko2015-04-101-4/+31
| | | | | | This is for a case when no '{' is used in the initialization code. An option name is -fold-struct-init-code. A linux 2.4.26 can't find initrd when compiled with a new algorithm.
* a bounds checking code for the ARCH=x86_64seyko2015-04-101-2/+17
|
* fix the bug #31403: parser bug in structureseyko2015-04-101-3/+16
| | | | | | - a warning: unnamed struct/union that defines no instances - allow a nested named struct declaration w/o identifier only when option -fms-extensions is used
* make a bound checking more compatible with Windows 64seyko2015-03-261-4/+4
| | | | | | On Linux 32: sizeof(long)=32 == sizeof(void *)=32 on Linux 64: sizeof(long)=64 == sizeof(void *)=64 on Windows 64: sizeof(long)=32 != sizeof(void *)=64
* A right fix for the array in struct initialization w/o '{'seyko2015-03-231-20/+9
| | | | | Parse a type if there is only one '(' before a type token. Otherwise a recursion will perform a job.
* Revert of the commit: fix for the array in struct initialization w/o '{', case 2seyko2015-03-231-16/+9
| | | | A right solution for this problem will follow.
* restore a linux 2.4.26 kernel compilation (commit 5bcc3eed7b93 correction)seyko2015-03-201-1/+5
| | | | | | | | The following check in tccgen.c is removed if (nocode_wanted) tcc_error("statement expression in global scope"); This check is introduced in commit 5bcc3eed7b93 and breaks compilation of the linux 2.4.26 kernel.
* tccgen.c: (!nocode_wanted) -> (nocode_wanted) in arm64 part.Edmund Grimley Evans2015-03-101-2/+2
|
* Add some missing nocode_wanted guardThomas Preud'homme2015-03-101-16/+27
| | | | | | int i = i++ causes a segfault because of missing guard. Looking recursively at all backend functions called from middle end several more guard appeared to be missing.
* Remove incorrect commentMichael Matz2015-03-091-2/+0
| | | | Not the code was confused, I was :)
* Fix stack overwrite on structure returnMichael Matz2015-03-091-8/+12
| | | | | | | | | The common code to move a returned structure packed into registers into memory on the caller side didn't take the register size into account when allocating local storage, so sometimes that lead to stack overwrites (e.g. in 73_arm64.c), on x86_64. This fixes it by generally making gfunc_sret also return the register size.
* arm64: Implement __clear_cache.Edmund Grimley Evans2015-03-081-0/+12
| | | | | | __clear_cache is defined in lib-arm64.c with a single call to __arm64_clear_cache, which is the real built-in function and is turned into inline assembler by gen_clear_cache in arm64-gen.c
* tccgen.c: Optimise 0<<x, 0>>x, -1>>x, x&0, x*0, x|-1, x%1.Edmund Grimley Evans2015-03-071-10/+25
| | | | | | | | | More precisely, treat (0 << x) and so on as constant expressions, but not if const_wanted as we do not want to allow "case (x*0):", ... Do not optimise (0 / x) and (0 % x) here as x might be zero, though for an architecture that does not generate an exception for division by zero the back end might choose to optimise those.
* fix for the array in struct initialization w/o '{', case 2seyko2015-03-071-9/+16
| | | | | | | | | | | | | | a test program: struct { int a[2], b[2]; } cases[] = { { ((int)0), (((int)0)) }, ((int)0), (((int)0)) /* error: ',' expected (got ")") */ }; int main() { return 0; } This commit allow to skip ')' in the decl_initializer() and to see ','
* Add __builtin_return_address.Edmund Grimley Evans2015-03-061-1/+13
| | | | | | Implementation is mostly shared with __builtin_frame_address. It seems to work on arm64, i386 and x86_64. It may need to be adapted for other targets.
* fixing decl_initializer() for size_only: don't eat ')'seyko2015-03-051-2/+8
| | | | | | | | | | a test program: struct { int c[1]; } s1[] = { (int)0 }; /* OK */ struct { int c[1]; } s2[] = { { ((int)0) } }; /* OK */ struct { int c[1]; } s3[] = { 0 }; /* OK */ struct { int c[1]; } sx[] = { ((int)0) }; /* error: ')' expected (got "}") */ int main() { return 0; }
* A reverse of the commit 14745bdeb because of the problems while compiling ↵seyko2015-03-031-18/+15
| | | | | | | | | | | | | | | | | | | | | | | | | linux 2.4.26 A test program: /////////// typedef unsigned int __u32; static inline const __u32 __fswab32(__u32 x) { return ({ __u32 __tmp = (x) ; ___swab32(__tmp); }); } void func() { int aaa = 1; int snd_wnd = 2; int TCP_FLAG_ACK = 3; int pred_flags = (__builtin_constant_p((__u32) (((aaa << 26) | (__builtin_constant_p((__u32)((TCP_FLAG_ACK))) ? ({ __u32 __x = (((TCP_FLAG_ACK))); ((__u32)( (((__u32)(__x) & (__u32)0x000000ffUL) << 24) | (((__u32)(__x) & (__u32)0x0000ff00UL) << 8) | (((__u32)(__x) & (__u32)0x00ff0000UL) >> 8) | (((__u32)(__x) & (__u32)0xff000000UL) >> 24) )); }) : __fswab32(((TCP_FLAG_ACK)))) | snd_wnd))) ? ({ __u32 __x = ((((aaa << 26) | (__builtin_constant_p((__u32)((TCP_FLAG_ACK))) ? ({ __u32 __x = (((TCP_FLAG_ACK))); ((__u32)( (((__u32)(__x) & (__u32)0x000000ffUL) << 24) | (((__u32)(__x) & (__u32)0x0000ff00UL) << 8) | (((__u32)(__x) & (__u32)0x00ff0000UL) >> 8) | (((__u32)(__x) & (__u32)0xff000000UL) >> 24) )); }) : __fswab32(((TCP_FLAG_ACK)))) | snd_wnd))); ((__u32)( (((__u32)(__x) & (__u32)0x000000ffUL) << 24) | (((__u32)(__x) & (__u32)0x0000ff00UL) << 8) | (((__u32)(__x) & (__u32)0x00ff0000UL) >> 8) | (((__u32)(__x) & (__u32)0xff000000UL) >> 24) )); }) : __fswab32((((aaa << 26) | (__builtin_constant_p((__u32)((TCP_FLAG_ACK))) ? ({ __u32 __x = (((TCP_FLAG_ACK))); ((__u32)( (((__u32)(__x) & (__u32)0x000000ffUL) << 24) | (((__u32)(__x) & (__u32)0x0000ff00UL) << 8) | (((__u32)(__x) & (__u32)0x00ff0000UL) >> 8) | (((__u32)(__x) & (__u32)0xff000000UL) >> 24) )); }) : __fswab32(((TCP_FLAG_ACK)))) | snd_wnd)))); } //////////// error: ';' expected (got "(")
* a void to void cast.seyko2015-03-031-2/+14
| | | | | | | | | | | Allow tcc to compile the following program /////// void func1() {} void func2() { return func1(); } ////// gcc accepts this program
* a statement expressions with a pointer return typeseyko2015-03-031-1/+5
| | | | | | | | | | | | | A test program: ////////////// int main() { void *p = ({ 0 ; ((void *)1); }); } ///////////// Porblem is introduced in a commit a80acab: Display error on statement expressions with complex return type This error is exposed when compiling a linux 2.4.26. tcc 0.9.23 can sucessfully compile this version of the linux.
* iitialisation of the empty structseyko2015-03-031-0/+20
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Current tcc don't understand an initialization of the empty struct This problem was found trying to compile a linux kernel 2.4.26 which can be compiled by tcc 0.9.23 A test program: //////////////////// // ./tcc -c test_3.c // test_3.c:31: error: too many field init #undef __GNUC__ #undef __GNUC_MINOR__ #define __GNUC__ 2 #define __GNUC_MINOR__ 95 typedef struct { } rwlock_t; struct fs_struct { int count; rwlock_t lock; int umask; }; #define INIT_FS { \ 1, \ RW_LOCK_UNLOCKED, \ 0022, \ } #if (__GNUC__ > 2 || __GNUC_MINOR__ > 91) typedef struct { } rwlock_t; #define RW_LOCK_UNLOCKED (rwlock_t) { } #else typedef struct { int gcc_is_buggy; } rwlock_t; #define RW_LOCK_UNLOCKED (rwlock_t) { 0 } #endif static struct fs_struct init_fs = INIT_FS; // static struct fs_struct init_fs = { { (1) }, (rwlock_t) { 0 }, 0022, }; // ^ with this all Ok // static struct fs_struct init_fs = { { (1) }, (rwlock_t) { }, 0022, }; // ^ current tcc don't understand, but tcc 0.9.23 can int main() { return 0; } //////////////////// A regression is detected after a patch 69fdb57eddd00c592828605819f0678522d346c6 //////////////////// // A test for patch 69fdb57eddd00c592828605819f0678522d346c6 // Author: grischka <grischka> // Date: Wed Jun 17 02:09:07 2009 +0200 // unions: initzialize only one field // struct { // union { // int a,b; // }; // int c; // } sss = { 1,2 }; // This had previously assigned 1,2 to a,b and 0 to c which is wrong. // // Expected: sss.a=1 sss.b=1 sss.c=2 int main() { struct { union { int a,b; }; int c; } sss = { 1, 2 }; printf ("sss.a=%d sss.b=%d sss.c=%d\n", sss.a, sss.b, sss.c); return 0; } ////////////////////
* tcc don't understand am extern array of structs.seyko2015-03-031-2/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | A regression was found trying to compile a linux kernel 2.4.26 which can be compiled by tcc 0.9.23 /////////////////// #include <stdio.h> // test for a bug: // compiler don't understand am extern array of structs // $ tcc test_1.c // test_1.c:8: error: unknown struct/union/enum extern struct FILE std_files[4]; int main() { return 0; } ////////////////// tcc-current /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */ static void struct_decl(CType *type, int u, int tdef) ... if (tok != '{') { v = tok; next(); /* struct already defined ? return it */ if (v < TOK_IDENT) expect("struct/union/enum name"); s = struct_find(v); if (s) { if (s->type.t != a) tcc_error("invalid type"); goto do_decl; } else if (tok >= TOK_IDENT && !tdef) tcc_error("unknown struct/union/enum"); } else { v = anon_sym++; } tcc-0.9.23 which don't have such error /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */ static void struct_decl(CType *type, int u) .... if (tok != '{') { v = tok; next(); /* struct already defined ? return it */ if (v < TOK_IDENT) expect("struct/union/enum name"); s = struct_find(v); if (s) { if (s->type.t != a) error("invalid type"); goto do_decl; } } else { v = anon_sym++; }
* tccgen.c: Make sure that gen_op always returns an rvalue.Edmund Grimley Evans2015-02-231-0/+3
| | | | Either this fix, or an alternative one, is required for arm64.
* Add arm64 (AArch64) as a target architecture.Edmund Grimley Evans2015-02-231-25/+102
|
* Use RELA relocations properly for R_DATA_PTR on x86_64.Edmund Grimley Evans2015-02-211-8/+24
| | | | | | | libtcc.c: Add greloca, a generalisation of greloc that takes an addend. tcc.h: Add greloca and put_elf_reloca. tccelf.c: Add put_elf_reloca, a generalisation of put_elf_reloc. tccgen.c: On x86_64, use greloca instead of greloc in init_putv.
* Fix handling of case_reg in switch statement.Edmund Grimley Evans2015-02-201-0/+3
| | | | | | The back end functions gen_op(comparison) and gtst() might allocate registers so case_reg should be left on the value stack while they are called and set again afterwards.
* tccgen: use lvalue as result from bitfield assignmentgrischka2014-09-231-7/+5
| | | | | | | | | | | | | | | | | | | test case: #include <stdio.h> int main(int argc, char **argv) { struct _s { unsigned a:9, b:5, c:7; } _s, *s = &_s; int n = 250; s->a = s->b = s->c = n + 4; printf("--> %d / %d / %d\n", s->a, s->b, s->c); return 0; } before: --> 254 / 30 / 126 now: --> 30 / 30 / 126
* tccgen: nocode_wanted: do not output constantsgrischka2014-08-011-15/+18
| | | | | | | | | | | | | | | | | | | | This for example suppresses string constants such as with int main() { return sizeof "foo"; } Actually, setting nocode_wanted = 1; in libtcc.c for the initial global level seemed wrong, since obviously "nocode_wanted" means code as any side effects, also such as string constants. This reverts a part of 2de1b2d14cc920e2c698ff0086f5558c2da7f569 (documented as "Some in-between fixes" in Changelog)
* Remove unused variableMichael Matz2014-04-141-1/+0
|
* Parse and emit hidden visibilityMichael Matz2014-04-141-3/+57
| | | | | | | This adds parsing of (GCC compatible) visibility attribute in order to mark selected global symbols as hidden. The generated .o files contain hidden symbols already, the TCC linker doesn't yet do the right thing.
* add missing prototypesUrs Janssen2014-04-101-4/+8
|
* Fix test for macro nestingThomas Preud'homme2014-04-071-0/+2
|
* Corrected spelling mistakes in comments and stringsVincent Lefevre2014-04-071-2/+2
|
* win32: warn people about using undeclared WINAPI functionsgrischka2014-04-061-4/+10
| | | | | | | | | | | *** UNCONDITIONALLY *** Esp. sihce tinycc winapi headers are not as complete as people might expect this can otherwise lead to obscure problems that are difficult to debug. (Originally 'warn_implicit_function_declaration' was set to 1 always for windows but someone must have deleted that line)
* tccgen: x86_64: fix garbage in the SValue upper bitsgrischka2014-04-041-21/+9
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This was going wrong (case TOK_LAND in unary: computed labels) - vset(&s->type, VT_CONST | VT_SYM, 0); - vtop->sym = s; This does the right thing and is shorter: + vpushsym(&s->type, s); Test case was: int main(int argc, char **argv) { int x; static void *label_return = &&lbl_return; printf("label_return = %p\n", label_return); goto *label_return; //<<<<< here segfault on linux X86_64 without the memset on vset printf("unreachable\n"); lbl_return: return 0; } Also:: - Rename "void* CValue.ptr" to more usable "addr_t ptr_offset" and start to use it in obvious cases. - use __attribute__ ((noreturn)) only with gnu compiler - Revert CValue memsets ("After several days searching ...") commit 4bc83ac3933efa565ae3326b55fcd711b63c073d Doesn't mean that the vsetX/vpush thingy isn't brittle and there still might be bugs as to differences in how the CValue union was set and is then interpreted later on. However the big memset hammer was just too slow (-3% overall).
* Allow local redefinition of enumeratorThomas Preud'homme2014-03-311-1/+1
|
* Fix typo in code added by b018bac9c8Thomas Preud'homme2014-03-291-1/+1
|
* Create bcheck region for argv and arge argumentThomas Preud'homme2014-03-291-0/+15
| | | | | | | | | | | For program manipulating argv or arge as pointer with construct such as: (while *argv++) { do_something_with_argv; } it is necessary to have argv and arge inside a region. This patch create regions argv and arge) if main is declared with those parameters.
* After several days searching why my code refactoring to remove globals was ↵mingodad2014-03-261-1/+8
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | crashing, I found the problem it was because CValue stack variables have rubish as it inital values and assigning to a member that is smaller than the big union item and trying to recover it later as a different member gives bak garbage. ST_FUNC void vset(TCCState* tcc_state, CType *type, int r, int v) { CValue cval; memset(&cval, 0, sizeof(CValue)); cval.i = v; //,<<<<<<<<<<< here is the main bug that mix with garbage vsetc(tcc_state, type, r, &cval); } /* store a value or an expression directly in global data or in local array */ static void init_putv(TCCState* tcc_state, CType *type, Section *sec, unsigned long c, int v, int expr_type) { ... case VT_PTR: if (tcc_state->tccgen_vtop->r & VT_SYM) { greloc(tcc_state, sec, tcc_state->tccgen_vtop->sym, c, R_DATA_PTR); } //<<< on the next line is where we try to get the assigned value to cvalue.i as cvalue.ull *(addr_t *)ptr |= (tcc_state->tccgen_vtop->c.ull & bit_mask) << bit_pos; break; Also this patch makes vla tests pass on linux 32 bits
* Make parse_btype only accept one basic typeThomas Preud'homme2014-03-241-8/+15
| | | | | This makes int char c; and struct {} int c; generate an error. Thanks Mobi Phil for reporting.
* Fix type_to_str test for unsigned intThomas Preud'homme2014-03-091-1/+1
|
* Fix various errors uncovered by static analysisThomas Preud'homme2014-03-081-1/+0
| | | | Reported-by: Carlos Montiers <cmontiers@gmail.com>
* Def signedness != signed != unsigned for charThomas Preud'homme2014-02-061-13/+23
| | | | | | | | When checking for exact compatibility between types (such as in __builtin_types_compatible_p) consider the case of default signedness to be incompatible with both of the explicit signedness for char. That is, char is incompatible with signed char *and* unsigned char, no matter what the default signedness for char is.
* Fix parameter passing of long long bitfieldThomas Preud'homme2014-02-041-0/+3
|
* switch last 2 params of TOK_memset on ARMThomas Preud'homme2014-02-031-0/+5
| | | | | On ARM, TOK_memset is executed via __aeabi_memset which reverse the order of the last two parameters.
* Fix floating point unary minus and plusMichael Matz2014-01-121-17/+21
| | | | | | | negate(x) is subtract(-0,x), not subtract(+0,x), which makes a difference with signed zeros. Also +x was expressed as x+0, in order for the integer promotions to happen, but also mangles signed zeros, so just don't do that with floating types.
* Fix Fixes for PE x86_64 for fail in codeMichael Matz2014-01-111-27/+20
| | | | | | | Applying 64bit relocs assumes that the CVal is initialized to zero for the whole 64bit. Consolidate this a bit, at the same time zeroing the .ull member more consistently when needed. Fixes segfault on x86_64-linux using global vars in tcctest.c.
* Fixes previous fixesArchidemon2014-01-101-5/+5
|
* Fixes for PE x86_64 for fail in codeArchidemon2014-01-101-3/+15
| | | | | | | | | | | | int (*fn1)=0x13fde16b5; and int fn1(int a) {...} struct { int (*fn2)(int a); } b = { fn1 };