Unified · Split
| @@ -1,61 +1,92 @@ | |||
| 1 | all: test cvt | 1 | # |
| 2 | # Tiny C Compiler Makefile | ||
| 3 | # | ||
| 4 | prefix=/usr/local | ||
| 2 | 5 | ||
| 3 | test: prog.bin | 6 | CFLAGS=-O2 -g -Wall -Wno-parentheses -I. |
| 4 | cmp -l prog.bin prog.bin.ref | 7 | LIBS=-ldl |
| 8 | #CFLAGS=-O2 -g -Wall -Wno-parentheses -I. -pg -static -DPROFILE | ||
| 9 | #LIBS= | ||
| 5 | 10 | ||
| 6 | run: tcc prog.c | 11 | CFLAGS+=-m386 -malign-functions=0 |
| 7 | ./tcc prog.c | 12 | DISAS=objdump -D -b binary -m i386 |
| 13 | INSTALL=install | ||
| 14 | VERSION=0.9 | ||
| 8 | 15 | ||
| 9 | run2: tcc tcc1.c prog.c | 16 | all: tcc |
| 10 | ./tcc tcc1.c prog.c | ||
| 11 | 17 | ||
| 12 | run3: tcc tcc1.c prog.c | 18 | # auto test |
| 13 | ./tcc tcc1.c tcc1.c prog.c | ||
| 14 | 19 | ||
| 15 | prog.bin: prog.c tcc | 20 | test: test.ref test.out |
| 16 | ./tc prog.c $@ | 21 | @if diff -u test.ref test.out ; then echo "Auto Test OK"; fi |
| 17 | ndisasm -b 32 $@ | ||
| 18 | 22 | ||
| 19 | p2.bin: p2.c tcc | 23 | prog.ref: prog.c |
| 20 | ./tcc $< $@ | 24 | gcc $(CFLAGS) -o $@ $< |
| 21 | ndisasm -b 32 $@ | ||
| 22 | 25 | ||
| 23 | # Tiny C Compiler | 26 | test.ref: prog.ref |
| 27 | ./prog.ref > $@ | ||
| 28 | |||
| 29 | test.out: tcc prog.c | ||
| 30 | ./tcc -I. prog.c > $@ | ||
| 31 | |||
| 32 | run: tcc prog.c | ||
| 33 | ./tcc -I. prog.c | ||
| 34 | |||
| 35 | run2: tcc tcc.c prog.c | ||
| 36 | ./tcc -I. tcc.c -I. prog.c | ||
| 24 | 37 | ||
| 25 | tcc: tcc.c | 38 | run3: tcc tcc.c prog.c |
| 26 | gcc -O2 -Wall -g -o $@ $< -ldl | 39 | ./tcc -I. tcc.c -I. tcc.c -I. prog.c |
| 27 | 40 | ||
| 28 | tcc1: tcc1.c | 41 | # speed test |
| 29 | gcc -O2 -Wall -g -o $@ $< | 42 | speed: tcc ex2 ex3 |
| 43 | time ./ex2 1238 2 3 4 10 13 4 | ||
| 44 | time ./tcc -I. ./ex2.c 1238 2 3 4 10 13 4 | ||
| 45 | time ./ex3 35 | ||
| 46 | time ./tcc -I. ./ex3.c 35 | ||
| 30 | 47 | ||
| 31 | tcc1.i: tcc.c Makefile | 48 | ex2: ex2.c |
| 32 | gcc -E -P -o $@ $< | 49 | gcc $(CFLAGS) -o $@ $< |
| 33 | 50 | ||
| 34 | tcc1.c: tcc1.i cvt Makefile | 51 | ex3: ex3.c |
| 35 | ./cvt -d $< $@ | 52 | gcc $(CFLAGS) -o $@ $< |
| 36 | @ls -l $@ | ||
| 37 | 53 | ||
| 38 | # obfuscated C compiler | 54 | # Tiny C Compiler |
| 39 | otcc: otcc.c | 55 | |
| 40 | gcc -O2 -Wall -g -o $@ $< -ldl | 56 | tcc_g: tcc.c Makefile |
| 57 | gcc $(CFLAGS) -o $@ $< $(LIBS) | ||
| 58 | |||
| 59 | tcc: tcc_g | ||
| 60 | strip -s -R .comment -R .note -o $@ $< | ||
| 41 | 61 | ||
| 42 | otcc.i: otcc.c Makefile | 62 | install: tcc |
| 43 | gcc -E -P -DTINY -o $@ $< | 63 | $(INSTALL) -m755 tcc $(prefix)/bin |
| 64 | mkdir -p $(prefix)/lib/tcc | ||
| 65 | $(INSTALL) -m644 stdarg.h stddef.h tcclib.h $(prefix)/lib/tcc | ||
| 44 | 66 | ||
| 45 | otcc1.c: otcc.i cvt Makefile | 67 | clean: |
| 46 | ./cvt $< $@ | 68 | rm -f *~ *.o tcc tcc1 tcct tcc_g prog.ref *.bin *.i ex2 \ |
| 47 | @ls -l $@ | 69 | core gmon.out test.out test.ref a.out |
| 48 | 70 | ||
| 49 | orun: otcc otcc1.c | 71 | # target for development |
| 50 | ./otcc otcc1.c ex1.c | ||
| 51 | 72 | ||
| 52 | # misc | 73 | %.bin: %.c tcct |
| 74 | ./tcct -I. $< $@ | ||
| 75 | $(DISAS) $@ | ||
| 53 | 76 | ||
| 54 | cvt: cvt.c | 77 | tcct: tcc.c |
| 55 | gcc -O2 -Wall -g -o $@ $< | 78 | gcc -DTEST $(CFLAGS) -o $@ $< -ldl |
| 56 | 79 | ||
| 57 | instr.o: instr.S | 80 | instr.o: instr.S |
| 58 | gcc -O2 -Wall -g -c -o $@ $< | 81 | gcc -O2 -Wall -g -c -o $@ $< |
| 59 | 82 | ||
| 60 | clean: | 83 | FILE=tcc-$(VERSION) |
| 61 | rm -f *~ *.o tcc tcc1 cvt | 84 | |
| 85 | tar: | ||
| 86 | rm -rf /tmp/$(FILE) | ||
| 87 | cp -r ../tcc /tmp/$(FILE) | ||
| 88 | ( cd /tmp ; tar zcvf ~/$(FILE).tar.gz \ | ||
| 89 | $(FILE)/Makefile $(FILE)/README $(FILE)/TODO $(FILE)/COPYING \ | ||
| 90 | $(FILE)/tcc.c $(FILE)/stddef.h $(FILE)/stdarg.h $(FILE)/tcclib.h \ | ||
| 91 | $(FILE)/ex*.c $(FILE)/prog.c ) | ||
| 92 | rm -rf /tmp/$(FILE) | ||
| @@ -1,49 +1,129 @@ | |||
| 1 | Tiny C Compiler - Make the best x86 Linux C compiler in less than 8192 bytes. | 1 | Tiny C Compiler - C Scripting Everywhere - The Smallest ANSI C compiler |
| 2 | ----------------------------------------------------------------------------- | 2 | ----------------------------------------------------------------------- |
| 3 | 3 | ||
| 4 | Differences with ANSI C: | 4 | Features: |
| 5 | ----------------------- | 5 | -------- |
| 6 | 6 | ||
| 7 | - Preprocessor: only '#define xx yy' is supported. Recursive defined | 7 | - SMALL! You can compile and execute C code everywhere, for example on |
| 8 | supported. All other directives are not supported. | 8 | rescue disks. |
| 9 | 9 | ||
| 10 | - Types: int, char, void, pointers and functions are | 10 | - FAST! tcc generates optimized x86 code. No byte code overhead. |
| 11 | supported. Function pointers are also supported. struct, union and | ||
| 12 | typedef not supported. | ||
| 13 | 11 | ||
| 14 | - Operations: 'x=' not supported. | 12 | - UNLIMITED! Any C dynamic library can be used directly. TCC is |
| 13 | heading torwards full ANSI C compliance. TCC can of course compile | ||
| 14 | itself. | ||
| 15 | 15 | ||
| 16 | - Keywords: the following keywords are supported: int void char if | 16 | - Compile and execute C source directly. No linking or assembly |
| 17 | else while break return for. | 17 | necessary. Full C preprocessor included. |
| 18 | 18 | ||
| 19 | - Symbol scope: local variables supported, but they cannot have the | 19 | - C script supported : just add '#!/usr/local/bin/tcc' at the first |
| 20 | same name as global variables. | 20 | line of your C source, and execute it directly from the command line ! |
| 21 | 21 | ||
| 22 | Features: | 22 | - For adventurers, tcc is conceived to be able to generate code for |
| 23 | -------- | 23 | other targets. |
| 24 | 24 | ||
| 25 | - SMALL! You can compile and execute C code everywhere, for example on | 25 | Documentation: |
| 26 | rescue disks. | 26 | ------------- |
| 27 | |||
| 28 | 1) Installation | ||
| 29 | |||
| 30 | ***TCC currently only work on Linux x86***. | ||
| 31 | |||
| 32 | Type 'make install' to compile and install tcc in /usr/local and | ||
| 33 | /usr/local/lib/tcc. | ||
| 34 | |||
| 35 | 2) Introduction | ||
| 36 | |||
| 37 | We assume here that you know ANSI C. Look at the example ex1.c to know | ||
| 38 | what the programs look like. | ||
| 39 | |||
| 40 | The main limitations of tcc are that you cannot use floats. | ||
| 41 | |||
| 42 | The include file <tcclib.h> can be used if you want a small basic libc | ||
| 43 | include support (especially useful for floppy disks). Of course, you | ||
| 44 | can also use standard headers, although they are slower to compile. | ||
| 45 | |||
| 46 | You can begin your C script with '#!/usr/local/bin/tcc' on the first | ||
| 47 | line and set its execute bits (chmod a+x your_script). Then, you can | ||
| 48 | launch the C code as a shell or perl script :-) The command line | ||
| 49 | arguments are put in 'argc' and 'argv' of the main functions, as in | ||
| 50 | ANSI C. | ||
| 51 | |||
| 52 | 3) Invokation | ||
| 53 | |||
| 54 | '-Idir' : specify an additionnal include path. The | ||
| 55 | default ones are: /usr/include, /usr/lib/tcc, /usr/local/lib/tcc. | ||
| 56 | |||
| 57 | '-Dsym' : define preprocessor symbol 'sym' to 1. | ||
| 58 | |||
| 59 | '-lxxx' : dynamically link your program with library | ||
| 60 | libxxx.so. Standard library paths are checked, including those | ||
| 61 | specificed with LD_LIBRARY_PATH. | ||
| 62 | |||
| 63 | Only one source code can be compiled. If you have multiple source | ||
| 64 | files, add one which includes all your sources. | ||
| 65 | |||
| 66 | 4) Examples | ||
| 67 | |||
| 68 | ex1.c: simplest example (hello world). Can also be launched directly | ||
| 69 | as a script: ./ex2.c. | ||
| 70 | |||
| 71 | ex2.c: more complicated example: find a number with the four | ||
| 72 | operations given a list of numbers (benchmark). | ||
| 73 | |||
| 74 | ex3.c: compute fibonacci numbers (benchmark). | ||
| 75 | |||
| 76 | ex4.c: more complicated: X11 program. Very complicated test in fact | ||
| 77 | because standard headers are being used ! Currently slow because | ||
| 78 | parsing does not use hash tables. | ||
| 79 | |||
| 80 | ex5.c: 'hello world' with standard glibc headers. | ||
| 81 | |||
| 82 | tcc.c: TCC can compile itself. Used to check the code generator. | ||
| 83 | |||
| 84 | prog.c: auto test for TCC which tests many subtle possible bugs. Used | ||
| 85 | when doing 'make test'. | ||
| 86 | |||
| 87 | Exact differences with ANSI C: | ||
| 88 | ----------------------------- | ||
| 89 | |||
| 90 | 1) Preprocessor | ||
| 91 | |||
| 92 | - the preprocessor tokens are the same as C. It means that in some | ||
| 93 | rare cases, preprocessed numbers are not handled exactly as in ANSI | ||
| 94 | C. This approach has the advantage of being simpler and FAST! | ||
| 95 | |||
| 96 | - __LINE__, __FILE__, __DATE__, __TIME__ are currently not handled. | ||
| 97 | |||
| 98 | - #line not handled | ||
| 99 | |||
| 100 | 2) C language | ||
| 101 | |||
| 102 | - Parsing: variables cannot be initialized ('int a = 1' or 'int tab[2] = | ||
| 103 | {1, 2}' not supported). | ||
| 104 | |||
| 105 | - Cannot pass struct/union as value. Cannot assign struct/union (use | ||
| 106 | memcpy instead). | ||
| 27 | 107 | ||
| 28 | - FAST! tcc generate x86 code. No byte code overhead. | 108 | - Types: floating point numbers are not supported. |
| 29 | 109 | ||
| 30 | - Compile and execute C source directly. No linking necessary. | 110 | - (BUG) 'char' and 'short' casts do not truncate correctly. |
| 31 | 111 | ||
| 32 | - C script supported : just add '#!/usr/bin/tcc' at the first line of | 112 | - 'sizeof' may not work if too complex expression is given. |
| 33 | your C source, and execute it directly from the command line ! | ||
| 34 | 113 | ||
| 35 | - All C library functions can be used via dynamic linking. | 114 | Supported C extensions: |
| 115 | ---------------------- | ||
| 36 | 116 | ||
| 37 | ------------------------------------------------------------------------- | 117 | - 'inline' keyword is ignored. |
| 38 | An even smaller compiler can be build from tcc by activating the | ||
| 39 | define 'TINY'. The following changes from tcc: | ||
| 40 | 118 | ||
| 41 | - Comments are not supported. | ||
| 42 | 119 | ||
| 43 | - Parsing: No char constants. No '\r' and '\t' in strings. Only base | 120 | License: |
| 44 | 10 numbers are supported. | 121 | ------- |
| 45 | 122 | ||
| 46 | - no 'for' loops. | 123 | TCC is distributed under the GNU Generic Public License (see COPYING |
| 124 | file). | ||
| 47 | 125 | ||
| 48 | - Operations: '?:', ',', 'x=', shifts, '&&', '||', '!', '~' not supported. | 126 | I accept only patches where you give your copyright explictely to me |
| 127 | to simplify licensing issues. | ||
| 49 | 128 | ||
| 129 | Fabrice Bellard - Nov 11, 2001. | ||
| @@ -1,7 +1,15 @@ | |||
| 1 | TODO list: | ||
| 1 | 2 | ||
| 2 | - static arrays | 3 | Critical: |
| 3 | - external symbols (vars) | 4 | |
| 4 | - continue/do while/switch/case/goto | 5 | - add hash tables for symbols (useful for long programs) |
| 5 | - 'x'= | 6 | - 0 is pointer - fix type compare |
| 6 | - constant propagation for '+', '-' and []. | 7 | - add message if external function or variable not found. |
| 7 | - verify function types | 8 | |
| 9 | Not critical: | ||
| 10 | |||
| 11 | - fix preprocessor symbol redefinition | ||
| 12 | - better constant opt (&&, ||, ?:) | ||
| 13 | - function pointers to forward reference (patch code generator) | ||
| 14 | - add PowerPC code generator. | ||
| 15 | - add portable byte code generator and interpreter. | ||
| @@ -4,8 +4,12 @@ · 3 unmodified lines | |||
| 4 | typedef char *va_list; | 4 | typedef char *va_list; |
| 5 | 5 | ||
| 6 | /* only correct for i386 */ | 6 | /* only correct for i386 */ |
| 7 | #define va_start(ap,last) ap=(char *)&(last); | 7 | /* XXX: incorrect for type size different than 4 bytes*/ |
| 8 | #define va_arg(ap,type) (ap-=sizeof (type), *(type *)(ap)) | 8 | #define va_start(ap,last) ap = ((char *)&(last)) + sizeof(int); |
| 9 | #define va_arg(ap,type) (ap += sizeof(int), *(type *)(ap - sizeof(int))) | ||
| 9 | #define va_end(ap) | 10 | #define va_end(ap) |
| 10 | 11 | ||
| 12 | /* fix a buggy dependency on GCC in libio.h */ | ||
| 13 | typedef va_list __gnuc_va_list; | ||
| 14 | |||
| 11 | #endif | 15 | #endif |
| @@ -3,7 +3,7 @@ · 2 unmodified lines | |||
| 3 | 3 | ||
| 4 | /* TCC include file */ | 4 | /* TCC include file */ |
| 5 | #define NULL ((void *)0) | 5 | #define NULL ((void *)0) |
| 6 | |||
| 7 | typedef unsigned int size_t; | 6 | typedef unsigned int size_t; |
| 7 | typedef int wchar_t; | ||
| 8 | 8 | ||
| 9 | #endif | 9 | #endif |
| @@ -19,6 +19,9 @@ unsigned long int strtoul(const char *nptr, char **endptr, int base); · 18 unmodified lines | |||
| 19 | /* stdio.h */ | 19 | /* stdio.h */ |
| 20 | typedef struct __FILE FILE; | 20 | typedef struct __FILE FILE; |
| 21 | #define EOF (-1) | 21 | #define EOF (-1) |
| 22 | extern FILE *stdin; | ||
| 23 | extern FILE *stdout; | ||
| 24 | extern FILE *stderr; | ||
| 22 | FILE *fopen(const char *path, const char *mode); | 25 | FILE *fopen(const char *path, const char *mode); |
| 23 | FILE *fdopen(int fildes, const char *mode); | 26 | FILE *fdopen(int fildes, const char *mode); |
| 24 | FILE *freopen(const char *path, const char *mode, FILE *stream); | 27 | FILE *freopen(const char *path, const char *mode, FILE *stream); |
| @@ -58,6 +61,10 @@ void *memset(void *s, int c, size_t n); · 33 unmodified lines | |||
| 58 | char *strdup(const char *s); | 61 | char *strdup(const char *s); |
| 59 | 62 | ||
| 60 | /* dlfcn.h */ | 63 | /* dlfcn.h */ |
| 64 | #define RTLD_LAZY 0x001 | ||
| 65 | #define RTLD_NOW 0x002 | ||
| 66 | #define RTLD_GLOBAL 0x100 | ||
| 67 | |||
| 61 | void *dlopen(const char *filename, int flag); | 68 | void *dlopen(const char *filename, int flag); |
| 62 | const char *dlerror(void); | 69 | const char *dlerror(void); |
| 63 | void *dlsym(void *handle, char *symbol); | 70 | void *dlsym(void *handle, char *symbol); |