From 75e743d23e77d9fef7576efe13dd7da492b4e955 Mon Sep 17 00:00:00 2001 From: bellard Date: Mon, 6 Jan 2003 20:19:20 +0000 Subject: [PATCH] update --- Makefile | 33 ++++++----- TODO | 30 +++++++--- tcc-doc.texi | 127 ++++++++++++++++++++++++++++++++++++++++- tcctest.c | 181 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 347 insertions(+), 24 deletions(-) diff --git a/Makefile b/Makefile index c971b2a5..23d8291b 100644 --- a/Makefile +++ b/Makefile @@ -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 \ diff --git a/TODO b/TODO index 17d72048..86faf7e9 100644 --- a/TODO +++ b/TODO @@ -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. diff --git a/tcc-doc.texi b/tcc-doc.texi index d5ddb409..2ac907b7 100644 --- a/tcc-doc.texi +++ b/tcc-doc.texi @@ -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 diff --git a/tcctest.c b/tcctest.c index 493730e5..4e2a3046 100644 --- a/tcctest.c +++ b/tcctest.c @@ -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 -- 2.11.4.GIT