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).
This requires correctly handling the REX prefix.
As bonus we now also support the four 8bit registers
spl,bpl,sil,dil, which are decoded as ah,ch,dh,bh in non-long-mode
(and require a REX prefix as well).
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.
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.
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.
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.
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).
lar can accept multiple sizes as well (wlx), like lsl. When using
autosize it's important to look at the destination operand first;
when it's a register that one determines the size, not the input
operand.
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).
In particular subtracting a defined symbol from current section
makes the value PC relative, and .org accepts symbolic expressions
as well, if the symbol is from the current section.
When tokens in macro definitions need cstr_buf inside get_tok_str,
the second might overwrite the first (happens when tokens are
multi-character non-identifiers, see testcase) in macro_is_equal,
failing to diagnose a difference. Use a real local buffer.
Now we can express prefixes with 0x0fxx opcodes we can correct the
movq mem64->xmm opcode, and restrict the movq xmm->mem64 movq to
not invalidly accept mmx.
In particular those that are extensions of existing mmx (or sse1)
instructions by a simple 0x66 prefix. There's one caveat for
x86-64: as we don't yet correctly handle the 0xf3 prefix
the movq mem64->xmm is wrong (tested in asmtest.S). Needs
some refactoring of the instr_type member.
- generate and use SYM@PLT for plt addresses
- get rid of patch_dynsym_undef hack (no idea what it did on FreeBSD)
- use sym_attrs instead of symtab_to_dynsym
- special case for function pointers into .so on i386
- libtcc_test: test tcc_add_symbol with data object
- move target specicic code to *-link.c files
- add R_XXX_RELATIVE (needed for PE)
The problem was with tcctest.c:
unsigned set;
__asm__("btsl %1,%0" : "=m"(set) : "Ir"(20) : "cc");
when with tcc compiled with the HAVE_SELINUX option, run with
tcc -run, it would use large addresses far beyond the 32bits
range when tcc did not use the pc-relative mode for accessing
'set' in global data memory. In fact the assembler did not
know about %rip at all.
Changes:
- memory operands use (%rax) not (%eax)
- conversion from VT_LLOCAL: use type VT_PTR
- support 'k' modifier
- support %rip register
- support X(%rip) pc-relative addresses
The test in tcctest.c is from Michael Matz.
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;
}
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
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)
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
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
Except
- that libtcc1.a is now installed in subdirs i386/ etc.
- the support for arm and arm64
- some of the "Darwin" fixes
- tests are mosly unchanged
Also
- removed the "legacy links for cross compilers" (was total mess)
- removed "out-of-tree" build support (was broken anyway)
- from win32/include/winapi: various .h
The winapi header set cannot be complete no matter what. So
lets have just the minimal set necessary to compile the examples.
- remove CMake support (hard to keep up to date)
- some other files
Also, drop useless changes in win32/lib/(win)crt1.c
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
There were two errors in the arithmetic imm8 instruction. They accept
only REGW, and in case the user write a xxxb opcode that variant
needs to be rejected as well (it's not automatically rejected by REGW
in case the destination is memory).
Two things: negative constants were rejected (e.g. "add $-15,%eax").
Second the insn order was such that the arithmetic IM8S forms
weren't used (always the IM32 ones). Switching them prefers those
but requires a fix for size calculation in case the opcodes were
OPC_ARITH and OPC_WLX (whose size starts with 1, not zero).
Fix it to actually be able to parse 64bit immediates (enlarge
operand value type). Then, generally there's no need for accepting
IM64 anywhere, except in the 0xba+r mov opcodes, so OP_IM is
unnecessary, as is OPT_IMNO64. Improve the generated code a bit
by preferring the 0xc7 opcode for im32->reg64, instead of the
im64->reg64 form (which we therefore hardcode).
A bag of assembler fixes, to be either compatible with GAS
(e.g. order of 'test' operands), accept more instructions,
count correct foo{bwlq} variants on x86_64, fix modrm/sib bytes
on x86_64 to not use %rip relative addressing mode, to not use
invalid insns in tests/asmtest.S for x86_64.
Result is that now output of GAS and of tcc on tests/asmtest.S
is mostly the same.
Insert a space when it is required to prevent mistokenisation of
the output, and also in a few cases where it is not strictly
required, imitating GCC's behaviour.
* correct -E output for the case ++ + ++ concatenation
do this only for expanded from macro string
and only when tcc_state->output_type == TCC_OUTPUT_PREPROCESS
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`
made like in pcc
(pcc.ludd.ltu.se/ftp/pub/pcc-docs/pcc-utf8-ver3.pdf)
We treat all chars with high bit set as alphabetic.
This allow code like
#include <stdio.h>
int Lefèvre=2;
int main() {
printf("Lefèvre=%d\n",Lefèvre);
return 0;
}
modified version of the old one which don't allow '.'
in #define Identifiers. This allow correctly preprocess
the following code in *.S
#define SRC(y...) \
9999: y; \
.section __ex_table, "a"; \
.long 9999b, 6001f ; \
// .previous
SRC(1: movw (%esi), %bx)
6001:
A test included.
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.
* 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...
Jsut for testing. It works for me (don't break anything)
Small fixes for x86_64-gen.c in "tccpp: fix issues, add tests"
are dropped in flavor of this patch.
Pip Cet:
Okay, here's a first patch that fixes the problem (but I've found
another bug, yet unfixed, in the process), though it's not
particularly pretty code (I tried hard to keep the changes to the
minimum necessary). If we decide to actually get rid of VT_QLONG and
VT_QFLOAT (please, can we?), there are some further simplifications in
tccgen.c that might offset some of the cost of this patch.
The idea is that an integer is no longer enough to describe how an
argument is stored in registers. There are a number of possibilities
(none, integer register, two integer registers, float register, two
float registers, integer register plus float register, float register
plus integer register), and instead of enumerating them I've
introduced a RegArgs type that stores the offsets for each of our
registers (for the other architectures, it's simply an int specifying
the number of registers). If someone strongly prefers an enum, we
could do that instead, but I believe this is a place where keeping
things general is worth it, because this way it should be doable to
add SSE or AVX support.
There is one line in the patch that looks suspicious:
} else {
addr = (addr + align - 1) & -align;
param_addr = addr;
addr += size;
- sse_param_index += reg_count;
}
break;
However, this actually fixes one half of a bug we have when calling a
function with eight double arguments "interrupted" by a two-double
structure after the seventh double argument:
f(double,double,double,double,double,double,double,struct { double
x,y; },double);
In this case, the last argument should be passed in %xmm7. This patch
fixes the problem in gfunc_prolog, but not the corresponding problem
in gfunc_call, which I'll try tackling next.
* fix some macro expansion issues
* add some pp tests in tests/pp
* improved tcc -E output for better diff'ability
* remove -dD feature (quirky code, exotic feature,
didn't work well)
Based partially on ideas / researches from PipCet
Some issues remain with VA_ARGS macros (if used in a
rather tricky way).
Also, to keep it simple, the pp doesn't automtically
add any extra spaces to separate tokens which otherwise
would form wrong tokens if re-read from tcc -E output
(such as '+' '=') GCC does that, other compilers don't.
* cleanups
- #line 01 "file" / # 01 "file" processing
- #pragma comment(lib,"foo")
- tcc -E: forward some pragmas to output (pack, comment(lib))
- fix macro parameter list parsing mess from
a3fc543459a715d7143d
(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)
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.