Commit Graph

283 Commits (4ac0e1971ede1ad3e5bf9f47fad0a8ca0e14525f)

Author SHA1 Message Date
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