Compare commits

..

20 Commits

Author SHA1 Message Date
Jan Nieuwenhuizen bb0a641cab
lotsa debug printing 2018-12-20 10:16:15 +01:00
Jan Nieuwenhuizen a41c019ff7
build: Support gash. 2018-12-20 09:03:00 +01:00
Jan Nieuwenhuizen 90075d68bd
test: run tests/tests2 tests. 2018-12-20 09:03:00 +01:00
Jan Nieuwenhuizen 6d88f740dd
build: Support building from bootstrap-mes. 2018-12-20 09:02:59 +01:00
Jan Nieuwenhuizen 30b55248fc
bootstrappable: Work around Nyacc-0.80.40 bug. 2018-12-20 09:02:59 +01:00
Jan Nieuwenhuizen 9bcd7c0c30
bootstrappable: Work around Nyacc-0.80.40 bug. 2018-12-20 09:02:59 +01:00
Jan Nieuwenhuizen 09604d2dfa
bootstrappable: Work around Nyacc-0.80.42 bug.
* tccgen.c (update_storage)[__MESC__]: Work around Nyacc-0.80.42 bug.
2018-12-20 09:02:58 +01:00
Jan Nieuwenhuizen b73113dc5c
bootstrappable: Remove gratuitous complex deep nesting. 2018-12-20 09:02:58 +01:00
Jan Nieuwenhuizen 0389b2d219
bootstrappable: NORETURN, ALIGN for MesCC. 2018-12-20 09:02:58 +01:00
Jan Nieuwenhuizen 1c509d5e85
bootstrappable: Force static link. 2018-12-20 09:02:58 +01:00
Jan Nieuwenhuizen 718fb1c231
bootstrappable: Work around MesCC bug.
* tccelf.c (squeeze_multi_relocs): Simplify expressions.
2018-12-20 09:02:57 +01:00
Jan Nieuwenhuizen 0ae7c6748b
bootstrappable: add tcc.h include guards to include location. 2018-12-20 09:02:57 +01:00
Jan Nieuwenhuizen abcc1e0cb2
bootstrappable: uint16_t in struct on heap. 2018-12-20 09:02:57 +01:00
Jan Nieuwenhuizen d12f4a449e
bootstrappable: handle libtcc1.a. 2018-12-20 09:02:56 +01:00
Jan Nieuwenhuizen a02a47aa94
bootstrappable: Skip tidy_section_headers.
* tccelf.c (elf_output_file)[BOOTSTRAPPABLE]: Skip tidy_section_headers.
2018-12-20 09:02:56 +01:00
Jan Nieuwenhuizen c21f824ee5
bootstrappable: HAVE_FLOAT. 2018-12-20 09:02:56 +01:00
Jan Nieuwenhuizen 194c97f0bd
bootstrappable: HAVE_BITFIELD. 2018-12-20 09:02:56 +01:00
Jan Nieuwenhuizen 59ef83545d
bootstrappable: HAVE_LONG_LONG.
* tccpp.c (parse_number)[!HAVE_LONG_LONG]: Skip overflow test.  Do not
  set TOK_CCLONG.
2018-12-20 09:02:55 +01:00
Jan Nieuwenhuizen f724254cdd
build: bootstrap build scripts.
* bootstrap.sh: New file.
* build.sh: New file.
* check.sh: New file.
* doit: New file.
* install.sh: New file.
* test.sh: New file.
2018-12-20 09:02:55 +01:00
Jan Nieuwenhuizen 1ad9950fb6
bootstrappable: Remove non-free grep test.
* tests/tests2/46_grep.c: Remove non-free grep code.
* tests/tests2/46_grep.expect: Remove.
2018-12-20 09:02:55 +01:00
58 changed files with 2953 additions and 1423 deletions

8
BOOT Normal file
View File

@ -0,0 +1,8 @@
#export LIBRARY_PATH=/home/janneke/src/tinycc-seed
#export INCLUDE_PATH=/home/janneke/src/mes/include
export C_INCLUDE_PATH=/home/janneke/src/mes/include
export LIBRARY_PATH=/home/janneke/src/tinycc-seed
./configure --cc='mes-tcc -static' --cpu=i386
make ONE_SOURCE=yes CPPFLAGS=-DONE_SOURCE=yes

View File

@ -190,7 +190,7 @@ $(X)%.o : %.c $(LIBTCC_INC)
$(X)tcc.o : tcctools.c
# Host Tiny C Compiler
tcc$(EXESUF): tcc.o $(LIBTCC)
$(PROGRAM_PREFIX)tcc$(EXESUF): tcc.o $(LIBTCC)
$(CC) -o $@ $^ $(LIBS) $(LDFLAGS) $(LINK_LIBTCC)
# Cross Tiny C Compilers
@ -349,9 +349,6 @@ test:
tests2.%:
$(MAKE) -C tests/tests2 $@
testspp.%:
$(MAKE) -C tests/pp $@
clean:
rm -f tcc$(EXESUF) tcc_p$(EXESUF) *-tcc$(EXESUF) tcc.pod
rm -f *~ *.o *.a *.so* *.out *.log lib*.def *.exe *.dll a.out tags TAGS
@ -397,8 +394,6 @@ help:
@echo ""
@echo "make tests2.all / make tests2.37 / make tests2.37+"
@echo " run all/single test(s) from tests2, optionally update .expect"
@echo "make testspp.all / make testspp.17"
@echo " run all/single test(s) from tests/pp"
@echo ""
@echo "Other supported make targets:"
@echo " install install-strip tags ETAGS tar clean distclean help"

67
README
View File

@ -1,70 +1,3 @@
Bootstrappable TCC/TinyCC -- Tiny C Compiler's bootstrappable fork
------------------------------------------------------------------
Bootstrappable TCC is a fork from mainline TCC development, that
started spring 2017 from
commit 307b7b183d4ee56e74090b0e525d6a587840e31f
Author: Aron BARATH <baratharon@caesar.elte.hu>
Date: Tue May 16 07:03:26 2017 +0200
the R_X86_64_GOTOFF64 relocation was missing
and can be compiled by MesCC (https://gnu.org/s/mes).
Initially the plan was to make TinyCC itself "bootstrappable"
(https://bootstrappable.org).
The best way to do so would be to gradually simplify the
implementation of TinyCC by restricting the use of language constructs
to a well-defined subset of C. In bootstrapping each stage or
compiler adds functionality; a compiler that is written in itself --a
so-called `self-hosting' compiler--is not considered to be
bootstrappable.
At the time this vision was not received with much enthousiasm
https://lists.nongnu.org/archive/html/tinycc-devel/2017-09/msg00019.html
so I decided to fork TinyCC and instead grow MesCC (a bootstrappable
sub-C compiler in a subset of Guile Scheme) into a full C99 compiler.
Currently, the Reduced Binary Seed Bootstrap of the GNU Guix System
(https://guix.gnu.org/blog/2019/guix-reduces-bootstrap-seed-by-50/)
uses bootstrappable-tinycc.
The fork consists of about 12 patches
cee58e0 build: Support building from bootstrap-mes.
39de356 bootstrappable: Force static link.
2b6271d bootstrappable: Work around MesCC bug.
379c62d bootstrappable: add tcc.h include guards to include location.
274bd06 bootstrappable: Handle libtcc1.a.
6ae9aa4 bootstrappable: Skip tidy_section_headers.
a130ce1 bootstrappable: HAVE_FLOAT.
de906df bootstrappable: HAVE_BITFIELD.
540ba0b bootstrappable: HAVE_LONG_LONG.
306f677 bootstrappable: Work around Nyacc-0.80.42 bug.
9c97705 build: bootstrap build scripts.
584478f bootstrappable: Remove non-free grep test.
that work around bugs and missing C language features in MesCC. Only
three of these are really interesting: the HAVE_* patches that allow
for stepwise introduction of bitfields, doubles/floats and long longs.
In time, I hope we can remove the need for this fork; either by
upstreaming some bootstrappable work or else by maturing MesCC.
At the time of writing, mainline (non-bootstrappable) tinycc lives
here
https://repo.or.cz/tinycc.git
https://lists.nongnu.org/mailman/listinfo/tinycc-devel
--
janneke
Tiny C Compiler - C Scripting Everywhere - The Smallest ANSI C compiler
-----------------------------------------------------------------------

View File

@ -225,12 +225,20 @@ void o(uint32_t i)
if (ind1 > cur_text_section->data_allocated)
section_realloc(cur_text_section, ind1);
cur_text_section->data[ind++] = i&255;
trace ("o "); eputs (itoa (i&255)); eputs ("\n");
trace ("o "); eputs (itoa (cur_text_section->data[ind-1])); eputs ("\n");
i>>=8;
cur_text_section->data[ind++] = i&255;
trace ("o "); eputs (itoa (i&255)); eputs ("\n");
trace ("o "); eputs (itoa (cur_text_section->data[ind-1])); eputs ("\n");
i>>=8;
cur_text_section->data[ind++] = i&255;
trace ("o "); eputs (itoa (i&255)); eputs ("\n");
trace ("o "); eputs (itoa (cur_text_section->data[ind-1])); eputs ("\n");
i>>=8;
cur_text_section->data[ind++] = i;
trace ("o "); eputs (itoa (i)); eputs ("\n");
trace ("o "); eputs (itoa (cur_text_section->data[ind-1])); eputs ("\n");
}
static uint32_t stuff_const(uint32_t op, uint32_t c)
@ -1410,16 +1418,6 @@ void gfunc_epilog(void)
}
}
ST_FUNC void gen_fill_nops(int bytes)
{
if ((bytes & 3))
tcc_error("alignment of code section not multiple of 4");
while (bytes > 0) {
o(0xE1A00000);
bytes -= 4;
}
}
/* generate a jump to a label */
int gjmp(int t)
{

View File

@ -580,8 +580,8 @@ ST_FUNC void store(int r, SValue *sv)
static void arm64_gen_bl_or_b(int b)
{
if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST && (vtop->r & VT_SYM)) {
assert(!b);
if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
assert(!b && (vtop->r & VT_SYM));
greloca(cur_text_section, vtop->sym, ind, R_AARCH64_CALL26, 0);
o(0x94000000); // bl .
}
@ -1276,16 +1276,6 @@ ST_FUNC void gfunc_epilog(void)
o(0xd65f03c0); // ret
}
ST_FUNC void gen_fill_nops(int bytes)
{
if ((bytes & 3))
tcc_error("alignment of code section not multiple of 4");
while (bytes > 0) {
o(0xd503201f); // nop
bytes -= 4;
}
}
// Generate forward branch to label:
ST_FUNC int gjmp(int t)
{

298
boot.sh Executable file
View File

@ -0,0 +1,298 @@
#! /bin/sh
set -e
if [ "$V" = 1 -o "$V" = 2 ]; then
set -x
fi
if [ "$TCC" = ./mes-tcc ]; then
PROGRAM_PREFIX=${PROGRAM_PREFIX-boot0-}
elif [ "$TCC" = ./boot0-tcc ]; then
PROGRAM_PREFIX=${PROGRAM_PREFIX-boot1-}
elif [ "$TCC" = ./boot1-tcc ]; then
PROGRAM_PREFIX=${PROGRAM_PREFIX-boot2-}
elif [ "$TCC" = ./boot2-tcc ]; then
PROGRAM_PREFIX=${PROGRAM_PREFIX-boot3-}
elif [ "$TCC" = ./boot3-tcc ]; then
PROGRAM_PREFIX=${PROGRAM_PREFIX-boot4-}
fi
unset C_INCLUDE_PATH LIBRARY_PATH
PREFIX=${PREFIX-usr}
mkdir -p $PREFIX
ABSPREFIX=$(cd $PREFIX && pwd && (cd - 2>&1 >/dev/null)) # FIXME: Gash
GUIX=${GUIX-$(command -v guix||:)}
MES_PREFIX=${MES_PREFIX-../mes}
##MES_PREFIX=${MES_PREFIX-$(dirname $MESCC)/../share/mes}
C_INCLUDE_PATH=${C_INCLUDE_PATH-$MES_PREFIX/include}
MES_SEED=${MES_SEED-../mes-seed}
LIBRARY_PATH=${LIBRARY_PATH-..$MES_SEED}
if [ -z "$interpreter" -a -n "$GUIX" ]; then
interpreter=$($GUIX environment --ad-hoc patchelf -- patchelf --print-interpreter $(guix build --system=i686-linux hello)/bin/hello)
elif [ -x /lib/ld-linux.so.2 ]; then
# legacy non-GuixSD support
interpreter=/lib/ld-linux.so.2
fi
interpreter=${interpreter-interpreter}
if [ "$(basename $SHELL)" = gash ]; then
if [ "$PROGRAM_PREFIX" = "boot0-" ]; then
./$TCC\
-v\
-static\
-o ${PROGRAM_PREFIX}tcc\
-D inline=\
-D BOOTSTRAP=1\
-D HAVE_FLOAT_STUB=1\
-D CONFIG_TCCBOOT=1\
-D CONFIG_USE_LIBGCC=1\
-D TCC_MES_LIBC=1\
-I .\
-I $MES_PREFIX/include\
-D TCC_TARGET_I386\
-D CONFIG_TCCDIR=\"$PREFIX/lib/tcc\"\
-D CONFIG_TCC_CRTPREFIX=\"$PREFIX/lib:"{B}"/lib:.\"\
-D CONFIG_TCC_ELFINTERP=\"$interpreter\"\
-D CONFIG_TCC_LIBPATHS=\"$ABSPREFIX/lib:"{B}"/lib:.\"\
-D CONFIG_TCC_SYSINCLUDEPATHS=\"$MES_PREFIX/include:$PREFIX/include:"{B}"/include\"\
-D TCC_LIBGCC=\"$ABSPREFIX/lib/libc.a\"\
-D ONE_SOURCE=yes\
-D CONFIG_TCC_LIBTCC1=1\
-D CONFIG_TCC_STATIC=1\
-D TCC_TARGET_I386=1\
-L .\
-L $MES_SEED\
tcc.c\
-ltcc1
elif [ "$PROGRAM_PREFIX" = "boot1-" ]; then
./$TCC\
-v\
-static\
-o ${PROGRAM_PREFIX}tcc\
-D BOOTSTRAP=1\
-D HAVE_BITFIELD=1\
-D HAVE_FLOAT_STUB=1\
-D CONFIG_TCCBOOT=1\
-D CONFIG_USE_LIBGCC=1\
-D TCC_MES_LIBC=1\
-I .\
-I $MES_PREFIX/include\
-D TCC_TARGET_I386\
-D CONFIG_TCCDIR=\"$PREFIX/lib/tcc\"\
-D CONFIG_TCC_CRTPREFIX=\"$PREFIX/lib:"{B}"/lib:.\"\
-D CONFIG_TCC_ELFINTERP=\"$interpreter\"\
-D CONFIG_TCC_LIBPATHS=\"$ABSPREFIX/lib:"{B}"/lib:.\"\
-D CONFIG_TCC_SYSINCLUDEPATHS=\"$MES_PREFIX/include:$PREFIX/include:"{B}"/include\"\
-D TCC_LIBGCC=\"$ABSPREFIX/lib/libc.a\"\
-D ONE_SOURCE=yes\
-D CONFIG_TCC_LIBTCC1=1\
-D CONFIG_TCC_STATIC=1\
-D TCC_TARGET_I386=1\
-L .\
-L $MES_SEED\
tcc.c\
-ltcc1
elif [ "$PROGRAM_PREFIX" = "boot2-" ]; then
./$TCC\
-v\
-static\
-o ${PROGRAM_PREFIX}tcc\
-D BOOTSTRAP=1\
-D HAVE_BITFIELD=1\
-D HAVE_FLOAT_STUB=1\
-D HAVE_LONG_LONG=1\
-D CONFIG_TCCBOOT=1\
-D CONFIG_USE_LIBGCC=1\
-D TCC_MES_LIBC=1\
-I .\
-I $MES_PREFIX/include\
-D TCC_TARGET_I386\
-D CONFIG_TCCDIR=\"$PREFIX/lib/tcc\"\
-D CONFIG_TCC_CRTPREFIX=\"$PREFIX/lib:"{B}"/lib:.\"\
-D CONFIG_TCC_ELFINTERP=\"$interpreter\"\
-D CONFIG_TCC_LIBPATHS=\"$ABSPREFIX/lib:"{B}"/lib:.\"\
-D CONFIG_TCC_SYSINCLUDEPATHS=\"$MES_PREFIX/include:$PREFIX/include:"{B}"/include\"\
-D TCC_LIBGCC=\"$ABSPREFIX/lib/libc.a\"\
-D ONE_SOURCE=yes\
-D CONFIG_TCC_LIBTCC1=1\
-D CONFIG_TCC_STATIC=1\
-D TCC_TARGET_I386=1\
-L .\
-L $MES_SEED\
tcc.c\
-ltcc1
elif [ "$PROGRAM_PREFIX" = "boot3-" ]; then
./$TCC\
-v\
-static\
-o ${PROGRAM_PREFIX}tcc\
-D BOOTSTRAP=1\
-D HAVE_FLOAT=1\
-D HAVE_BITFIELD=1\
-D HAVE_LONG_LONG=1\
-D CONFIG_TCCBOOT=1\
-D CONFIG_USE_LIBGCC=1\
-D TCC_MES_LIBC=1\
-I .\
-I $MES_PREFIX/include\
-D TCC_TARGET_I386\
-D CONFIG_TCCDIR=\"$PREFIX/lib/tcc\"\
-D CONFIG_TCC_CRTPREFIX=\"$PREFIX/lib:"{B}"/lib:.\"\
-D CONFIG_TCC_ELFINTERP=\"$interpreter\"\
-D CONFIG_TCC_LIBPATHS=\"$ABSPREFIX/lib:"{B}"/lib:.\"\
-D CONFIG_TCC_SYSINCLUDEPATHS=\"$MES_PREFIX/include:$PREFIX/include:"{B}"/include\"\
-D TCC_LIBGCC=\"$ABSPREFIX/lib/libc.a\"\
-D ONE_SOURCE=yes\
-D CONFIG_TCC_LIBTCC1=1\
-D CONFIG_TCC_STATIC=1\
-D TCC_TARGET_I386=1\
-L .\
-L $MES_SEED\
tcc.c
elif [ "$PROGRAM_PREFIX" = "boot4-" ]; then
./$TCC\
-v\
-static\
-o ${PROGRAM_PREFIX}tcc\
-D BOOTSTRAP=1\
-D HAVE_FLOAT=1\
-D HAVE_BITFIELD=1\
-D HAVE_LONG_LONG=1\
-D CONFIG_TCCBOOT=1\
-D CONFIG_USE_LIBGCC=1\
-D TCC_MES_LIBC=1\
-I .\
-I $MES_PREFIX/include\
-D TCC_TARGET_I386\
-D CONFIG_TCCDIR=\"$PREFIX/lib/tcc\"\
-D CONFIG_TCC_CRTPREFIX=\"$PREFIX/lib:"{B}"/lib:.\"\
-D CONFIG_TCC_ELFINTERP=\"$interpreter\"\
-D CONFIG_TCC_LIBPATHS=\"$ABSPREFIX/lib:"{B}"/lib:.\"\
-D CONFIG_TCC_SYSINCLUDEPATHS=\"$MES_PREFIX/include:$PREFIX/include:"{B}"/include\"\
-D TCC_LIBGCC=\"$ABSPREFIX/lib/libc.a\"\
-D ONE_SOURCE=yes\
-D CONFIG_TCC_LIBTCC1=1\
-D CONFIG_TCC_STATIC=1\
-D TCC_TARGET_I386=1\
-L .\
-L $MES_SEED\
tcc.c
fi
else
if [ "$PROGRAM_PREFIX" = "boot0-" ]; then
BOOT_CPPFLAGS=${BOOT_CPPFLAGS-"
-D inline=
-D BOOTSTRAP=1
-D HAVE_FLOAT_STUB=1
-D CONFIG_TCCBOOT=1
-D CONFIG_USE_LIBGCC=1
-D TCC_MES_LIBC=1
"}
LIBTCC1=-ltcc1
elif [ "$PROGRAM_PREFIX" = "boot1-" ]; then
BOOT_CPPFLAGS=${BOOT_CPPFLAGS-"
-D BOOTSTRAP=1
-D HAVE_BITFIELD=1
-D HAVE_FLOAT_STUB=1
-D CONFIG_TCCBOOT=1
-D CONFIG_USE_LIBGCC=1
-D TCC_MES_LIBC=1
"}
LIBTCC1=-ltcc1
elif [ "$PROGRAM_PREFIX" = "boot2-" ]; then
BOOT_CPPFLAGS=${BOOT_CPPFLAGS-"
-D BOOTSTRAP=1
-D HAVE_BITFIELD=1
-D HAVE_FLOAT_STUB=1
-D HAVE_LONG_LONG=1
-D CONFIG_TCCBOOT=1
-D CONFIG_USE_LIBGCC=1
-D TCC_MES_LIBC=1
"}
LIBTCC1=-ltcc1
elif [ "$PROGRAM_PREFIX" = "boot3-" ]; then
BOOT_CPPFLAGS=${BOOT_CPPFLAGS-"
-D BOOTSTRAP=1
-D HAVE_FLOAT=1
-D HAVE_BITFIELD=1
-D HAVE_LONG_LONG=1
-D CONFIG_TCCBOOT=1
-D CONFIG_USE_LIBGCC=1
-D TCC_MES_LIBC=1
"}
elif [ "$PROGRAM_PREFIX" = "boot4-" ]; then
BOOT_CPPFLAGS=${BOOT_CPPFLAGS-"
-D BOOTSTRAP=1
-D HAVE_FLOAT=1
-D HAVE_BITFIELD=1
-D HAVE_LONG_LONG=1
-D CONFIG_TCCBOOT=1
-D CONFIG_USE_LIBGCC=1
-D TCC_MES_LIBC=1
"}
fi
echo $TCC\
-v\
-static\
-o ${PROGRAM_PREFIX}tcc\
$BOOT_CPPFLAGS\
-I .\
-I $MES_PREFIX/include\
-D TCC_TARGET_I386\
-D CONFIG_TCCDIR=\"$PREFIX/lib/tcc\"\
-D CONFIG_TCC_CRTPREFIX=\"$PREFIX/lib:"{B}"/lib:.\"\
-D CONFIG_TCC_ELFINTERP=\"$interpreter\"\
-D CONFIG_TCC_LIBPATHS=\"$ABSPREFIX/lib:"{B}"/lib:.\"\
-D CONFIG_TCC_SYSINCLUDEPATHS=\"$MES_PREFIX/include:$PREFIX/include:"{B}"/include\"\
-D TCC_LIBGCC=\"$ABSPREFIX/lib/libc.a\"\
-D ONE_SOURCE=yes\
-D CONFIG_TCC_LIBTCC1=1\
-D CONFIG_TCC_STATIC=1\
-D TCC_TARGET_I386=1\
-L .\
-L $MES_SEED\
tcc.c\
$LIBTCC1
./$TCC\
-v\
-static\
-o ${PROGRAM_PREFIX}tcc\
$BOOT_CPPFLAGS\
-I .\
-I $MES_PREFIX/include\
-D TCC_TARGET_I386\
-D CONFIG_TCCDIR=\"$PREFIX/lib/tcc\"\
-D CONFIG_TCC_CRTPREFIX=\"$PREFIX/lib:"{B}"/lib:.\"\
-D CONFIG_TCC_ELFINTERP=\"$interpreter\"\
-D CONFIG_TCC_LIBPATHS=\"$ABSPREFIX/lib:"{B}"/lib:.\"\
-D CONFIG_TCC_SYSINCLUDEPATHS=\"$MES_PREFIX/include:$PREFIX/include:"{B}"/include\"\
-D TCC_LIBGCC=\"$ABSPREFIX/lib/libc.a\"\
-D ONE_SOURCE=yes\
-D CONFIG_TCC_LIBTCC1=1\
-D CONFIG_TCC_STATIC=1\
-D TCC_TARGET_I386=1\
-L .\
-L $MES_SEED\
tcc.c\
$LIBTCC1
fi
for i in 1 i n; do
rm -f crt$i.o;
./${PROGRAM_PREFIX}tcc -c $MES_PREFIX/lib/linux/x86-mes-gcc/crt$i.c
done
rm -f libtcc1.a
./${PROGRAM_PREFIX}tcc -c -g -D TCC_TARGET_I386=1 -o libtcc1.o lib/libtcc1.c
./${PROGRAM_PREFIX}tcc -ar rc libtcc1.a libtcc1.o
mkdir -p $PREFIX/lib/tcc
cp libtcc1.a $PREFIX/lib/tcc
cp -f libtcc1.a $PREFIX/lib/tcc
echo "boot.sh: done"

66
bootstrap.sh Executable file
View File

@ -0,0 +1,66 @@
#! /bin/sh
set -e
if [ "$V" = 1 -o "$V" = 2 ]; then
set -x
fi
prefix=${prefix-/usr/local}
MES_PREFIX=${MES_PREFIX-mes}
MES_SEED=${MES_SEED-../mes-seed}
interpreter=${interpreter-interpreter}
cp $MES_SEED/linux/x86-mes-gcc/crt1.o crt1.o
cp $MES_SEED/linux/x86-mes-gcc/crti.o crti.o
cp $MES_SEED/linux/x86-mes-gcc/crtn.o crtn.o
mescc=$(command -v mescc)
sh $mescc --help
[ "$V" = 1 ] && echo "sh $mescc -S ... tcc.c"
sh $mescc\
-v\
-S\
-o tcc.S\
-D ONE_SOURCE=1\
-I .\
-I $MES_PREFIX/lib\
-I $MES_PREFIX/include\
-D inline=\
-D CONFIG_TCCDIR=\"$prefix/lib/tcc\"\
-D CONFIG_TCC_CRTPREFIX=\"$prefix/lib:"{B}"/lib:.\"\
-D CONFIG_TCC_ELFINTERP=\"$interpreter\"\
-D CONFIG_TCC_LIBPATHS=\"$prefix/lib:"{B}"/lib:.\"\
-D CONFIG_TCC_SYSINCLUDEPATHS=\"$MES_PREFIX/include:$prefix/include:"{B}"/include\"\
-D TCC_LIBGCC=\"$prefix/lib/libc.a\"\
-D BOOTSTRAP=1\
-D CONFIG_TCCBOOT=1\
-D CONFIG_TCC_STATIC=1\
-D CONFIG_USE_LIBGCC=1\
-D TCC_MES_LIBC=1\
-D TCC_TARGET_I386=1\
tcc.c
sh $mescc -v -g -o mes-tcc -L $MES_SEED -l c+tcc tcc.S $MES_SEED/x86-$MES_PREFIX/libc+tcc.o
rm -f libc.a
cp -f $MES_SEED/x86-mes-gcc/libc+gnu.o .
./mes-tcc -ar rc libc.a libc+gnu.o
rm -f libtcc1.a
cp -f $MES_SEED/x86-mes-gcc/libtcc1.o .
./mes-tcc -ar rc libtcc1.a libtcc1.o
if [ "$(basename $SHELL)" = gash ]; then
echo "bootstrap.sh: run boot.sh sequence manually"
else
TCC=./mes-tcc sh boot.sh
TCC=./boot0-tcc sh boot.sh
TCC=./boot1-tcc sh boot.sh
TCC=./boot2-tcc sh boot.sh
TCC=./boot3-tcc sh boot.sh
cmp boot3-tcc boot4-tcc
cp -f boot4-tcc tcc
echo "bootstrap.sh: done"
fi

20
build-gcc.sh Executable file
View File

@ -0,0 +1,20 @@
#! /bin/sh
set -ex
rm -f tcc
GUIX=${GUIX-$(command -v guix||:)}
MES_PREFIX=${MES_PREFIX-../mes}
touch config.mak
make clean
rm -f crt*.o
crt1=$(gcc --print-file-name=crt1.o)
#crtdir=$(dirname $crt1)
#crti=$(gcc --print-file-name=crti.o)
#crtn=$(gcc --print-file-name=crtn.o)
unset ONE_SOURCE
./configure --tccdir=$PWD --crtprefix=$crtdir --extra-cflags="-DHAVE_FLOAT=1 -DHAVE_BITFIELD=1"
make ETAGS
make PROGRAM_PREFIX=gcc- gcc-tcc
make libtcc1.a

62
build-x86.sh Executable file
View File

@ -0,0 +1,62 @@
#! /bin/sh
set -ex
rm -f i686-unknown-linux-gnu-tcc
# crt1=$(i686-unknown-linux-gnu-gcc --print-file-name=crt1.o)
# crtdir=$(dirname $crt1)
unset C_INCLUDE_PATH LIBRARY_PATH
PREFIX=${PREFIX-usr}
GUIX=${GUIX-$(command -v guix||:)}
MES_PREFIX=${MES_PREFIX-../mes}
MES_PREFIX=${MES_PREFIX-${MESCC%/*}/../share/mes}
MES_SEED=${MES_SEED-../mes-seed}
cp $MES_SEED/x86-mes-gcc/crt1.o crt1.o
cp $MES_SEED/x86-mes-gcc/crti.o crti.o
cp $MES_SEED/x86-mes-gcc/crtn.o crtn.o
CC=${CC-i686-unknown-linux-gnu-gcc}
CFLAGS="
-nostdinc
-nostdlib
-fno-builtin
--include=$MES_PREFIX/lib/linux/x86-mes-gcc/crt1.c
--include=$MES_PREFIX/lib/libc+tcc.c
--include=$MES_PREFIX/lib/libtcc1.c
-Wl,-Ttext-segment=0x1000000
"
if [ -z "$interpreter" -a -n "$GUIX" ]; then
interpreter=$($GUIX environment --ad-hoc patchelf -- patchelf --print-interpreter $(guix build --system=i686-linux hello)/bin/hello)
elif [ -x /lib/ld-linux.so.2 ]; then
# legacy non-GuixSD support
interpreter=/lib/ld-linux.so.2
fi
interpreter=${interpreter-interpreter}
export interpreter
mkdir -p $PREFIX/lib
ABSPREFIX=$(cd $PREFIX && pwd)
cp $MES_SEED/x86-mes-gcc/libc+tcc.o $ABSPREFIX/lib
cp $MES_SEED/x86-mes-gcc/libtcc1.o $ABSPREFIX/lib
$CC -g -o i686-unknown-linux-gnu-tcc\
$CFLAGS\
-I.\
-I $MES_PREFIX/lib\
-I $MES_PREFIX/include\
-D 'CONFIG_TCCDIR="'$PREFIX'/lib/tcc"'\
-D 'CONFIG_TCC_CRTPREFIX="'$PREFIX'/lib:{B}/lib:."'\
-D 'CONFIG_TCC_ELFINTERP="'$interpreter'"'\
-D 'CONFIG_TCC_LIBPATHS="'$ABSPREFIX'/lib:{B}/lib:."'\
-D 'CONFIG_TCC_SYSINCLUDEPATHS="'$MES_PREFIX'/include:'$PREFIX'/include:{B}/include"'\
-D CONFIG_USE_LIBGCC=1\
-D 'TCC_LIBGCC="'$ABSPREFIX'/lib/libc.a"'\
-D BOOTSTRAP=1\
-D CONFIG_TCCBOOT=1\
-D CONFIG_TCC_STATIC=1\
-D CONFIG_USE_LIBGCC=1\
-D ONE_SOURCE=1\
-D TCC_MES_LIBC=1\
-D TCC_TARGET_I386=1\
tcc.c

108
build.sh Executable file
View File

@ -0,0 +1,108 @@
#! /bin/sh
set -e
export BUILD_DEBUG
export MES_DEBUG
export MES_PREFIX
export PREFIX
export MES_SEED
export interpreter
if [ -n "$BUILD_DEBUG" ]; then
set -x
MESCCFLAGS="$MESCCFLAGS -v"
fi
rm -f tcc.E tcc.hex2 tcc.M1 tcc.m1 mes-tcc boot?-tcc
unset C_INCLUDE_PATH LIBRARY_PATH
PREFIX=${PREFIX-usr}
GUIX=${GUIX-$(command -v guix||:)}
CC=${MESCC-mescc}
MES=${MES-../mes/src/mes}
MESCC=${MESCC-mescc}
HEX2=${HEX2-hex2}
M1=${M1-M1}
BLOOD_ELF=${BLOOD_ELF-blood-elf}
MES_PREFIX=${MES_PREFIX-${MESCC%/*}/../share/mes}
#MES_PREFIX=${MES_PREFIX-../mes}
MES_SEED=${MES_SEED-../mes-seed}
cp $MES_SEED/x86-mes-gcc/crt1.o crt1.o
cp $MES_SEED/x86-mes-gcc/crti.o crti.o
cp $MES_SEED/x86-mes-gcc/crtn.o crtn.o
if [ -z "$interpreter" -a -n "$GUIX" ]; then
interpreter=$($GUIX environment --ad-hoc patchelf -- patchelf --print-interpreter $(guix build --system=i686-linux hello)/bin/hello)
elif [ -x /lib/ld-linux.so.2 ]; then
# legacy non-GuixSD support
interpreter=/lib/ld-linux.so.2
fi
interpreter=${interpreter-interpreter}
export interpreter
mkdir -p $PREFIX/lib
ABSPREFIX=$(cd $PREFIX && pwd)
cp $MES_SEED/x86-mes-gcc/libc+tcc.o $ABSPREFIX/lib
if [ -n "$ONE_SOURCE" ]; then
sh cc.sh tcc
files="tcc.S"
else
sh cc.sh tccpp
sh cc.sh tccgen
sh cc.sh tccelf
sh cc.sh tccrun
sh cc.sh i386-gen
sh cc.sh i386-link
sh cc.sh i386-asm
sh cc.sh tccasm
sh cc.sh libtcc
sh cc.sh tcc
files="
tccpp.S
tccgen.S
tccelf.S
tccrun.S
i386-gen.S
i386-link.S
i386-asm.S
tccasm.S
libtcc.S
tcc.S
"
fi
$MESCC\
$MESCCFLAGS\
-g\
-o mes-tcc\
-L $MES_SEED\
-l c+tcc\
$files\
$MES_SEED/x86-mes/libc+tcc.o
rm -f libc.a
if false; then
# ../mes/lib/linux-gcc.c:33: error: bad operand with opcode 'mov'
# it works with bootx-tcc
./mes-tcc -c -I $MES_PREFIX/include -I $MES_PREFIX/lib $MES_PREFIX/lib/libc+gnu.c
./mes-tcc -ar rc libc.a libc+gnu.o
else
##./mes-tcc -ar rc libc.a $MES_SEED/x86-mes-gcc/libc+gnu.o
cp -f $MES_SEED/x86-mes-gcc/libc+gnu.o .
./mes-tcc -ar rc libc.a libc+gnu.o
fi
rm -f libtcc1.a
cp -f $MES_SEED/x86-mes-gcc/libtcc1.o .
./mes-tcc -ar rc libtcc1.a libtcc1.o
sh boot.sh
TCC=./boot0-tcc sh boot.sh
TCC=./boot1-tcc sh boot.sh
TCC=./boot2-tcc sh boot.sh
TCC=./boot3-tcc sh boot.sh
ln -f boot4-tcc tcc

View File

@ -2035,16 +2035,6 @@ void gfunc_epilog(void)
}
}
ST_FUNC void gen_fill_nops(int bytes)
{
if ((bytes & 3))
tcc_error("alignment of code section not multiple of 4");
while (bytes > 0) {
C67_NOP(4);
bytes -= 4;
}
}
/* generate a jump to a label */
int gjmp(int t)
{

78
cc.sh Executable file
View File

@ -0,0 +1,78 @@
#! /bin/sh
set -e
if [ -n "$BUILD_DEBUG" ]; then
set -x
MESCCFLAGS="$MESCCFLAGS -v"
fi
t=$1
rm -f $t.E $t.M1 $t.m1
GUIX=${GUIX-$(command -v guix||:)}
CC=${MESCC-mescc}
MES=${MES-../mes/src/mes}
MESCC=${MESCC-mescc}
CFLAGS=${CFLAGS-}
MES_PREFIX=${MES_PREFIX-${MESCC%/*}}
ABSPREFIX=$(cd $PREFIX && pwd)
if [ -z "$interpreter" -a -n "$GUIX" ]; then
interpreter=$($GUIX environment --ad-hoc patchelf -- patchelf --print-interpreter $(guix build --system=i686-linux hello)/bin/hello)
elif [ -x /lib/ld-linux.so.2 ]; then
# legacy non-GuixSD support
interpreter=/lib/ld-linux.so.2
fi
ulimit -s 17030
if [ -n "$ONE_SOURCE" ]; then
CFLAGS="$CFLAGS -D ONE_SOURCE=$ONE_SOURCE"
fi
if [ -n "$PREPROCESS" ]; then
time sh $MESCC $MESCCFLAGS -E -o $t.E\
$CFLAGS\
-I .\
-I $MES_PREFIX/lib\
-I $MES_PREFIX/include\
-D inline=\
-D 'CONFIG_TCCDIR="'$PREFIX'/lib/tcc"'\
-D 'CONFIG_TCC_CRTPREFIX="'$PREFIX'/lib:{B}/lib:."'\
-D 'CONFIG_TCC_ELFINTERP="'$interpreter'"'\
-D 'CONFIG_TCC_LIBPATHS="'$ABSPREFIX'/lib:{B}/lib:."'\
-D 'CONFIG_TCC_SYSINCLUDEPATHS="'$MES_PREFIX'/include:'$PREFIX'/include:{B}/include"'\
-D 'TCC_LIBGCC="'$ABSPREFIX'/lib/libc.a"'\
-D BOOTSTRAP=1\
-D CONFIG_TCCBOOT=1\
-D CONFIG_TCC_STATIC=1\
-D CONFIG_USE_LIBGCC=1\
-D TCC_MES_LIBC=1\
-D TCC_TARGET_I386=1\
$t.c
time sh $MESCC $MESCCFLAGS -S -o $t.M1 $t.E
else
time sh $MESCC $MESCCFLAGS -S -o $t.M1\
$CFLAGS\
-I .\
-I $MES_PREFIX/lib\
-I $MES_PREFIX/include\
-D inline=\
-D 'CONFIG_TCCDIR="'$PREFIX'/lib/tcc"'\
-D 'CONFIG_TCC_CRTPREFIX="'$PREFIX'/lib:{B}/lib:."'\
-D 'CONFIG_TCC_ELFINTERP="'$interpreter'"'\
-D 'CONFIG_TCC_LIBPATHS="'$ABSPREFIX'/lib:{B}/lib:."'\
-D 'CONFIG_TCC_SYSINCLUDEPATHS="'$MES_PREFIX'/include:'$PREFIX'/include:{B}/include"'\
-D CONFIG_USE_LIBGCC=1\
-D 'TCC_LIBGCC="'$ABSPREFIX'/lib/libc.a"'\
-D BOOTSTRAP=1\
-D CONFIG_TCCBOOT=1\
-D CONFIG_TCC_STATIC=1\
-D CONFIG_USE_LIBGCC=1\
-D TCC_MES_LIBC=1\
-D TCC_TARGET_I386=1\
$t.c
fi
tr -d '\r' < $t.M1 > $t.S

334
check.sh Executable file
View File

@ -0,0 +1,334 @@
#! /bin/sh
###MESCC=${MESCC-mescc}
MES_ARENA=${MES_ARENA-100000000}
MES_MAX_ARENA=${MES_MAX_ARENA-100000000}
MES_STACK=${MES_STACK-10000000}
export MES_ARENA MES_MAX_ARENA MES_STACK
MES=${MES-mes}
MESCC=${MESCC-mescc}
MES_PREFIX=${MES_PREFIX-../mes}
tests="
t
00-exit-0
01-return-0
02-return-1
03-call
04-call-0
05-call-1
06-call-!1
06-!call-1
06-call-2
06-call-string
06-call-variable
06-return-void
07-include
08-assign
08-assign-negative
08-assign-global
10-if-0
11-if-1
12-if-==
13-if-!=
14-if-goto
15-if-!f
16-if-t
17-compare-ge
17-compare-gt
17-compare-le
17-compare-lt
17-compare-unsigned-ge
17-compare-unsigned-gt
17-compare-unsigned-le
17-compare-unsigned-lt
17-compare-and
17-compare-or
17-compare-and-or
17-compare-assign
17-compare-call
18-assign-shadow
20-while
21-char[]-simple
21-char[]
22-while-char[]
23-global-pointer-init-null
23-global-pointer-init
23-global-pointer-ref
23-global-pointer-pointer-ref
23-pointer-sub
23-pointer
30-strlen
31-oputs
32-call-wrap
32-compare
33-and-or
34-pre-post
35-compare-char
36-compare-arithmetic
37-compare-assign
38-compare-call-2
38-compare-call-3
38-compare-call
40-if-else
41-?
42-goto-label
43-for-do-while
44-switch
44-switch-fallthrough
44-switch-body-fallthrough
45-void-call
46-function-static
47-function-expression
48-global-static
50-assert
51-pointer-sub
51-itoa
51-strcmp
51-strncmp
53-strcpy
54-argc
54-argv
55-char-array
60-math
61-array
62-array
63-struct
63-struct-pointer
63-struct-local
63-struct-function
63-struct-assign
63-struct-array
63-struct-array-assign
63-struct-array-compare
63-struct-cell
64-make-cell
65-read
66-local-char-array
70-strchr
70-stdarg
70-printf-hello
70-printf-simple
70-printf
71-struct-array
72-typedef-struct-def
73-union-hello
73-union
74-multi-line-string
75-struct-union
76-pointer-arithmetic-pp
76-pointer-arithmetic
77-pointer-assign
78-union-struct
79-int-array-simple
79-int-array
7a-struct-char-array
7b-struct-int-array-hello
7b-struct-int-array-pointer
7b-struct-int-array
7c-dynarray
7d-cast-char
7e-struct-array-access
7f-struct-pointer-arithmetic
7g-struct-byte-word-field
7h-struct-assign
7i-struct-struct-simple
7i-struct-struct
7j-strtoull
7k-empty-for
7k-for-each-elem-simple
7k-for-each-elem
7l-struct-any-size-array-simple
7l-struct-any-size-array
7m-struct-char-array-assign
7n-struct-struct-array
7o-struct-pre-post-simple
7o-struct-pre-post
7p-struct-cast
7q-bit-field-simple
7q-bit-field
7r-sign-extend
7s-struct-short
7s-unsigned-compare
7t-function-destruct
7u-double
7u-long-long
7u-?-expression
7u-call-?
7u-inc-byte-word
7u-struct-func
7u-struct-size10
7u-vstack
80-setjmp
81-qsort
81-qsort-dupes
82-define
83-heterogenoous-init
84-struct-field-list
85-sizeof
86-strncpy
87-sscanf
88-strrchr
90-strspn
90-strpbrk
91-fseek
92-stat
93-fread-fwrite
94-unsetenv
95-signal
96-strto
97-fopen
98-fopen
99-readdir
"
broken="
t
00-exit-0
54-argc
66-local-char-array
70-strchr
91-fseek
99-readdir
"
if [ ! -x ./i686-unknown-linux-gnu-tcc ]; then
broken="$broken
02-return-1
05-call-1
"
fi
expect=$(echo $broken | wc -w)
mkdir -p scaffold/tests
set +e
pass=0
fail=0
total=0
for t in $tests; do
sh test.sh "$MES_PREFIX/scaffold/tests/$t" &> "scaffold/tests/$t".log
r=$?
total=$((total+1))
if [ $r = 0 ]; then
echo $t: [OK]
pass=$((pass+1))
else
echo $t: [FAIL]
fail=$((fail+1))
fi
done
tests="
00_assignment
01_comment
02_printf
03_struct
04_for
05_array
06_case
07_function
08_while
09_do_while
10_pointer
11_precedence
12_hashdefine
13_integer_literals
14_if
15_recursion
16_nesting
17_enum
18_include
19_pointer_arithmetic
20_pointer_comparison
21_char_array
22_floating_point
23_type_coercion
24_math_library
25_quicksort
26_character_constants
27_sizeof
28_strings
29_array_address
30_hanoi
31_args
32_led
33_ternary_op
34_array_assignment
35_sizeof
36_array_initialisers
37_sprintf
38_multiple_array_index
39_typedef
40_stdio
41_hashif
42_function_pointer
43_void_param
44_scoped_declarations
45_empty_for
47_switch_return
48_nested_break
49_bracket_evaluation
50_logical_second_arg
51_static
52_unnamed_enum
54_goto
55_lshift_type
"
broken="$broken
22_floating_point
23_type_coercion
24_math_library
49_bracket_evaluation
55_lshift_type
"
#22_floating_point ; float
#23_type_coercion ; float
#24_math_library ; float
#27_sizeof ; float
#34_array_assignment ; fails with GCC
#37_sprintf ; integer formatting unsupported
#49_bracket_evaluation ; float
mkdir -p scaffold/tinycc
expect=$(echo $broken | wc -w)
for t in $tests; do
if [ ! -f tests/tests2/"$t.c" ]; then
echo ' [SKIP]'
continue;
fi
sh test.sh tests/tests2/"$t" &> tests/tests2/"$t".log
r=$?
total=$((total+1))
if [ $r = 0 ]; then
echo $t: [OK]
pass=$((pass+1))
else
echo $t: [FAIL]
fail=$((fail+1))
fi
done
[ $expect != 0 ] && echo "expect: $expect"
[ $fail != 0 ] && echo "failed: $fail"
echo "passed: $pass"
[ $fail -lt $expect ] && echo "solved: $(($expect - $fail))"
echo "total: $total"
if [ $fail != 0 -a $fail -gt $expect ]; then
echo FAILED: $fail/$total
exit 1
elif [ $fail != 0 ]; then
echo PASS: $pass/$total
else
echo PASS: $total
fi

15
compile.sh Executable file
View File

@ -0,0 +1,15 @@
#! /bin/sh
set -ex
rm -f *.i686-unknown-linux-gnu-o *.mes-o
rm -f 1 2 1.elf 2.elf 1.a 2.a
# trivial object
./tcc -c -I ../mes/include ../mes/scaffold/main.c 2>/dev/null
./i686-unknown-linux-gnu-tcc -o main.i686-unknown-linux-gnu-o -c -I ../mes/include ../mes/scaffold/main.c 2> 1
set +e
./mes-tcc -o main.mes-o -c -I ../mes/include ../mes/scaffold/main.c &> 2
diff -y 1 2
readelf -a main.i686-unknown-linux-gnu-o > 1.elf
readelf -a main.mes-o > 2.elf
diff -y 1.elf 2.elf || :

2
configure vendored
View File

@ -335,7 +335,7 @@ if test -z "$cross_prefix" ; then
if test "$cpu" = "arm" ; then
if test "${triplet%eabihf}" != "$triplet" ; then
confvars="$confvars arm_eabihf arm_vfp"
confvars="$confvars arm_eabihf"
elif test "${triplet%eabi}" != "$triplet" ; then
confvars="$confvars arm_eabi"
fi

21
d Executable file
View File

@ -0,0 +1,21 @@
#! /bin/sh
set -ex
rm -f *.o *.a *.E *.hex2 *.mesc-o *.i686-unknown-linux-gnu-o *.M1
rm -f 1 2 1.elf 2.elf
# trivial object
set +e
./tcc -c -I ../mes/mlibc/include ../mes/scaffold/main.c 2>/dev/null
./i686-unknown-linux-gnu-tcc -o main.i686-unknown-linux-gnu-o -c -I ../mes/mlibc/include ../mes/scaffold/main.c 2> 1
./tcc.mes -o main.mesc-o -c -I ../mes/mlibc/include ../mes/scaffold/main.c &> 2
diff -y 1 2
readelf -a main.i686-unknown-linux-gnu-o > 1.elf
readelf -a main.mesc-o > 2.elf
diff -y 1.elf 2.elf
# trivial bin
./tcc ../mes/scaffold/main.c
./i686-unknown-linux-gnu-tcc -o a.i686-unknown-linux-gnu-out -I ../mes/mlibc/include ../mes/scaffold/main.c 2> 1.a
./tcc.mes -o a.mes-out -I ../mes/mlibc/include ../mes/scaffold/main.c 2> 2.a
diff -y 1.a 2.a

62
doit Executable file
View File

@ -0,0 +1,62 @@
#! /bin/sh
set -ex
export BLOOD_ELF
export BUILD_DEBUG
export GUILE_LOAD_PATH
export HEX2
export M1
export MES
export MESCC
export MES_DEBUG
export MES_PREFIX
export ONE_SOURCE
export PREFIX
export PREPROCESS
export TINYCC_SEED
PREFIX=usr
HEX2=../mescc-tools/bin/hex2
M1=../mescc-tools/bin/M1
BLOOD_ELF=../mescc-tools/bin/blood-elf
MES=${MES-../mes/src/mes}
MES_ARENA=70000000
MES_MAX_ARENA=70000000
export MES_ARENA MES_MAX_ARENA
MES=guile
#MES=${MES-../mes/src/mes.gcc}
#MES=${MES-../mes/src/mes.mlibc-gcc}
MESCC=${MESCC-../mes/pre-inst-env mescc}
#GUILE_LOAD_PATH=/home/janneke/src/nyacc/module:$GUILE_LOAD_PATH
GUILE_LOAD_PATH=nyacc
MES_DEBUG=2
MES_PREFIX=${MES_PREFIX-../mes}
TINYCC_SEED=${TINYCC_SEED-../tinycc-seed}
rm -f mes
ln -sf $MES_PREFIX mes
if [ -z "$interpreter" -a -n "$GUIX" ]; then
interpreter=$($GUIX environment --ad-hoc patchelf -- patchelf --print-interpreter $(guix build --system=i686-linux hello)/bin/hello)
elif [ -x /lib/ld-linux.so.2 ]; then
# legacy non-GuixSD support
interpreter=/lib/ld-linux.so.2
fi
interpreter=${interpreter-interpreter}
export interpreter
sh build-gcc.sh
PREPROCESS=1
ONE_SOURCE=1
sh build-x86.sh
sh build.sh
sh compile.sh
sh link.sh ||:
sh check.sh
rm -rf usr
sh install.sh

View File

@ -19,7 +19,9 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _TCC_H
#include "tcc.h"
#endif
#define MAX_OPERANDS 3
@ -1597,6 +1599,7 @@ ST_FUNC void asm_gen_code(ASMOperand *operands, int nb_operands,
ASMOperand *op;
int i, reg;
trace_enter ("asm_gen_code");
/* Strictly speaking %Xbp and %Xsp should be included in the
call-preserved registers, but currently it doesn't matter. */
#ifdef TCC_TARGET_X86_64
@ -1690,6 +1693,7 @@ ST_FUNC void asm_gen_code(ASMOperand *operands, int nb_operands,
}
}
}
trace_exit ("asm_gen_code");
}
ST_FUNC void asm_clobber(uint8_t *clobber_regs, const char *str)

View File

@ -74,7 +74,9 @@ enum {
/******************************************************/
#else /* ! TARGET_DEFS_ONLY */
/******************************************************/
#ifndef _TCC_H
#include "tcc.h"
#endif
/* define to 1/0 to [not] have EBX as 4th register */
#define USE_EBX 0
@ -97,6 +99,8 @@ static unsigned long func_bound_ind;
/* XXX: make it faster ? */
ST_FUNC void g(int c)
{
trace_enter ("g");
trace ("gen o c="); eputs (itoa (c)); eputs ("\n");
int ind1;
if (nocode_wanted)
return;
@ -104,7 +108,9 @@ ST_FUNC void g(int c)
if (ind1 > cur_text_section->data_allocated)
section_realloc(cur_text_section, ind1);
cur_text_section->data[ind] = c;
trace ("gen o data="); eputs (itoa (cur_text_section->data[ind])); eputs ("\n");
ind = ind1;
trace_exit ("g");
}
ST_FUNC void o(unsigned int c)
@ -157,12 +163,6 @@ static int oad(int c, int s)
return t;
}
ST_FUNC void gen_fill_nops(int bytes)
{
while (bytes--)
g(0x90);
}
/* generate jmp to a label */
#define gjmp2(instr,lbl) oad(instr,lbl)
@ -210,6 +210,7 @@ ST_FUNC void load(int r, SValue *sv)
int v, t, ft, fc, fr;
SValue v1;
trace_enter ("load");
#ifdef TCC_TARGET_PE
SValue v2;
sv = pe_getimport(sv, &v2);
@ -281,6 +282,7 @@ ST_FUNC void load(int r, SValue *sv)
o(0xc0 + r + v * 8); /* mov v, r */
}
}
trace_exit ("load");
}
/* store register 'r' in lvalue 'v' */
@ -288,6 +290,7 @@ ST_FUNC void store(int r, SValue *v)
{
int fr, bt, ft, fc;
trace_enter ("store");
#ifdef TCC_TARGET_PE
SValue v2;
v = pe_getimport(v, &v2);
@ -324,6 +327,7 @@ ST_FUNC void store(int r, SValue *v)
} else if (fr != r) {
o(0xc0 + fr + r * 8); /* mov r, fr */
}
trace_exit ("store");
}
static void gadd_sp(int val)
@ -428,6 +432,7 @@ ST_FUNC void gfunc_call(int nb_args)
int size, align, r, args_size, i, func_call;
Sym *func_sym;
trace_enter ("gfunc_call");
args_size = 0;
for(i = 0;i < nb_args; i++) {
if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) {
@ -507,6 +512,7 @@ ST_FUNC void gfunc_call(int nb_args)
if (args_size && func_call != FUNC_STDCALL && func_call != FUNC_FASTCALLW)
gadd_sp(args_size);
vtop--;
trace_exit ("gfunc_call");
}
#ifdef TCC_TARGET_PE
@ -524,30 +530,40 @@ ST_FUNC void gfunc_prolog(CType *func_type)
Sym *sym;
CType *type;
trace_enter ("gfunc_prolog");
sym = func_type->ref;
func_call = sym->f.func_call;
addr = 8;
loc = 0;
func_vc = 0;
trace ("gfunc_prolog 10\n");
if (func_call >= FUNC_FASTCALL1 && func_call <= FUNC_FASTCALL3) {
trace ("gfunc_prolog 11\n");
fastcall_nb_regs = func_call - FUNC_FASTCALL1 + 1;
fastcall_regs_ptr = fastcall_regs;
} else if (func_call == FUNC_FASTCALLW) {
trace ("gfunc_prolog 15\n");
fastcall_nb_regs = 2;
fastcall_regs_ptr = fastcallw_regs;
} else {
trace ("gfunc_prolog 18\n");
fastcall_nb_regs = 0;
fastcall_regs_ptr = NULL;
}
param_index = 0;
trace ("gfunc_prolog 20\n");
ind += FUNC_PROLOG_SIZE;
trace ("gfunc_prolog 21\n");
func_sub_sp_offset = ind;
trace ("gfunc_prolog 22\n");
/* if the function returns a structure, then add an
implicit pointer parameter */
func_vt = sym->type;
trace ("gfunc_prolog 23\n");
func_var = (sym->f.func_type == FUNC_ELLIPSIS);
trace ("gfunc_prolog 24\n");
#ifdef TCC_TARGET_PE
size = type_size(&func_vt,&align);
if (((func_vt.t & VT_BTYPE) == VT_STRUCT)
@ -555,29 +571,35 @@ ST_FUNC void gfunc_prolog(CType *func_type)
#else
if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
#endif
trace ("gfunc_prolog 25\n");
/* XXX: fastcall case ? */
func_vc = addr;
addr += 4;
param_index++;
}
trace ("gfunc_prolog 30\n");
/* define parameters */
while ((sym = sym->next) != NULL) {
trace ("gfunc_prolog 31 param_index="); eputs (itoa (param_index)); eputs ("\n");
type = &sym->type;
size = type_size(type, &align);
size = (size + 3) & ~3;
#ifdef FUNC_STRUCT_PARAM_AS_PTR
/* structs are passed as pointer */
if ((type->t & VT_BTYPE) == VT_STRUCT) {
trace ("gfunc_prolog 36\n");
size = 4;
}
#endif
if (param_index < fastcall_nb_regs) {
trace ("gfunc_prolog 38\n");
/* save FASTCALL register */
loc -= 4;
o(0x89); /* movl */
gen_modrm(fastcall_regs_ptr[param_index], VT_LOCAL, NULL, loc);
param_addr = loc;
} else {
trace ("gfunc_prolog 39\n");
param_addr = addr;
addr += size;
}
@ -586,6 +608,7 @@ ST_FUNC void gfunc_prolog(CType *func_type)
param_index++;
}
func_ret_sub = 0;
trace ("gfunc_prolog 50\n");
/* pascal type call or fastcall ? */
if (func_call == FUNC_STDCALL || func_call == FUNC_FASTCALLW)
func_ret_sub = addr - 8;
@ -594,15 +617,18 @@ ST_FUNC void gfunc_prolog(CType *func_type)
func_ret_sub = 4;
#endif
trace ("gfunc_prolog 60\n");
#ifdef CONFIG_TCC_BCHECK
/* leave some room for bound checking code */
if (tcc_state->do_bounds_check) {
trace ("gfunc_prolog 61\n");
func_bound_offset = lbounds_section->data_offset;
func_bound_ind = ind;
oad(0xb8, 0); /* lbound section pointer */
oad(0xb8, 0); /* call to function */
}
#endif
trace_exit ("gfunc_prolog");
}
/* generate function epilog */
@ -610,9 +636,11 @@ ST_FUNC void gfunc_epilog(void)
{
addr_t v, saved_ind;
trace ("gfunc_epilog\n");
#ifdef CONFIG_TCC_BCHECK
if (tcc_state->do_bounds_check
&& func_bound_offset != lbounds_section->data_offset) {
trace ("gfunc_epilog 01\n");
addr_t saved_ind;
addr_t *bounds_ptr;
Sym *sym_data;
@ -641,18 +669,22 @@ ST_FUNC void gfunc_epilog(void)
}
#endif
trace ("gfunc_epilog 20\n");
/* align local size to word & save local variables */
v = (-loc + 3) & -4;
#if USE_EBX
trace ("gfunc_epilog 21\n");
o(0x8b);
gen_modrm(TREG_EBX, VT_LOCAL, NULL, -(v+4));
#endif
o(0xc9); /* leave */
if (func_ret_sub == 0) {
trace ("gfunc_epilog 23\n");
o(0xc3); /* ret */
} else {
trace ("gfunc_epilog 24\n");
o(0xc2); /* ret n */
g(func_ret_sub);
g(func_ret_sub >> 8);
@ -666,6 +698,7 @@ ST_FUNC void gfunc_epilog(void)
} else
#endif
{
trace ("gfunc_epilog 30\n");
o(0xe58955); /* push %ebp, mov %esp, %ebp */
o(0xec81); /* sub esp, stacksize */
gen_le32(v);
@ -757,6 +790,8 @@ ST_FUNC void gen_opi(int op)
{
int r, fr, opc, c;
trace_enter ("gen_opi");
trace ("gen_opi op="); eputs (itoa (op)); eputs ("\n");
switch(op) {
case '+':
case TOK_ADDC1: /* add with carry generation */
@ -768,7 +803,13 @@ ST_FUNC void gen_opi(int op)
r = gv(RC_INT);
vswap();
c = vtop->c.i;
trace ("gen_opi 14 c ="); eputs (itoa (c)); eputs ("\n");
#if __MESC__
char ch = c;
if (c == ch && ((ch >= 0 && ch < 128) || c < 0)) {
#else
if (c == (char)c) {
#endif
/* generate inc and dec for smaller code */
if (c==1 && opc==0 && op != TOK_ADDC1) {
o (0x40 | r); // inc
@ -780,6 +821,7 @@ ST_FUNC void gen_opi(int op)
g(c);
}
} else {
trace ("gen_opi 20\n");
o(0x81);
oad(0xc0 | (opc << 3) | r, c);
}

View File

@ -20,7 +20,9 @@
#else /* !TARGET_DEFS_ONLY */
#ifndef _TCC_H
#include "tcc.h"
#endif
/* Returns 1 for a code relocation, 0 for a data relocation. For unknown
relocations, returns -1. */

28
install.sh Executable file
View File

@ -0,0 +1,28 @@
#! /bin/sh
if [ -n "$BUILD_DEBUG" ]; then
set -x
fi
set -e
PREFIX=${PREFIX-usr}
MES_PREFIX=${MES_PREFIX-${MESCC%/*}}
MES_SEED=${MES_SEED-../mes-seed}
mkdir -p $PREFIX/bin
cp tcc $PREFIX/bin
tar -C $MES_PREFIX -cf- include | tar -C $PREFIX -xf-
mkdir -p $PREFIX/lib
cp crt1.o $PREFIX/lib/crt1.o
cp crti.o $PREFIX/lib/crti.o
cp crtn.o $PREFIX/lib/crtn.o
mkdir -p $PREFIX/lib/tcc
cp libc.a $PREFIX/lib
cp libtcc1.a $PREFIX/lib/tcc
tar -C $MES_SEED -cf- . | tar -C $PREFIX/lib -xf-
rm -f $PREFIX/lib/linux/x86_64-mes/crt1

208
libtcc.c
View File

@ -18,7 +18,9 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _TCC_H
#include "tcc.h"
#endif
/********************************************************/
/* global variables */
@ -220,10 +222,14 @@ PUB_FUNC void *tcc_mallocz(unsigned long size)
PUB_FUNC void *tcc_realloc(void *ptr, unsigned long size)
{
trace_enter ("tcc_realloc");
trace ("tcc_realloc size="); eputs (itoa (size)); eputs ("\n");
void *ptr1;
ptr1 = realloc(ptr, size);
if (!ptr1 && size)
tcc_error("memory full (realloc)");
trace_exit ("tcc_realloc");
return ptr1;
}
@ -433,11 +439,16 @@ ST_FUNC void dynarray_reset(void *pp, int *n)
static void tcc_split_path(TCCState *s, void *p_ary, int *p_nb_ary, const char *in)
{
const char *p;
//eputs ("sp in="); //eputs (in); //eputs ("\n");
do {
int c;
CString str;
//eputs ("sp in="); //eputs (in); //eputs ("\n");
//if (s->nb_files) {struct filespec *f = s->files[0]; //eputs ("sp 01 file[0]="); //eputs (f->name); //eputs ("\n");}
cstr_new(&str);
//if (s->nb_files) {struct filespec *f = s->files[0]; //eputs ("sp 02 file[0]="); //eputs (f->name); //eputs ("\n");}
for (p = in; c = *p, c != '\0' && c != PATHSEP[0]; ++p) {
if (c == '{' && p[1] && p[2] == '}') {
c = p[1], p += 2;
@ -449,11 +460,15 @@ static void tcc_split_path(TCCState *s, void *p_ary, int *p_nb_ary, const char *
}
if (str.size) {
cstr_ccat(&str, '\0');
//if (s->nb_files) {struct filespec *f = s->files[0]; //eputs ("sp 14 file[0]="); //eputs (f->name); //eputs ("\n");}
dynarray_add(p_ary, p_nb_ary, tcc_strdup(str.data));
}
//if (s->nb_files) {struct filespec *f = s->files[0]; //eputs ("sp 15 file[0]="); //eputs (f->name); //eputs ("\n");}
cstr_free(&str);
//if (s->nb_files) {struct filespec *f = s->files[0]; //eputs ("sp 16 file[0]="); //eputs (f->name); //eputs ("\n");}
in = p+1;
} while (*p);
//eputs ("sp 99\n");
}
/********************************************************/
@ -570,81 +585,112 @@ PUB_FUNC void tcc_warning(const char *fmt, ...)
ST_FUNC void tcc_open_bf(TCCState *s1, const char *filename, int initlen)
{
trace_enter ("tcc_open_bf");
BufferedFile *bf;
int buflen = initlen ? initlen : IO_BUF_SIZE;
bf = tcc_mallocz(sizeof(BufferedFile) + buflen);
trace ("tcc_open_bf buflen="); eputs (itoa (buflen)); eputs ("\n");
//eputs ("tcc_open_bf bf size="); //eputs (itoa (sizeof (BufferedFile) + buflen)); //eputs ("\n");
trace ("tcc_open_bf 10\n");
bf->buf_ptr = bf->buffer;
trace ("tcc_open_bf 11\n");
bf->buf_end = bf->buffer + initlen;
trace ("tcc_open_bf 12\n");
bf->buf_end[0] = CH_EOB; /* put eob symbol */
trace ("tcc_open_bf 13\n");
pstrcpy(bf->filename, sizeof(bf->filename), filename);
trace ("tcc_open_bf 14\n");
bf->true_filename = bf->filename;
trace ("tcc_open_bf 15\n");
bf->line_num = 1;
bf->ifdef_stack_ptr = s1->ifdef_stack_ptr;
bf->fd = -1;
bf->prev = file;
file = bf;
tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
trace_exit ("tcc_open_bf");
}
ST_FUNC void tcc_close(void)
{
trace_enter ("tcc_close");
BufferedFile *bf = file;
//eputs ("tcc_close file:"); //eputs (itoa (file)); //eputs ("\n");
//eputs ("tcc_close bf->fd:"); //eputs (itoa (bf->fd)); //eputs ("\n");
//eputs ("tcc_close bf->prev:"); //eputs (itoa (bf->prev)); //eputs ("\n");
if (bf->fd > 0) {
//eputs ("tcc_close bf->filename:"); //eputs (bf->filename); //eputs ("\n");
close(bf->fd);
total_lines += bf->line_num;
}
if (bf->true_filename != bf->filename)
tcc_free(bf->true_filename);
trace ("tcc_close file->buf_ptr="); eputs (file->buf_ptr); eputs ("\n");
file = bf->prev;
tcc_free(bf);
trace_exit ("tcc_close");
}
ST_FUNC int tcc_open(TCCState *s1, const char *filename)
{
int fd;
trace_enter ("tcc_open");
trace ("tcc_open file-name="); eputs (filename); eputs ("\n");
if (strcmp(filename, "-") == 0)
fd = 0, filename = "<stdin>";
else
fd = open(filename, O_RDONLY | O_BINARY);
trace ("tcc_open fd="); eputs (itoa (fd)); eputs ("\n");
if ((s1->verbose == 2 && fd >= 0) || s1->verbose == 3)
printf("%s %*s%s\n", fd < 0 ? "nf":"->",
(int)(s1->include_stack_ptr - s1->include_stack), "", filename);
if (fd < 0)
if (fd < 0) {
trace_exit ("tcc_open");
return -1;
eputs ("tcc_open 10\n");
tcc_open_bf(s1, filename, 0);
eputs ("tcc_open 11\n");
#ifdef _WIN32
normalize_slashes(file->filename);
#endif
file->fd = fd;
trace_exit ("tcc_open");
return fd;
}
/* compile the file opened in 'file'. Return non zero if errors. */
static int tcc_compile(TCCState *s1, int filetype)
static int tcc_compile(TCCState *s1)
{
Sym *define_start;
int is_asm;
int filetype, is_asm;
trace_enter ("tcc_compile");
define_start = define_stack;
is_asm = !!(filetype & (AFF_TYPE_ASM|AFF_TYPE_ASMPP));
filetype = s1->filetype;
is_asm = filetype == AFF_TYPE_ASM || filetype == AFF_TYPE_ASMPP;
tccelf_begin_file(s1);
if (setjmp(s1->error_jmp_buf) == 0) {
s1->nb_errors = 0;
s1->error_set_jmp_enabled = 1;
trace ("tcc_compile 05 nb_errors="); eputs (itoa (s1->nb_errors)); eputs ("\n");
preprocess_start(s1, is_asm);
trace ("tcc_compile 06 nb_errors="); eputs (itoa (s1->nb_errors)); eputs ("\n");
if (s1->output_type == TCC_OUTPUT_PREPROCESS) {
tcc_preprocess(s1);
} else if (is_asm) {
#ifdef CONFIG_TCC_ASM
tcc_assemble(s1, !!(filetype & AFF_TYPE_ASMPP));
tcc_assemble(s1, filetype == AFF_TYPE_ASMPP);
#else
tcc_error_noabort("asm not supported");
#endif
} else {
trace ("tcc_compile 13 nb_errors="); eputs (itoa (s1->nb_errors)); eputs ("\n");
tccgen_compile(s1);
trace ("tcc_compile 14 nb_errors="); eputs (itoa (s1->nb_errors)); eputs ("\n");
}
}
s1->error_set_jmp_enabled = 0;
@ -656,6 +702,7 @@ static int tcc_compile(TCCState *s1, int filetype)
sym_pop(&global_stack, NULL, 0);
sym_pop(&local_stack, NULL, 0);
tccelf_end_file(s1);
trace_exit ("tcc_compile");
return s1->nb_errors != 0 ? -1 : 0;
}
@ -666,7 +713,7 @@ LIBTCCAPI int tcc_compile_string(TCCState *s, const char *str)
len = strlen(str);
tcc_open_bf(s, "<string>", len);
memcpy(file->buffer, str, len);
ret = tcc_compile(s, s->filetype);
ret = tcc_compile(s);
tcc_close();
return ret;
}
@ -674,23 +721,35 @@ LIBTCCAPI int tcc_compile_string(TCCState *s, const char *str)
/* define a preprocessor symbol. A value can also be provided with the '=' operator */
LIBTCCAPI void tcc_define_symbol(TCCState *s1, const char *sym, const char *value)
{
trace_enter ("tcc_define_symbol");
trace ("tcc_define_symbol value="); eputs (itoa (value)); eputs ("\n");
int len1, len2;
/* default value */
if (!value)
value = "1";
trace ("tcc_define_symbol 01\n");
len1 = strlen(sym);
trace ("tcc_define_symbol 02\n");
len2 = strlen(value);
trace ("tcc_define_symbol 03\n");
/* init file structure */
tcc_open_bf(s1, "<define>", len1 + len2 + 1);
trace ("tcc_define_symbol 04\n");
memcpy(file->buffer, sym, len1);
file->buffer[len1] = ' ';
memcpy(file->buffer + len1 + 1, value, len2);
trace ("tcc_define_symbol X="); //eputs (file->buffer); //eputs ("\n");
/* parse with define parser */
next_nomacro();
trace ("tcc_define_symbol 09\n");
parse_define();
trace ("tcc_define_symbol 10\n");
tcc_close();
trace_exit ("tcc_define_symbol");
}
/* undefine a preprocessor symbol */
@ -708,14 +767,17 @@ LIBTCCAPI void tcc_undefine_symbol(TCCState *s1, const char *sym)
/* cleanup all static data used during compilation */
static void tcc_cleanup(void)
{
if (NULL == tcc_state)
return;
while (file)
tcc_close();
tccpp_delete(tcc_state);
//eputs ("tcc_cleanup01\n");
tcc_state = NULL;
/* free sym_pools */
dynarray_reset(&sym_pools, &nb_sym_pools);
//eputs ("tcc_cleanup02\n");
/* reset symbol stack */
sym_free_first = NULL;
}
@ -724,14 +786,29 @@ LIBTCCAPI TCCState *tcc_new(void)
{
TCCState *s;
//eputs ("tcc_new\n");
tcc_cleanup();
//eputs ("tcc_new01\n");
s = tcc_mallocz(sizeof(TCCState));
//eputs ("size:"); //eputs (itoa (sizeof(TCCState))); //eputs ("\n");
//eputs ("tcc_new02\n");
//eputs ("s="); //eputs (itoa (s)); //eputs ("\n");
if (!s)
return NULL;
tcc_state = s;
trace ("tccnew include_stack="); eputs (itoa (&s->include_stack[0])); eputs ("\n");
++nb_states;
#if BOOTSTRAP
s->static_link = 1;
#endif
eputs ("tcc_new03\n");
s->alacarte_link = 1;
s->nocommon = 1;
s->warn_implicit_function_declaration = 1;
s->ms_extensions = 1;
@ -887,6 +964,8 @@ LIBTCCAPI TCCState *tcc_new(void)
/* Some GCC builtins that are simple to express as macros. */
tcc_define_symbol(s, "__builtin_extract_return_addr(x)", "x");
#endif /* ndef TCC_TARGET_PE */
//eputs ("tcc_new99\n");
return s;
}
@ -992,12 +1071,35 @@ LIBTCCAPI int tcc_add_sysinclude_path(TCCState *s, const char *pathname)
return 0;
}
#if !__x86_64__
#undef eputs
#endif
#if !BOOTSTRAP // MESC
#define for_each_elem(sec, startoff, elem, type) \
for (elem = (type *) sec->data + startoff; \
elem < (type *) (sec->data + sec->data_offset); elem++)
#else
#define for_each_elem(sec, startoff, elem, type) \
elem = sec->data + sizeof (type) * startoff; \
for (;elem < ((type *) (sec->data + sec->data_offset)); elem++)
#endif
ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
{
int ret;
/* open the file */
trace ("tcc_add_file_internal filename="); eputs (filename); eputs ("\n");
ret = tcc_open(s1, filename);
trace ("tcc_add_file_internal 20 ret="); eputs (itoa (ret));; eputs ("\n");
for_each_elem(symtab_section, 1, esym, ElfW(Sym)) {
trace ("tcc_add_file_internal num="); eputs (itoa (esym->st_shndx)); eputs ("\n");
name = (char *) strtab_section->data + esym->st_name;
trace ("tcc_add_file_internal name="); eputs (name); eputs ("\n");
}
if (ret < 0) {
if (flags & AFF_PRINT_ERROR)
tcc_error_noabort("file '%s' not found", filename);
@ -1023,52 +1125,70 @@ ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
switch (obj_type) {
case AFF_BINTYPE_REL:
{
ret = tcc_load_object_file(s1, fd, 0);
trace ("tcc_add_file_internal 41 ret="); eputs (itoa (ret));; eputs ("\n");
break;
}
#ifndef TCC_TARGET_PE
case AFF_BINTYPE_DYN:
{
if (s1->output_type == TCC_OUTPUT_MEMORY) {
ret = 0;
#ifdef TCC_IS_NATIVE
if (NULL == dlopen(filename, RTLD_GLOBAL | RTLD_LAZY))
ret = -1;
#endif
trace ("tcc_add_file_internal 42 ret="); eputs (itoa (ret));; eputs ("\n");
} else {
ret = tcc_load_dll(s1, fd, filename,
(flags & AFF_REFERENCED_DLL) != 0);
trace ("tcc_add_file_internal 43 ret="); eputs (itoa (ret));; eputs ("\n");
}
break;
#endif
}
case AFF_BINTYPE_AR:
ret = tcc_load_archive(s1, fd, !(flags & AFF_WHOLE_ARCHIVE));
{
ret = tcc_load_archive(s1, fd);
trace ("tcc_add_file_internal 51 ret="); eputs (itoa (ret));; eputs ("\n");
break;
}
#ifdef TCC_TARGET_COFF
case AFF_BINTYPE_C67:
ret = tcc_load_coff(s1, fd);
trace ("tcc_add_file_internal 52 ret="); eputs (itoa (ret));; eputs ("\n");
break;
#endif
default:
{
#ifdef TCC_TARGET_PE
ret = pe_load_file(s1, filename, fd);
#else
/* as GNU ld, consider it is an ld script if not recognized */
ret = tcc_load_ldscript(s1);
trace ("tcc_add_file_internal 61 ret="); eputs (itoa (ret));; eputs ("\n");
#endif
if (ret < 0)
tcc_error_noabort("unrecognized file type");
break;
}
}
} else {
ret = tcc_compile(s1, flags);
ret = tcc_compile(s1);
}
trace ("tcc_add_file_internal 90\n");
tcc_close();
trace_exit ("tcc_add_file_internal");
return ret;
}
LIBTCCAPI int tcc_add_file(TCCState *s, const char *filename)
{
int filetype = s->filetype;
if (0 == (filetype & AFF_TYPE_MASK)) {
int flags = AFF_PRINT_ERROR;
if (filetype == 0) {
/* use a file extension to detect a filetype */
const char *ext = tcc_fileextension(filename);
if (ext[0]) {
@ -1080,17 +1200,22 @@ LIBTCCAPI int tcc_add_file(TCCState *s, const char *filename)
else if (!PATHCMP(ext, "c") || !PATHCMP(ext, "i"))
filetype = AFF_TYPE_C;
else
filetype |= AFF_TYPE_BIN;
flags |= AFF_TYPE_BIN;
} else {
filetype = AFF_TYPE_C;
}
s->filetype = filetype;
}
return tcc_add_file_internal(s, filename, filetype | AFF_PRINT_ERROR);
return tcc_add_file_internal(s, filename, flags);
}
LIBTCCAPI int tcc_add_library_path(TCCState *s, const char *pathname)
{
trace ("tcc_add_library_path path="); eputs (pathname); eputs ("\n");
tcc_split_path(s, &s->library_paths, &s->nb_library_paths, pathname);
for(int i = 0; i < s->nb_library_paths; i++) {
trace ("tcc_add_library_path dir="); eputs (s->library_paths[i]); eputs ("\n");
}
return 0;
}
@ -1100,8 +1225,11 @@ static int tcc_add_library_internal(TCCState *s, const char *fmt,
char buf[1024];
int i;
trace ("tcc_add_library_internal file-name="); eputs (filename); eputs ("\n");
trace ("tcc_add_library_internal nb_paths="); eputs (itoa (nb_paths)); eputs ("\n");
for(i = 0; i < nb_paths; i++) {
snprintf(buf, sizeof(buf), fmt, paths[i], filename);
trace ("tcc_add_library_internal buf="); eputs (buf); eputs ("\n");
if (tcc_add_file_internal(s, buf, flags | AFF_TYPE_BIN) == 0)
return 0;
}
@ -1118,6 +1246,7 @@ ST_FUNC int tcc_add_dll(TCCState *s, const char *filename, int flags)
ST_FUNC int tcc_add_crt(TCCState *s, const char *filename)
{
trace ("tcc_add_crt file name="); eputs (filename); eputs ("\n");
if (-1 == tcc_add_library_internal(s, "%s/%s",
filename, 0, s->crt_paths, s->nb_crt_paths))
tcc_error_noabort("file '%s' not found", filename);
@ -1137,10 +1266,9 @@ LIBTCCAPI int tcc_add_library(TCCState *s, const char *libraryname)
const char *libs[] = { "%s/lib%s.so", "%s/lib%s.a", NULL };
const char **pp = s->static_link ? libs + 1 : libs;
#endif
int flags = s->filetype & AFF_WHOLE_ARCHIVE;
while (*pp) {
if (0 == tcc_add_library_internal(s, *pp,
libraryname, flags, s->library_paths, s->nb_library_paths))
libraryname, 0, s->library_paths, s->nb_library_paths))
return 0;
++pp;
}
@ -1149,6 +1277,7 @@ LIBTCCAPI int tcc_add_library(TCCState *s, const char *libraryname)
PUB_FUNC int tcc_add_library_err(TCCState *s, const char *libname)
{
trace ("tcc_add_library_err libname="); eputs (libname); eputs ("\n");
int ret = tcc_add_library(s, libname);
if (ret < 0)
tcc_error_noabort("library '%s' not found", libname);
@ -1170,6 +1299,7 @@ LIBTCCAPI int tcc_add_symbol(TCCState *s, const char *name, const void *val)
So it is handled here as if it were in a DLL. */
pe_putimport(s, 0, name, (uintptr_t)val);
#else
trace ("tcc_add_symbol name="); eputs (name); eputs ("\n");
set_elf_sym(symtab_section, (uintptr_t)val, 0,
ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
SHN_ABS, name);
@ -1234,10 +1364,13 @@ ST_FUNC int set_flag(TCCState *s, const FlagDef *flags, const char *name)
static int strstart(const char *val, const char **str)
{
//eputs ("strstart val:"); //eputs (val); //eputs ("\n");
//eputs ("strstart *str:"); //eputs (*str); //eputs ("\n");
const char *p, *q;
p = *str;
q = val;
while (*q) {
//eputs ("*q:"); //eputc (*q); //eputs ("\n");
if (*p != *q)
return 0;
p++;
@ -1365,8 +1498,6 @@ static int tcc_set_linker(TCCState *s, const char *option)
ignoring = 1;
} else if (link_option(option, "export-all-symbols", &p)) {
s->rdynamic = 1;
} else if (link_option(option, "export-dynamic", &p)) {
s->rdynamic = 1;
} else if (link_option(option, "rpath=", &p)) {
copy_linker_arg(&s->rpath, p, ':');
} else if (link_option(option, "enable-new-dtags", &p)) {
@ -1408,10 +1539,7 @@ static int tcc_set_linker(TCCState *s, const char *option)
goto err;
#endif
} else if (ret = link_option(option, "?whole-archive", &p), ret) {
if (ret > 0)
s->filetype |= AFF_WHOLE_ARCHIVE;
else
s->filetype &= ~AFF_WHOLE_ARCHIVE;
s->alacarte_link = ret < 0;
} else if (p) {
return 0;
} else {
@ -1429,8 +1557,13 @@ static int tcc_set_linker(TCCState *s, const char *option)
typedef struct TCCOption {
const char *name;
#if !BOOTSTRAP
uint16_t index;
uint16_t flags;
#else
int index;
int flags;
#endif
} TCCOption;
enum {
@ -1502,7 +1635,7 @@ static const TCCOption tcc_options[] = {
{ "P", TCC_OPTION_P, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
{ "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG },
{ "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
{ "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG },
{ "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
{ "bench", TCC_OPTION_bench, 0 },
#ifdef CONFIG_TCC_BACKTRACE
{ "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG },
@ -1596,9 +1729,16 @@ static void parse_option_D(TCCState *s1, const char *optarg)
static void args_parser_add_file(TCCState *s, const char* filename, int filetype)
{
struct filespec *f = tcc_malloc(sizeof *f + strlen(filename));
trace ("arg_parser_add file name="); eputs (filename); eputs ("\n");
f->type = filetype;
f->alacarte = s->alacarte_link;
strcpy(f->name, filename);
trace ("arg_parser_add file f->name="); //eputs (f->name); //eputs ("\n");
trace ("arg_parser_add nb_files="); //eputs (itoa (s->nb_files)); //eputs ("\n");
dynarray_add(&s->files, &s->nb_files, f);
//struct filespec *= s->files[s->nb_files - 1];
struct filespec * fs = s->files[0];
//eputs ("arg_parser_add file fs->name="); //eputs (fs->name); //eputs ("\n");
}
static int args_parser_make_argv(const char *r, int *argc, char ***argv)
@ -1643,6 +1783,7 @@ static void args_parser_listfile(TCCState *s,
int argc = 0;
char **argv = NULL;
trace ("arg_parser_listfile filename="); eputs (filename); eputs ("\n");
fd = open(filename, O_RDONLY | O_BINARY);
if (fd < 0)
tcc_error("listfile '%s' not found", filename);
@ -1664,6 +1805,8 @@ static void args_parser_listfile(TCCState *s,
PUB_FUNC int tcc_parse_args(TCCState *s, int *pargc, char ***pargv, int optind)
{
trace ("tcc_parse_args\n");
const TCCOption *popt;
const char *optarg, *r;
const char *run = NULL;
@ -1677,7 +1820,11 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int *pargc, char ***pargv, int optind)
cstr_new(&linker_arg);
while (optind < argc) {
trace ("tcc_parse_args 02 arg:"); eputs (itoa (optind)); eputs ("\n");
r = argv[optind];
trace ("tcc_parse_args 03 r:"); eputs (r); eputs ("\n");
if (r[0] == '@' && r[1] != '\0') {
args_parser_listfile(s, r + 1, optind, &argc, &argv);
continue;
@ -1700,10 +1847,17 @@ reparse:
continue;
}
trace ("tcc_parse_args 20\n");
trace ("tcc_parse_args 20 opt0="); eputs (tcc_options[0].name); eputs ("\n");
trace ("tcc_parse_args 20 opt1="); eputs (tcc_options[1].name); eputs ("\n");
/* find option in table */
for(popt = tcc_options; ; ++popt) {
trace ("tcc_parse_args 21\n");
trace ("tcc_parse_args 22 popt:"); eputs (popt->name); eputs ("\n");
const char *p1 = popt->name;
const char *r1 = r + 1;
trace ("tcc_parse_args 23 r1:"); eputs (r1); eputs ("\n");
if (p1 == NULL)
tcc_error("invalid option -- '%s'", r);
if (!strstart(p1, &r1))
@ -1721,6 +1875,8 @@ reparse:
break;
}
trace ("pars_arg 2\n");
switch(popt->index) {
case TCC_OPTION_HELP:
return OPT_HELP;
@ -1743,7 +1899,7 @@ reparse:
tcc_set_lib_path(s, optarg);
break;
case TCC_OPTION_l:
args_parser_add_file(s, optarg, AFF_TYPE_LIB | (s->filetype & ~AFF_TYPE_MASK));
args_parser_add_file(s, optarg, AFF_TYPE_LIB);
s->nb_libraries++;
break;
case TCC_OPTION_pthread:
@ -1897,18 +2053,14 @@ reparse:
exit(0);
break;
case TCC_OPTION_x:
x = 0;
if (*optarg == 'c')
x = AFF_TYPE_C;
s->filetype = AFF_TYPE_C;
else if (*optarg == 'a')
x = AFF_TYPE_ASMPP;
else if (*optarg == 'b')
x = AFF_TYPE_BIN;
s->filetype = AFF_TYPE_ASMPP;
else if (*optarg == 'n')
x = AFF_TYPE_NONE;
s->filetype = AFF_TYPE_NONE;
else
tcc_warning("unsupported language '%s'", optarg);
s->filetype = x | (s->filetype & ~AFF_TYPE_MASK);
break;
case TCC_OPTION_O:
last_o = atoi(optarg);

29
link.sh Executable file
View File

@ -0,0 +1,29 @@
#! /bin/sh
set -ex
rm -f 1.a 2.a
MES_PREFIX=${MES_PREFIX-../mes}
MES_SEED=${MES_SEED-../mes-seed}
# trivial bin
###./tcc ../mes/scaffold/main.c
c=${1-$MES_PREFIX/scaffold/main}
b=scaffold/${c##*/}
rm -f "$b".mes-gcc-out
rm -f "$b".mes-out
./i686-unknown-linux-gnu-tcc\
-static -g -o "$b".mes-gcc-out -I $MES_PREFIX/include -L $MES_SEED "$c".c 2> "$b".mes-gcc-stderr
set +e
${MES_TCC-./mes-tcc}\
-static -g -o "$b".mes-out -I $MES_PREFIX/include -L $MES_SEED "$c".c 2> "$b".mes-stderr
objdump -d "$b".mes-gcc-out > "$b".mes-gcc-d
objdump -d "$b".mes-out > "$b".mes-d
#readelf -a a.i686-unknown-linux-gnu-out > 1.r
#readelf -a a.mes-out > 2.r
#diff -y 1.a 2.a
echo diff -y "$b".mes-gcc-stderr "$b".mes-stderr
echo diff -y "$b".mes-gcc-d "$b".mes-d
"$b".mes-out

View File

@ -322,11 +322,6 @@ Binary image (only for executable output)
COFF output format (only for executable output for TMS320C67xx target)
@end table
@item -Wl,--export-all-symbols
@item -Wl,--export-dynamic
Export global symbols to the dynamic linker. It is useful when a library
opened with @code{dlopen()} needs to access executable symbols.
@item -Wl,-subsystem=console/gui/wince/...
Set type for PE (Windows) executables.
@ -548,7 +543,6 @@ instead of
@cindex stdcall attribute
@cindex regparm attribute
@cindex dllexport attribute
@cindex nodecorate attribute
@item The keyword @code{__attribute__} is handled to specify variable or
function attributes. The following attributes are supported:
@ -576,8 +570,6 @@ registers @code{%eax}, @code{%edx} and @code{%ecx}.
@item @code{dllexport}: export function from dll/executable (win32 only)
@item @code{nodecorate}: do not apply any decorations that would otherwise be applied when exporting function from dll/executable (win32 only)
@end itemize
Here are some examples:

47
tcc.c
View File

@ -62,7 +62,7 @@ static const char help[] =
" -bt N show N callers in stack traces\n"
#endif
"Misc. options:\n"
" -x[c|a|b|n] specify type of the next infile (C,ASM,BIN,NONE)\n"
" -x[c|a|n] specify type of the next infile\n"
" -nostdinc do not use standard system include paths\n"
" -nostdlib do not link with standard crt and libraries\n"
" -Bdir set tcc's private include/library dir\n"
@ -117,7 +117,6 @@ static const char help2[] =
" -nostdlib do not link with standard crt/libs\n"
" -[no-]whole-archive load lib(s) fully/only as needed\n"
" -export-all-symbols same as -rdynamic\n"
" -export-dynamic same as -rdynamic\n"
" -image-base= -Ttext= set base address of executable\n"
" -section-alignment= set section alignment in executable\n"
#ifdef TCC_TARGET_PE
@ -183,10 +182,8 @@ static void print_search_dirs(TCCState *s)
/* print_dirs("programs", NULL, 0); */
print_dirs("include", s->sysinclude_paths, s->nb_sysinclude_paths);
print_dirs("libraries", s->library_paths, s->nb_library_paths);
#ifdef TCC_TARGET_PE
printf("libtcc1:\n %s/lib/"TCC_LIBTCC1"\n", s->tcc_lib_path);
#else
printf("libtcc1:\n %s/"TCC_LIBTCC1"\n", s->tcc_lib_path);
#ifndef TCC_TARGET_PE
print_dirs("crt", s->crt_paths, s->nb_crt_paths);
printf("elfinterp:\n %s\n", DEFAULT_ELFINTERP(s));
#endif
@ -255,10 +252,22 @@ int main(int argc0, char **argv0)
int argc; char **argv;
FILE *ppfp = stdout;
trace_enter ("main");
redo:
argc = argc0, argv = argv0;
trace ("main 01\n");
s = tcc_new();
trace ("main 02\n");
opt = tcc_parse_args(s, &argc, &argv, 1);
trace ("main 03\n");
if (s->nb_files) {
struct filespec *f = s->files[0];
trace ("main 05 file[0]="); eputs (f->name); eputs ("\n");
}
trace ("main 06\n");
if ((n | t) == 0) {
if (opt == OPT_HELP)
@ -290,7 +299,7 @@ redo:
tcc_error("no input files\n");
if (s->output_type == TCC_OUTPUT_PREPROCESS) {
if (s->outfile && 0!=strcmp("-",s->outfile)) {
if (s->outfile) {
ppfp = fopen(s->outfile, "w");
if (!ppfp)
tcc_error("could not write '%s'", s->outfile);
@ -301,17 +310,18 @@ redo:
if (n > 1 && s->outfile)
tcc_error("cannot specify output file with -c many files");
} else {
if (s->option_pthread) {
if (s->option_pthread)
tcc_set_options(s, "-lpthread");
n = s->nb_files;
}
}
if (s->do_bench)
start_time = getclock_ms();
}
trace ("main 20\n");
set_environment(s);
trace ("main 21\n");
if (s->output_type == 0)
s->output_type = TCC_OUTPUT_EXE;
tcc_set_output_type(s, s->output_type);
@ -321,13 +331,20 @@ redo:
|| s->output_type == TCC_OUTPUT_PREPROCESS) && (s->dflag & 16))
s->dflag |= t ? 32 : 0, s->run_test = ++t, n = s->nb_files;
trace ("main 23\n");
/* compile or add each files or library */
for (first_file = NULL, ret = 0;;) {
trace ("main 24 nb-files="); eputs (itoa (s->nb_files)); eputs ("\n");
trace ("main 24 n="); eputs (itoa (n)); eputs ("\n");
struct filespec *f = s->files[s->nb_files - n];
trace ("for f->name="); eputs (f->name); eputs ("\n");
s->filetype = f->type;
if (f->type & AFF_TYPE_LIB) {
s->alacarte_link = f->alacarte;
if (f->type == AFF_TYPE_LIB) {
if (tcc_add_library_err(s, f->name) < 0)
ret = 1;
trace ("main 32 ret="); eputs (itoa (ret)); eputs ("\n");
} else {
if (1 == s->verbose)
printf("-> %s\n", f->name);
@ -335,24 +352,33 @@ redo:
first_file = f->name;
if (tcc_add_file(s, f->name) < 0)
ret = 1;
trace ("main 33 ret="); eputs (itoa (ret)); eputs ("\n");
}
trace ("ret="); eputs (itoa (ret)); eputs ("\n");
s->filetype = 0;
s->alacarte_link = 1;
if (--n == 0 || ret
|| (s->output_type == TCC_OUTPUT_OBJ && !s->option_r))
break;
}
trace ("main 40\n");
if (s->run_test) {
t = 0;
} else if (s->output_type == TCC_OUTPUT_PREPROCESS) {
;
} else if (0 == ret) {
trace ("main 42 ret == 0\n");
if (s->output_type == TCC_OUTPUT_MEMORY) {
trace ("main RUN\n");
#ifdef TCC_IS_NATIVE
ret = tcc_run(s, argc, argv);
#endif
} else {
trace ("main 44 gonna output_file\n");
if (!s->outfile)
s->outfile = default_outputfile(s, first_file);
trace ("main 45 output_file\n");
if (tcc_output_file(s, s->outfile))
ret = 1;
else if (s->gen_deps)
@ -369,5 +395,6 @@ redo:
goto redo; /* run more tests with -dt -run */
if (ppfp && ppfp != stdout)
fclose(ppfp);
trace_exit ("main");
return ret;
}

48
tcc.h
View File

@ -92,6 +92,9 @@ extern long double strtold (const char *__nptr, char **__endptr);
#ifdef _MSC_VER
# define NORETURN __declspec(noreturn)
# define ALIGNED(x) __declspec(align(x))
#elif __MESC__
#define NORETURN
#define ALIGNED(x)
#else
# define NORETURN __attribute__((noreturn))
# define ALIGNED(x) __attribute__((aligned(x)))
@ -433,23 +436,42 @@ typedef struct SValue {
/* symbol attributes */
struct SymAttr {
#if HAVE_BITFIELD
unsigned short
aligned : 5, /* alignment as log2+1 (0 == unspecified) */
packed : 1,
weak : 1,
visibility : 2,
dllexport : 1,
nodecorate : 1,
dllimport : 1,
unused : 4;
unused : 5;
#else // !HAVE_BITFIELD
struct {
unsigned aligned;
unsigned packed;
unsigned weak;
unsigned visibility;
unsigned dllexport;
unsigned dllimport;
unsigned unused;
};
#endif // !HAVE_BITFIELD
};
/* function attributes or temporary attributes for parsing */
struct FuncAttr {
#if HAVE_BITFIELD
unsigned
func_call : 3, /* calling convention (0..5), see below */
func_type : 2, /* FUNC_OLD/NEW/ELLIPSIS */
func_args : 8; /* PE __stdcall args */
#else // !HAVE_BITFIELD
struct {
unsigned func_call;
unsigned func_type;
unsigned func_args;
};
#endif // !HAVE_BITFIELD
};
/* GNUC attribute definition */
@ -467,19 +489,15 @@ typedef struct Sym {
int v; /* symbol token */
unsigned short r; /* associated register or VT_CONST/VT_LOCAL and LVAL type */
struct SymAttr a; /* symbol attributes */
union {
struct {
int c; /* associated number or Elf symbol index */
union {
int sym_scope; /* scope level for locals */
int jnext; /* next jump label */
struct FuncAttr f; /* function attributes */
int auxtype; /* bitfield access type */
};
};
long long enum_val; /* enum constant if IS_ENUM_VAL */
int *d; /* define token stream */
};
long long enum_val; /* enum constant if IS_ENUM_VAL */
int *d; /* define token stream */
CType type; /* associated type */
union {
struct Sym *next; /* next related symbol (for fields and anoms) */
@ -639,6 +657,7 @@ struct sym_attr {
};
struct TCCState {
int verbose; /* if true, display some information during compilation */
int nostdinc; /* if true, no standard headers are added */
int nostdlib; /* if true, no standard libraries are added */
@ -646,7 +665,7 @@ struct TCCState {
int static_link; /* if true, static linking is performed */
int rdynamic; /* if true, all symbols are exported */
int symbolic; /* if true, resolve symbols in the current module first */
int filetype; /* file type for compilation (NONE,C,ASM) */
int alacarte_link; /* if true, only link in referenced objects from archive */
char *tcc_lib_path; /* CONFIG_TCCDIR or -B option */
char *soname; /* as specified on the command line (-soname) */
@ -811,6 +830,7 @@ struct TCCState {
struct filespec **files; /* files seen on command line */
int nb_files; /* number thereof */
int nb_libraries; /* number of libs thereof */
int filetype;
char *outfile; /* output filename */
int option_r; /* option -r */
int do_bench; /* option -bench */
@ -823,6 +843,7 @@ struct TCCState {
struct filespec {
char type;
char alacarte;
char name[1];
};
@ -1148,14 +1169,12 @@ ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
#define AFF_PRINT_ERROR 0x10 /* print error if file not found */
#define AFF_REFERENCED_DLL 0x20 /* load a referenced dll from another dll */
#define AFF_TYPE_BIN 0x40 /* file to add is binary */
#define AFF_WHOLE_ARCHIVE 0x80 /* load all objects from archive */
/* s->filetype: */
#define AFF_TYPE_NONE 0
#define AFF_TYPE_C 1
#define AFF_TYPE_ASM 2
#define AFF_TYPE_ASMPP 4
#define AFF_TYPE_LIB 8
#define AFF_TYPE_MASK (15 | AFF_TYPE_BIN)
#define AFF_TYPE_ASMPP 3
#define AFF_TYPE_LIB 4
/* values from tcc_object_type(...) */
#define AFF_BINTYPE_REL 1
#define AFF_BINTYPE_DYN 2
@ -1423,7 +1442,7 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s);
ST_FUNC int tcc_object_type(int fd, ElfW(Ehdr) *h);
ST_FUNC int tcc_load_object_file(TCCState *s1, int fd, unsigned long file_offset);
ST_FUNC int tcc_load_archive(TCCState *s1, int fd, int alacarte);
ST_FUNC int tcc_load_archive(TCCState *s1, int fd);
ST_FUNC void tcc_add_bcheck(TCCState *s1);
ST_FUNC void tcc_add_runtime(TCCState *s1);
@ -1475,7 +1494,6 @@ ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *align, int *reg
ST_FUNC void gfunc_call(int nb_args);
ST_FUNC void gfunc_prolog(CType *func_type);
ST_FUNC void gfunc_epilog(void);
ST_FUNC void gen_fill_nops(int);
ST_FUNC int gjmp(int t);
ST_FUNC void gjmp_addr(int a);
ST_FUNC int gtst(int inv, int t);

View File

@ -18,7 +18,10 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _TCC_H
#include "tcc.h"
#endif
#ifdef CONFIG_TCC_ASM
ST_FUNC int asm_get_local_label_name(TCCState *s1, unsigned int n)
@ -1108,9 +1111,12 @@ static void parse_asm_operands(ASMOperand *operands, int *nb_operands_ptr,
next();
skip(']');
}
parse_mult_str(&astr, "string constant");
parse_mult_str(&astr, "parse_asm_operands string constant");
trace ("parse arm_operands tokc.str.data="); eputs (tokc.str.data); eputs ("\n");
op->constraint = tcc_malloc(astr.size);
trace ("parse arm_operands tokc.str.data="); eputs (tokc.str.data); eputs ("\n");
strcpy(op->constraint, astr.data);
trace ("parse arm_operands tokc.str.data="); eputs (tokc.str.data); eputs ("\n");
cstr_free(&astr);
skip('(');
gexpr();
@ -1149,13 +1155,17 @@ ST_FUNC void asm_instr(void)
int nb_outputs, nb_operands, i, must_subst, out_reg;
uint8_t clobber_regs[NB_ASM_REGS];
trace_enter ("asm_instr");
next();
trace ("asm_instr 01\n");
/* since we always generate the asm() instruction, we can ignore
volatile */
if (tok == TOK_VOLATILE1 || tok == TOK_VOLATILE2 || tok == TOK_VOLATILE3) {
next();
}
trace ("asm_instr 02\n");
parse_asm_str(&astr);
trace ("asm_instr astr.data="); eputs (astr.data); eputs ("\n");
nb_operands = 0;
nb_outputs = 0;
must_subst = 0;
@ -1208,6 +1218,7 @@ ST_FUNC void asm_instr(void)
#ifdef ASM_DEBUG
printf("asm: \"%s\"\n", (char *)astr.data);
#endif
trace ("asm_instr asm:"); eputs (astr.data); eputs ("\n");
if (must_subst) {
subst_asm_operands(operands, nb_operands, &astr1, &astr);
cstr_free(&astr);
@ -1217,6 +1228,7 @@ ST_FUNC void asm_instr(void)
#ifdef ASM_DEBUG
printf("subst_asm: \"%s\"\n", (char *)astr1.data);
#endif
trace ("asm_instr subst:"); eputs (astr1.data); eputs ("\n");
/* generate loads */
asm_gen_code(operands, nb_operands, nb_outputs, 0,
@ -1240,6 +1252,7 @@ ST_FUNC void asm_instr(void)
vpop();
}
cstr_free(&astr1);
trace_exit ("asm_instr");
}
ST_FUNC void asm_global_instr(void)

View File

@ -19,7 +19,9 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _TCC_H
#include "tcc.h"
#endif
#define MAXNSCNS 255 /* MAXIMUM NUMBER OF SECTIONS */
#define MAX_STR_TABLE 1000000

343
tccelf.c

File diff suppressed because it is too large Load Diff

841
tccgen.c

File diff suppressed because it is too large Load Diff

View File

@ -18,7 +18,9 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _TCC_H
#include "tcc.h"
#endif
#define PE_MERGE_DATA
/* #define PE_PRINT_SECTIONS */
@ -1866,6 +1868,8 @@ static void pe_add_runtime(TCCState *s1, struct pe_info *pe)
ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
SHN_UNDEF, start_symbol);
tcc_add_pragma_libs(s1);
if (0 == s1->nostdlib) {
static const char *libs[] = {
TCC_LIBTCC1, "msvcrt", "kernel32", "", "user32", "gdi32", NULL
@ -1946,7 +1950,7 @@ ST_FUNC int pe_output_file(TCCState *s1, const char *filename)
pe.filename = filename;
pe.s1 = s1;
tcc_add_runtime(s1);
tcc_add_bcheck(s1);
pe_add_runtime(s1, &pe);
resolve_common_syms(s1);
pe_set_options(s1, &pe);

441
tccpp.c

File diff suppressed because it is too large Load Diff

View File

@ -18,7 +18,9 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _TCC_H
#include "tcc.h"
#endif
/* only native compiler supports -run */
#ifdef TCC_IS_NATIVE
@ -169,12 +171,9 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
}
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
/* To avoid that x86 processors would reload cached instructions
each time when data is written in the near, we need to make
sure that code and data do not share the same 64 byte unit */
#define RUN_SECTION_ALIGNMENT 63
#else
#define RUN_SECTION_ALIGNMENT 0
#define RUN_SECTION_ALIGNMENT 15
#endif
/* relocate code. Return -1 on error, required size if ptr is NULL,
@ -182,8 +181,8 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
static int tcc_relocate_ex(TCCState *s1, void *ptr, addr_t ptr_diff)
{
Section *s;
unsigned offset, length, align, max_align, i, k, f;
addr_t mem, addr;
unsigned offset, length, fill, i, k;
addr_t mem;
if (NULL == ptr) {
s1->nb_errors = 0;
@ -198,32 +197,39 @@ static int tcc_relocate_ex(TCCState *s1, void *ptr, addr_t ptr_diff)
return -1;
}
offset = max_align = 0, mem = (addr_t)ptr;
offset = 0, mem = (addr_t)ptr;
fill = -mem & RUN_SECTION_ALIGNMENT;
#ifdef _WIN64
offset += sizeof (void*); /* space for function_table pointer */
offset += sizeof (void*);
#endif
for (k = 0; k < 2; ++k) {
f = 0, addr = k ? mem : mem + ptr_diff;
for(i = 1; i < s1->nb_sections; i++) {
s = s1->sections[i];
if (0 == (s->sh_flags & SHF_ALLOC))
continue;
if (k != !(s->sh_flags & SHF_EXECINSTR))
continue;
align = s->sh_addralign - 1;
if (++f == 1 && align < RUN_SECTION_ALIGNMENT)
align = RUN_SECTION_ALIGNMENT;
if (max_align < align)
max_align = align;
offset += -(addr + offset) & align;
s->sh_addr = mem ? addr + offset : 0;
offset += s->data_offset;
offset += fill;
if (!mem)
s->sh_addr = 0;
else if (s->sh_flags & SHF_EXECINSTR)
s->sh_addr = mem + offset + ptr_diff;
else
s->sh_addr = mem + offset;
#if 0
if (mem)
printf("%-16s %p len %04x align %2d\n",
s->name, (void*)s->sh_addr, (unsigned)s->data_offset, align + 1);
printf("%-16s +%02lx %p %04x\n",
s->name, fill, (void*)s->sh_addr, (unsigned)s->data_offset);
#endif
offset += s->data_offset;
fill = -(mem + offset) & 15;
}
#if RUN_SECTION_ALIGNMENT > 15
/* To avoid that x86 processors would reload cached instructions each time
when data is written in the near, we need to make sure that code and data
do not share the same 64 byte unit */
fill = -(mem + offset) & RUN_SECTION_ALIGNMENT;
#endif
}
/* relocate symbols */
@ -232,7 +238,7 @@ static int tcc_relocate_ex(TCCState *s1, void *ptr, addr_t ptr_diff)
return -1;
if (0 == mem)
return offset + max_align;
return offset + RUN_SECTION_ALIGNMENT;
#ifdef TCC_TARGET_PE
s1->pe_imagebase = mem;

View File

@ -53,7 +53,6 @@
DEF(TOK_ATTRIBUTE2, "__attribute__")
DEF(TOK_ALIGNOF1, "__alignof")
DEF(TOK_ALIGNOF2, "__alignof__")
DEF(TOK_ALIGNOF3, "_Alignof")
DEF(TOK_TYPEOF1, "typeof")
DEF(TOK_TYPEOF2, "__typeof")
DEF(TOK_TYPEOF3, "__typeof__")
@ -133,7 +132,6 @@
DEF(TOK_DLLEXPORT, "dllexport")
DEF(TOK_DLLIMPORT, "dllimport")
DEF(TOK_NODECORATE, "nodecorate")
DEF(TOK_NORETURN1, "noreturn")
DEF(TOK_NORETURN2, "__noreturn__")
DEF(TOK_VISIBILITY1, "visibility")

View File

@ -28,7 +28,9 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef _TCC_H
#include "tcc.h"
#endif
//#define ARMAG "!<arch>\n"
#define ARFMAG "`\n"

87
test.sh Executable file
View File

@ -0,0 +1,87 @@
#! /bin/sh
set -ex
TCC=${TCC-./mes-tcc}
MESCC=${MESCC-mescc}
MES_PREFIX=${MES_PREFIX-../mes}
MES_PREFIX=${MES_PREFIX-${MESCC%/*}}
MES_SEED=${MES_SEED-../mes-seed}
OBJDUMP=${OBJDUMP-objdump}
DIFF=${DIFF-diff}
unset C_INCLUDE_PATH LIBRARY_PATH
t=${1-$MES_PREFIX/scaffold/tests/t}
mkdir -p scaffold
b=scaffold/${t##*/}
rm -f "$b".i686-unknown-linux-gnu-out
rm -f "$b".mes-out
r=0
if [ -x ./i686-unknown-linux-gnu-tcc ]; then
./i686-unknown-linux-gnu-tcc\
-c\
-o "$b".mes-gcc-o\
-nostdlib\
-g\
-m32\
-D __TINYC__=1\
-I $MES_PREFIX/include\
-I $MES_PREFIX/scaffold/tests\
-I $MES_PREFIX/scaffold/tinycc\
"$t".c &> 1
#$OBJDUMP -d "$t".mes-gcc-o > 1.s
./i686-unknown-linux-gnu-tcc\
-static\
-o "$b".mes-gcc-out\
-L .\
-L $MES_SEED\
"$b".mes-gcc-o &> 1.link
set +e
"$b".mes-gcc-out arg1 arg2 arg3 arg4 arg5 > "$b".mes-gcc-stdout
m=$?
set -e
[ -f "$t".exit ] && r=$(cat "$t".exit)
[ $m = $r ]
if [ -f "$t".expect ]; then
$DIFF -ub "$t".expect "$b".mes-gcc-stdout;
fi
fi
$TCC\
-c\
-g\
-m32\
-o "$b".mes-o\
-D __TINYC__=1\
-I $MES_PREFIX/include\
-I $MES_PREFIX/scaffold/tests\
-I $MES_PREFIX/scaffold/tinycc\
"$t".c &> 2
$OBJDUMP -d "$b".mes-o > 2.s || true
$TCC\
-static\
-o "$b".mes-out\
-g\
-m32\
-D __TINYC__=1\
-I $MES_PREFIX/include\
-I $MES_PREFIX/scaffold/tests\
-I $MES_PREFIX/scaffold/tinycc\
-L $MES_SEED\
"$t".c &> 2.link
set +e
"$b".mes-out arg1 arg2 arg3 arg4 arg5 > "$b".mes-stdout
m=$?
#$OBJDUMP -d "$t".mes-out > 2.x
set -e
[ $m = $r ]
[ -f "$t".exit ] && r=$(cat "$t".exit)
if [ -f "$t".expect ]; then
$DIFF -ub "$t".expect "$b".mes-stdout;
fi
#diff -y 1.s 2.s
#diff -y 1 2

View File

@ -279,7 +279,7 @@ cache: tcc_g
clean:
rm -f *~ *.o *.a *.bin *.i *.ref *.out *.out? *.out?b *.cc *.gcc
rm -f *-cc *-gcc *-tcc *.exe hello libtcc_test vla_test tcctest[1234]
rm -f asm-c-connect$(EXESUF) asm-c-connect-sep$(EXESUF)
rm -f asm-c-connect$(EXESUF)
rm -f ex? tcc_g weaktest.*.txt *.def
@$(MAKE) -C tests2 $@
@$(MAKE) -C pp $@

View File

@ -10,7 +10,7 @@ VPATH = $(SRC)
files = $(patsubst %.$1,%.test,$(notdir $(wildcard $(SRC)/*.$1)))
TESTS = $(call files,c) $(call files,S)
all test testspp.all: $(sort $(TESTS))
all test : $(sort $(TESTS))
DIFF_OPTS = -Nu -b -B
@ -29,8 +29,6 @@ FILTER = 2>&1 | sed 's,$(SRC)/,,g'
diff $(DIFF_OPTS) $(SRC)/$*.expect $*.output \
&& rm -f $*.output
testspp.%: %.test ;
# automatically generate .expect files with gcc:
%.expect: # %.c
gcc -E -P $*.[cS] >$*.expect 2>&1

View File

@ -2234,9 +2234,6 @@ void float_test(void)
double da, db;
int a;
unsigned int b;
static double nan2 = 0.0/0.0;
static double inf1 = 1.0/0.0;
static double inf2 = 1e5000;
printf("float_test:\n");
printf("sizeof(float) = %d\n", sizeof(float));
@ -2258,7 +2255,6 @@ void float_test(void)
b = 4000000000;
db = b;
printf("db = %f\n", db);
printf("nan != nan = %d, inf1 = %f, inf2 = %f\n", nan2 != nan2, inf1, inf2);
#endif
}
@ -2270,8 +2266,6 @@ int fib(int n)
return fib(n-1) + fib(n-2);
}
void __attribute__((aligned(16))) aligned_function(int i) {}
void funcptr_test()
{
void (*func)(int);
@ -2302,10 +2296,6 @@ void funcptr_test()
func(42);
(func + diff)(42);
(num + a)(43);
/* Check that we can align functions */
func = aligned_function;
printf("aligned_function (should be zero): %d\n", ((int)func) & 15);
}
void lloptest(long long a, long long b)
@ -2497,11 +2487,6 @@ void longlong_test(void)
a = 0x123;
long long *p = &a;
llshift(*p, 5);
/* shortening followed by widening */
unsigned long long u = 0x8000000000000001ULL;
u = (unsigned)(u + 1);
printf("long long u=" ULONG_LONG_FORMAT "\n", u);
}
void manyarg_test(void)

View File

@ -15,19 +15,6 @@ void qfunc()
printf("qfunc()\n");
}
#if !defined(__ARMEL__)
/*
* At least on ARM (like RPi), zfunc below fails with something like:
* +tcc: error: can't relocate value at 1ef93bc,1
* Test is temporary removed for this architecture until ARM maintainers
* see what happens with this test.
*/
void zfunc()
{
((void (*)(void))0) ();
}
#endif
int main()
{
printf("%d\n", myfunc(3));

View File

@ -1,34 +0,0 @@
void foo(int [5]);
void fooc(int x[const 5]);
void foos(int x[static 5]);
void foov(int x[volatile 5]);
void foor(int x[restrict 5]);
void fooc(int [const 5]);
void foos(int [static 5]);
void foov(int [volatile 5]);
void foor(int [restrict 5]);
void fooc(int (* const x));
void foos(int *x);
void foov(int * volatile x);
void foor(int * restrict x);
void fooc(int x[volatile 5])
{
x[3] = 42;
#ifdef INVALID
x = 0;
#endif
}
void foovm(int x[const *]);
void foovm(int * const x);
#ifdef INVALID
void wrongc(int x[3][const 4]);
void wrongvm(int x[static *]);
void foovm(int x[const *])
{
x[2] = 1;
}
#endif
int main()
{
return 0;
}

View File

@ -1,30 +1,4 @@
#include <stdio.h>
#include <assert.h>
char arr[1];
static void f (void){}
void (*fp)(void) = f;
void call_fp()
{
(fp?f:f)();
(fp?fp:fp)();
(fp?fp:&f)();
(fp?&f:fp)();
(fp?&f:&f)();
_Generic(0?arr:arr, char*: (void)0);
_Generic(0?&arr[0]:arr, char*: (void)0);
_Generic(0?arr:&arr[0], char*: (void)0);
_Generic(1?arr:arr, char*: (void)0);
_Generic(1?&arr[0]:arr, char*: (void)0);
_Generic(1?arr:&arr[0], char*: (void)0);
_Generic((__typeof(1?f:f)*){0}, void (**)(void): (void)0);
(fp?&f:f)();
(fp?f:&f)();
_Generic((__typeof(fp?0L:(void)0)*){0}, void*: (void)0);
//Should cleanly fail, not segfault:
/*(fp?f:1);*/
}
int main()
{
@ -35,19 +9,6 @@ int main()
printf("%d\n", (Count < 5) ? (Count*Count) : (Count * 3));
}
{
int c = 0;
#define ASSERT(X) assert(X)
static struct stru { int x; } a={'A'},b={'B'};
ASSERT('A'==(*(1?&a:&b)).x);
ASSERT('A'==(1?a:b).x);
ASSERT('A'==(c?b:a).x);
ASSERT('A'==(0?b:a).x);
c=1;
ASSERT('A'==(c?a:b).x);
}
return 0;
}

View File

@ -1,568 +0,0 @@
/*
* The information in this document is subject to change
* without notice and should not be construed as a commitment
* by Digital Equipment Corporation or by DECUS.
*
* Neither Digital Equipment Corporation, DECUS, nor the authors
* assume any responsibility for the use or reliability of this
* document or the described software.
*
* Copyright (C) 1980, DECUS
*
* General permission to copy or modify, but not for profit, is
* hereby granted, provided that the above copyright notice is
* included and reference made to the fact that reproduction
* privileges were granted by DECUS.
*/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h> // tolower()
/*
* grep
*
* Runs on the Decus compiler or on vms, On vms, define as:
* grep :== "$disk:[account]grep" (native)
* grep :== "$disk:[account]grep grep" (Decus)
* See below for more information.
*/
char *documentation[] = {
"grep searches a file for a given pattern. Execute by",
" grep [flags] regular_expression file_list\n",
"Flags are single characters preceded by '-':",
" -c Only a count of matching lines is printed",
" -f Print file name for matching lines switch, see below",
" -n Each line is preceded by its line number",
" -v Only print non-matching lines\n",
"The file_list is a list of files (wildcards are acceptable on RSX modes).",
"\nThe file name is normally printed if there is a file given.",
"The -f flag reverses this action (print name no file, not if more).\n",
0 };
char *patdoc[] = {
"The regular_expression defines the pattern to search for. Upper- and",
"lower-case are always ignored. Blank lines never match. The expression",
"should be quoted to prevent file-name translation.",
"x An ordinary character (not mentioned below) matches that character.",
"'\\' The backslash quotes any character. \"\\$\" matches a dollar-sign.",
"'^' A circumflex at the beginning of an expression matches the",
" beginning of a line.",
"'$' A dollar-sign at the end of an expression matches the end of a line.",
"'.' A period matches any character except \"new-line\".",
"':a' A colon matches a class of characters described by the following",
"':d' character. \":a\" matches any alphabetic, \":d\" matches digits,",
"':n' \":n\" matches alphanumerics, \": \" matches spaces, tabs, and",
"': ' other control characters, such as new-line.",
"'*' An expression followed by an asterisk matches zero or more",
" occurrences of that expression: \"fo*\" matches \"f\", \"fo\"",
" \"foo\", etc.",
"'+' An expression followed by a plus sign matches one or more",
" occurrences of that expression: \"fo+\" matches \"fo\", etc.",
"'-' An expression followed by a minus sign optionally matches",
" the expression.",
"'[]' A string enclosed in square brackets matches any character in",
" that string, but no others. If the first character in the",
" string is a circumflex, the expression matches any character",
" except \"new-line\" and the characters in the string. For",
" example, \"[xyz]\" matches \"xx\" and \"zyx\", while \"[^xyz]\"",
" matches \"abc\" but not \"axb\". A range of characters may be",
" specified by two characters separated by \"-\". Note that,",
" [a-z] matches alphabetics, while [z-a] never matches.",
"The concatenation of regular expressions is a regular expression.",
0};
#define LMAX 512
#define PMAX 256
#define CHAR 1
#define BOL 2
#define EOL 3
#define ANY 4
#define CLASS 5
#define NCLASS 6
#define STAR 7
#define PLUS 8
#define MINUS 9
#define ALPHA 10
#define DIGIT 11
#define NALPHA 12
#define PUNCT 13
#define RANGE 14
#define ENDPAT 15
int cflag=0, fflag=0, nflag=0, vflag=0, nfile=0, debug=0;
char *pp, lbuf[LMAX], pbuf[PMAX];
char *cclass();
char *pmatch();
void store(int);
void error(char *);
void badpat(char *, char *, char *);
int match(void);
/*** Display a file name *******************************/
void file(char *s)
{
printf("File %s:\n", s);
}
/*** Report unopenable file ****************************/
void cant(char *s)
{
fprintf(stderr, "%s: cannot open\n", s);
}
/*** Give good help ************************************/
void help(char **hp)
{
char **dp;
for (dp = hp; *dp; ++dp)
printf("%s\n", *dp);
}
/*** Display usage summary *****************************/
void usage(char *s)
{
fprintf(stderr, "?GREP-E-%s\n", s);
fprintf(stderr,
"Usage: grep [-cfnv] pattern [file ...]. grep ? for help\n");
exit(1);
}
/*** Compile the pattern into global pbuf[] ************/
void compile(char *source)
{
char *s; /* Source string pointer */
char *lp; /* Last pattern pointer */
int c; /* Current character */
int o; /* Temp */
char *spp; /* Save beginning of pattern */
s = source;
if (debug)
printf("Pattern = \"%s\"\n", s);
pp = pbuf;
while (c = *s++) {
/*
* STAR, PLUS and MINUS are special.
*/
if (c == '*' || c == '+' || c == '-') {
if (pp == pbuf ||
(o=pp[-1]) == BOL ||
o == EOL ||
o == STAR ||
o == PLUS ||
o == MINUS)
badpat("Illegal occurrence op.", source, s);
store(ENDPAT);
store(ENDPAT);
spp = pp; /* Save pattern end */
while (--pp > lp) /* Move pattern down */
*pp = pp[-1]; /* one byte */
*pp = (c == '*') ? STAR :
(c == '-') ? MINUS : PLUS;
pp = spp; /* Restore pattern end */
continue;
}
/*
* All the rest.
*/
lp = pp; /* Remember start */
switch(c) {
case '^':
store(BOL);
break;
case '$':
store(EOL);
break;
case '.':
store(ANY);
break;
case '[':
s = cclass(source, s);
break;
case ':':
if (*s) {
switch(tolower(c = *s++)) {
case 'a':
case 'A':
store(ALPHA);
break;
case 'd':
case 'D':
store(DIGIT);
break;
case 'n':
case 'N':
store(NALPHA);
break;
case ' ':
store(PUNCT);
break;
default:
badpat("Unknown : type", source, s);
}
break;
}
else badpat("No : type", source, s);
case '\\':
if (*s)
c = *s++;
default:
store(CHAR);
store(tolower(c));
}
}
store(ENDPAT);
store(0); /* Terminate string */
if (debug) {
for (lp = pbuf; lp < pp;) {
if ((c = (*lp++ & 0377)) < ' ')
printf("\\%o ", c);
else printf("%c ", c);
}
printf("\n");
}
}
/*** Compile a class (within []) ***********************/
char *cclass(char *source, char *src)
/* char *source; // Pattern start -- for error msg. */
/* char *src; // Class start */
{
char *s; /* Source pointer */
char *cp; /* Pattern start */
int c; /* Current character */
int o; /* Temp */
s = src;
o = CLASS;
if (*s == '^') {
++s;
o = NCLASS;
}
store(o);
cp = pp;
store(0); /* Byte count */
while ((c = *s++) && c!=']') {
if (c == '\\') { /* Store quoted char */
if ((c = *s++) == '\0') /* Gotta get something */
badpat("Class terminates badly", source, s);
else store(tolower(c));
}
else if (c == '-' &&
(pp - cp) > 1 && *s != ']' && *s != '\0') {
c = pp[-1]; /* Range start */
pp[-1] = RANGE; /* Range signal */
store(c); /* Re-store start */
c = *s++; /* Get end char and*/
store(tolower(c)); /* Store it */
}
else {
store(tolower(c)); /* Store normal char */
}
}
if (c != ']')
badpat("Unterminated class", source, s);
if ((c = (pp - cp)) >= 256)
badpat("Class too large", source, s);
if (c == 0)
badpat("Empty class", source, s);
*cp = c;
return(s);
}
/*** Store an entry in the pattern buffer **************/
void store(int op)
{
if (pp >= &pbuf[PMAX])
error("Pattern too complex\n");
*pp++ = op;
}
/*** Report a bad pattern specification ****************/
void badpat(char *message, char *source, char *stop)
/* char *message; // Error message */
/* char *source; // Pattern start */
/* char *stop; // Pattern end */
{
fprintf(stderr, "-GREP-E-%s, pattern is\"%s\"\n", message, source);
fprintf(stderr, "-GREP-E-Stopped at byte %ld, '%c'\n",
stop-source, stop[-1]);
error("?GREP-E-Bad pattern\n");
}
/*** Scan the file for the pattern in pbuf[] ***********/
void grep(FILE *fp, char *fn)
/* FILE *fp; // File to process */
/* char *fn; // File name (for -f option) */
{
int lno, count, m;
lno = 0;
count = 0;
while (fgets(lbuf, LMAX, fp)) {
++lno;
m = match();
if ((m && !vflag) || (!m && vflag)) {
++count;
if (!cflag) {
if (fflag && fn) {
file(fn);
fn = 0;
}
if (nflag)
printf("%d\t", lno);
printf("%s\n", lbuf);
}
}
}
if (cflag) {
if (fflag && fn)
file(fn);
printf("%d\n", count);
}
}
/*** Match line (lbuf) with pattern (pbuf) return 1 if match ***/
int match()
{
char *l; /* Line pointer */
for (l = lbuf; *l; ++l) {
if (pmatch(l, pbuf))
return(1);
}
return(0);
}
/*** Match partial line with pattern *******************/
char *pmatch(char *line, char *pattern)
/* char *line; // (partial) line to match */
/* char *pattern; // (partial) pattern to match */
{
char *l; /* Current line pointer */
char *p; /* Current pattern pointer */
char c; /* Current character */
char *e; /* End for STAR and PLUS match */
int op; /* Pattern operation */
int n; /* Class counter */
char *are; /* Start of STAR match */
l = line;
if (debug > 1)
printf("pmatch(\"%s\")\n", line);
p = pattern;
while ((op = *p++) != ENDPAT) {
if (debug > 1)
printf("byte[%ld] = 0%o, '%c', op = 0%o\n",
l-line, *l, *l, op);
switch(op) {
case CHAR:
if (tolower(*l++) != *p++)
return(0);
break;
case BOL:
if (l != lbuf)
return(0);
break;
case EOL:
if (*l != '\0')
return(0);
break;
case ANY:
if (*l++ == '\0')
return(0);
break;
case DIGIT:
if ((c = *l++) < '0' || (c > '9'))
return(0);
break;
case ALPHA:
c = tolower(*l++);
if (c < 'a' || c > 'z')
return(0);
break;
case NALPHA:
c = tolower(*l++);
if (c >= 'a' && c <= 'z')
break;
else if (c < '0' || c > '9')
return(0);
break;
case PUNCT:
c = *l++;
if (c == 0 || c > ' ')
return(0);
break;
case CLASS:
case NCLASS:
c = tolower(*l++);
n = *p++ & 0377;
do {
if (*p == RANGE) {
p += 3;
n -= 2;
if (c >= p[-2] && c <= p[-1])
break;
}
else if (c == *p++)
break;
} while (--n > 1);
if ((op == CLASS) == (n <= 1))
return(0);
if (op == CLASS)
p += n - 2;
break;
case MINUS:
e = pmatch(l, p); /* Look for a match */
while (*p++ != ENDPAT); /* Skip over pattern */
if (e) /* Got a match? */
l = e; /* Yes, update string */
break; /* Always succeeds */
case PLUS: /* One or more ... */
if ((l = pmatch(l, p)) == 0)
return(0); /* Gotta have a match */
case STAR: /* Zero or more ... */
are = l; /* Remember line start */
while (*l && (e = pmatch(l, p)))
l = e; /* Get longest match */
while (*p++ != ENDPAT); /* Skip over pattern */
while (l >= are) { /* Try to match rest */
if (e = pmatch(l, p))
return(e);
--l; /* Nope, try earlier */
}
return(0); /* Nothing else worked */
default:
printf("Bad op code %d\n", op);
error("Cannot happen -- match\n");
}
}
return(l);
}
/*** Report an error ***********************************/
void error(char *s)
{
fprintf(stderr, "%s", s);
exit(1);
}
/*** Main program - parse arguments & grep *************/
int main(int argc, char **argv)
{
char *p;
int c, i;
int gotpattern;
FILE *f;
if (argc <= 1)
usage("No arguments");
if (argc == 2 && argv[1][0] == '?' && argv[1][1] == 0) {
help(documentation);
help(patdoc);
return 0;
}
nfile = argc-1;
gotpattern = 0;
for (i=1; i < argc; ++i) {
p = argv[i];
if (*p == '-') {
++p;
while (c = *p++) {
switch(tolower(c)) {
case '?':
help(documentation);
break;
case 'C':
case 'c':
++cflag;
break;
case 'D':
case 'd':
++debug;
break;
case 'F':
case 'f':
++fflag;
break;
case 'n':
case 'N':
++nflag;
break;
case 'v':
case 'V':
++vflag;
break;
default:
usage("Unknown flag");
}
}
argv[i] = 0;
--nfile;
} else if (!gotpattern) {
compile(p);
argv[i] = 0;
++gotpattern;
--nfile;
}
}
if (!gotpattern)
usage("No pattern");
if (nfile == 0)
grep(stdin, 0);
else {
fflag = fflag ^ (nfile > 0);
for (i=1; i < argc; ++i) {
if (p = argv[i]) {
if ((f=fopen(p, "r")) == NULL)
cant(p);
else {
grep(f, p);
fclose(f);
}
}
}
}
return 0;
}
/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/

View File

@ -1,3 +0,0 @@
File 46_grep.c:
/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/

View File

@ -48,80 +48,4 @@ enum rgb3 c = 42;
#elif defined test_74_non_const_init
int i = i++;
#elif defined test_pointer_assignment
void (*f1)(void);
void f2(void) {}
struct s1 *ps1;
struct s2 *ps2;
void *v1, **v2, ***v3;
enum e1 { a = 4 } e10, *e11, *e12;
enum e2 { b = -4 } e20, *e21;
enum e3 { c = 5000000000LL } e30;
int *ip;
unsigned int *up;
long *lp;
long long *llp;
char **c1;
char const **c2;
unsigned char **u1;
int no_main ()
{
// function
f1 = f2;
// struct
ps1 = ps2;
// void*
v1 = v3;
v2 = v3;
// enum
e11 = e12;
e11 = e21;
e11 = &e10;
ip = &e10;
ip = &e20;
up = &e10;
up = &e20;
up = &e30;
lp = ip;
lp = llp;
// constness
c1 = c2;
*c1 = *c2;
**c1 = **c2;
// unsigned = signed
u1 = c2;
*u1 = *c2;
**u1 = **c2;
c2 = c1;
*c2 = *c1;
**c2 = **c1;
return 0;
}
#elif defined test_enum_compat
enum e4;
enum e5;
void f3(enum e4 e);
void f3(enum e5 e);
#elif defined test_ptr_to_str
void f() { _Generic((int const *[]){0}, int:0); }
#elif defined test_fnptr_to_str
void f() { _Generic((int (*(*)(float,char))(double,int)){0}, int:0); }
#elif defined test_array_to_str
void f() { _Generic((int(*)[3]){0}, int:0); }
#endif

View File

@ -26,30 +26,3 @@
[test_74_non_const_init]
60_errors_and_warnings.c:49: error: initializer element is not constant
[test_pointer_assignment]
60_errors_and_warnings.c:79: warning: assignment from incompatible pointer type
60_errors_and_warnings.c:82: warning: assignment from incompatible pointer type
60_errors_and_warnings.c:86: warning: assignment from incompatible pointer type
60_errors_and_warnings.c:88: warning: assignment from incompatible pointer type
60_errors_and_warnings.c:91: warning: assignment from incompatible pointer type
60_errors_and_warnings.c:92: warning: assignment from incompatible pointer type
60_errors_and_warnings.c:94: warning: assignment from incompatible pointer type
60_errors_and_warnings.c:95: warning: assignment from incompatible pointer type
60_errors_and_warnings.c:98: warning: assignment discards qualifiers from pointer target type
60_errors_and_warnings.c:99: warning: assignment discards qualifiers from pointer target type
60_errors_and_warnings.c:103: warning: assignment discards qualifiers from pointer target type
60_errors_and_warnings.c:104: warning: assignment discards qualifiers from pointer target type
60_errors_and_warnings.c:109: warning: assignment of read-only location
[test_enum_compat]
60_errors_and_warnings.c:119: error: incompatible types for redefinition of 'f3'
[test_ptr_to_str]
60_errors_and_warnings.c:122: error: type 'const int **' does not match any association
[test_fnptr_to_str]
60_errors_and_warnings.c:124: error: type 'int (*(*)(float, char))(double, int)' does not match any association
[test_array_to_str]
60_errors_and_warnings.c:126: error: type 'int (*)[3]' does not match any association

View File

@ -16,25 +16,4 @@ void __attribute__((stdcall)) foo (void)
{
}
/* The actual attribute isn't important, must just be
parsable. */
#define ATTR __attribute__((__noinline__))
int ATTR actual_function() {
return 42;
}
extern int printf (const char *, ...);
int main()
{
void *function_pointer = &actual_function;
int a = ((ATTR int(*) (void)) function_pointer)();
printf("%i\n", a);
/* In the following we once misparsed 'ATTR *' is a btype
and hence the whole type was garbled. */
int b = ( (int(ATTR *)(void)) function_pointer)();
printf("%i\n", b);
return 0;
}
int main () { return 0; }

View File

@ -1,2 +0,0 @@
42
42

View File

@ -26,36 +26,6 @@ static void kb_wait_1(void)
timeout--;
} while (timeout);
}
static int global;
static void foo(int i)
{
global+=i;
printf ("g=%d\n", global);
}
static int check(void)
{
printf ("check %d\n", global);
return 1;
}
static void dowhile(void)
{
do {
foo(1);
if (global == 1) {
continue;
} else if (global == 2) {
continue;
}
/* The following break shouldn't disable the check() call,
as it's reachable by the continues above. */
break;
} while (check());
}
int main (void)
{
int i = 1;
@ -148,8 +118,5 @@ enterloop3:
printf ("error4\n");
}
}
dowhile();
return 0;
}

View File

@ -16,8 +16,3 @@ once3
twice3
caseok
caseok2
g=1
check 1
g=2
check 2
g=3

View File

@ -20,12 +20,6 @@ int b_f()
return 10;
}
typedef int (*fptr)(int);
int foo(int i)
{
return i;
}
typedef int int_type1;
#define gen_sw(a) _Generic(a, const char *: 1, default: 8, int: 123);
@ -66,50 +60,5 @@ int main()
long long: "long long"));
i = _Generic(l, long: 1, int: 2);
printf("%d\n", i);
i = _Generic(foo, fptr: 3, int: 4);
printf("%d\n", i);
(void)_Generic((int(*)[2]){0}, int(*)[2]:0, int(*)[4]:0); //shouldn't match twice
//should accept ({ }) in the controlling expr of _Generic even in const_wanted contexts
struct { _Bool x_0: _Generic(({0;}),default:1); } my_x;
_Generic((__typeof((float const)((float const){42}))*){0}, float*: 0); //casts lose top-level qualifiers
int const x = 42; __typeof((__typeof(x))x) *xp = 0; (void)_Generic(xp, int*: 0); //casts lose top-level qualifiers
//TEST TERNARY:
//Same type
_Generic( 0?(long*)0:(long*)0, long*: (void)0);
//combining of qualifiers
_Generic( 0?(long volatile*)0:(long const*)0, long const volatile*: (void)0);
//nul-ptr constant selects other type
_Generic( 0?(long*)0:0, long*: (void)0);
_Generic( 0?(long*)0:(void*)0, long*: (void)0);
//void ptrs get chosen preferentially; qualifs still combine
_Generic( 0?(int volatile*)0: (void const*)1, void volatile const*: (void)0);
//like gcc but not clang, don't treat (void* const as the null-ptr constant)
_Generic( 0?(int volatile*)0: (void const*)0, void volatile const*: (void)0);
//ptrs to incomplete types get completed
(void)(sizeof(struct { int x:_Generic( 0?(int (*)[4])0 : (int (*)[])0, int (*)[4]:+1, int (*)[5]:(void)0); }));
(void)(sizeof(struct { int x:_Generic( 0?(int (*)[])0 : (int (*)[4])0, int (*)[4]:+1, int (*)[5]:(void)0); }));
{
/* completion shouldn't affect the type of decl */
char **argv;
_Generic(argv, char**: (void)0);
_Generic(0?(char const*)0:argv[0], char const*: (void)0);
_Generic(argv, char**: (void)0);
}
{
extern int (*ar)[];
(void)(sizeof(struct { int x:_Generic( 0?(int (*)[4])0 : (int (*)[])0, int (*)[4]:+1, int (*)[5]:(void)0); }));
(void)(sizeof(struct { int x:_Generic( 0?(int (*)[])0 : (int (*)[4])0, int (*)[4]:+1, int (*)[5]:(void)0); }));
(void)(sizeof(struct { int x:_Generic( 0?ar : (int (*)[4])0, int (*)[4]:+1, int (*)[5]:(void)0); }));
(void)(sizeof(struct { int x:_Generic( 0?(int (*)[4])0 : ar, int (*)[4]:+1, int (*)[5]:(void)0); }));
(void)(sizeof(struct { int x:_Generic( 0?(int (*)[5])0 : ar, int (*)[5]:+1, int (*)[4]:(void)0); }));
}
return 0;
}

View File

@ -10,5 +10,4 @@
3
4
long
1
3
1

View File

@ -55,10 +55,11 @@ te0:;
static char ds1 = 0;
ts1:;
if (!SKIP) {
void *p = (void*)&main;
char cc[] = "static string";
double d = 8.0;
struct __attribute__((packed)) {
static void *p = (void*)&main;
static char cc[] = "static string";
static double d = 8.0;
static struct __attribute__((packed)) {
unsigned x : 12;
unsigned char y : 7;
unsigned z : 28, a: 4, b: 5;
@ -80,19 +81,4 @@ te1:;
/*printf("# %d/%d\n", dl, tl);*/
}
#elif defined test_static_data
#include <stdio.h>
int main(int argc, char **argv)
{
goto there;
if (0) {
static int a = 1;
printf("hello\n"); /* the "hello\n" string is still suppressed */
there:
printf("a = %d\n", a);
}
return 0;
}
#endif

View File

@ -21,6 +21,3 @@ size of data/text:
[test_data_suppression_on]
size of data/text:
zero/zero
[test_static_data]
a = 1

View File

@ -3,9 +3,7 @@ include $(TOP)/Makefile
SRC = $(TOPSRC)/tests/tests2
VPATH = $(SRC)
TESTS = $(patsubst %.c,%.test,\
$(sort $(notdir $(wildcard $(SRC)/??_*.c)))\
$(sort $(notdir $(wildcard $(SRC)/???_*.c))))
TESTS = $(patsubst %.c,%.test,$(sort $(notdir $(wildcard $(SRC)/*.c))))
# some tests do not pass on all platforms, remove them for now
SKIP = 34_array_assignment.test # array assignment is not in C standard

View File

@ -81,9 +81,9 @@ extern "C" {
#else
#define _fstat _fstat64i32
#define _fstati64 _fstat64
#define _stat _stat64
#define _stat _stat64i32
#define _stati64 _stat64
#define _wstat _wstat64
#define _wstat _wstat64i32
#define _wstati64 _wstat64
#endif

View File

@ -623,13 +623,20 @@ static void gcall_or_jmp(int is_jmp)
{
int r;
if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST &&
((vtop->r & VT_SYM) && (vtop->c.i-4) == (int)(vtop->c.i-4))) {
/* constant symbolic case -> simple relocation */
((vtop->r & VT_SYM) || (vtop->c.i-4) == (int)(vtop->c.i-4))) {
/* constant case */
if (vtop->r & VT_SYM) {
/* relocation case */
#ifdef TCC_TARGET_PE
greloca(cur_text_section, vtop->sym, ind + 1, R_X86_64_PC32, (int)(vtop->c.i-4));
greloca(cur_text_section, vtop->sym, ind + 1, R_X86_64_PC32, (int)(vtop->c.i-4));
#else
greloca(cur_text_section, vtop->sym, ind + 1, R_X86_64_PLT32, (int)(vtop->c.i-4));
greloca(cur_text_section, vtop->sym, ind + 1, R_X86_64_PLT32, (int)(vtop->c.i-4));
#endif
} else {
/* put an empty PC32 relocation */
put_elf_reloca(symtab_section, cur_text_section,
ind + 1, R_X86_64_PC32, 0, (int)(vtop->c.i-4));
}
oad(0xe8 + is_jmp, 0); /* call/jmp im */
} else {
/* otherwise, indirect call */
@ -870,18 +877,19 @@ void gfunc_call(int nb_args)
if (is_sse_float(vtop->type.t)) {
if (tcc_state->nosse)
tcc_error("SSE disabled");
gv(RC_XMM0); /* only use one float register */
if (arg >= REGN) {
gv(RC_XMM0);
/* movq %xmm0, j*8(%rsp) */
gen_offs_sp(0xd60f66, 0x100, arg*8);
} else {
/* Load directly to xmmN register */
gv(RC_XMM0 << arg);
/* movaps %xmm0, %xmmN */
o(0x280f);
o(0xc0 + (arg << 3));
d = arg_prepare_reg(arg);
/* mov %xmmN, %rxx */
/* mov %xmm0, %rxx */
o(0x66);
orex(1,d,0, 0x7e0f);
o(0xc0 + arg*8 + REG_VALUE(d));
o(0xc0 + REG_VALUE(d));
}
} else {
if (bt == VT_STRUCT) {
@ -981,8 +989,7 @@ void gfunc_prolog(CType *func_type)
if (reg_param_index < REGN) {
gen_modrm64(0x89, arg_regs[reg_param_index], VT_LOCAL, NULL, addr);
}
sym_push(sym->v & ~SYM_FIELD, type,
VT_LLOCAL | lvalue_type(type->t), addr);
sym_push(sym->v & ~SYM_FIELD, type, VT_LLOCAL | VT_LVAL, addr);
} else {
if (reg_param_index < REGN) {
/* save arguments passed by register */
@ -995,8 +1002,7 @@ void gfunc_prolog(CType *func_type)
gen_modrm64(0x89, arg_regs[reg_param_index], VT_LOCAL, NULL, addr);
}
}
sym_push(sym->v & ~SYM_FIELD, type,
VT_LOCAL | lvalue_type(type->t), addr);
sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | VT_LVAL, addr);
}
addr += 8;
reg_param_index++;
@ -1562,7 +1568,7 @@ void gfunc_prolog(CType *func_type)
default: break; /* nothing to be done for x86_64_mode_none */
}
sym_push(sym->v & ~SYM_FIELD, type,
VT_LOCAL | lvalue_type(type->t), param_addr);
VT_LOCAL | VT_LVAL, param_addr);
}
#ifdef CONFIG_TCC_BCHECK
@ -1633,12 +1639,6 @@ void gfunc_epilog(void)
#endif /* not PE */
ST_FUNC void gen_fill_nops(int bytes)
{
while (bytes--)
g(0x90);
}
/* generate a jump to a label */
int gjmp(int t)
{