tcc-xref
bellard 2003-01-06 20:19:20 +00:00
parent 7808b4046e
commit 75e743d23e
4 changed files with 347 additions and 24 deletions

View File

@ -13,7 +13,7 @@ CFLAGS+=-m386 -malign-functions=0 -mpreferred-stack-boundary=2
CFLAGS+=-DCONFIG_TCC_PREFIX=\"$(prefix)\"
DISAS=objdump -d
INSTALL=install
VERSION=0.9.15
VERSION=0.9.16
# run local version of tcc with local libraries and includes
TCC=./tcc -B. -I.
@ -103,7 +103,7 @@ ex3: ex3.c
# Native Tiny C Compiler
tcc_g: tcc.c i386-gen.c tccelf.c tcctok.h libtcc.h Makefile
tcc_g: tcc.c i386-gen.c tccelf.c tccasm.c i386-asm.c tcctok.h libtcc.h i386-asm.h Makefile
gcc $(CFLAGS) -o $@ $< $(LIBS)
tcc: tcc_g
@ -128,17 +128,9 @@ install: tcc libtcc1.o bcheck.o
clean:
rm -f *~ *.o tcc tcc1 tcct tcc_g tcctest.ref *.bin *.i ex2 \
core gmon.out test.out test.ref a.out tcc_p \
*.exe iltcc iltcc_g tcc-doc.html \
*.exe tcc-doc.html \
tcctest[1234] test[1234].out
# IL TCC
iltcc_g: tcc.c il-gen.c bcheck.c Makefile
gcc $(CFLAGS) -DTCC_TARGET_IL -o $@ $< $(LIBS)
iltcc: iltcc_g
strip -s -R .comment -R .note -o $@ $<
# win32 TCC
tcc_g.exe: tcc.c i386-gen.c bcheck.c Makefile
i386-mingw32msvc-gcc $(CFLAGS) -DCONFIG_TCC_STATIC -o $@ $<
@ -176,6 +168,22 @@ libtest: libtcc_test
instr: instr.o
objdump -d instr.o
# tiny assembler testing
asmtest.ref: asmtest.S
gcc -c -o asmtest.ref.o asmtest.S
objdump -D asmtest.ref.o > $@
# XXX: we compute tcc.c to go faster during development !
asmtest.out: asmtest.S tcc
# ./tcc tcc.c -c asmtest.S
#asmtest.out: asmtest.S tcc
./tcc -c asmtest.S
objdump -D asmtest.o > $@
asmtest: asmtest.out asmtest.ref
@if diff -u --ignore-matching-lines="file format" asmtest.ref asmtest.out ; then echo "ASM Auto Test OK"; fi
instr.o: instr.S
gcc -O2 -Wall -g -c -o $@ $<
@ -191,9 +199,8 @@ FILES= Makefile Makefile.uClibc \
README TODO COPYING \
Changelog tcc-doc.texi tcc-doc.html \
tcc.1 \
tcc.c i386-gen.c tccelf.c tcctok.h \
tcc.c i386-gen.c tccelf.c tcctok.h tccasm.c i386-asm.c i386-asm.h\
bcheck.c libtcc1.c \
il-opcodes.h il-gen.c \
elf.h stab.h stab.def \
stddef.h stdarg.h stdbool.h float.h varargs.h \
tcclib.h libtcc.h libtcc_test.c \

30
TODO
View File

@ -1,21 +1,33 @@
TODO list:
- add statment expressions (linux kernel compilation)
- implement minimal 'asm' extension (linux kernel compilation)
- handle static inline, then normal prototype.
- fix asm without input/output (no % preprocessing)
- handle inline functions as macros.
- see transparent union pb in /urs/include/sys/socket.h
- precise behaviour of typeof with arrays ? (__put_user macro)
- #include_next support for /usr/include/limits ?
but should suffice for most cases)
- handle '? x, y : z' in reversed function arguments or unsized
variable initialization (',' is considered incorrectly as separator
in preparser) : change func argument code generator ?
- function pointers/lvalues in ? : (linux kernel net/core/dev.c)
- add A x86 asm constraint (linux asm-i386/div64.h)
- transform functions to function pointers in function parameters (net/ipv4/ip_output.c)
- fix function pointer type display
- fix bound exit on RedHat 7.3
- fix static link on RedHat 7.3
- check lcc test suite -> fix bitfield binary operations
- check section alignment in C
- fix invalid cast in comparison 'if (v == (int8_t)v)'
- packed attribute
- look at patches from Scott Lafferty
- look at bugs from Jason Petrasko.
- support link once trick (gcc 3.2 / glibc compilation issue)
- finish varargs.h support (gcc 3.2 testsuite issue)
- add alloca()
- fix static functions declared inside block
- fix bitfield binary operations
- C99: add variable size arrays (gcc 3.2 testsuite issue)
- C99: add complex types (gcc 3.2 testsuite issue)
- ignore __extension__ keyword (see 20010328-1.c).
- Add __restrict keyword (20010611-1.c).
- postfix compound literals (see 20010124-1.c)
- handle '? x, y : z' in reversed function arguments or unsized
variable initialization (',' is considered incorrectly as separator
in preparser) : use a "record" parse mode ?
- fix multiple unions init
- test includes in libtcc_test.
- look at GCC 3.2 compatibility problems.

View File

@ -17,7 +17,7 @@ TCC compiles so @emph{fast} that even for big projects @code{Makefile}s may
not be necessary.
TCC not only supports ANSI C, but also most of the new ISO C99
standard and many GNUC extensions.
standard and many GNUC extensions including inline assembly.
TCC can also be used to make @emph{C scripts}, i.e. pieces of C source
that you run as a Perl or Python script. Compilation is so fast that
@ -70,6 +70,14 @@ link a.o and b.o together and generate the executable myprog.
@item tcc -c a.c
Compile a.c and generate object file a.o
@item tcc -c asmfile.S
Preprocess with C preprocess and assemble asmfile.S and generate
object file asmfile.o.
@item tcc -c asmfile.s
Assemble (but not preprocess) asmfile.s and generate object file
asmfile.o.
@item tcc -r -o ab.o a.c b.c
Compile a.c and b.c, link them together and generate the object file ab.o.
@ -332,6 +340,31 @@ to get the alignment of a type or an expression.
@code{void *} on the goto label @code{label}. @code{goto *expr} can be
used to jump on the pointer resulting from @code{expr}.
@item Inline assembly with asm instruction:
@example
static inline void * my_memcpy(void * to, const void * from, size_t n)
{
int d0, d1, d2;
__asm__ __volatile__(
"rep ; movsl\n\t"
"testb $2,%b4\n\t"
"je 1f\n\t"
"movsw\n"
"1:\ttestb $1,%b4\n\t"
"je 2f\n\t"
"movsb\n"
"2:"
: "=&c" (d0), "=&D" (d1), "=&S" (d2)
:"0" (n/4), "q" (n),"1" ((long) to),"2" ((long) from)
: "memory");
return (to);
}
@end example
TCC includes its own x86 inline assembler with a @code{gas}-like (GNU
assembler) syntax. No intermediate files are generated. GCC 3.x named
operands are supported.
@end itemize
@section TinyCC extensions
@ -350,6 +383,98 @@ indicate that you use TCC.
@end itemize
@chapter TinyCC Assembler
Since version 0.9.16, TinyCC integrates its own assembler. TinyCC
assembler supports a gas-like syntax (GNU assembler). You can
desactivate assembler support if you want a smaller TinyCC executable
(the C compiler does not rely on the assembler).
TinyCC Assembler is used to handle files with @file{.S} (C
preprocessed assembler) and @file{.s} extensions. It is also used to
handle the GNU inline assembler with the @code{asm} keyword.
@section Syntax
TinyCC Assembler supports most of the gas syntax. The tokens are the
same as C.
@itemize
@item C and C++ comments are supported.
@item Identifiers are the same as C, so you cannot use '.' or '$'.
@item Only 32 bit integer numbers are supported.
@end itemize
@section Expressions
@itemize
@item Integers in decimal, octal and hexa are supported.
@item Unary operators: +, -, ~.
@item Binary operators in decreasing priority order:
@enumerate
@item *, /, %
@item &, |, ^
@item +, -
@end enumerate
@item A value is either an absolute number or a label plus an offset.
All operators accept absolute values except '+' and '-'. '+' or '-' can be
used to add an offset to a label. '-' supports two labels only if they
are the same or if they are both defined and in the same section.
@end itemize
@section Labels
@itemize
@item All labels are considered as local, except undefined ones.
@item Numeric labels can be used as local @code{gas}-like labels.
They can be defined several times in the same source. Use 'b'
(backward) or 'f' (forward) as suffix to reference them:
@example
1:
jmp 1b /* jump to '1' label before */
jmp 1f /* jump to '1' label after */
1:
@end example
@end itemize
@section Directives
All directives are preceeded by a '.'. The following directives are
supported:
@itemize
@item .align n[,value]
@item .skip n[,value]
@item .space n[,value]
@item .byte value1[,value2...]
@item .word value1[,value2...]
@item .short value1[,value2...]
@item .int value1[,value2...]
@item .long value1[,value2...]
@end itemize
@section X86 Assembler
All X86 opcodes are supported. Only ATT syntax is supported (source
then destination operand order). If no size suffix is given, TinyCC
tries to guess it from the operand sizes.
Currently, MMX opcodes are supported but not SSE ones.
@chapter TinyCC Linker
@section ELF file generation

181
tcctest.c
View File

@ -67,6 +67,9 @@ void relocation_test(void);
void old_style_function(void);
void sizeof_test(void);
void typeof_test(void);
void local_label_test(void);
void statement_expr_test(void);
void asm_test(void);
int fib(int n);
void num(int n);
@ -200,7 +203,7 @@ void macro_test(void)
#line 203 "test"
printf("__LINE__=%d __FILE__=%s\n",
__LINE__, __FILE__);
#line 200 "tcctest.c"
#line 206 "tcctest.c"
/* not strictly preprocessor, but we test it there */
#ifdef C99_MACROS
@ -467,6 +470,9 @@ int main(int argc, char **argv)
old_style_function();
sizeof_test();
typeof_test();
statement_expr_test();
local_label_test();
asm_test();
return 0;
}
@ -839,6 +845,16 @@ void bool_test()
}
}
/* test ? : GCC extension */
{
static int v1 = 34 ? : -1; /* constant case */
static int v2 = 0 ? : -1; /* constant case */
int a = 30;
printf("%d %d\n", v1, v2);
printf("%d %d\n", a - 30 ? : a * 2, a + 1 ? : a * 2);
}
/* again complex expression */
for(i=0;i<256;i++) {
if (toupper1 (i) != TOUPPER (i))
@ -846,7 +862,13 @@ void bool_test()
}
}
/* GCC accepts that */
static int tab_reinit[];
static int tab_reinit[10];
//int cinit1; /* a global variable can be defined several times without error ! */
int cinit1;
int cinit1;
int cinit1 = 0;
int *cinit2 = (int []){3, 2, 1};
@ -1072,6 +1094,12 @@ struct bar {
"a2", 1
};
int sinit18[10] = {
[2 ... 5] = 20,
2,
[8] = 10,
};
void init_test(void)
{
int linit1 = 2;
@ -1161,8 +1189,12 @@ void init_test(void)
printf("sinit17=%s %d %s %d\n",
sinit17[0].s, sinit17[0].len,
sinit17[1].s, sinit17[1].len);
for(i=0;i<10;i++)
printf("%x ", sinit18[i]);
printf("\n");
}
void switch_test()
{
int i;
@ -1659,3 +1691,150 @@ void typeof_test(void)
c = 3.5;
printf("a=%f b=%f c=%f\n", a, b, c);
}
void statement_expr_test(void)
{
int a, i;
a = 0;
for(i=0;i<10;i++) {
a += 1 +
( { int b, j;
b = 0;
for(j=0;j<5;j++)
b += j; b;
} );
}
printf("a=%d\n", a);
}
void local_label_test(void)
{
int a;
goto l1;
l2:
a = 1 + ({
__label__ l1, l2, l3;
goto l4;
l5:
printf("aa1\n");
goto l1;
l2:
printf("aa3\n");
goto l3;
l1:
printf("aa2\n");
goto l2;
l3:;
1;
});
printf("a=%d\n", a);
return;
l1:
printf("bb1\n");
goto l2;
l4:
printf("bb2\n");
goto l5;
}
/* inline assembler test */
#ifdef __i386__
/* from linux kernel */
static char * strncat1(char * dest,const char * src,size_t count)
{
int d0, d1, d2, d3;
__asm__ __volatile__(
"repne\n\t"
"scasb\n\t"
"decl %1\n\t"
"movl %8,%3\n"
"1:\tdecl %3\n\t"
"js 2f\n\t"
"lodsb\n\t"
"stosb\n\t"
"testb %%al,%%al\n\t"
"jne 1b\n"
"2:\txorl %2,%2\n\t"
"stosb"
: "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3)
: "0" (src),"1" (dest),"2" (0),"3" (0xffffffff), "g" (count)
: "memory");
return dest;
}
static inline void * memcpy1(void * to, const void * from, size_t n)
{
int d0, d1, d2;
__asm__ __volatile__(
"rep ; movsl\n\t"
"testb $2,%b4\n\t"
"je 1f\n\t"
"movsw\n"
"1:\ttestb $1,%b4\n\t"
"je 2f\n\t"
"movsb\n"
"2:"
: "=&c" (d0), "=&D" (d1), "=&S" (d2)
:"0" (n/4), "q" (n),"1" ((long) to),"2" ((long) from)
: "memory");
return (to);
}
static __inline__ void sigaddset1(unsigned int *set, int _sig)
{
__asm__("btsl %1,%0" : "=m"(*set) : "Ir"(_sig - 1) : "cc");
}
static __inline__ void sigdelset1(unsigned int *set, int _sig)
{
asm("btrl %1,%0" : "=m"(*set) : "Ir"(_sig - 1) : "cc");
}
static __inline__ __const__ unsigned int swab32(unsigned int x)
{
__asm__("xchgb %b0,%h0\n\t" /* swap lower bytes */
"rorl $16,%0\n\t" /* swap words */
"xchgb %b0,%h0" /* swap higher bytes */
:"=q" (x)
: "0" (x));
return x;
}
unsigned int set;
void asm_test(void)
{
char buf[128];
unsigned int val;
printf("inline asm:\n");
memcpy1(buf, "hello", 6);
strncat1(buf, " worldXXXXX", 3);
printf("%s\n", buf);
set = 0xff;
sigdelset1(&set, 2);
sigaddset1(&set, 16);
/* NOTE: we test here if C labels are correctly restored after the
asm statement */
goto label1;
label2:
__asm__("btsl %1,%0" : "=m"(set) : "Ir"(20) : "cc");
printf("set=0x%x\n", set);
val = 0x01020304;
printf("swab32(0x%08x) = 0x%0x\n", val, swab32(val));
return;
label1:
goto label2;
}
#else
void asm_test(void)
{
}
#endif