Commit Graph

571 Commits

Author SHA1 Message Date
Michael Matz
c7dbc900c8 Cleanups (float consts, sections, symbols)
introduce common_section (SHN_COMMON), factorize some handling
in decl_initializer_alloc, add section_add and use it to factorize
some code that allocates stuff in sections (at the same time also fixing
harmless bugs re section alignment), use init_putv to emit float consts
into .data from gv() (fixing an XXX).
2017-05-02 03:13:55 +02:00
Michael Matz
25522e4799 Merge func_decl_list into decl0
Removes some code duplication and also implements one feature:
checking for duplicate decls for old style parameters.
2017-05-02 03:07:37 +02:00
Michael Matz
7aef0522b0 Tidy decl_designator
The fixme therein is long solved.
2017-05-02 03:07:37 +02:00
Michael Matz
8ca98e23c4 Tidy unary() a bit
factor code a bit for transforming tokens into SValues.  This revealed
a bug in TOK_GET (see testcase), which happened to be harmless before.
So fix that as well.
2017-05-02 03:07:37 +02:00
Michael Matz
21b12ea10d Factor some code
Three places that skip (and store) tokens in some fashion can
be factored a bit.
2017-05-02 03:07:37 +02:00
Michael Matz
328b06a3fc Extend type_to_str
to also print storage-class specifiers.
2017-05-02 03:07:36 +02:00
Michael Matz
182367e232 Reorganize type parsing
Various corner cases for declarator parsing were incorrect.  This
reorganizes and fixes it, and somewhat simplifies it as well.
2017-05-02 03:07:36 +02:00
Michael Matz
5891fbc0c8 Tidy typename parsing a bit 2017-05-02 03:07:36 +02:00
Michael Matz
51314932e3 Tidy arg parsing for builtins
Saves some lines of code.
2017-05-02 03:07:36 +02:00
Michael Matz
a8b83ce43a Remove VT_REF
The canonical way to describe a local variable that actually holds
the address of an lvalue is VT_LLOCAL.  Remove the last user of VT_REF,
and handling of it, thereby freeing a flag for SValue.r.
2017-05-02 03:07:36 +02:00
Michael Matz
8b9697ca6b Fix bogus check for VT_LLOCAL types
VT_LLOCAL is a flag on .r, not on type.t.  Fixing this requires
minor surgery for compound literals which accidentally happened
to be subsumed by the bogus test.
2017-05-02 03:07:36 +02:00
Michael Matz
3c39cb5cd8 fix __builtin_expect
the second argument can be an arbitrary expression (including
side-effects), not just a constant.  This removes the last user
of expr_lor_const and hence also that function (and expr_land_const).
Also the argument to __builtin_constant_p can be only a non-comma
expression (like all functions arguments).
2017-05-02 03:07:36 +02:00
Michael Matz
8d9dd3c008 Fix more bitfield corner cases
Our code generation assumes that it can load/store with the
bit-fields base type, so bit_pos/bit_size must be in range for this.
We could change the fields type or adjust offset/bit_pos; we do the
latter.
2017-05-01 06:18:48 +02:00
Michael Matz
4ce73354fc Fix last change
Skipping anonymous bit-fields is correct, but not other
anonymous ones like unions or structs.
2017-05-01 06:04:19 +02:00
Michael Matz
f775d68725 Remove a bit-field TODO
Checked the lcc testsuite for bitfield stuff (in cq.c and fields.c),
fixed one more error in initializing unnamed members (which have
to be skipped), removed the TODO.
2017-04-29 22:09:10 +02:00
Michael Matz
28084420fe Fix char bitfields corner case
See testcase.
2017-04-29 21:25:31 +02:00
grischka
7acf9aa862 final adjustments for release
- configure/Makefiles: minor adjustments

- build-tcc.bat: add -static to gcc options
  (avoids libgcc_s*.dll dependency with some mingw versions)

- tccpe.c/tcctools.c: eliminate MAX_PATH
  (not available for cross compilers)

- tccasm.c: use uint64_t/strtoull in unary()
  (unsigned long sometimes is only uint32_t, as always on windows)

- tccgen.c: Revert (f077d16c) "tccgen: gen_cast: cast FLOAT to DOUBLE"
  Was a rather experimental, tentative commit, not really necessary
  and somewhat ugly too.

- cleanup recent osx support:
  - Makefile/libtcc.c: cleanup copy&paste code
  - tccpp.c: restore deleted function
2017-04-25 21:01:54 +02:00
grischka
536ed76d5a tccgen/win32: let __declspec(dllimport) imply extern
Also, retain storage qualifiers in type_decl, in particular
also for function pointers.  This allows to get rid of this
very early hack in decl()
    type.t |= (btype.t & VT_STATIC); /* Retain "static". */
which was to fix the case of
    int main() { static int (*foo)(); ...

Also:
- missing __declspec(dllimport) is an error now
- except if the symbol is "_imp__symbol"
- demonstrate export/import of data in the dll example (while
  'extern' isn't strictly required with dllimport anymore)
- new function 'patch_storage()' replaces 'weaken_symbol()'
  and 'apply_visibility()'
- new function 'update_storage()' applies storage attributes
  to Elf symbols.
- put_extern_sym/2 accepts new pseudo section SECTION_COMMON
- add -Wl,-export-all-symbols as alias for -rdynamic
- add -Wl,-subsystem=windows for mingw compatibility
- redefinition of 'sym' error for initialized global data
2017-04-04 08:34:52 +02:00
grischka
5f33d313c8 tcc: re-enable correct option -r support
Forgot about it.  It allows to compile several
sources (and other .o's) to one single .o file;

    tcc -r -o all.o f1.c f2.c f3.S o4.o ...

Also:
- option -fold-struct-init-code removed, no effect anymore
- (tcc_)set_environment() moved to tcc.c
- win32/lib/(win)crt1 minor fix & add dependency
- debug line output for asm (tcc -c -g xxx.S) enabled
- configure/Makefiles: x86-64 -> x86_64 changes
- README: cleanup
2017-02-20 18:58:08 +01:00
grischka
a4a20360e9 fixes & cleanups
- tccgen.c/tcc.h: allow function declaration after use:
      int f() { return g(); }
      int g() { return 1; }
  may be a warning but not an error
  see also 76cb1144ef

- tccgen.c: redundant code related to inline functions removed
  (functions used anywhere have sym->c set automatically)

- tccgen.c: make 32bit llop non-equal test portable
  (probably not on C67)

- dynarray_add: change prototype to possibly avoid aliasing
  problems or at least warnings

- lib/alloca*.S: ".section .note.GNU-stack,"",%progbits" removed
  (has no effect)

- tccpe: set SizeOfCode field (for correct upx decompression)

- libtcc.c: fixed alternative -run invocation
      tcc "-run -lxxx ..." file.c
  (meant to load the library after file).
  Also supported now:
      tcc files ... options ... -run @ arguments ...
2017-02-13 18:23:43 +01:00
grischka
ec6a997f80 tccgen: yet another nocode_wanted fix
Some code in gen_opl was depending on a gvtst label
which in nocode_wanted mode is not set.

This was causing vstack leaks and crashes with for example

  long long ll;
  if (0)
      return ll - 10 < 0;
2017-02-12 13:21:20 +01:00
grischka
68666eee2a tccgen: factor out gfunc_return
Also:
- on windows i386 and x86-64, structures of size <= 8 are
  NOT returned in registers if size is not one of 1,2,4,8.
- cleanup: put all tv-push/pop/swap/rot into one place
2017-02-08 19:45:31 +01:00
grischka
f077d16c20 tccgen: gen_cast: cast FLOAT to DOUBLE
... to avoid precision loss when casting to int,
also when saving FLOATs to stack
2017-02-05 14:30:20 +01:00
Michael Matz
42e2a67f23 Fix some code suppression fallout
Some more subtle issues with code suppression:
- outputting asms but not their operand setup is broken
- but global asms must always be output
- statement expressions are transparent to code suppression
- vtop can't be transformed from VT_CMP/VT_JMP when nocode_wanted

Also remove .exe files from tests2 if they don't fail.
2016-12-20 04:58:34 +01:00
grischka
559ee1e940 i386-gen: fix USE_EBX
Restore ebx from *ebp because alloca might change esp.

Also disable USE_EBX for upcoming release.

Actually the benefit is less than one would expect, it
appears that tcc can't do much with more than 3 registers
except with extensive use of long longs where the disassembly
looks much prettier (and shorter also).

Also: tccgen/expr_cond() : fix wrong gv/save_regs order
2016-12-19 00:33:01 +01:00
grischka
a1c12b9fb9 tests: add memory leak test
Also ...

tcctest.c:
- exclude stuff that gcc doesn't compile on windows.

libtcc.c/tccpp.c:
- use unsigned for memory sizes to avoid printf format warnings
- use "file:line: message" to make IDE error parsers happy.

tccgen.c: fix typo
2016-12-18 22:05:42 +01:00
grischka
f7fc4f02cf tccgen: nocode_wanted++/--
uses 'nocode_wanted' as a level couter instead of
'saved_nocode_wanted' everywhere.
2016-12-18 18:58:33 +01:00
grischka
e5efd18435 tccgen: fix expr_cond for alt. nocode_wanted
making shure that both the active and the passive branches
do exacly the same thing.
2016-12-18 18:55:55 +01:00
grischka
f843cadb6b tccgen: nocode_wanted alternatively
tccgen.c: remove any 'nocode_wanted' checks, except in
- greloca(), disables output elf symbols and relocs
- get_reg(), will return just the first suitable reg)
- save_regs(), will do nothing

Some minor adjustments were made where nocode_wanted is set.

xxx-gen.c: disable code output directly where it happens
in functions:
- g(), output disabled
- gjmp(), will do nothing
- gtst(), dto.
2016-12-18 18:53:21 +01:00
Michael Matz
b5b12b89a0 arm64: Fix a case of dead code suppression
82_nocode_wanted.c:kb_wait_2_1 was miscompiled on arm64.
2016-12-15 17:49:56 +01:00
Michael Matz
f5ae4daa5f struct-layout: Allow lowering of member alignment
when an alignment is explicitely given on the member itself,
or on its types attributes then respect it always.  Was only
allowed to increase before, but GCC is allowing it.
2016-12-15 17:49:56 +01:00
Michael Matz
8859dc9e6d Support large alignment requests
The linux kernel has some structures that are page aligned,
i.e. 4096.  Instead of enlarging the bit fields to specify this,
use the fact that alignment is always power of two, and store only
the log2 minus 1 of it.  The 5 bits are enough to specify an alignment
of 1 << 30.
2016-12-15 17:49:56 +01:00
Michael Matz
d815a0f658 struct-layout: cleanup code a bit 2016-12-15 17:49:56 +01:00
Michael Matz
23b257a8d2 bitfields: Fix MS layout some more
Another corner case:
  struct foo6_1
  {
    char x;
    short p:8;
    short :0;
    short :0;
    short p2:8;
    char y;
  };

In MS layout the second anon :0 bit-field does _not_ adjust size or
alignment of the struct again.  The first one does, though.
2016-12-15 17:49:56 +01:00
Michael Matz
ed680da951 bitfields: fix PCC layout
Fixes some corner cases in PCC layout.  Testcases coming
up.
2016-12-15 17:49:56 +01:00
Michael Matz
bd69bce20f bitfields: Implement MS compatible layout
Bit-fields are layed out differently in visual C, this implements
a compatible mode.  Checked against Visual C/C++ 2016.
Unfortunately the GCC implementation of MS layout (behind
-mms-bitfields) actually is different, and hence not compatible
with MS in all cases :-/
2016-12-15 17:49:56 +01:00
Michael Matz
78c7096162 Fix struct layout some more
Anonymous sub-sub-members weren't handled correctly.  Bit-fields
neither: this implements PCC layout for now.  It temporarily disables
MS-compatible bit-field layout.
2016-12-15 17:49:56 +01:00
Michael Matz
ddecb0e685 Split off record layouting
Such struct decl:

  struct S { char a; int i;} __attribute__((packed));

should be accepted and cause S to be five bytes long (i.e.
the packed attribute should matter).  So we can't layout
the members during parsing already.  Split off the offset
and alignment calculation for this.
2016-12-15 17:49:56 +01:00
Michael Matz
22f5fccc2c Fix 64bit enums and switch cases
See testcases.  We now support 64bit case constants.  At the same time
also 64bit enum constants on L64 platforms (otherwise the Sym struct
isn't large enough for now).  The testcase also checks for various
cases where sign/zero extension was confused.
2016-12-15 17:49:56 +01:00
Michael Matz
d042e71e9f Fix miscompile with dead switches
In certain very specific situations (involving switches
with asms inside dead statement expressions) we could generate
invalid code (clobbering the buffer so much that we generated
invalid instructions).  Don't emit the decision table if the
switch itself is dead.
2016-12-15 17:49:55 +01:00
Michael Matz
235711f3d3 64bit: Fix addends > 32 bits
If a symbolic reference is offsetted by a constant > 32bit
the backends can't deal with that, so don't construct such
values.
2016-12-15 17:49:55 +01:00
Michael Matz
ddd461dcc8 Fix initializing members multiple times
When intializing members where the initializer needs relocations
and the member is initialized multiple times we can't allow
that to lead to multiple relocations to the same place.  The last
one must win.
2016-12-15 17:49:53 +01:00
Michael Matz
f081acbfba Support local register variables
Similar to GCC a local asm register variable enforces the use of a
specified register in asm operands (and doesn't otherwise
matter).  Works only if the variable is directly mentioned as
operand.  For that we now generally store a backpointer from
an SValue to a Sym when the SValue was the result of unary()
parsing a symbol identifier.
2016-12-15 17:47:13 +01:00
Michael Matz
3bc9c325c5 Fix const folding of 64bit pointer constants
See testcase.
2016-12-15 17:47:12 +01:00
Michael Matz
7ab35c6265 struct-init: Copy relocs for compound literals
When copying the content of compound literals we must
include relocations as well.
2016-12-15 17:47:12 +01:00
Michael Matz
ad8e14b740 opt: Don't emit inline functions from dead code
Inside dead code don't regard inline functions as being
referenced.
2016-12-15 17:47:12 +01:00
Michael Matz
fb933ae0eb opt: constprop also 'cond && 0'
We didn't handle constants in logical expressions when they weren't
the first operand.  Some reordering in the loop structure is enough
to handle them.
2016-12-15 17:47:12 +01:00
Michael Matz
ca435dc2e3 opt: Make break and goto not fallthrough
As we can optimize dead code a bit already it's fitting
to disable code emission after break and goto.
2016-12-15 17:47:12 +01:00
Michael Matz
31c7ea0165 opt: Start optimizing dead code a bit
If a condition is always zero/non-zero we can omit the
then or else code.  This is complicated a bit by having to
deal with labels that might make such code reachable without
us yet knowing during parsing.
2016-12-15 17:47:12 +01:00
Michael Matz
b303a00ce0 Revert "Reject jumping inside stmtexprs"
Not fully thought out.  You can't jump inside stmt exprs,
but you can jump out of them.  So there's a difference
between undefined but declared labels at the end of stmt
exprs and those defined inside.  Additionally it should
also be checked if a label defined inside a stmt expr
was tentatively created as declared from outside.

I'm not prepared doing that right now, so simply revert.

This reverts commit 9160e4cab9147d77840cc44a285031fdb4640cf9.
2016-12-15 17:47:11 +01:00
Michael Matz
d4d3144e75 Factor out const condition detection
Creating condition_3way for this.
2016-12-15 17:47:11 +01:00
Michael Matz
892c3d996f Reject jumping inside stmtexprs
One can't jump into statement expressions from outside
them, like the following:

  int i = ({ label: foo(); 42; });
  goto label;

We reject this by making the labels simply not available
outside (GCC has a nicer error message about jumping into
a statement expression).
2016-12-15 17:47:11 +01:00
Michael Matz
1602998751 Fix more nocode_wanted jump problems
In statement expression we really mustn't emit backward jumps
under nocode_wanted (they will form infinte loops as no expressions
are evaluated).  Do-while and explicit loop with gotos weren't
handled.
2016-12-15 17:47:11 +01:00
Michael Matz
f2a071e808 Fix aliases on 64 bit
Use correct width ELF structure.
2016-12-15 17:47:11 +01:00
Michael Matz
9656560f14 Fix sizeof(char[a])
The sizes of VLAs need to be evaluated even inside sizeof,
i.e. when nocode_wanted is set.
2016-12-15 17:47:11 +01:00
Michael Matz
49bb5a7e06 Fix __builtin_constant_p(1000/x)
was incorrectly treated as constant because the vpop removed
all traces of non-constness.
2016-12-15 17:47:11 +01:00
Michael Matz
372f4b6a4e Fix enum bitfields passed to stdarg functions
VT_ENUM types use the .ref member and can be VT_BITFIELD,
so we need to copy it as well.  Simply do it always.
2016-12-15 17:47:11 +01:00
Michael Matz
d720865fb6 Addresses of non-weak symbols are non-zero
Use this fact in some foldings of comparisons.  See testcase.
2016-12-15 17:47:10 +01:00
Michael Matz
be6d8ffc10 Fix access-after-free with statement expressions
The return value of statement expressions might refer to local
symbols, so those can't be popped.  The old error message always
was just a band-aid, and since disabling it for pointer types it
wasn't effective anyway.  It also never considered that also the
vtop->sym member might have referred to such symbols (see the
testcase with the local static, that used to segfault).

For fixing this (can be seen better with valgrind and SYM_DEBUG)
simply leave local symbols of stmt exprs on the stack.
2016-12-15 17:47:10 +01:00
Michael Matz
34fc6435ee enums and ints are compatible
But like GCC do warn about changes in signedness.  The latter
leads to some changes in gen_assign_cast to not also warn about
  unsigned* = int*
(where GCC warns, but only with extra warnings).
2016-12-15 17:47:10 +01:00
Michael Matz
b1a906b970 enums and ints are compatible 2016-12-15 17:47:10 +01:00
Michael Matz
4e46c22d5c struct-init: Support range inits for local vars
Implement missing support for range init for local variables.
2016-12-15 17:47:09 +01:00
Michael Matz
b7ca74577b struct-init: Allow member initialization from qualified lvalues
See testcase.
2016-12-15 17:47:09 +01:00
Michael Matz
9e86ebee94 struct-init: Correctly parse unnamed member initializers
For
  union U { struct {int a,b}; int c; };
  union U u = {{ 1, 2, }};
The unnamed first member of union U needs to actually exist in the
structure so initializer parsing isn't confused about the double braces.
That means also the a and b members must be part of _that_, not of
union U directly.  Which in turn means we need to do a bit more work
for field lookup.

See the testcase extension for more things that need to work.
2016-12-15 17:47:09 +01:00
Michael Matz
21da73c383 struct-init: Cleanup some more
Some parameters aren't actually necessary.  Also join the
two parsing loops for the initializer list of arrays and structs.
2016-12-15 17:47:09 +01:00
Michael Matz
7bf323843e struct-init: Cleanup
Remove dead code and variables.  Properly check for unions when
skipping fields in initializers.  Make tests2/*.expect depend
on the .c files so they are automatically rebuilt when the latter
change.
2016-12-15 17:47:09 +01:00
Michael Matz
ed7d54651d struct-init: Implement initializing subaggregates
E.g. "struct { struct S s; int a;} = { others, 42 };"
if 'others' is also a 'struct S'.  Also when the value is a
compound literal.  See added testcases.
2016-12-15 17:47:09 +01:00
Michael Matz
968bccdd2a struct-init: Reimplement
Start reimplementing the whole initializer handling to be
conforming to ISO C.  This patch just reimplements current
functionality to prepare for further changes, all tests pass.
2016-12-15 17:47:09 +01:00
Michael Matz
5d0c16a884 Support attribute between double pointer stars
"int * __attribute__((something)) *" is supported by GCC.
2016-12-15 17:47:09 +01:00
Michael Matz
662338f116 Fix function to pointer conversion
This snippet is valid:
  void foo(void);
  ... foo + 42 ...
the function designator is converted to pointer to function
implicitely.  gen_op didn't do that and bailed out.
2016-12-15 17:47:08 +01:00
Michael Matz
e034853b38 Fix parsing array typedefs of unknown size
This must compile:
 typedef int arrtype1[];
 arrtype1 sinit19 = {1};
 arrtype1 sinit20 = {2,3};
and generate two arrays of one resp. two elements.  Before the fix
the determined size of the first array was encoded in the type
directly, so sinit20 couldn't be parsed anymore (because arrtype1
was thought to be only one element long).
2016-12-15 17:47:08 +01:00
Michael Matz
8a1a2a6033 Implement __builtin_choose_expr
Follows GCC implementation.
2016-12-15 17:47:08 +01:00
Michael Matz
2b618c1ab4 Fix parsing attributes for struct decls
Given this code:

  struct __attribute__((...)) Name {...};

TCC was eating "Name", hence generating an anonymous struct.
It also didn't apply any packed attributes to the parsed
members.  Both fixed.  The testcase also contains a case
that isn't yet handled by TCC (under a BROKEN #define).
2016-12-15 17:47:08 +01:00
Michael Matz
bbce31552e inline asm: accept concatenated strings in constraints
This really should be handled implicitly in the preprocessor,
but for now this is enough.
2016-12-15 17:47:08 +01:00
Michael Matz
10c3514889 Accept symbols in initializers also on 64 bit
Those should use long or long long type, and generate a 64bit reloc.
2016-12-15 17:47:07 +01:00
Michael Matz
6763b02abc Accept empty struct member decls
struct S { /*nothing*/; int a; };

is an acceptable struct declaration, there may be stray semicolons
in the member list.
2016-12-15 17:47:06 +01:00
Michael Matz
8531de319a Accept concatenated strings in attributes
attribute(section("one" "two")) should be accepted (the section
name being "onetwo"), it's normal string concatenation.
2016-12-15 17:47:06 +01:00
Edmund Grimley Evans
e0fe69050d arm64: Fix regression introduced by 6245db9. 2016-12-05 23:29:25 +00:00
Thomas Preud'homme
64b5ee2dea Rename add_elf_sym to set_elf_sym
add_elf_sym is a confusing name because it is not clear what the
function does compared to put_elf_sym. As a matter of fact, put_elf_sym
also adds a symbol in a symbol table. Besides, "add_elf_sym" fails to
convey that the function can be used to update a symbol (for instance
its value). "set_elf_sym" seems like a more appropriate name: it will
set a symbol to a given set of properties (value, size, etc.) and create
a new one if non exist for that name as one would expect.
2016-12-03 17:26:51 +00:00
David Mertens
d2e2f42382 Implement gcc bitfield algorithm; add -mms-bitfields 2016-11-28 09:01:12 -05:00
grischka
59216d3db0 tccgen: fix inline_functions double free fix 2016-11-11 20:25:13 +01:00
grischka
7c28c9b13f tccgen: inline_functions double free fix
Fix double free of the inline function token_string which
could happen when an error/longjmp occurred while compiling
the inline function.
2016-11-11 18:29:45 +01:00
Pavlas, Zdenek
7e7f2e5d1b bcheck: access fields of local structs w/o bcheck
Revert previous commit, this is probably a better fix.
2016-11-10 05:15:07 -08:00
Pavlas, Zdenek
550e861bf7 bcheck: add structs to local regions
int test()
{
  struct { int i; } s = { 42 };
  return s.i; // bound checked
}
2016-11-09 04:11:40 -08:00
grischka
0be098929a tccpp_new/delete and other cleanups 2016-10-17 23:24:01 +02:00
Michael Matz
68a7af632c x86-64: Fix long long bug
With the last improvements to lexpand it's now harmful
to use on native 64bit platforms when not necessary.  For gv_dup
it's not necessary there.  It can still be used with really
transforming a 64bit value into two 32bit ones.
2016-10-17 00:57:16 +02:00
grischka
d9b7f018ce i386: do not 'lexpand' into registers necessarily
Previously, long longs were 'lexpand'ed into two registers
always.

Now, it expands
- constants into two constants (lo-part, hi-part)
- variables into two lvalues with offset+4 for the hi-part.

This makes long long operations look a bit nicer.

Also: don't apply i386 'inc/dec' optimization if carry
generation is wanted.
2016-10-16 19:04:40 +02:00
grischka
6245db9fca tccgen/32bits: fix unsigned long long -> int cast
gen_cast() failed to truncate long long's if they
were unsigned, which was causing mess on the vstack.

There was a similar bug here
    tccgen: 32bits: fix PTR +/- long long
    ed15cddacd

Both were not visible until this patch
    tccgen: arm/i386: save_reg_upstack
    b691585785

I'd still assume that this patch is correct per se.

Also:
- remove 2x !nocode_wanted (we are already under a general
  "else if (!nocode_wanted)" clause above).
2016-10-16 11:03:57 +02:00
grischka
f3c1ea6c2d #define __GNUC__ = 2.1
__GNUC__ nowadays as macro seems to mean the "GNU C dialect"
rather than the compiler itself.  See also

  http://gcc.gnu.org/ml/gcc/2008-07/msg00026.html

This patch will probably cause problems of various kinds but
maybe we should try nonetheless.
2016-10-15 16:01:16 +02:00
grischka
4d247c00a3 tccgen/tccelf: move code from libtcc.c 2016-10-15 15:55:31 +02:00
Michael Matz
383f568a64 Fix misleading indentation 2016-10-14 17:46:04 +02:00
grischka
ed15cddacd tccgen: 32bits: fix PTR +/- long long
Previously in order to perform a ll+ll operation tcc
was trying to 'lexpand' PTR in gen_opl which did
not work well.  The case:


    int printf(const char *, ...);
    char t[] = "012345678";

    int main(void)
    {
        char *data = t;
        unsigned long long r = 4;
        unsigned a = 5;
        unsigned long long b = 12;

        *(unsigned*)(data + r) += a - b;

        printf("data %s\n", data);
        return 0;
    }
2016-10-13 19:21:43 +02:00
Pavlas, Zdenek
7bd30a488a gcase() clean up
remove tail recursion, simplify
2016-10-11 02:05:02 -07:00
Edmund Grimley Evans
94d8d12c26 Fix handling of case_reg in switch statement.
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.

This bug fix was first applied as ff3f9aa (20 Feb 2015), but the fix
was reverted by fc0fc6a (21 Sep 2016, "switch: collect case ranges
first, then generate code"). Here the fix is updated for the new code.
2016-10-10 20:15:20 +01:00
grischka
71b16f4e18 tccpp : "tcc -E -P" : suppress empty lines
Also:
- regenerate all tests/pp/*.expect with gcc
- test "insert one space" feature
- test "0x1E-1" in asm mode case
- PARSE_FLAG_SPACES: ignore \f\v\r better
- tcc.h: move some things
2016-10-09 20:33:14 +02:00
Daniel Glöckner
bf10bca192 tccgen.c: make vla_runtime_type_size always return the alignment 2016-10-09 00:13:31 +02:00
Daniel Glöckner
6775c7cb3a tccgen.c: fix multi-register structure return when not on stack
We need to preserve the type of the pointer to the structure, f.ex.
when a global structure is returned.

This is not a perfect solution. Registers loaded in the first iteration
might be overwritten in a following iteration as the register is no
longer on vtop. This is not a problem for ARM32 as gfunc_sret returns
a maximum of 1 in the integer case.
2016-10-08 19:03:01 +02:00
Daniel Glöckner
c09b6ce975 tccgen.c: use correct type for storing long double constants 2016-10-08 18:52:28 +02:00
grischka
b42cb16b65 Misc. fixes
Makefile :
- do not 'uninstall' peoples /usr/local/doc entirely
libtcc.c :
- MEM_DEBUG : IDE-friendly output "file:line: ..."
- always ELF for objects
tccgen.c :
- fix memory leak in new switch code
- move static 'in_sizeof' out of function
profiling :
- define 'static' to empty
resolve_sym() :
- replace by dlsym()

win32/64: fix R_XXX_RELATIVE fixme
- was fixed for i386 already in
  8e4d64be2f
- do not -Lsystemdir if compiling to .o
2016-10-05 18:34:17 +02:00
grischka
b691585785 tccgen: arm/i386: save_reg_upstack
tccgen.c:gv() when loading long long from lvalue, before
was saving all registers which caused problems in the arm
function call register parameter preparation, as with

    void foo(long long y, int x);
    int main(void)
    {
      unsigned int *xx[1], x;
      unsigned long long *yy[1], y;
      foo(**yy, **xx);
      return 0;
    }

Now only the modified register is saved if necessary,
as in this case where it is used to store the result
of the post-inc:

        long long *p, v, **pp;
        v = 1;
        p = &v;
        p[0]++;
        printf("another long long spill test : %lld\n", *p);

i386-gen.c :
- found a similar problem with TOK_UMULL caused by the
  vstack juggle in tccgen:gen_opl()
  (bug seen only when using EBX as 4th register)
2016-10-04 17:36:51 +02:00
grischka
5805b07218 Alternative fix for "Incorrect function call code on ARMv6"
"make test" crashes without that "save_regs()".

This partially reverts
commit 49d3118621.

Found another solution:  In a 2nd pass Just look if
any of the argument registers has been saved again,
and restore if so.
2016-10-03 12:33:41 +02:00
Pavlas, Zdenek
f795e1be83 switch: binary search 2016-10-03 03:14:34 -07:00
Pavlas, Zdenek
da63695cf3 switch: fix label sorting 2016-10-03 00:43:28 -07:00
grischka
c2ad11ac70 tccgen: fix long long -> char/short cast
This was causing assembler bugs in a tcc compiled by itself
at i386-asm.c:352 when ExprValue.v was changed to uint64_t:

    if (op->e.v == (int8_t)op->e.v)
        op->type |= OP_IM8S;

A general test case:

    #include <stdio.h>
    int main(int argc, char **argv)
    {
        long long ll = 4000;
        int i = (char)ll;
        printf("%d\n", i);
        return 0;
    }

Output was "4000", now "-96".

Also: add "asmtest2" as asmtest with tcc compiled by itself
2016-10-02 01:39:14 +02:00
Balazs Kezes
49d3118621 Incorrect function call code on ARMv6
On 2016-08-11 09:24 +0100, Balazs Kezes wrote:
> I think it's just that that copy_params() never restores the spilled
> registers. Maybe it needs some extra code at the end to see if any
> parameters have been spilled to stack and then restore them?

I've spent some time on this and I've found an alternative solution.
Although I'm not entirely sure about it but I've attached a patch
nevertheless.

And while poking at that I've found another problem affecting the
unsigned long long division on arm and I've attached a patch for that
too.

More details in the patches themselves. Please review and consider them
for merging! Thank you!

--
Balazs

[PATCH 1/2] Fix slow unsigned long long division on ARM

The macro AEABI_UXDIVMOD expands to this bit:

  #define AEABI_UXDIVMOD(name,type, rettype, typemacro)                     \
  ...
      while (num >= den) {                                                  \
  ...
          while ((q << 1) * den <= num && q * den <= typemacro ## _MAX / 2) \
              q <<= 1;                                                      \
  ...

With the current ULONG_MAX version the inner loop goes only until 4
billion so the outer loop will progress very slowly if num is large.
With ULLONG_MAX the inner loop works as expected. The current version is
probably a result of a typo.

The following bash snippet demonstrates the bug:

  $ uname -a
  Linux eper 4.4.16-2-ARCH #1 Wed Aug 10 20:03:13 MDT 2016 armv6l GNU/Linux
  $ cat div.c
  int printf(const char *, ...);
  int main(void) {
    unsigned long long num, denom;
    num = 12345678901234567ULL;
    denom = 7;
    printf("%lld\n", num / denom);
    return 0;
  }
  $ time tcc -run div.c
  1763668414462081

  real    0m16.291s
  user    0m15.860s
  sys     0m0.020s

[PATCH 2/2] Fix long long dereference during argument passing on ARMv6

For some reason the code spills the register to the stack. copy_params
in arm-gen.c doesn't expect this so bad code is generated. It's not
entirely clear why the saving part is necessary. It was added in commit
59c35638 with the comment "fixed long long code gen bug" with no further
clarification. Given that tcctest.c passes without this, maybe it's no
longer needed? Let's remove it.

Also add a new testcase just for this. After I've managed to make the
tests compile on a raspberry pi, I get the following diff without this
patch:

  --- test.ref    2016-08-22 22:12:43.380000000 +0100
  +++ test.out3   2016-08-22 22:12:49.990000000 +0100
  @@ -499,7 +499,7 @@
   2
   1 0 1 0
   4886718345
  -shift: 9 9 9312
  +shift: 291 291 291
   shiftc: 36 36 2328
   shiftc: 0 0 9998683865088
   manyarg_test:

More discussion on this thread:
https://lists.nongnu.org/archive/html/tinycc-devel/2016-08/msg00004.html
2016-10-01 23:10:11 +02:00
grischka
9c5bb16447 Revert part of "fix installation amd bcheck for Windows"
tccelf.c : force linking bcheck by adding elf symbol __bound_init
bcheck.c : use (size_t)1 for x86_64

Fixes 7e7e6148fd
2016-10-01 20:47:36 +02:00
grischka
766ba3694d tccpp: cleanup
- "utf8 in identifiers"
  from 936819a1b9

- CValue: remove member str.data_allocated
- make tiny allocator private to tccpp

- allocate macro_stack objects on heap
  because otherwise it could crash after error/setjmp
  in preprocess_delete():end_macro()

- mov "TinyAlloc" defs to tccpp.c

- define_push: take int* str again
2016-10-01 20:26:50 +02:00
Pavlas, Zdenek
e238e6521b gtst_addr(): short conditional jumps (i386, x86_64) 2016-09-30 07:33:20 -07:00
Pavlas, Zdenek
fc0fc6aba3 switch: collect case ranges first, then generate code
Collect cases first, then emit lookup code. Elliminates
jumps to implement pass-through and jumps to link cases.
2016-09-30 07:33:20 -07:00
Pavlas, Zdenek
71b6220963 tccgen: return: avoid jmp to retsym if possible
When 'return' is the last statement of the top-level block
(very common and often recommended case) jump is not needed.
2016-08-11 05:02:40 -07:00
grischka
41349948f8 win64: fix va_arg
fixes 5c35ba66c5

Implementation was consistent within tcc but incompatible
with the ABI (for example library functions vprintf etc)

Also:
- tccpp.c/get_tok_str() : avoid "unknown format "%llu" warning
- x86_64_gen.c/gen_vla_alloc() : fix vstack leak
2016-07-10 20:44:49 +02:00
grischka
1ca685f887 tccgen: gen_assign_cast(): cannot cast struct to scalar
The case below previously was causing an assertion failure
in the target specific generator.

It probably is not incorrect not to allow this even if
gcc does.

    struct S { long b; };

    void f(struct S *x)
    {
        struct S y[1] = { *x };
    }
2016-05-25 18:52:08 +02:00
Michael Matz
a66ba1f2a1 Error out on operations on structs
The check for structs was too late and on amd64 and aarch64 could
lead to accepting and then asserting with code like:
  struct S {...} s;
  char *c = (char*)0x10 - s;
2016-05-12 01:12:04 +02:00
grischka
a94e8d439a tccgen: scopes levels for local symbols (update 2)
allow
    typedef int xxx;
    typedef int xxx;
in the same scope as long as it is the same type
2016-05-06 08:32:54 +02:00
grischka
d48662d496 tccgen: scopes levels for local symbols (update 1)
Catch top level redeclarations too.

Also fix mistakes in tcctest.c and the tcc sources (win32)
showing up now.
2016-05-05 20:04:00 +02:00
grischka
caebbc3ee1 tccgen: scope levels for local symbols
... for fast redeclaration checks

Also, check function parameters too:
    void foo(int a) { int a; ... }

Also, try to fix struct/union/enum's on different scopes:
    { struct xxx { int x; };
         { struct xxx { int y; }; ... }}
and some (probably not all) combination with incomplete
declarations "struct xxx;"

Replaces 2bfedb1867
and 07d896c8e5

Fixes cf95ac399c
2016-05-05 10:39:09 +02:00
seyko
07d896c8e5 sym_push2 optimized for the local_stack case.
A constant expression removed from the loop.
    If subroutine have 50000+ local variables, then currently
    compilation of such code takes obly 15 sec. Was 2 min.
    gcc-4.1.2 compiles such code in 7 sec. pcc -- 3.44 min.

    A test generator:
    #include <stdio.h>
    int main() {
        puts("#include <stdio.h>"); puts("int main()"); puts("{");
        for (int i = 0; i < 50000; ++i) printf("int X%d = 1;\n", i);
        for (int i = 0; i < 50000; ++i) puts("scanf(\"%d\", &X0);");
        puts("}");
        return 0;
    }
2016-05-04 17:23:25 +03:00
seyko
2bfedb1867 -fno-type-redefinition-check
don't catch redefinition for local vars. With this option on
    tcc accepts the following code:
    int main()
    {
        int a = 0;
        long a = 0;
    }
    But if you shure there is no problem with your local variables,
    then a compilation speed can be improved if you have a lots of
    the local variables (50000+)
2016-05-04 17:17:51 +03:00
Vlad Vissoultchev
224236f57c Improve hash performance
- better `TOK_HASH_FUNC`
- increases `hash_ident` initial size to 16k (from 8k)
- `cstr_cat` uses single `realloc` + `memcpy`
- `cstr_cat` can append terminating zero
- `tok_str_realloc` initial size to 16 (from 8)
- `parse_define` uses static `tokstr_buf`
- `next` uses static `tokstr_buf`
- fixes two latent bugs (wrong deallocations in libtcc.c:482 and
  tccpp.c:2987)
2016-04-17 17:25:55 +03:00
seyko
e010b1396b __builtin_expect no-op
Taken from David Mertens tcc branch on github
    https://github.com/run4flat/tinycc.git
2016-04-16 12:41:53 +03:00
Vlad Vissoultchev
0691b7630b tccgen.c: Allow type attributes to prefix enum/struct/union name
From gcc docs: "You may also specify attributes between the enum, struct or union tag and the name of the type rather than after the closing brace."

Adds `82_attribs_position.c` in `tests/tests2`
2016-04-06 14:32:52 +03:00
seyko
c9473a7529 nocode_wanted with while/for inside ({})
a test included.
2016-04-05 11:47:20 +03:00
Michael Matz
f85db99ff0 Fix type parsing
the check on incomplete struct/union/enum types was too early,
disallowing mixed specifiers and qualifiers.  Simply rely on
the size (->c) field for that.  See testcases.
2016-03-24 15:44:01 +01:00
Vlad Vissoultchev
9d778c7bb6 Keep lvalue category on structs when evaluating ternary operator 2016-03-13 04:32:18 +02:00
Michael Matz
ceccd3ead3 tccgen.c: Fix flex array members some more
Last fix didn't work for function f1int in the added testcase.
2016-03-11 22:35:44 +01:00
Henry Kroll III
7e0ad4fdd2 tccgen.c: off by one in flexible array members
tccgen.c: fix fexible array member breaking struct alignment
2016-03-10 08:28:26 -08:00
Edmund Grimley Evans
f75f89fc8f tccgen.c: In parse_btype, handle type qualifiers applied to arrays.
Also add some test cases in tests/tests2/39_typedef.c.
2016-01-11 07:51:58 +00:00
Edmund Grimley Evans
1c2dfa1f4b Change the way struct CStrings are handled.
A CString used to be copied into a token string, which is an int array.
On a 64-bit architecture the pointers were misaligned, so ASan gave
lots of warnings. On a 64-bit architecture that required memory
accesses to be correctly aligned it would not work at all.

The CString is now included in CValue instead.
2015-11-26 12:40:50 +00:00
Edmund Grimley Evans
99372bb1d3 tccgen.c: Give error if statement expression found when const wanted.
Some test cases:

#define SE ({ switch (0) { } 0; })

// Should give error:
int x = SE;
void f(void) { static int x = SE; }
void f(void) { enum e { a = SE }; }
void f(void) { switch (0) { case SE: break; } }

// Correct:
int f(void) { return SE; }
int f(void) { return sizeof(SE); }
2015-11-26 12:28:42 +00:00
Edmund Grimley Evans
7301b42e36 tccgen.c: Try to make sizeof(!x) work.
tests/tests2/27_sizeof.*: Add test.
2015-11-22 00:00:36 +00:00
Edmund Grimley Evans
737f984213 tccgen.c: Bug fix for 992cbda and 3ff77a1: set nocode_wanted.
tests/tests2/78_vla_label.*: Add test.
2015-11-21 23:58:58 +00:00
Edmund Grimley Evans
3ff77a1d6f Improve constant propagation with "&&" and "||". 2015-11-20 23:33:49 +00:00
grischka
54cf57ab1a tccgen: asm_label cleanup
- avoid memory allocation by using its (int) token number
- avoid additional function parameter by using Attribute

Also: fix some strange looking error messages
2015-11-20 11:22:56 +01:00
Edmund Grimley Evans
992cbda8d0 tccgen.c: Recognise constant expressions with conditional operator.
tests/tests2/78_vla_label.c: Check that int a[1 ? 1 : 1] is not a VLA.
2015-11-20 00:24:46 +00:00
Edmund Grimley Evans
30c54c9d43 tccgen.c: In parse_btype, handle typedef types with added type qualifiers.
In a case like

    typedef int T[1];
    const T x;

we must make a copy of the typedef type so that we can add the type
qualifiers to it.

The following code used to give

error: incompatible types for redefinition of 'f'

    typedef int T[1];
    void f(const int [1]);
    void f(const T);
2015-11-19 23:45:33 +00:00
Edmund Grimley Evans
58a34d22c9 tccgen.c: Improvements to type_to_str (only used for error messages).
1. Handle array types.
2. Print the type qualifiers of pointers.
2015-11-19 23:35:36 +00:00
Edmund Grimley Evans
5d496b1695 tccgen.c: Avoid undefined behaviour in constant propagation. 2015-11-17 19:34:31 +00:00
Edmund Grimley Evans
569fba6db9 Merge the integer members of union CValue into "uint64_t i". 2015-11-17 19:09:35 +00:00
Edmund Grimley Evans
b051549f2e tccgen.c: Use memmove for struct assignment: dest and src may be equal. 2015-11-04 20:23:17 +00:00
Edmund Grimley Evans
8eab556ac5 tccgen.c: Fix memory leak involving asm_label. 2015-11-04 20:22:30 +00:00
Edmund Grimley Evans
c899659d39 tccgen.c: Remove undefined shift of negative signed value. 2015-10-15 19:02:57 +01:00
seyko
8077f0acc7 a number as a field name (part 2)
don't crash
    a test program:
    ================
    typedef struct X { int len; } X;
    #define init(s,len)  s.len = len;
    int main(void) {
	X myX;
	init(myX,10);
	return 0;
    }
    ================
    After a patch:
    	error: field name expected
2015-09-25 02:31:34 +03:00
seyko
e7e7a0d301 a number as a field name
a test program:
    ========
    typedef struct X { int len; } X;
    int main(void) {
       X myX;
       myX.10 = 10;
       return 0;
    }
    ========
    Error message before a patch:
	error: ';' expected (got "(null)")
    After a patch:
	error: field name expected
2015-09-25 01:44:23 +03:00
gus knight
ef3d38c5c9 Revert "fix-mixed-struct (patch by Pip Cet)"
This reverts commit 4e04f67c94. Requested by grischka.
2015-07-29 16:57:41 -04:00
gus knight
89ad24e7d6 Revert all of my changes to directories & codingstyle. 2015-07-29 16:57:12 -04:00
gus knight
47e06c6d4e Reorganize the source tree.
* Documentation is now in "docs".
 * Source code is now in "src".
 * Misc. fixes here and there so that everything still works.

I think I got everything in this commit, but I only tested this
on Linux (Make) and Windows (CMake), so I might've messed
something up on other platforms...
2015-07-27 16:03:25 -04:00
gus knight
d6b64e2574 Clean up lots of rogue tabs.
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.
2015-07-27 14:14:41 -04:00
gus knight
41031221c8 Trim trailing spaces everywhere. 2015-07-27 12:43:40 -04:00
seyko
4e04f67c94 fix-mixed-struct (patch by Pip Cet)
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.
2015-05-14 07:32:24 +03:00
grischka
30df3189b1 tccpp: fix issues, add tests
* 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
    a3fc543459
    a715d7143d
    (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)
2015-05-09 14:29:39 +02:00
seyko
999274ca90 a lot simpler VLA code
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
2015-05-04 04:09:05 +03:00
Philip
4126056fbe fix vstack leak
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.
2015-04-29 21:48:30 +00:00
Philip
44c330d647 VLA fix: save stack pointer right after modification
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.
2015-04-28 09:23:29 +00:00
Philip
d2dd6fdbfb fix VLA/continue issue
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.
2015-04-27 16:42:27 +00:00
grischka
7c27186a83 Revert "* and #pragma pop_macro("macro_name")"
- 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 0c8447db79.
2015-04-23 23:26:46 +02:00
seyko
0c8447db79 * and #pragma pop_macro("macro_name")
* 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.
2015-04-21 06:34:35 +03:00
seyko
5c9dde7255 option to use an old algorithm of the array in struct initialization
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.
2015-04-10 23:44:10 +03:00
seyko
559675b90a a bounds checking code for the ARCH=x86_64 2015-04-10 15:17:22 +03:00
seyko
dec959358a fix the bug #31403: parser bug in structure
- 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
2015-04-10 06:31:58 +03:00
seyko
acef4ff244 make a bound checking more compatible with Windows 64
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
2015-03-26 07:47:45 +03:00
seyko
bd531ec1fd A right fix for the array in struct initialization w/o '{'
Parse a type if there is only one '(' before a type token.
Otherwise a recursion will perform a job.
2015-03-23 08:27:16 +03:00
seyko
367bb6f4b7 Revert of the commit: fix for the array in struct initialization w/o '{', case 2
A right solution for this problem will follow.
2015-03-23 07:40:41 +03:00
seyko
78c076a70f restore a linux 2.4.26 kernel compilation (commit 5bcc3eed7b correction)
The following check in tccgen.c is removed
    if (nocode_wanted)
	tcc_error("statement expression in global scope");
This check is introduced in commit 5bcc3eed7b and breaks compilation
of the linux 2.4.26 kernel.
2015-03-20 10:44:26 +03:00
Edmund Grimley Evans
0e79df499a tccgen.c: (!nocode_wanted) -> (nocode_wanted) in arm64 part. 2015-03-10 22:37:36 +00:00
Thomas Preud'homme
5bcc3eed7b Add some missing nocode_wanted guard
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.
2015-03-10 23:27:14 +08:00
Michael Matz
2eb4f4a3ba Remove incorrect comment
Not the code was confused, I was :)
2015-03-09 01:33:42 +01:00
Michael Matz
50899e30ab Fix stack overwrite on structure return
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.
2015-03-09 00:19:59 +01:00
Edmund Grimley Evans
d73b488401 arm64: Implement __clear_cache.
__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
2015-03-08 00:10:44 +00:00
Edmund Grimley Evans
ac70e6b840 tccgen.c: Optimise 0<<x, 0>>x, -1>>x, x&0, x*0, x|-1, x%1.
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.
2015-03-07 17:32:39 +00:00
seyko
8d4c861144 fix for the array in struct initialization w/o '{', case 2
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 ','
2015-03-07 09:40:12 +03:00
Edmund Grimley Evans
238e760a29 Add __builtin_return_address.
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.
2015-03-06 21:01:14 +00:00
seyko
d9b87c087c fixing decl_initializer() for size_only: don't eat ')'
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; }
2015-03-05 20:18:25 +03:00
seyko
c45a8695eb A reverse of the commit 14745bdeb because of the problems while compiling 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 "(")
2015-03-03 15:44:29 +03:00
seyko
6fd4e5bace a void to void cast.
Allow tcc to compile the following program
    ///////
	void func1() {}
	void func2() {
	  return func1();
	}
    //////
gcc accepts this program
2015-03-03 15:39:57 +03:00
seyko
09feeca5df a statement expressions with a pointer return type
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.
2015-03-03 15:29:14 +03:00
seyko
1a1e9548fb iitialisation of the empty struct
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 69fdb57edd
  ////////////////////
  // A test for patch 69fdb57edd
  // 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;
  }
  ////////////////////
2015-03-03 15:15:48 +03:00
seyko
bbf8221ec3 tcc don't understand am extern array of structs.
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++;
    }
2015-03-03 15:00:13 +03:00
Edmund Grimley Evans
40f7e11c53 tccgen.c: Make sure that gen_op always returns an rvalue.
Either this fix, or an alternative one, is required for arm64.
2015-02-23 22:51:10 +00:00
Edmund Grimley Evans
b14ef0e24b Add arm64 (AArch64) as a target architecture. 2015-02-23 22:51:03 +00:00
Edmund Grimley Evans
738606dbd5 Use RELA relocations properly for R_DATA_PTR on x86_64.
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.
2015-02-21 21:29:03 +00:00
Edmund Grimley Evans
ff3f9aa6ba Fix handling of case_reg in switch statement.
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.
2015-02-20 23:16:00 +00:00
grischka
9d7fb33360 tccgen: use lvalue as result from bitfield assignment
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
2014-09-23 12:30:08 +02:00
grischka
14745bdeb7 tccgen: nocode_wanted: do not output constants
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 2de1b2d14c
(documented as "Some in-between fixes" in Changelog)
2014-08-01 10:59:38 +02:00
Michael Matz
356c6f6293 Remove unused variable 2014-04-14 05:41:57 +02:00
Michael Matz
fbda78aefe Parse and emit hidden visibility
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.
2014-04-14 02:53:11 +02:00
Urs Janssen
822f4630e3 add missing prototypes 2014-04-10 11:53:54 +02:00
Thomas Preud'homme
c2422ba87f Fix test for macro nesting 2014-04-07 21:16:04 +08:00
Vincent Lefevre
3e9a7e9d69 Corrected spelling mistakes in comments and strings 2014-04-07 13:31:00 +02:00
grischka
0e43f3aef4 win32: warn people about using undeclared WINAPI functions
*** 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)
2014-04-06 10:59:40 +02:00
grischka
5879c854fb tccgen: x86_64: fix garbage in the SValue upper bits
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 4bc83ac393

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).
2014-04-04 20:20:44 +02:00
Thomas Preud'homme
3e56584223 Allow local redefinition of enumerator 2014-03-31 22:59:10 +08:00
Thomas Preud'homme
f272407353 Fix typo in code added by b018bac9c8 2014-03-29 14:57:59 +08:00
Thomas Preud'homme
b125743323 Create bcheck region for argv and arge argument
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.
2014-03-29 14:46:26 +08:00
mingodad
4bc83ac393 After several days searching why my code refactoring to remove globals was 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
2014-03-26 20:18:48 +00:00
Thomas Preud'homme
b68499e971 Make parse_btype only accept one basic type
This makes int char c; and struct {} int c; generate an error. Thanks
Mobi Phil for reporting.
2014-03-24 23:40:39 +08:00
Thomas Preud'homme
33cea54dc7 Fix type_to_str test for unsigned int 2014-03-09 13:32:40 +08:00
Thomas Preud'homme
fdb3b10d06 Fix various errors uncovered by static analysis
Reported-by: Carlos Montiers <cmontiers@gmail.com>
2014-03-08 18:38:49 +08:00
Thomas Preud'homme
b0b5165d16 Def signedness != signed != unsigned for char
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.
2014-02-06 21:40:22 +08:00
Thomas Preud'homme
17314a1fb3 Fix parameter passing of long long bitfield 2014-02-04 20:55:24 +08:00
Thomas Preud'homme
4e5f15c685 switch last 2 params of TOK_memset on ARM
On ARM, TOK_memset is executed via __aeabi_memset which reverse the
order of the last two parameters.
2014-02-03 22:28:08 +08:00
Michael Matz
05c9b76131 Fix floating point unary minus and plus
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.
2014-01-12 04:44:27 +01:00
Michael Matz
9e11476e15 Fix Fixes for PE x86_64 for fail in code
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.
2014-01-11 23:42:58 +01:00
Archidemon
fdf9fba578 Fixes previous fixes 2014-01-10 11:58:16 +06:00
Archidemon
ea7b17f641 Fixes for PE x86_64 for fail in code
int (*fn1)=0x13fde16b5;

and

int fn1(int a) {...}

struct {
  int (*fn2)(int a);
} b = { fn1 };
2014-01-10 09:45:18 +06:00
grischka
3fe2a95d7f be stricter with aliasing
Refactoring (no logical changes):
- use memcpy in tccgen.c:ieee_finite(double d)
- use union to store attribute flags in Sym
Makefile: "CFLAGS+=-fno-strict-aliasing" basically not necessary
anymore but I left it for now because gcc sometimes behaves
unexpectedly without.

Also:
- configure: back to mode 100755
- tcc.h: remove unused variables tdata/tbss_section
- x86_64-gen.c: adjust gfunc_sret for prototype
2014-01-07 14:57:07 +01:00
grischka
2bd0daabbe misc. fixes
- tccgen: error out for cast to void, as in
      void foo(void) { return 1; }
  This avoids an assertion failure in x86_64-gen.c, also.
  also fix tests2/03_struct.c accordingly

- Error: "memory full" - be more specific

- Makefiles: remove circular dependencies, lookup tcctest.c from VPATH

- tcc.h: cleanup lib, include, crt and libgcc search paths"
  avoid duplication or trailing slashes with no CONFIG_MULTIARCHDIR
  (as from 9382d6f1a0)

- tcc.h: remove ";{B}" from PE search path
  in ce5e12c2f9 James Lyon wrote:
  "... I'm not sure this is the right way to fix this problem."
  And the answer is: No, please. (copying libtcc1.a for tests instead)

- win32/build_tcc.bat: do not move away a versioned file
2014-01-06 19:56:26 +01:00
Thomas Preud'homme
8efaa71190 Fix struct ret in variadic fct with ARM hardfloat
The procedure calling standard for ARM architecture mandate the use of
the base standard for variadic function. Therefore, hgen float aggregate
must be returned via stack when greater than 4 bytes and via core
registers else in case of variadic function.

This patch improve gfunc_sret() to take into account whether the
function is variadic or not and make use of gfunc_sret() return value to
determine whether to pass a structure via stack in gfunc_prolog(). It
also take advantage of knowing if a function is variadic or not move
float result value from VFP register to core register in gfunc_epilog().
2014-01-06 22:57:05 +08:00
Thomas Preud'homme
eda2c756ed Move logic for if (int value) to tccgen.c
Move the logic to do a test of an integer value (ex if (0)) out of
arch-specific code to tccgen.c to avoid code duplication. This also
fixes test of long long value which was only testing the bottom half of
such values on 32 bits architectures.
2014-01-04 21:10:05 +08:00
Thomas Preud'homme
3eed3506b4 Fix negation of 0.0 and -0.0 2014-01-04 17:07:58 +08:00
grischka
fbc8810334 Fix "Add support for struct > 4B returned via registers"
- avoid assumption "ret_align == register_size" which is
  false for non-arm targets
- rename symbol "sret" to more descriptive "ret_nregs"

This fixes commit dcec8673f2

Also:
- remove multiple definitions in win32/include/math.h
2013-12-16 15:38:10 +01:00
Thomas Preud'homme
dcec8673f2 Add support for struct > 4B returned via registers
On ARM with hardfloat calling convention, structure containing 4 fields
or less of the same float type are returned via float registers. This
means that a structure can be returned in up to 4 double registers in a
structure is composed of 4 doubles. This commit adds support for return
of structures in several registers.
2013-11-22 09:27:15 +08:00
Thomas Preud'homme
cf02f920c1 Revert "Add support for thread-local storage variables"
TLS support in tinyCC is absolutely not ready:
- segment register not select in load and store
- no relocation added for computing offset of per-thread symbol
- no support for TLS-specific relocations
- no program header added as per Drepper document about TLS

This reverts commit 1c4afd1350.
2013-11-03 18:55:54 +08:00
Thomas Preud'homme
1c4afd1350 Add support for thread-local storage variables 2013-10-29 22:10:02 +08:00
Amine Najahi
3b07a15fd1 Detect usage of incomplete types inside struct/union
Make sure the only exception is for a flexible array member
as the last element of a structure
2013-10-06 14:51:29 +02:00
Thomas Preud'homme
0f5942c6b3 Avoid warnings with gcc 4.8 + default CFLAGS 2013-09-24 15:37:12 +02:00
Thomas Preud'homme
673befd2d7 Report error when redefining enumerator
Prevent the following code from compiling:

enum color {RED, GREEN, BLUE};
enum rgb {RED, G, B};
2013-09-20 22:49:49 +02:00
Thomas Preud'homme
82969f045c Report error when using undefined enum
Prevent the following code from compiling:

int main(void)
{
	enum rgb c = 42;
	return c;
}

Reported-by: John Haque <j.eh@mchsi.com>
2013-09-20 21:22:11 +02:00
Thomas Preud'homme
0f522fb32a Forbid enum redefinition.
Prevent the following code from compiling:

enum color {RED, GREEN, BLUE};
enum color {R, G, B};

int main()
{
        return R;
}

Reported-by: John Haque <j.eh@mchsi.com>
2013-09-20 01:06:43 +02:00
Thomas Preud'homme
a465b7f58f Forbid the use of array of functions
Prevent the following code from compiling:

int (*fct)[42](int x);

Reported-by: Abdul Wadud Mohammad Mohibur Rashid <mohibur_rashid@yahoo.com>
2013-09-19 18:58:46 +02:00
Thomas Preud'homme
76cb1144ef Generate an error when a function is redefined
Use one more bit in AttributeDef to differenciate between declared
function (only its prototype is known) and defined function (its body is
also known). This allows to generate an error in cases like:

int f(){return 0;}
int f(){return 1;}
2013-09-16 14:48:33 +02:00
grischka
69c2e7f96c tccgen: fix crash with undeclared struct
... as in:
    #include<stdio.h>
    int main()
    {
        struct asdasd x;
        printf("%d\n", sizeof(x));
    }
This fixes commit 17571298f3
2013-07-24 17:06:13 +02:00
grischka
be1b6ba7b7 avoid "decl after statement" please
for compiling tcc with msc
2013-04-30 00:33:34 +02:00
James Lyon
41b3c7a507 Improved variable length array support.
VLA storage is now freed when it goes out of scope. This makes it
possible to use a VLA inside a loop without consuming an unlimited
amount of memory.

Combining VLAs with alloca() should work as in GCC - when a VLA is
freed, memory allocated by alloca() after the VLA was created is also
freed. There are some exceptions to this rule when using goto: if a VLA
is in scope at the goto, jumping to a label will reset the stack pointer
to where it was immediately after the last VLA was created prior to the
label, or to what it was before the first VLA was created if the label
is outside the scope of any VLA. This means that in some cases combining
alloca() and VLAs will free alloca() memory where GCC would not.
2013-04-27 22:58:52 +01:00
James Lyon
5c35ba66c5 64-bit tests now pass (well, nearly).
tcctest1-3 fail, but this appears to be due to bugs in GCC rather than TCC
(from manual inspection of the output).
2013-04-24 02:19:15 +01:00
James Lyon
8a81f9e103 Added CMake build system (to facilitate Win64 builds)
Win32 build and tests work under CMake, however I haven't added
install code yet. Win64 build fails due to chkstk.S failing to
assemble.
2013-04-21 11:20:20 +01:00
James Lyon
23f73e92f3 Fixed 64-bit integer bug introduced by x86-64 ABI work.
Now I need to check that the x86-64 stuff still works.
2013-04-19 22:55:09 +01:00
James Lyon
cbce6d2bac Improved x86-64 XMM register argument passing.
Also made XMM0-7 available for use as temporary registers, since they
are not used by the ABI. I'd like to do the same with RSI and RDI but
that's trickier since they can be used by gv() as temporary registers
and there isn't a way to disable that.
2013-04-19 22:05:49 +01:00
James Lyon
946afd2343 Fixed problems with XMM1 use on Linux/x86-64.
All tests pass. I think I've caught all the cases assuming only XMM0 is
used. I expect that Win64 is horribly broken by this point though,
because I haven't altered it to cope with XMM1.
2013-04-19 18:33:30 +01:00
James Lyon
0e17671f72 Most x86-64 tests now work; only on error in test1-3.
I've had to introduce the XMM1 register to get the calling convention
to work properly, unfortunately this has broken a fair bit of code
which assumes that only XMM0 is used.
2013-04-19 15:33:16 +01:00
James Lyon
b961ba5396 Got test1-3 working on x86-64.
There are probably still issues on x86-64 I've missed.
I've added a few new tests to abitest, which fail (2x long long and 2x double
in a struct should be passed in registers).
2013-04-19 11:10:13 +01:00
James Lyon
55ea6d3fc1 x86-64 ABI fixes.
abitest now passes; however test1-3 fail in init_test. All other tests
pass. I need to re-test Win32 and Linux-x86.

I've added a dummy implementation of gfunc_sret to c67-gen.c so it
should now compile, and I think it should behave as before I created
gfunc_sret.
2013-04-19 00:46:49 +01:00
James Lyon
2bbfaf436f Tests in abitest.c now work on Win32.
I expect that Linux-x86 is probably fine. All other architectures
except ARM are definitely broken since I haven't yet implemented
gfunc_sret for these, although replicating the current behaviour
should be straightforward.
2013-04-18 17:27:34 +01:00
grischka
d6d7686b60 tcc.h: declare CValue.tab[LDOUBLE_SIZE/4]
Should fix some warnings wrt. access out of array bounds.

tccelf.c: fix "static function unused" warning
x86_64-gen.c: fix "ctype.ref uninitialzed" warning and cleanup
tcc-win32.txt: remove obsolete limitation notes.
2013-02-08 19:07:11 +01:00
Thomas Preud'homme
6f4983af5b Revert "Add predictability in CType initialization."
This reverts commit 93785149ed.
2013-01-31 13:43:04 +01:00
grischka
2f6b8469cc safety: replace occurrences of strcpy by pstrcpy 2013-01-31 13:23:19 +01:00
Thomas Preud'homme
370547a550 Revert "Check whether structure fields have a type"
This reverts commit 981eb84d8a.
2013-01-31 13:02:04 +01:00
Thomas Preud'homme
981eb84d8a Check whether structure fields have a type 2013-01-31 12:32:31 +01:00
Domingo Alvarez Duarte
93785149ed Add predictability in CType initialization.
Initialize the ref field to 0 when manipulating a CType.

Signed-off-by: Thomas Preud'homme <robotux@celest.fr>
2013-01-31 12:04:10 +01:00
grischka
c5892fe4f5 Revert "Optimize vswap()"
This reverts commit 63193d1794.

Had some problems (_STATIC_ASSERT) and was too ugly anyway.
For retry, I'd suggest to implement a general function
    static inline void memswap (void *p1, void* p2, size_t n);
and then use that.  If you do so, please keep the original code
as comment.
2013-01-14 18:41:37 +01:00
Thomas Preud'homme
ea583f7b8a Fix C99ism in vswap()
Declare vtopl in vswap at the beginning of the function before any
assignments. Doing otherwise means C99 is assumed when compiling.
2013-01-13 23:38:33 +01:00
grischka
2358b378b3 tccpp: alternative fix for #include_next infinite loop bug
This replaces commit 3d409b0889

- revert old fix in libtcc.c
- #include_next: look up the file in the include stack to see
  if it is already included.
Also:
- streamline include code
- remove 'type' from struct CachedInclude (obsolete because we check
  full filename anyway)
- remove inc_type & inc_filename from struct Bufferedfile (obsolete)
- fix bug with TOK_FLAG_ENDIF not being reset
- unrelated: get rid of an 'variable potentially uninitialized' warning
2013-01-06 17:20:44 +01:00
Kirill Smelkov
63193d1794 Optimize vswap()
vswap() is called often enough and shows in profile and it was easy to
hand optimize swapping vtop[-1] and vtop[0] - instead of large (28 bytes
on i386) tmp variable and two memory to memory copies, let's swap areas
by longs through registers with streamlined assembly.

For

    $ ./tcc -B. -bench -DONE_SOURCE -DCONFIG_MULTIARCHDIR=\"i386-linux-gnu\" -c tcc.c

before:

 # Overhead      Command        Shared Object                                          Symbol
 # ........  ...........  ...................  ..............................................
 #
     15.19%          tcc  tcc                  [.] next_nomacro1
      5.19%          tcc  libc-2.13.so         [.] _int_malloc
      4.57%          tcc  tcc                  [.] next
      3.36%          tcc  tcc                  [.] tok_str_add2
      3.03%          tcc  tcc                  [.] macro_subst_tok
      2.93%          tcc  tcc                  [.] macro_subst
      2.53%          tcc  tcc                  [.] next_nomacro_spc
      2.49%          tcc  tcc                  [.] vswap
      2.36%          tcc  libc-2.13.so         [.] _int_free

       │    ST_FUNC void vswap(void)
       │    {
  1,96 │      push   %edi
  2,65 │      push   %esi
  1,08 │      sub    $0x20,%esp
       │        SValue tmp;
       │
       │        /* cannot let cpu flags if other instruction are generated. Also
       │           avoid leaving VT_JMP anywhere except on the top of the stack
       │           because it would complicate the code generator. */
       │        if (vtop >= vstack) {
  0,98 │      mov    0x8078cac,%eax
       │      cmp    $0x8078d3c,%eax
  1,18 │   ┌──jb     24
       │   │        int v = vtop->r & VT_VALMASK;
  1,08 │   │  mov    0x8(%eax),%edx
  0,78 │   │  and    $0x3f,%edx
       │   │        if (v == VT_CMP || (v & ~1) == VT_JMP)
  0,78 │   │  cmp    $0x33,%edx
  0,69 │   │↓ je     54
  0,59 │   │  and    $0xfffffffe,%edx
  0,49 │   │  cmp    $0x34,%edx
  0,29 │   │↓ je     54
       │   │            gv(RC_INT);
       │   │    }
       │   │    tmp = vtop[0];
  1,08 │24:└─→lea    0x4(%esp),%edi
  0,39 │      mov    $0x7,%ecx
       │      mov    %eax,%esi
 14,41 │      rep    movsl %ds:(%esi),%es:(%edi)
       │        vtop[0] = vtop[-1];
  9,51 │      lea    -0x1c(%eax),%esi
  1,96 │      mov    $0x7,%cl
       │      mov    %eax,%edi
 17,06 │      rep    movsl %ds:(%esi),%es:(%edi)
       │        vtop[-1] = tmp;
 10,20 │      mov    0x8078cac,%edi
  2,35 │      sub    $0x1c,%edi
  0,78 │      lea    0x4(%esp),%esi
       │      mov    $0x7,%cl
 15,20 │      rep    movsl %ds:(%esi),%es:(%edi)
       │    }
  9,90 │      add    $0x20,%esp
  2,25 │      pop    %esi
  1,67 │      pop    %edi
  0,69 │      ret

after:

 # Overhead      Command        Shared Object                                          Symbol
 # ........  ...........  ...................  ..............................................
 #
     15.27%          tcc  tcc                  [.] next_nomacro1
      5.08%          tcc  libc-2.13.so         [.] _int_malloc
      4.57%          tcc  tcc                  [.] next
      3.17%          tcc  tcc                  [.] tok_str_add2
      3.12%          tcc  tcc                  [.] macro_subst
      2.99%          tcc  tcc                  [.] macro_subst_tok
      2.43%          tcc  tcc                  [.] next_nomacro_spc
      2.32%          tcc  libc-2.13.so         [.] _int_free

      . . .

      0.71%          tcc  tcc                  [.] vswap

       │    ST_FUNC void vswap(void)
       │    {
  7,22 │      push   %eax
       │        /* cannot let cpu flags if other instruction are generated. Also
       │           avoid leaving VT_JMP anywhere except on the top of the stack
       │           because it would complicate the code generator. */
       │        if (vtop >= vstack) {
 11,34 │      mov    0x8078cac,%eax
  2,75 │      cmp    $0x8078d3c,%eax
  0,34 │   ┌──jb     20
       │   │        int v = vtop->r & VT_VALMASK;
  0,34 │   │  mov    0x8(%eax),%edx
  8,93 │   │  and    $0x3f,%edx
       │   │        if (v == VT_CMP || (v & ~1) == VT_JMP)
  2,06 │   │  cmp    $0x33,%edx
  2,41 │   │↓ je     74
  2,41 │   │  and    $0xfffffffe,%edx
  0,34 │   │  cmp    $0x34,%edx
  2,41 │   │↓ je     74
       │   │        vtopl[-1*VSIZEL + i] = tmpl;    \
       │   │      } do {} while (0)
       │   │
       │   │    VSWAPL(15); VSWAPL(14); VSWAPL(13); VSWAPL(12);
       │   │    VSWAPL(11); VSWAPL(10); VSWAPL( 9); VSWAPL( 8);
       │   │    VSWAPL( 7); VSWAPL( 6); VSWAPL( 5); VSWAPL( 4);
  2,06 │20:└─→mov    0x18(%eax),%edx
  1,37 │      mov    -0x4(%eax),%ecx
  2,06 │      mov    %ecx,0x18(%eax)
  1,37 │      mov    %edx,-0x4(%eax)
  2,06 │      mov    0x14(%eax),%edx
  2,06 │      mov    -0x8(%eax),%ecx
  2,41 │      mov    %ecx,0x14(%eax)
  3,09 │      mov    %edx,-0x8(%eax)
  3,09 │      mov    0x10(%eax),%edx
  1,72 │      mov    -0xc(%eax),%ecx
  2,75 │      mov    %ecx,0x10(%eax)
  1,72 │      mov    %edx,-0xc(%eax)
       │        VSWAPL( 3); VSWAPL( 2); VSWAPL( 1); VSWAPL( 0);
  2,41 │      mov    0xc(%eax),%edx
  2,41 │      mov    -0x10(%eax),%ecx
  2,41 │      mov    %ecx,0xc(%eax)
  0,69 │      mov    %edx,-0x10(%eax)
  1,72 │      mov    0x8(%eax),%edx
  0,69 │      mov    -0x14(%eax),%ecx
  1,03 │      mov    %ecx,0x8(%eax)
  1,37 │      mov    %edx,-0x14(%eax)
  1,37 │      mov    0x4(%eax),%edx
  0,69 │      mov    -0x18(%eax),%ecx
  3,09 │      mov    %ecx,0x4(%eax)
  2,06 │      mov    %edx,-0x18(%eax)
  1,37 │      mov    (%eax),%edx
  2,41 │      mov    -0x1c(%eax),%ecx
  1,37 │      mov    %ecx,(%eax)
  4,12 │      mov    %edx,-0x1c(%eax)
       │        }
       │
       │    #   undef VSWAPL
       │    #   undef VSIZEL
       │    }
  1,03 │      pop    %eax
  3,44 │      ret

Overal speedup:

    # best of 5 runs
    before: 8268 idents, 47203 lines, 1526763 bytes, 0.148 s, 319217 lines/s, 10.3 MB/s
    after:  8273 idents, 47231 lines, 1527685 bytes, 0.146 s, 324092 lines/s, 10.5 MB/s

Static ASSERT macro taken from CCAN's[1] build_assert[2] which is in
public domain.

[1] http://ccodearchive.net/
[2] http://git.ozlabs.org/?p=ccan;a=blob;f=ccan/build_assert/build_assert.h;h=24e59c44cd930173178ac9b6e101b0af64a879e9;hb=HEAD
2012-12-21 20:46:26 +04:00
Kirill Smelkov
43a11a7ed1 Make tcc work after self-compiling with bounds-check enabled
For vstack Fabrice used the trick to initialize vtop to &vstack[-1], so
that on first push, vtop becomes &vstack[0] and a value is also stored
there - everything works.

Except that when tcc is compiled with bounds-checking enabled, vstack - 1
returns INVALID_POINTER and oops...

Let's workaround it with artificial 1 vstack slot which will not be
used, but only serve as an indicator that pointing to &vstack[-1] is ok.

Now, tcc, after being self-compiled with -b works:

    $ ./tcc -B. -o tccb  -DONE_SOURCE -DCONFIG_MULTIARCHDIR=\"i386-linux-gnu\" tcc.c  -ldl
    $ cd tests
    $ ../tcc -B.. -run tcctest.c >1
    $ ../tccb -B.. -run tcctest.c >2
    $ diff -u 1 2

and note, tcc's compilation speed is not affected:

    $ ./tcc -B. -bench -DONE_SOURCE -DCONFIG_MULTIARCHDIR=\"i386-linux-gnu\" -c tcc.c

    before: 8270 idents, 47221 lines, 1527730 bytes, 0.152 s, 309800 lines/s, 10.0 MB/s
    after:  8271 idents, 47221 lines, 1527733 bytes, 0.152 s, 310107 lines/s, 10.0 MB/s

But note, that `tcc -b -run tcc` is still broken - for example it crashes
on
    $ cat x.c
    double get100 () { return 100.0; }

    $ ./tcc -B. -b -DTCC_TARGET_I386 -DCONFIG_MULTIARCHDIR=\"i386-linux-gnu\"  -run   \
        -DONE_SOURCE ./tcc.c -B. -c x.c
    Runtime error: dereferencing invalid pointer
    ./tccpp.c:1953: at 0xa7beebdf parse_number() (included from ./libtcc.c, ./tcc.c)
    ./tccpp.c:3003: by 0xa7bf0708 next() (included from ./libtcc.c, ./tcc.c)
    ./tccgen.c:4465: by 0xa7bfe348 block() (included from ./libtcc.c, ./tcc.c)
    ./tccgen.c:4440: by 0xa7bfe212 block() (included from ./libtcc.c, ./tcc.c)
    ./tccgen.c:5529: by 0xa7c01929 gen_function() (included from ./libtcc.c, ./tcc.c)
    ./tccgen.c:5767: by 0xa7c02602 decl0() (included from ./libtcc.c, ./tcc.c)

that's because lib/bcheck.c runtime needs more fixes -- see next
patches.
2012-12-09 18:06:09 +04:00
Kirill Smelkov
b2a02961b4 Add support for __builtin_frame_address(level)
Continuing d6072d37 (Add __builtin_frame_address(0)) implement
__builtin_frame_address for levels greater than zero, in order for
tinycc to be able to compile its own lib/bcheck.c after
cffb7af9 (lib/bcheck: Prevent __bound_local_new / __bound_local_delete
from being miscompiled).

I'm new to the internals, and used the most simple way to do it.
Generated code is not very good for levels >= 2, compare

                gcc                         tcc

    level=0     mov    %ebp,%eax            lea    0x0(%ebp),%eax

    level=1     mov    0x0(%ebp),%eax       mov    0x0(%ebp),%eax

    level=2     mov    0x0(%ebp),%eax       mov    0x0(%ebp),%eax
                mov    (%eax),%eax          mov    %eax,-0x10(%ebp)
                                            mov    -0x10(%ebp),%eax
                                            mov    (%eax),%eax

    level=3     mov    0x0(%ebp),%eax       mov    0x0(%ebp),%eax
                mov    (%eax),%eax          mov    (%eax),%ecx
                mov    (%eax),%eax          mov    (%ecx),%eax

But this is still an improvement and for bcheck we need level=1 for
which the code is good.

For the tests I had to force gcc use -O0 to not inline the functions.
And -fno-omit-frame-pointer just in case.

If someone knows how to improve the generated code - help is
appreciated.

Thanks,
Kirill

Cc: Michael Matz <matz@suse.de>
Cc: Shinichiro Hamaji <shinichiro.hamaji@gmail.com>
2012-11-16 10:22:14 +04:00
Hitoshi Mitake
5eb64357b1 forbid invalid comparison of struct
Current tcc permits comparison of structs and comparison between
struct and other typed values.
2012-11-05 22:34:43 +09:00
Thomas Preud'homme
508df168f4 Fix commit 85f6fad3a6
Don't reset nocode_wanted with saved_nocode_wanted if it hasn't been
modified (and hence saved_nocode_wanted is uninitialized).
2012-10-25 20:14:55 +02:00
Thomas Preud'homme
cf95ac399c Error out in case of variable name clash
Error out when two local variable with same name are defined in the same
scope. This fixes bug #15597 in savannah's BTS.
2012-10-25 19:40:50 +02:00
Thomas Preud'homme
85f6fad3a6 Forbid VLA as static variables
Currently, VLA are not forbidden for static variable. This leads to
problems even if for fixed-size array when the size expression uses the
ternary operator (cond ? then-value : else-value) because it is parsed
as a general expression which leads to code generated in this case.

This commit solve the problem by forbidding VLA for static variables.
Although not required for the fix, avoiding code generation when the
expression is constant would be a nice addition though.
2012-10-25 18:07:13 +02:00
Thomas Preud'homme
d1694f7d7e get_reg(): try to free r2 for an SValue first
To be able to load a long long value correctly on i386, gv() rely on the
fact that when get_reg() look at an SValue it tries first to free the
register in r2 and then r. More information about the context can be
found at
http://lists.nongnu.org/archive/html/tinycc-devel/2012-06/msg00017.html
and later at
http://lists.nongnu.org/archive/html/tinycc-devel/2012-07/msg00021.html
2012-07-11 23:39:05 +02:00
Vincent Lefevre
d27a0b3548 Incorrect shift result type on unsigned short first argument.
The code for shifts is now similar to code for binary arithmetic operations,
except that only the first argument is considered, as required by the ISO C
standard.
2012-07-06 14:22:37 +02:00