aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile33
-rw-r--r--TODO30
-rw-r--r--tcc-doc.texi127
-rw-r--r--tcctest.c181
4 files changed, 347 insertions, 24 deletions
diff --git a/Makefile b/Makefile
index c971b2a..23d8291 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 17d7204..86faf7e 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 d5ddb40..2ac907b 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 493730e..4e2a304 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