mirror of
https://github.com/mirror/tinycc.git
synced 2025-02-26 08:00:09 +08:00
update
This commit is contained in:
parent
7808b4046e
commit
75e743d23e
33
Makefile
33
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 \
|
||||
|
30
TODO
30
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.
|
||||
|
127
tcc-doc.texi
127
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
|
||||
|
181
tcctest.c
181
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
|
||||
|
Loading…
Reference in New Issue
Block a user