| Commit message (Collapse) | Author | Age | Files | Lines |
| |
|
|
|
|
| |
Still some more tabs to be taken care of. arm-gen.c and tcccoff.c
have so many style issues that I'm just going to throw clang-format
at them.
|
| | |
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Jsut for testing. It works for me (don't break anything)
Small fixes for x86_64-gen.c in "tccpp: fix issues, add tests"
are dropped in flavor of this patch.
Pip Cet:
Okay, here's a first patch that fixes the problem (but I've found
another bug, yet unfixed, in the process), though it's not
particularly pretty code (I tried hard to keep the changes to the
minimum necessary). If we decide to actually get rid of VT_QLONG and
VT_QFLOAT (please, can we?), there are some further simplifications in
tccgen.c that might offset some of the cost of this patch.
The idea is that an integer is no longer enough to describe how an
argument is stored in registers. There are a number of possibilities
(none, integer register, two integer registers, float register, two
float registers, integer register plus float register, float register
plus integer register), and instead of enumerating them I've
introduced a RegArgs type that stores the offsets for each of our
registers (for the other architectures, it's simply an int specifying
the number of registers). If someone strongly prefers an enum, we
could do that instead, but I believe this is a place where keeping
things general is worth it, because this way it should be doable to
add SSE or AVX support.
There is one line in the patch that looks suspicious:
} else {
addr = (addr + align - 1) & -align;
param_addr = addr;
addr += size;
- sse_param_index += reg_count;
}
break;
However, this actually fixes one half of a bug we have when calling a
function with eight double arguments "interrupted" by a two-double
structure after the seventh double argument:
f(double,double,double,double,double,double,double,struct { double
x,y; },double);
In this case, the last argument should be passed in %xmm7. This patch
fixes the problem in gfunc_prolog, but not the corresponding problem
in gfunc_call, which I'll try tackling next.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* fix some macro expansion issues
* add some pp tests in tests/pp
* improved tcc -E output for better diff'ability
* remove -dD feature (quirky code, exotic feature,
didn't work well)
Based partially on ideas / researches from PipCet
Some issues remain with VA_ARGS macros (if used in a
rather tricky way).
Also, to keep it simple, the pp doesn't automtically
add any extra spaces to separate tokens which otherwise
would form wrong tokens if re-read from tcc -E output
(such as '+' '=') GCC does that, other compilers don't.
* cleanups
- #line 01 "file" / # 01 "file" processing
- #pragma comment(lib,"foo")
- tcc -E: forward some pragmas to output (pack, comment(lib))
- fix macro parameter list parsing mess from
a3fc54345949535524d01319e1ca6378b7c2c201
a715d7143d9d17da17e67fec6af1c01409a71a31
(some coffee might help, next time ;)
- introduce TOK_PPSTR - to have character constants as
written in the file (similar to TOK_PPNUM)
- allow '\' appear in macros
- new functions begin/end_macro to:
- fix switching macro levels during expansion
- allow unget_tok to unget more than one tok
- slight speedup by using bitflags in isidnum_table
Also:
- x86_64.c : fix decl after statements
- i386-gen,c : fix a vstack leak with VLA on windows
- configure/Makefile : build on windows (MSYS) was broken
- tcc_warning: fflush stderr to keep output order (win32)
|
| |
|
|
|
|
|
|
| |
Author: Philip <pipcet@gmail.com>
Our VLA code can be made a lot simpler (simple enough for
even me to understand it) by giving up on the optimization idea, which
is very tempting. There's a patch to do that attached, feel free to
test and commit it if you like. (It passes all the tests, at least
|
| |
|
|
|
|
|
|
| |
I think this code only affects the ARM EABI target, and only when
returning small structures that might be unaligned. However, it was both
leaking vstack entries and failing to achieve what I think is its
purpose, to ensure the sret argument would be aligned properly. Both
issues fixed.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This patch disables the optimization of saving stack pointers lazily,
which didn't fully take into account that control flow might not reach
the stack-saving instructions. I've decided to leave in the extra calls
to vla_sp_save() in case anyone wants to restore this optimization.
Tests added and enabled.
There are two remaining bugs: VLA variables can be modified, and jumping
into the scope of a declared VLA will cause a segfault rather than a
compiler error. Both of these do not affect correct C code, but should
be fixed at some point. Once VLA variables have been made properly
immutable, we can share them with the saved stack pointer and save stack
and instructions.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
as reported in
http://lists.nongnu.org/archive/html/tinycc-devel/2015-04/msg00131.html. Note
that this is one of two separate VLA bugs:
A. labels aren't reached by program execution, so the stack pointer is
never saved
B. continue doesn't restore the stack pointer as goto does
This fixes only B. I'm not sure whether the same issue applies to break
as well as continue.
Add a test case, but disable tests #78 and #79 for now as they're not
fully fixed until the issue described in
http://lists.nongnu.org/archive/html/tinycc-devel/2015-04/msg00110.html
is resolved.
|
| |
|
|
|
|
|
|
|
|
|
|
| |
- 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.
|
| |
|
|
|
|
|
|
|
|
| |
* 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.
|
| |
|
|
|
|
| |
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 warning: unnamed struct/union that defines no instances
- allow a nested named struct declaration w/o identifier
only when option -fms-extensions is used
|
| |
|
|
|
|
| |
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
|
| |
|
|
|
| |
Parse a type if there is only one '(' before a type token.
Otherwise a recursion will perform a job.
|
| |
|
|
| |
A right solution for this problem will follow.
|
| |
|
|
|
|
|
|
| |
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.
|
| | |
|
| |
|
|
|
|
| |
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.
|
| |
|
|
| |
Not the code was confused, I was :)
|
| |
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
| |
__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
|
| |
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
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 ','
|
| |
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
| |
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; }
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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 "(")
|
| |
|
|
|
|
|
|
|
|
|
| |
Allow tcc to compile the following program
///////
void func1() {}
void func2() {
return func1();
}
//////
gcc accepts this program
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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;
}
////////////////////
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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++;
}
|
| |
|
|
| |
Either this fix, or an alternative one, is required for arm64.
|
| | |
|
| |
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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)
|
| | |
|
| |
|
|
|
|
|
| |
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.
|
| | |
|
| | |
|
| | |
|
| |
|
|
|
|
|
|
|
|
|
| |
*** 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)
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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).
|
| | |
|
| | |
|
| |
|
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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
|
| |
|
|
|
| |
This makes int char c; and struct {} int c; generate an error. Thanks
Mobi Phil for reporting.
|
| | |
|