Compare commits
20 Commits
master
...
wip-bootst
Author | SHA1 | Date |
---|---|---|
Jan Nieuwenhuizen | bb0a641cab | |
Jan Nieuwenhuizen | a41c019ff7 | |
Jan Nieuwenhuizen | 90075d68bd | |
Jan Nieuwenhuizen | 6d88f740dd | |
Jan Nieuwenhuizen | 30b55248fc | |
Jan Nieuwenhuizen | 9bcd7c0c30 | |
Jan Nieuwenhuizen | 09604d2dfa | |
Jan Nieuwenhuizen | b73113dc5c | |
Jan Nieuwenhuizen | 0389b2d219 | |
Jan Nieuwenhuizen | 1c509d5e85 | |
Jan Nieuwenhuizen | 718fb1c231 | |
Jan Nieuwenhuizen | 0ae7c6748b | |
Jan Nieuwenhuizen | abcc1e0cb2 | |
Jan Nieuwenhuizen | d12f4a449e | |
Jan Nieuwenhuizen | a02a47aa94 | |
Jan Nieuwenhuizen | c21f824ee5 | |
Jan Nieuwenhuizen | 194c97f0bd | |
Jan Nieuwenhuizen | 59ef83545d | |
Jan Nieuwenhuizen | f724254cdd | |
Jan Nieuwenhuizen | 1ad9950fb6 |
|
@ -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
|
7
Makefile
7
Makefile
|
@ -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
67
README
|
@ -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
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
|
|
18
arm-gen.c
18
arm-gen.c
|
@ -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)
|
||||
{
|
||||
|
|
14
arm64-gen.c
14
arm64-gen.c
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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"
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
10
c67-gen.c
10
c67-gen.c
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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 || :
|
||||
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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)
|
||||
|
|
54
i386-gen.c
54
i386-gen.c
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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
208
libtcc.c
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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
47
tcc.c
|
@ -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
48
tcc.h
|
@ -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);
|
||||
|
|
15
tccasm.c
15
tccasm.c
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
6
tccpe.c
6
tccpe.c
|
@ -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);
|
||||
|
|
46
tccrun.c
46
tccrun.c
|
@ -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;
|
||||
|
|
2
tcctok.h
2
tcctok.h
|
@ -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")
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
|
@ -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 $@
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 :*/
|
|
@ -1,3 +0,0 @@
|
|||
File 46_grep.c:
|
||||
/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/
|
||||
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
42
|
||||
42
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -16,8 +16,3 @@ once3
|
|||
twice3
|
||||
caseok
|
||||
caseok2
|
||||
g=1
|
||||
check 1
|
||||
g=2
|
||||
check 2
|
||||
g=3
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -10,5 +10,4 @@
|
|||
3
|
||||
4
|
||||
long
|
||||
1
|
||||
3
|
||||
1
|
|
@ -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
|
||||
|
|
|
@ -21,6 +21,3 @@ size of data/text:
|
|||
[test_data_suppression_on]
|
||||
size of data/text:
|
||||
zero/zero
|
||||
|
||||
[test_static_data]
|
||||
a = 1
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
40
x86_64-gen.c
40
x86_64-gen.c
|
@ -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)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue