diff --git a/lib/tinycc/examples/ex1.c b/lib/tinycc/examples/ex1.c new file mode 100755 index 000000000..3d2a3e18f --- /dev/null +++ b/lib/tinycc/examples/ex1.c @@ -0,0 +1,8 @@ +#!/usr/local/bin/tcc -run +#include + +int main() +{ + printf("Hello World\n"); + return 0; +} diff --git a/lib/tinycc/examples/ex2.c b/lib/tinycc/examples/ex2.c new file mode 100644 index 000000000..d415e39d7 --- /dev/null +++ b/lib/tinycc/examples/ex2.c @@ -0,0 +1,98 @@ +#include +#include + +#define N 20 + +int nb_num; +int tab[N]; +int stack_ptr; +int stack_op[N]; +int stack_res[60]; +int result; + +int find(int n, int i1, int a, int b, int op) +{ + int i, j; + int c; + + if (stack_ptr >= 0) { + stack_res[3*stack_ptr] = a; + stack_op[stack_ptr] = op; + stack_res[3*stack_ptr+1] = b; + stack_res[3*stack_ptr+2] = n; + if (n == result) + return 1; + tab[i1] = n; + } + + for(i=0;i + +int fib(n) +{ + if (n <= 2) + return 1; + else + return fib(n-1) + fib(n-2); +} + +int main(int argc, char **argv) +{ + int n; + if (argc < 2) { + printf("usage: fib n\n" + "Compute nth Fibonacci number\n"); + return 1; + } + + n = atoi(argv[1]); + printf("fib(%d) = %d\n", n, fib(n, 2)); + return 0; +} diff --git a/lib/tinycc/examples/ex4.c b/lib/tinycc/examples/ex4.c new file mode 100755 index 000000000..f92c0da9f --- /dev/null +++ b/lib/tinycc/examples/ex4.c @@ -0,0 +1,26 @@ +#!/usr/local/bin/tcc -run -L/usr/X11R6/lib -lX11 +#include +#include +#include + +/* Yes, TCC can use X11 too ! */ + +int main(int argc, char **argv) +{ + Display *display; + Screen *screen; + + display = XOpenDisplay(""); + if (!display) { + fprintf(stderr, "Could not open X11 display\n"); + exit(1); + } + printf("X11 display opened.\n"); + screen = XScreenOfDisplay(display, 0); + printf("width = %d\nheight = %d\ndepth = %d\n", + screen->width, + screen->height, + screen->root_depth); + XCloseDisplay(display); + return 0; +} diff --git a/lib/tinycc/examples/ex5.c b/lib/tinycc/examples/ex5.c new file mode 100644 index 000000000..156425e39 --- /dev/null +++ b/lib/tinycc/examples/ex5.c @@ -0,0 +1,8 @@ +#include +#include + +int main() +{ + printf("Hello World\n"); + return 0; +} diff --git a/lib/tinycc/tests/42test.h b/lib/tinycc/tests/42test.h new file mode 100644 index 000000000..5db7d1c47 --- /dev/null +++ b/lib/tinycc/tests/42test.h @@ -0,0 +1,13 @@ +/* This file is to test compute #include directives. It's named so + that it starts with a pre-processing number which isn't a valid + number (42test.h). Including this must work. */ +#ifndef INC42_FIRST +int have_included_42test_h; +#define INC42_FIRST +#elif !defined INC42_SECOND +#define INC42_SECOND +int have_included_42test_h_second; +#else +#define INC42_THIRD +int have_included_42test_h_third; +#endif diff --git a/lib/tinycc/tests/Makefile b/lib/tinycc/tests/Makefile new file mode 100644 index 000000000..26924e5fa --- /dev/null +++ b/lib/tinycc/tests/Makefile @@ -0,0 +1,349 @@ +# +# Tiny C Compiler Makefile - tests +# + +TOP = .. +include $(TOP)/Makefile +VPATH = $(TOPSRC)/tests $(TOPSRC) $(TOP) +CFLAGS := $(filter-out -g% -O%,$(CFLAGS)) -I$(TOPSRC) $(LDFLAGS) + +# what tests to run +TESTS = \ + hello-exe \ + hello-run \ + libtest \ + libtest_mt \ + test3 \ + abitest \ + asm-c-connect-test \ + vla_test-run \ + tests2-dir \ + pp-dir \ + memtest \ + dlltest \ + cross-test + +# test4_static -- Not all relocation types are implemented yet. +# asmtest / asmtest2 -- minor differences with gcc + +ifeq ($(CONFIG_backtrace),no) + TESTS := $(filter-out libtest_mt, $(TESTS)) +else ifneq ($(CONFIG_bcheck),no) + TESTS += btest test1b tccb +endif +ifeq ($(CONFIG_dll),no) + TESTS := $(filter-out dlltest, $(TESTS)) +endif +ifeq (-$(CONFIG_arm_eabi)-$(CONFIG_arm_vfp)-,-yes--) + TESTS := $(filter-out test3 test1b,$(TESTS)) +endif +ifeq (,$(filter i386 x86_64,$(ARCH))) + TESTS := $(filter-out asm-c-connect-test,$(TESTS)) +endif +ifeq ($(OS),Windows_NT) # for libtcc_test to find libtcc.dll + PATH := $(CURDIR)/$(TOP)$(if $(findstring ;,$(PATH)),;,:)$(PATH) +endif +ifdef CONFIG_OSX +LIBS += $(LINK_LIBTCC) +endif +ifeq ($(ARCH),arm) +# tcctest refers to the alignment of functions, and with thumb mode +# the low bit of code addresses selects the mode, so the "alignment" +# of functions via bit masking comes out as 1. Just disable thumb. +test.ref: CFLAGS+=-marm +endif +ifeq ($(ARCH)$(CONFIG_WIN32),i386) +# tcctest.c:get_asm_string uses a construct that is checked too strictly +# by GCC in 32bit mode when PIC is enabled. +test.ref: CFLAGS+=-fno-PIC -fno-PIE -Wl,-z,notext +endif +ifeq ($(CC_NAME),msvc) +test.ref abitest : CC = gcc +endif +ifeq ($(TARGETOS),OpenBSD) +dlltest: CFLAGS+=-fno-stack-protector +endif +ifneq (,$(filter FreeBSD NetBSD,$(TARGETOS))) + # test3 has dlsym problems + TESTS := $(filter-out test3,$(TESTS)) + TESTS += test1 +endif + +RUN_TCC = $(NATIVE_DEFINES) -run $(TOPSRC)/tcc.c $(TCCFLAGS) +DISAS = objdump -d +ifdef CONFIG_OSX +DUMPTCC = (set -x; $(TOP)/tcc -vv; otool -L $(TOP)/tcc; exit 1) +else +DUMPTCC = (set -x; $(TOP)/tcc -vv; ldd $(TOP)/tcc; exit 1) +endif + +all test : + @echo ------------ version ------------ + @$(TCC_LOCAL) -v + @$(MAKE) --no-print-directory -s clean + @$(MAKE) --no-print-directory -s -r _all + +_all : $(TESTS) + +hello-exe: ../examples/ex1.c + @echo ------------ $@ ------------ + $(TCC) $< -o hello$(EXESUF) && ./hello$(EXESUF) || $(DUMPTCC) + +hello-run: ../examples/ex1.c + @echo ------------ $@ ------------ + $(TCC) -run $< || $(DUMPTCC) + +libtes%: libtcc_tes%$(EXESUF) + @echo ------------ $@ ------------ + ./libtcc_tes$*$(EXESUF) $(TOPSRC)/tcc.c $(TCCFLAGS) $(NATIVE_DEFINES) + +libtcc_test$(EXESUF): libtcc_test.c $(LIBTCC) + $(CC) -o $@ $^ $(CFLAGS) $(LIBS) + +libtcc_test_mt$(EXESUF): libtcc_test_mt.c $(LIBTCC) + $(CC) -o $@ $^ $(CFLAGS) $(LIBS) + +%-dir: + @echo ------------ $@ ------------ + $(MAKE) -k -C $* + +# test.ref - generate using cc +test.ref: tcctest.c + $(CC) -o tcctest.gcc $< $(NATIVE_DEFINES) $(CFLAGS) -w -O0 -std=gnu99 -fno-omit-frame-pointer + ./tcctest.gcc > $@ + +# auto test +test1 test1b: tcctest.c test.ref + @echo ------------ $@ ------------ + $(TCC) $(RUN_TCC) -w -run $< > test.out1 + @diff -u test.ref test.out1 && echo "$(AUTO_TEST) OK" + +# iterated test2 (compile tcc then compile tcctest.c !) +test2 test2b: tcctest.c test.ref + @echo ------------ $@ ------------ + $(TCC) $(RUN_TCC) $(RUN_TCC) -w -run $< > test.out2 + @diff -u test.ref test.out2 && echo "$(AUTO_TEST)2 OK" + +# iterated test3 (compile tcc then compile tcc then compile tcctest.c !) +test3 test3b: tcctest.c test.ref + @echo ------------ $@ ------------ + $(TCC) $(RUN_TCC) $(RUN_TCC) $(RUN_TCC) -w -run $< > test.out3 + @diff -u test.ref test.out3 && echo "$(AUTO_TEST)3 OK" + +AUTO_TEST = Auto Test +test%b : TCCFLAGS += -b -bt1 +test%b : AUTO_TEST = Auto Bound-Test + +# binary output test +test4: tcctest.c test.ref + @echo ------------ $@ ------------ +# object + link output + $(TCC) -c -o tcctest3.o $< + $(TCC) -o tcctest3 tcctest3.o + ./tcctest3 > test3.out + @if diff -u test.ref test3.out ; then echo "Object $(AUTO_TEST) OK"; fi +# dynamic output + $(TCC) -o tcctest1 $< + ./tcctest1 > test1.out + @if diff -u test.ref test1.out ; then echo "Dynamic $(AUTO_TEST) OK"; fi +# dynamic output + bound check + $(TCC) -b -o tcctest4 $< + ./tcctest4 > test4.out + @if diff -u test.ref test4.out ; then echo "BCheck $(AUTO_TEST) OK"; fi + +test4_static: tcctest.c test.ref + @echo ------------ $@ ------------ +# static output. + $(TCC) -static -o tcctest2 $< + ./tcctest2 > test2.out + @if diff -u test.ref test2.out ; then echo "Static $(AUTO_TEST) OK"; fi + +# use tcc to create libtcc.so/.dll and the tcc(.exe) frontend and run them +dlltest: + @echo ------------ $@ ------------ + $(TCC) $(NATIVE_DEFINES) -DLIBTCC_AS_DLL $(TOPSRC)/libtcc.c $(LIBS) -shared -o libtcc2$(DLLSUF) + $(TCC) $(NATIVE_DEFINES) -DONE_SOURCE=0 $(TOPSRC)/tcc.c libtcc2$(DLLSUF) $(LIBS) -Wl,-rpath=. -o tcc2$(EXESUF) + ./tcc2$(EXESUF) $(TCCFLAGS) $(RUN_TCC) -run $(TOPSRC)/examples/ex1.c +ifeq (,$(filter Darwin WIN32,$(TARGETOS))) + @echo ------------ $@ with PIC ------------ + $(CC) $(CFLAGS) -fPIC $(NATIVE_DEFINES) -DLIBTCC_AS_DLL -c $(TOPSRC)/libtcc.c + $(TCC) libtcc.o $(LIBS) -shared -o libtcc2$(DLLSUF) + $(TCC) $(NATIVE_DEFINES) -DONE_SOURCE=0 $(TOPSRC)/tcc.c libtcc2$(DLLSUF) $(LIBS) -Wl,-rpath=. -o tcc2$(EXESUF) + ./tcc2$(EXESUF) $(TCCFLAGS) $(RUN_TCC) -run $(TOPSRC)/examples/ex1.c +endif + @rm tcc2$(EXESUF) libtcc2$(DLLSUF) + +memtest: + @echo ------------ $@ ------------ + $(CC) $(CFLAGS) $(NATIVE_DEFINES) -DMEM_DEBUG=2 $(TOPSRC)/tcc.c $(LIBS) -o memtest-tcc$(EXESUF) + ./memtest-tcc$(EXESUF) $(TCCFLAGS) $(NATIVE_DEFINES) $(TOPSRC)/tcc.c $(LIBS) + ./memtest-tcc$(EXESUF) $(TCCFLAGS) $(NATIVE_DEFINES) -run $(TOPSRC)/tcc.c $(TCCFLAGS) -w $(TOPSRC)/tests/tcctest.c + @echo OK + +# memory and bound check auto test +BOUNDS_OK = 1 4 8 10 14 16 +BOUNDS_FAIL= 2 5 6 7 9 11 12 13 15 17 18 + +btest: boundtest.c + @echo ------------ $@ ------------ + @for i in $(BOUNDS_OK); do \ + if $(TCC) -b -run $< $$i >/dev/null 2>&1 ; then \ + echo "Test $$i succeeded as expected" ; \ + else\ + echo "Failed positive test $$i" ; exit 1 ; \ + fi ;\ + done ;\ + for i in $(BOUNDS_FAIL); do \ + if $(TCC) -b -bt1 -run $< $$i >/dev/null 2>&1 ; then \ + echo "Failed negative test $$i" ; exit 1 ;\ + else\ + echo "Test $$i failed as expected" ; \ + fi ;\ + done ;\ + echo Bound-Test OK + +tccb: + @echo ------------ $@ ------------ + $(TCC) -b $(TOPSRC)/tcc.c $(TCCFLAGS) $(NATIVE_DEFINES) -o tccb1.exe + mv tccb1.exe tccb2.exe + ./tccb2.exe -b $(TOPSRC)/tcc.c $(TCCFLAGS) $(NATIVE_DEFINES) -o tccb1.exe + cmp -s tccb1.exe tccb2.exe && echo "Exe Bound-Test OK" + + +# speed test +speedtest: ex2 ex3 + @echo ------------ $@ ------------ + time ./ex2 1238 2 3 4 10 13 4 + time $(TCC) -run $(TOPSRC)/examples/ex2.c 1238 2 3 4 10 13 4 + time ./ex3 35 + time $(TCC) -run $(TOPSRC)/examples/ex3.c 35 + +weaktest: tcctest.c test.ref + @echo ------------ $@ ------------ + $(TCC) -c $< -o weaktest.tcc.o + $(CC) -c $< -o weaktest.gcc.o $(NATIVE_DEFINES) $(CFLAGS) -w -O0 -std=gnu99 -fno-omit-frame-pointer + objdump -t weaktest.tcc.o | grep ' w ' | sed -e 's/.* \([a-zA-Z0-9_]*\)$$/\1/' | LC_ALL=C sort > weaktest.tcc.o.txt + objdump -t weaktest.gcc.o | grep ' w ' | sed -e 's/.* \([a-zA-Z0-9_]*\)$$/\1/' | LC_ALL=C sort > weaktest.gcc.o.txt + diff weaktest.gcc.o.txt weaktest.tcc.o.txt && echo "Weak Auto Test OK" + +ex%: $(TOPSRC)/examples/ex%.c + $(CC) -o $@ $< $(CFLAGS) + +# tiny assembler testing +asmtest.ref: asmtest.S + $(CC) -Wa,-W -Wa,-mx86-used-note=no -o asmtest.ref.o -c asmtest.S + objdump -D asmtest.ref.o > asmtest.ref + +ifeq ($(ARCH),arm) +asmtest asmtest2: + TCC="${TCC}" ./arm-asm-testsuite.sh +else +asmtest asmtest2: asmtest.ref + @echo ------------ $@ ------------ + $(TCC) $(MAYBE_RUN_TCC) -c asmtest.S + objdump -D asmtest.o > asmtest.out + @if diff -u --ignore-matching-lines="file format" asmtest.ref asmtest.out ; then echo "ASM Auto Test OK"; fi +endif + +# test assembler with tcc compiled by itself +asmtest2: MAYBE_RUN_TCC = $(RUN_TCC) + +# Check that code generated by libtcc is binary compatible with +# that generated by CC +abitest-cc.exe: abitest.c $(LIBTCC) + $(CC) -o $@ $^ $(CFLAGS) $(LIBS) -w + +abitest-tcc.exe: abitest.c libtcc.c + $(TCC) -o $@ $^ $(NATIVE_DEFINES) $(LIBS) + +abitest-% : abitest-%.exe + @echo ------------ $@ ------------ + ./$< $(TCCFLAGS) + +abitest: abitest-cc +ifneq (-$(CONFIG_arm_eabi)-$(CONFIG_arm_vfp)-,-yes--) +abitest: abitest-tcc +endif + +vla_test$(EXESUF): vla_test.c + $(TCC) -o $@ $^ + +vla_test-run: vla_test$(EXESUF) + @echo ------------ $@ ------------ + ./vla_test$(EXESUF) + +.PHONY: abitest vla_test tccb + +asm-c-connect$(EXESUF): asm-c-connect-1.c asm-c-connect-2.c + $(TCC) -o $@ $^ + +asm-c-connect-%.o: asm-c-connect-%.c + $(TCC) -c -o $@ $< + +asm-c-connect-sep$(EXESUF): asm-c-connect-1.o asm-c-connect-2.o + $(TCC) -o $@ $^ + +asm-c-connect-test: asm-c-connect$(EXESUF) asm-c-connect-sep$(EXESUF) + @echo ------------ $@ ------------ + ./asm-c-connect$(EXESUF) > asm-c-connect.out1 && cat asm-c-connect.out1 + ./asm-c-connect-sep$(EXESUF) > asm-c-connect.out2 && cat asm-c-connect.out2 + @diff -u asm-c-connect.out1 asm-c-connect.out2 || (echo "error"; exit 1) + +# quick sanity check for cross-compilers +cross-test : tcctest.c examples/ex3.c + @echo ------------ $@ ------------ + $(foreach T,$(CROSS-TGTS),$(call CROSS-COMPILE,$T)) + +CROSS-TGTS = \ + i386 \ + i386-win32 \ + i386-OpenBSD \ + x86_64 \ + x86_64-win32 \ + x86_64-osx \ + x86_64-FreeBSD \ + x86_64-NetBSD \ + x86_64-OpenBSD \ + arm-fpa \ + arm-eabihf \ + arm-NetBSD \ + arm-wince \ + arm64 \ + arm64-osx \ + arm64-FreeBSD \ + arm64-NetBSD \ + arm64-OpenBSD \ + riscv64 \ + c67 + +define CROSS-COMPILE + @echo " . $(1)" + $(TCC) $(DEF-$1) -DTCC_CROSS_TEST -run $(TOPSRC)/tcc.c \ + -c $(if $(findstring c67,$1),$(filter %/ex3.c,$^),$<) -w $(TCCFLAGS) + +endef + +# targets for development +%.bin: %.c tcc + $(TCC) -g -o $@ $< + $(DISAS) $@ + +instr: instr.o + objdump -d instr.o + +instr.o: instr.S + $(CC) -o $@ -c $< -O2 -Wall -g + +cache: tcc_g + cachegrind ./tcc_g -o /tmp/linpack -lm bench/linpack.c + vg_annotate tcc.c > /tmp/linpack.cache.log + +# clean +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 asm-c-connect-sep + rm -f ex? tcc_g weaktest.*.txt *.def *.pdb *.obj libtcc_test_mt + @$(MAKE) -C tests2 $@ + @$(MAKE) -C pp $@ + diff --git a/lib/tinycc/tests/abitest.c b/lib/tinycc/tests/abitest.c new file mode 100644 index 000000000..5fc868a99 --- /dev/null +++ b/lib/tinycc/tests/abitest.c @@ -0,0 +1,691 @@ +#include +#include +#include +#include +#include + +// MinGW has 80-bit rather than 64-bit long double which isn't compatible with TCC or MSVC +#if defined(_WIN32) && defined(__GNUC__) +#define LONG_DOUBLE double +#define LONG_DOUBLE_LITERAL(x) x +#else +#define LONG_DOUBLE long double +#define LONG_DOUBLE_LITERAL(x) x ## L +#endif + +static int g_argc; +static char **g_argv; + +static void set_options(TCCState *s, int argc, char **argv) +{ + int i; + for (i = 1; i < argc; ++i) { + char *a = argv[i]; + if (a[0] == '-') { + if (a[1] == 'B') + tcc_set_lib_path(s, a+2); + else if (a[1] == 'I') + tcc_add_include_path(s, a+2); + else if (a[1] == 'L') + tcc_add_library_path(s, a+2); + } + } +} + +typedef int (*callback_type) (void*); + +/* + * Compile source code and call a callback with a pointer to the symbol "f". + */ +static int run_callback(const char *src, callback_type callback) { + TCCState *s; + int result; + void *ptr; + + s = tcc_new(); + if (!s) + return -1; + + set_options(s, g_argc, g_argv); + + if (tcc_set_output_type(s, TCC_OUTPUT_MEMORY) == -1) + return -1; + if (tcc_compile_string(s, src) == -1) + return -1; + if (tcc_relocate(s) == -1) + return -1; + + ptr = tcc_get_symbol(s, "f"); + if (!ptr) + return -1; + result = callback(ptr); + + tcc_delete(s); + + return result; +} + +#define STR2(x) #x +#define STR(x) STR2(x) + +#define RET_PRIMITIVE_TEST(name, type, val) \ + static int ret_ ## name ## _test_callback(void *ptr) { \ + type (*callback) (type) = (type(*)(type))ptr; \ + type x = val; \ + type y = callback(x); \ + return (y == x+x) ? 0 : -1; \ + } \ + \ + static int ret_ ## name ## _test(void) { \ + const char *src = STR(type) " f(" STR(type) " x) {return x+x;}"; \ + return run_callback(src, ret_ ## name ## _test_callback); \ + } + +RET_PRIMITIVE_TEST(int, int, 70000) +RET_PRIMITIVE_TEST(longlong, long long, 4333369356528LL) +RET_PRIMITIVE_TEST(float, float, 63.0) +RET_PRIMITIVE_TEST(double, double, 14789798.0) +RET_PRIMITIVE_TEST(longdouble, LONG_DOUBLE, LONG_DOUBLE_LITERAL(378943892.0)) + +/* + * ret_2float_test: + * + * On x86-64, a struct with 2 floats should be packed into a single + * SSE register (VT_DOUBLE is used for this purpose). + */ +typedef struct ret_2float_test_type_s {float x, y;} ret_2float_test_type; +typedef ret_2float_test_type (*ret_2float_test_function_type) (ret_2float_test_type); + +static int ret_2float_test_callback(void *ptr) { + ret_2float_test_function_type f = (ret_2float_test_function_type)ptr; + ret_2float_test_type a = {10, 35}; + ret_2float_test_type r; + r = f(a); + return ((r.x == a.x*5) && (r.y == a.y*3)) ? 0 : -1; +} + +static int ret_2float_test(void) { + const char *src = + "typedef struct ret_2float_test_type_s {float x, y;} ret_2float_test_type;" + "ret_2float_test_type f(ret_2float_test_type a) {\n" + " ret_2float_test_type r = {a.x*5, a.y*3};\n" + " return r;\n" + "}\n"; + + return run_callback(src, ret_2float_test_callback); +} + +/* + * ret_2double_test: + * + * On x86-64, a struct with 2 doubles should be passed in two SSE + * registers. + */ +typedef struct ret_2double_test_type_s {double x, y;} ret_2double_test_type; +typedef ret_2double_test_type (*ret_2double_test_function_type) (ret_2double_test_type); + +static int ret_2double_test_callback(void *ptr) { + ret_2double_test_function_type f = (ret_2double_test_function_type)ptr; + ret_2double_test_type a = {10, 35}; + ret_2double_test_type r; + r = f(a); + return ((r.x == a.x*5) && (r.y == a.y*3)) ? 0 : -1; +} + +static int ret_2double_test(void) { + const char *src = + "typedef struct ret_2double_test_type_s {double x, y;} ret_2double_test_type;" + "ret_2double_test_type f(ret_2double_test_type a) {\n" + " ret_2double_test_type r = {a.x*5, a.y*3};\n" + " return r;\n" + "}\n"; + + return run_callback(src, ret_2double_test_callback); +} + +/* + * ret_8plus2double_test: + * + * This catches a corner case in the x86_64 ABI code: the first 7 + * arguments fit into registers, the 8th doesn't, but the 9th argument + * fits into the 8th XMM register. + * + * Note that the purpose of the 10th argument is to avoid a situation + * in which gcc would accidentally put the double at the right + * address, thus causing a success message even though TCC actually + * generated incorrect code. + */ +typedef ret_2double_test_type (*ret_8plus2double_test_function_type) (double, double, double, double, double, double, double, ret_2double_test_type, double, double); + +static int ret_8plus2double_test_callback(void *ptr) { + ret_8plus2double_test_function_type f = (ret_8plus2double_test_function_type)ptr; + ret_2double_test_type a = {10, 35}; + ret_2double_test_type r; + r = f(0, 0, 0, 0, 0, 0, 0, a, 37, 38); + return ((r.x == 37) && (r.y == 37)) ? 0 : -1; +} + +static int ret_8plus2double_test(void) { + const char *src = + "typedef struct ret_2double_test_type_s {double x, y;} ret_2double_test_type;" + "ret_2double_test_type f(double x1, double x2, double x3, double x4, double x5, double x6, double x7, ret_2double_test_type a, double x8, double x9) {\n" + " ret_2double_test_type r = { x8, x8 };\n" + " return r;\n" + "}\n"; + + return run_callback(src, ret_8plus2double_test_callback); +} + +/* + * ret_mixed_test: + * + * On x86-64, a struct with a double and a 64-bit integer should be + * passed in one SSE register and one integer register. + */ +typedef struct ret_mixed_test_type_s {double x; long long y;} ret_mixed_test_type; +typedef ret_mixed_test_type (*ret_mixed_test_function_type) (ret_mixed_test_type); + +static int ret_mixed_test_callback(void *ptr) { + ret_mixed_test_function_type f = (ret_mixed_test_function_type)ptr; + ret_mixed_test_type a = {10, 35}; + ret_mixed_test_type r; + r = f(a); + return ((r.x == a.x*5) && (r.y == a.y*3)) ? 0 : -1; +} + +static int ret_mixed_test(void) { + const char *src = + "typedef struct ret_mixed_test_type_s {double x; long long y;} ret_mixed_test_type;" + "ret_mixed_test_type f(ret_mixed_test_type a) {\n" + " ret_mixed_test_type r = {a.x*5, a.y*3};\n" + " return r;\n" + "}\n"; + + return run_callback(src, ret_mixed_test_callback); +} + +/* + * ret_mixed2_test: + * + * On x86-64, a struct with two floats and two 32-bit integers should + * be passed in one SSE register and one integer register. + */ +typedef struct ret_mixed2_test_type_s {float x,x2; int y,y2;} ret_mixed2_test_type; +typedef ret_mixed2_test_type (*ret_mixed2_test_function_type) (ret_mixed2_test_type); + +static int ret_mixed2_test_callback(void *ptr) { + ret_mixed2_test_function_type f = (ret_mixed2_test_function_type)ptr; + ret_mixed2_test_type a = {10, 5, 35, 7 }; + ret_mixed2_test_type r; + r = f(a); + return ((r.x == a.x*5) && (r.y == a.y*3)) ? 0 : -1; +} + +static int ret_mixed2_test(void) { + const char *src = + "typedef struct ret_mixed2_test_type_s {float x, x2; int y,y2;} ret_mixed2_test_type;" + "ret_mixed2_test_type f(ret_mixed2_test_type a) {\n" + " ret_mixed2_test_type r = {a.x*5, 0, a.y*3, 0};\n" + " return r;\n" + "}\n"; + + return run_callback(src, ret_mixed2_test_callback); +} + +/* + * ret_mixed3_test: + * + * On x86-64, this struct should be passed in two integer registers. + */ +typedef struct ret_mixed3_test_type_s {float x; int y; float x2; int y2;} ret_mixed3_test_type; +typedef ret_mixed3_test_type (*ret_mixed3_test_function_type) (ret_mixed3_test_type); + +static int ret_mixed3_test_callback(void *ptr) { + ret_mixed3_test_function_type f = (ret_mixed3_test_function_type)ptr; + ret_mixed3_test_type a = {10, 5, 35, 7 }; + ret_mixed3_test_type r; + r = f(a); + return ((r.x == a.x*5) && (r.y2 == a.y*3)) ? 0 : -1; +} + +static int ret_mixed3_test(void) { + const char *src = + "typedef struct ret_mixed3_test_type_s {float x; int y; float x2; int y2;} ret_mixed3_test_type;" + "ret_mixed3_test_type f(ret_mixed3_test_type a) {\n" + " ret_mixed3_test_type r = {a.x*5, 0, 0, a.y*3};\n" + " return r;\n" + "}\n"; + + return run_callback(src, ret_mixed3_test_callback); +} + +/* + * reg_pack_test: return a small struct which should be packed into + * registers (Win32) during return. + */ +typedef struct reg_pack_test_type_s {int x, y;} reg_pack_test_type; +typedef reg_pack_test_type (*reg_pack_test_function_type) (reg_pack_test_type); + +static int reg_pack_test_callback(void *ptr) { + reg_pack_test_function_type f = (reg_pack_test_function_type)ptr; + reg_pack_test_type a = {10, 35}; + reg_pack_test_type r; + r = f(a); + return ((r.x == a.x*5) && (r.y == a.y*3)) ? 0 : -1; +} + +static int reg_pack_test(void) { + const char *src = + "typedef struct reg_pack_test_type_s {int x, y;} reg_pack_test_type;" + "reg_pack_test_type f(reg_pack_test_type a) {\n" + " reg_pack_test_type r = {a.x*5, a.y*3};\n" + " return r;\n" + "}\n"; + + return run_callback(src, reg_pack_test_callback); +} + +/* + * reg_pack_longlong_test: return a small struct which should be packed into + * registers (x86-64) during return. + */ +typedef struct reg_pack_longlong_test_type_s {long long x, y;} reg_pack_longlong_test_type; +typedef reg_pack_longlong_test_type (*reg_pack_longlong_test_function_type) (reg_pack_longlong_test_type); + +static int reg_pack_longlong_test_callback(void *ptr) { + reg_pack_longlong_test_function_type f = (reg_pack_longlong_test_function_type)ptr; + reg_pack_longlong_test_type a = {10, 35}; + reg_pack_longlong_test_type r; + r = f(a); + return ((r.x == a.x*5) && (r.y == a.y*3)) ? 0 : -1; +} + +static int reg_pack_longlong_test(void) { + const char *src = + "typedef struct reg_pack_longlong_test_type_s {long long x, y;} reg_pack_longlong_test_type;" + "reg_pack_longlong_test_type f(reg_pack_longlong_test_type a) {\n" + " reg_pack_longlong_test_type r = {a.x*5, a.y*3};\n" + " return r;\n" + "}\n"; + + return run_callback(src, reg_pack_longlong_test_callback); +} + +/* + * ret_6plus2longlong_test: + * + * This catches a corner case in the x86_64 ABI code: the first 5 + * arguments fit into registers, the 6th doesn't, but the 7th argument + * fits into the 6th argument integer register, %r9. + * + * Note that the purpose of the 10th argument is to avoid a situation + * in which gcc would accidentally put the longlong at the right + * address, thus causing a success message even though TCC actually + * generated incorrect code. + */ +typedef reg_pack_longlong_test_type (*ret_6plus2longlong_test_function_type) (long long, long long, long long, long long, long long, reg_pack_longlong_test_type, long long, long long); + +static int ret_6plus2longlong_test_callback(void *ptr) { + ret_6plus2longlong_test_function_type f = (ret_6plus2longlong_test_function_type)ptr; + reg_pack_longlong_test_type a = {10, 35}; + reg_pack_longlong_test_type r; + r = f(0, 0, 0, 0, 0, a, 37, 38); + return ((r.x == 37) && (r.y == 37)) ? 0 : -1; +} + +static int ret_6plus2longlong_test(void) { + const char *src = + "typedef struct reg_pack_longlong_test_type_s {long long x, y;} reg_pack_longlong_test_type;" + "reg_pack_longlong_test_type f(long long x1, long long x2, long long x3, long long x4, long long x5, reg_pack_longlong_test_type a, long long x8, long long x9) {\n" + " reg_pack_longlong_test_type r = { x8, x8 };\n" + " return r;\n" + "}\n"; + + return run_callback(src, ret_6plus2longlong_test_callback); +} + +/* + * sret_test: Create a struct large enough to be returned via sret + * (hidden pointer as first function argument) + */ +typedef struct sret_test_type_s {long long a, b, c;} sret_test_type; +typedef sret_test_type (*sret_test_function_type) (sret_test_type); + +static int sret_test_callback(void *ptr) { + sret_test_function_type f = (sret_test_function_type)(ptr); + sret_test_type x = {5436LL, 658277698LL, 43878957LL}; + sret_test_type r = f(x); + return ((r.a==x.a*35)&&(r.b==x.b*19)&&(r.c==x.c*21)) ? 0 : -1; +} + +static int sret_test(void) { + const char *src = + "typedef struct sret_test_type_s {long long a, b, c;} sret_test_type;\n" + "sret_test_type f(sret_test_type x) {\n" + " sret_test_type r = {x.a*35, x.b*19, x.c*21};\n" + " return r;\n" + "}\n"; + + return run_callback(src, sret_test_callback); +} + +/* + * one_member_union_test: + * + * In the x86-64 ABI a union should always be passed on the stack. However + * it appears that a single member union is treated by GCC as its member. + */ +typedef union one_member_union_test_type_u {int x;} one_member_union_test_type; +typedef one_member_union_test_type (*one_member_union_test_function_type) (one_member_union_test_type); + +static int one_member_union_test_callback(void *ptr) { + one_member_union_test_function_type f = (one_member_union_test_function_type)ptr; + one_member_union_test_type a, b; + a.x = 34; + b = f(a); + return (b.x == a.x*2) ? 0 : -1; +} + +static int one_member_union_test(void) { + const char *src = + "typedef union one_member_union_test_type_u {int x;} one_member_union_test_type;\n" + "one_member_union_test_type f(one_member_union_test_type a) {\n" + " one_member_union_test_type b;\n" + " b.x = a.x * 2;\n" + " return b;\n" + "}\n"; + return run_callback(src, one_member_union_test_callback); +} + +/* + * two_member_union_test: + * + * In the x86-64 ABI a union should always be passed on the stack. + */ +typedef union two_member_union_test_type_u {int x; long y;} two_member_union_test_type; +typedef two_member_union_test_type (*two_member_union_test_function_type) (two_member_union_test_type); + +static int two_member_union_test_callback(void *ptr) { + two_member_union_test_function_type f = (two_member_union_test_function_type)ptr; + two_member_union_test_type a, b; + a.x = 34; + b = f(a); + return (b.x == a.x*2) ? 0 : -1; +} + +static int two_member_union_test(void) { + const char *src = + "typedef union two_member_union_test_type_u {int x; long y;} two_member_union_test_type;\n" + "two_member_union_test_type f(two_member_union_test_type a) {\n" + " two_member_union_test_type b;\n" + " b.x = a.x * 2;\n" + " return b;\n" + "}\n"; + return run_callback(src, two_member_union_test_callback); +} + +/* + * Win64 calling convention test. + */ + +typedef struct many_struct_test_type_s {long long a, b, c;} many_struct_test_type; +typedef many_struct_test_type (*many_struct_test_function_type) (many_struct_test_type,many_struct_test_type,many_struct_test_type,many_struct_test_type,many_struct_test_type,many_struct_test_type); + +static int many_struct_test_callback(void *ptr) { + many_struct_test_function_type f = (many_struct_test_function_type)ptr; + many_struct_test_type v = {1, 2, 3}; + many_struct_test_type r = f(v,v,v,v,v,v); + return ((r.a == 6) && (r.b == 12) && (r.c == 18))?0:-1; +} + +static int many_struct_test(void) { + const char *src = + "typedef struct many_struct_test_type_s {long long a, b, c;} many_struct_test_type;\n" + "many_struct_test_type f(many_struct_test_type x1, many_struct_test_type x2, many_struct_test_type x3, many_struct_test_type x4, many_struct_test_type x5, many_struct_test_type x6) {\n" + " many_struct_test_type y;\n" + " y.a = x1.a + x2.a + x3.a + x4.a + x5.a + x6.a;\n" + " y.b = x1.b + x2.b + x3.b + x4.b + x5.b + x6.b;\n" + " y.c = x1.c + x2.c + x3.c + x4.c + x5.c + x6.c;\n" + " return y;\n" + "}\n"; + return run_callback(src, many_struct_test_callback); +} + +/* + * Win64 calling convention test. + */ + +typedef struct many_struct_test_2_type_s {int a, b;} many_struct_test_2_type; +typedef many_struct_test_2_type (*many_struct_test_2_function_type) (many_struct_test_2_type,many_struct_test_2_type,many_struct_test_2_type,many_struct_test_2_type,many_struct_test_2_type,many_struct_test_2_type); + +static int many_struct_test_2_callback(void *ptr) { + many_struct_test_2_function_type f = (many_struct_test_2_function_type)ptr; + many_struct_test_2_type v = {1,2}; + many_struct_test_2_type r = f(v,v,v,v,v,v); + return ((r.a == 6) && (r.b == 12))?0:-1; +} + +static int many_struct_test_2(void) { + const char *src = + "typedef struct many_struct_test_2_type_s {int a, b;} many_struct_test_2_type;\n" + "many_struct_test_2_type f(many_struct_test_2_type x1, many_struct_test_2_type x2, many_struct_test_2_type x3, many_struct_test_2_type x4, many_struct_test_2_type x5, many_struct_test_2_type x6) {\n" + " many_struct_test_2_type y;\n" + " y.a = x1.a + x2.a + x3.a + x4.a + x5.a + x6.a;\n" + " y.b = x1.b + x2.b + x3.b + x4.b + x5.b + x6.b;\n" + " return y;\n" + "}\n"; + return run_callback(src, many_struct_test_2_callback); +} + +/* + * Win64 calling convention test. + */ + +typedef struct many_struct_test_3_type_s {int a, b;} many_struct_test_3_type; +typedef many_struct_test_3_type (*many_struct_test_3_function_type) (many_struct_test_3_type,many_struct_test_3_type,many_struct_test_3_type,many_struct_test_3_type,many_struct_test_3_type,many_struct_test_3_type, ...); +typedef struct many_struct_test_3_struct_type { many_struct_test_3_function_type f; many_struct_test_3_function_type *f2; } many_struct_test_3_struct_type; + +static void many_struct_test_3_dummy(double d, ...) +{ + volatile double x = d; +} + +static int many_struct_test_3_callback(void *ptr) { + many_struct_test_3_struct_type s = { ptr, }; + many_struct_test_3_struct_type *s2 = &s; + s2->f2 = &s2->f; + many_struct_test_3_dummy(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, &s2); + many_struct_test_3_function_type f = *(s2->f2); + many_struct_test_3_type v = {1,2}; + many_struct_test_3_type r = (*((s2->f2=&f)+0))(v,v,v,v,v,v,1.0); + return ((r.a == 6) && (r.b == 12))?0:-1; +} + +static int many_struct_test_3(void) { + const char *src = + "typedef struct many_struct_test_3_type_s {int a, b;} many_struct_test_3_type;\n" + "many_struct_test_3_type f(many_struct_test_3_type x1, many_struct_test_3_type x2, many_struct_test_3_type x3, many_struct_test_3_type x4, many_struct_test_3_type x5, many_struct_test_3_type x6, ...) {\n" + " many_struct_test_3_type y;\n" + " y.a = x1.a + x2.a + x3.a + x4.a + x5.a + x6.a;\n" + " y.b = x1.b + x2.b + x3.b + x4.b + x5.b + x6.b;\n" + " return y;\n" + "}\n"; + return run_callback(src, many_struct_test_3_callback); +} + +/* + * stdarg_test: Test variable argument list ABI + */ + +typedef struct {long long a, b, c;} stdarg_test_struct_type; +typedef void (*stdarg_test_function_type) (int,int,int,...); + +static int stdarg_test_callback(void *ptr) { + stdarg_test_function_type f = (stdarg_test_function_type)ptr; + int x; + double y; + stdarg_test_struct_type z = {1, 2, 3}, w; + f(10, 10, 5, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, &x, + 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, &y, + z, z, z, z, z, &w); + return ((x == 55) && (y == 55) && (w.a == 5) && (w.b == 10) && (w.c == 15)) ? 0 : -1; +} + +static int stdarg_test(void) { + const char *src = + "#include \n" + "typedef struct {long long a, b, c;} stdarg_test_struct_type;\n" + "void f(int n_int, int n_float, int n_struct, ...) {\n" + " int i, ti = 0;\n" + " double td = 0.0;\n" + " stdarg_test_struct_type ts = {0,0,0}, tmp;\n" + " va_list ap;\n" + " va_start(ap, n_struct);\n" + " for (i = 0, ti = 0; i < n_int; ++i)\n" + " ti += va_arg(ap, int);\n" + " *va_arg(ap, int*) = ti;\n" + " for (i = 0, td = 0; i < n_float; ++i)\n" + " td += va_arg(ap, double);\n" + " *va_arg(ap, double*) = td;\n" + " for (i = 0; i < n_struct; ++i) {\n" + " tmp = va_arg(ap, stdarg_test_struct_type);\n" + " ts.a += tmp.a; ts.b += tmp.b; ts.c += tmp.c;" + " }\n" + " *va_arg(ap, stdarg_test_struct_type*) = ts;\n" + " va_end(ap);" + "}\n"; + return run_callback(src, stdarg_test_callback); +} + +typedef struct {long long a, b;} stdarg_many_test_struct_type; +typedef void (*stdarg_many_test_function_type) (int, int, int, int, int, + stdarg_many_test_struct_type, + int, int, ...); + +static int stdarg_many_test_callback(void *ptr) +{ + stdarg_many_test_function_type f = (stdarg_many_test_function_type)ptr; + int x; + stdarg_many_test_struct_type l = {10, 11}; + f(1, 2, 3, 4, 5, l, 6, 7, &x, 44); + return x == 44 ? 0 : -1; +} + +static int stdarg_many_test(void) +{ + const char *src = + "#include \n" + "typedef struct {long long a, b;} stdarg_many_test_struct_type;\n" + "void f (int a, int b, int c, int d, int e, stdarg_many_test_struct_type l, int f, int g, ...){\n" + " va_list ap;\n" + " int *p;\n" + " va_start (ap, g);\n" + " p = va_arg(ap, int*);\n" + " *p = va_arg(ap, int);\n" + " va_end (ap);\n" + "}\n"; + return run_callback(src, stdarg_many_test_callback); +} + +/* + * Test Win32 stdarg handling, since the calling convention will pass a pointer + * to the struct and the stdarg pointer must point to that pointer initially. + */ + +typedef struct {long long a, b, c;} stdarg_struct_test_struct_type; +typedef int (*stdarg_struct_test_function_type) (stdarg_struct_test_struct_type a, ...); + +static int stdarg_struct_test_callback(void *ptr) { + stdarg_struct_test_function_type f = (stdarg_struct_test_function_type)ptr; + stdarg_struct_test_struct_type v = {10, 35, 99}; + int x = f(v, 234); + return (x == 378) ? 0 : -1; +} + +static int stdarg_struct_test(void) { + const char *src = + "#include \n" + "typedef struct {long long a, b, c;} stdarg_struct_test_struct_type;\n" + "int f(stdarg_struct_test_struct_type a, ...) {\n" + " va_list ap;\n" + " va_start(ap, a);\n" + " int z = va_arg(ap, int);\n" + " va_end(ap);\n" + " return z + a.a + a.b + a.c;\n" + "}\n"; + return run_callback(src, stdarg_struct_test_callback); +} + +/* Test that x86-64 arranges the stack correctly for arguments with alignment >8 bytes */ + +typedef LONG_DOUBLE (*arg_align_test_callback_type) (LONG_DOUBLE,int,LONG_DOUBLE,int,LONG_DOUBLE); + +static int arg_align_test_callback(void *ptr) { + arg_align_test_callback_type f = (arg_align_test_callback_type)ptr; + long double x = f(12, 0, 25, 0, 37); + return (x == 74) ? 0 : -1; +} + +static int arg_align_test(void) { + const char *src = + "long double f(long double a, int b, long double c, int d, long double e) {\n" + " return a + c + e;\n" + "}\n"; + return run_callback(src, arg_align_test_callback); +} + +#define RUN_TEST(t) \ + if (!testname || (strcmp(#t, testname) == 0)) { \ + fputs(#t "... ", stdout); \ + fflush(stdout); \ + if (t() == 0) { \ + fputs("success\n", stdout); \ + } else { \ + fputs("failure\n", stdout); \ + retval = EXIT_FAILURE; \ + } \ + } + +int main(int argc, char **argv) { + int i; + const char *testname = NULL; + int retval = EXIT_SUCCESS; + + /* if tcclib.h and libtcc1.a are not installed, where can we find them */ + for (i = 1; i < argc; ++i) { + if (!memcmp(argv[i], "run_test=", 9)) + testname = argv[i] + 9; + } + + g_argv = argv, g_argc = argc; + + RUN_TEST(ret_int_test); + RUN_TEST(ret_longlong_test); + RUN_TEST(ret_float_test); + RUN_TEST(ret_double_test); + RUN_TEST(ret_longdouble_test); + RUN_TEST(ret_2float_test); + RUN_TEST(ret_2double_test); + RUN_TEST(ret_8plus2double_test); + RUN_TEST(ret_6plus2longlong_test); +#if !defined __x86_64__ || defined _WIN32 + /* currently broken on x86_64 linux */ + RUN_TEST(ret_mixed_test); + RUN_TEST(ret_mixed2_test); +#endif + RUN_TEST(ret_mixed3_test); + RUN_TEST(reg_pack_test); + RUN_TEST(reg_pack_longlong_test); + RUN_TEST(sret_test); + RUN_TEST(one_member_union_test); + RUN_TEST(two_member_union_test); + RUN_TEST(many_struct_test); + RUN_TEST(many_struct_test_2); + RUN_TEST(many_struct_test_3); + RUN_TEST(stdarg_test); + RUN_TEST(stdarg_many_test); + RUN_TEST(stdarg_struct_test); + RUN_TEST(arg_align_test); + return retval; +} diff --git a/lib/tinycc/tests/arm-asm-testsuite.sh b/lib/tinycc/tests/arm-asm-testsuite.sh new file mode 100755 index 000000000..61c5dadba --- /dev/null +++ b/lib/tinycc/tests/arm-asm-testsuite.sh @@ -0,0 +1,243 @@ +#!/bin/sh + +set -e + +# Note: "{r3}" is definitely different--but would complicate the assembler. + +state="`mktemp -d`" +cat ../arm-tok.h | \ + grep DEF_ASM | \ + grep -v 'not useful' | \ + grep -v '#define' | \ + grep -v '/[*]' | \ + grep -v 'DEF_ASM_CONDED_WITH_SUFFIX(x' | \ + sed -e 's;^[ ]*DEF_ASM_CONDED_VFP_F32_F64[^(]*(\(.*\)).*$; DEF_ASM_CONDED(\1.f32)\ + DEF_ASM_CONDED(\1.f64);g' | \ + sed -e 's;^[ ]*DEF_ASM[^(]*(\(.*\)).*$;\1;g' -e 's;, ;.;g' | \ + egrep -v '^((r|c|p|s|d)[0-9]+|fp|ip|sp|lr|pc|asl|apsr_nzcv|fpsid|fpscr|fpexc)$' | while read s +do + as_opts="" + if [ "${s#v}" != "${s}" ] + then + if grep -q "CONFIG_arm_vfp=yes" ../config.mak + then + as_opts="${as_opts} -mfpu=vfp" + else + echo "note: skipping VFP instruction: $s (because VFP is disabled)">&2 + continue + fi + fi + ok=0 + for args in "r3, r4, r5, r6" \ + "r3, r4, r5" \ + "r3, r4, r5, asl #7" \ + "r3, r4, r5, lsl #7" \ + "r3, r4, r5, asr #7" \ + "r3, r4, r5, lsr #7" \ + "r3, r4, r5, ror #7" \ + "r3, r4, r5, rrx" \ + "r3, r4, r5, asl r6" \ + "r3, r4, r5, lsl r6" \ + "r3, r4, r5, asr r6" \ + "r3, r4, r5, lsr r6" \ + "r3, r4, r5, ror r6" \ + "r3, r4, #5, asl #7" \ + "r3, r4, #5, lsl #7" \ + "r3, r4, #5, asr #7" \ + "r3, r4, #5, lsr #7" \ + "r3, r4, #5, ror #7" \ + "r3, r4, #5, rrx" \ + "r3, #5, r4" \ + "r3, #4, #8" \ + "r3, r4, asl #5" \ + "r3, r4, lsl #5" \ + "r3, r4, asr #5" \ + "r3, r4, lsr #5" \ + "r3, r4, ror #5" \ + "r3, r4, ror #8" \ + "r3, r4, asl r5" \ + "r3, r4, lsl r5" \ + "r3, r4, asr r5" \ + "r3, r4, lsr r5" \ + "r3, r4, ror r5" \ + "r3, r4, ror #8" \ + "r3, r4, ror #16" \ + "r3, r4, ror #24" \ + "r3, r4, rrx" \ + "r3, #4, asl #5" \ + "r3, #4, lsl #5" \ + "r3, #4, asr #5" \ + "r3, #4, lsr #5" \ + "r3, #4, ror #5" \ + "r3, r4, rrx" \ + "r3, r4" \ + "r3" \ + "{r3,r4,r5}" \ + "{r3,r5,r4}" \ + "r2!, {r3,r4,r5}" \ + "r2!, {r3,r5,r4}" \ + "r2, {r3,r4,r5}" \ + "r2, {r3,r5,r4}" \ + "r2, [r3, r4]" \ + "r2, [r3, r4]!" \ + "r2, [r3, -r4]" \ + "r2, [r3, -r4]!" \ + "r2, [r3], r4" \ + "r2, [r3], -r4" \ + "r2, [r3]" \ + "r2, r3, [r4, lsl# 2]" \ + "r2, [r3, r4, lsr# 1]" \ + "r2, [r3, r4, lsr# 2]!" \ + "r2, [r3, -r4, ror# 3]" \ + "r2, [r3, -r4, lsl# 1]!" \ + "r2, [r3], r4, lsl# 3" \ + "r2, [r3], -r4, asr# 31" \ + "r2, [r3], -r4, asl# 1" \ + "r2, [r3], -r4, rrx" \ + "r2, [r3]" \ + "r2, r3, [r4]" \ + "r2, [r3, #4]" \ + "r2, [r3, #-4]" \ + "r2, [r3, #0x45]" \ + "r2, [r3, #-0x45]" \ + "r2, r3, #4" \ + "r2, r3, #-4" \ + "p10, #7, c2, c0, c1, #4" \ + "p10, #7, r2, c0, c1, #4" \ + "p10, #0, c2, c0, c1, #4" \ + "p10, #0, r2, c0, c1, #4" \ + "r2, #4" \ + "r2, #-4" \ + "r2, #0xEFFF" \ + "r3, #0x0000" \ + "r4, #0x0201" \ + "r4, #0xFFFFFF00" \ + "r2, #-4" \ + "p10, #7, c2, c0, c1, #4" \ + "p10, #7, r2, c0, c1, #4" \ + "#4" \ + "#-4" \ + "p5, c2, [r3]" \ + "p5, c3, [r4]" \ + "p5, c2, [r3, #4]" \ + "p5, c2, [r3, #-4]" \ + "p5, c2, [r3, #0x45]" \ + "p5, c2, [r3, #-0x45]" \ + "s2, [r3]" \ + "s3, [r4]" \ + "s2, [r3, #4]" \ + "s2, [r3, #-4]" \ + "s2, [r3, #0x45]" \ + "s2, [r3, #-0x45]" \ + "r1, {d3-d4}" \ + "r1!, {d3-d4}" \ + "r2, {d4-d15}" \ + "r3!, {d4-d15}" \ + "r3!, {d4}" \ + "r2, {s4-s31}" \ + "r3!, {s4}" \ + "{d3-d4}" \ + "{d4-d15}" \ + "{d4}" \ + "{s4-s31}" \ + "{s4}" \ + "s2, s3, s4" \ + "s2, s3" \ + "d2, d3, d4" \ + "d2, d3" \ + "s2, #0" \ + "d2, #0" \ + "s3, #0.0" \ + "d3, #0.0" \ + "s4, #-0.1796875" \ + "d4, #0.1796875" \ + "r2, r3, d1" \ + "d1, r2, r3" \ + "s1, r2" \ + "r2, s1" \ + "r2, fpexc" \ + "r2, fpscr" \ + "r2, fpsid" \ + "apsr_nzcv, fpscr" \ + "fpexc, r2" \ + "fpscr, r2" \ + "fpsid, r2" \ + "s3, d4" \ + "d4, s3" \ + "" + do + #echo ".syntax unified" > a.s + err="`mktemp --suffix=-stderr.log`" + as_object="${state}/as-$s $args.o" + tcc_object="${state}/tcc-$s $args.o" + expected="${state}/expected-$s $args" + got="${state}/got-$s $args" + if echo "$s $args" | "${CROSS_COMPILE}as" -mlittle-endian ${as_opts} -o "${as_object}" - 2>"${err}" + then + cat "${err}" + rm -f "${err}" + total_count=`expr $total_count + 1` + "${CROSS_COMPILE}objdump" -S "${as_object}" |grep "^[ ]*0:" >"${expected}" + + #echo '__asm__("'"$s ${args}"'");' > "${csource}" + if echo '__asm__("'"$s ${args}"'");'| ${TCC} -o "${tcc_object}" -c - + then + "${CROSS_COMPILE}objdump" -S "${tcc_object}" |grep "^[ ]*0:" >"${got}" + if diff -u "${got}" "${expected}" + then + touch "${state}/ok-$s $args" + else + echo "warning: '$s $args' did not work in tcc (see above)">&2 + fi + else + rm -f "${tcc_object}" + echo "warning: '$s $args' did not work in tcc">&2 + fi + ok=1 + else # GNU as can't do it either--so we don't care + rm -f "${as_object}" + fi + rm -f "${err}" + done + if [ "${ok}" -eq "0" ] + then + echo "warning: $s could not be used.">&2 + continue + fi +done + +successful_count="$(ls -1 "${state}/ok-"* |wc -l)" +total_count="$(ls -1 "${state}/as-"*.o |wc -l)" +echo "${successful_count} of ${total_count} tests succeeded.">&2 +if [ "${successful_count}" -eq "${total_count}" ] +then + rm -rf "${state}" + exit 0 +else + status=0 + for s in "${state}/as-"*.o + do + test="$(basename "$s")" + test="${test%.o}" + test="${test#as-}" + t="${state}/ok-${test}" + if [ ! -f "$t" ] + then + case "${test}" in + "bl r3"|"b r3"|"mov r2, #0xEFFF"|"mov r4, #0x0201") + known_failure=" (known failure)" + ;; + "vmov.f32 r2, r3, d1"|"vmov.f32 d1, r2, r3") # GNU as bug + known_failure=" (known failure)" + ;; + *) + known_failure="" + status=1 + ;; + esac + echo "Failed test: ${test}${known_failure}">&2 + fi + done + rm -rf "${state}" + exit "${status}" +fi diff --git a/lib/tinycc/tests/asm-c-connect-1.c b/lib/tinycc/tests/asm-c-connect-1.c new file mode 100644 index 000000000..90f59c83b --- /dev/null +++ b/lib/tinycc/tests/asm-c-connect-1.c @@ -0,0 +1,69 @@ +#include + +#if (defined _WIN32 || defined __APPLE__) && (!defined __TINYC__ || defined __leading_underscore) +# define _ "_" +#else +# define _ +#endif + +#ifdef __clang__ +/* clang needs some help tp not throw functions away even at -O0 */ +#define __USED __attribute__((__used__)) +#else +#define __USED +#endif + +static int __USED x1_c (void) +{ + printf(" x1"); + return 1; +} + +#if __i386__ +asm(".text;"_"x1: call "_"x1_c; ret"); +#else +/* Keep stack aligned */ +asm(".text;"_"x1: sub $8,%rsp; call "_"x1_c; add $8,%rsp; ret"); +#endif + +void callx4(void); +void callx5_again(void); + +void x6() +{ + printf(" x6-1"); +} + +int main(int argc, char *argv[]) +{ + printf("*"); + asm("call "_"x1"); + asm("call "_"x2"); + asm("call "_"x3"); + callx4(); + asm("call "_"x5"); + callx5_again(); + x6(); + printf(" *\n"); + return 0; +} + +static +int __USED x2(void) +{ + printf(" x2"); + return 2; +} + +extern int x3(void); + +void x4(void) +{ + printf(" x4"); +} + +void x5(void); +void x5(void) +{ + printf(" x5"); +} diff --git a/lib/tinycc/tests/asm-c-connect-2.c b/lib/tinycc/tests/asm-c-connect-2.c new file mode 100644 index 000000000..654db0e33 --- /dev/null +++ b/lib/tinycc/tests/asm-c-connect-2.c @@ -0,0 +1,48 @@ +#include + +#if (defined _WIN32 || defined __APPLE__) && (!defined __TINYC__ || defined __leading_underscore) +# define _ "_" +#else +# define _ +#endif + +#ifdef __clang__ +/* clang needs some help tp not throw functions away even at -O0 */ +#define __USED __attribute__((__used__)) +#else +#define __USED +#endif + +int x3(void) +{ + printf(" x3"); + return 3; +} + +/* That callx4 is defined globally (as if ".globl callx4") + is a TCC extension. GCC doesn't behave like this. */ +void callx4(void); +#if __i386__ +__asm__(_"callx4: call "_"x4; ret;" +#else +/* Keep stack aligned */ +__asm__(_"callx4: sub $8,%rsp; call "_"x4; add $8,%rsp; ret;" +#endif +#ifndef __TINYC__ + " .global "_"callx4" +#endif +); + +extern void x5(void); + +void callx5_again(void); +void callx5_again(void) +{ + x5(); + asm("call "_"x6"); +} + +static void __USED x6() +{ + printf(" x6-2"); +} diff --git a/lib/tinycc/tests/asmtest.S b/lib/tinycc/tests/asmtest.S new file mode 100644 index 000000000..7f31ce59b --- /dev/null +++ b/lib/tinycc/tests/asmtest.S @@ -0,0 +1,1025 @@ +# gas comment with ``gnu'' style quotes + +/* some directive tests */ + + .byte 0xff + .byte 1, 2, 3 + .short 1, 2, 3 + .word 1, 2, 3 + .long 1, 2, 3 + .int 1, 2, 3 + .align 8 + .byte 1 +/* .align 16, 0x90 gas is too clever for us with 0x90 fill */ + .balign 4, 0x92 + .align 16, 0x91 /* 0x91 tests the non-clever behaviour */ + .skip 3 + .skip 15, 0x90 + .string "hello\0world" +/* Macro expansion should work like with C, the #n shouldn't be parsed + as asm line comment */ +#define __stringify(n) #n +#define stringify(n) __stringify(n) + .skip 8,0x90 + .asciz stringify(BLA) + .skip 8,0x90 + +# 28 "asmtest.S" # a line directive (and a line comment) + movl %eax, %ebx # some more asm comment +/* some label tests */ +L1: + movl %eax, %ebx + mov 0x10000, %eax +L2: + movl $L2 - L1, %ecx +var1: + nop ; nop ; nop ; nop + + mov var1, %eax + +/* instruction tests */ +movl %eax, %ebx +mov 0x10000, %eax +mov 0x10000, %ax +mov 0x10000, %al +mov %al, 0x10000 + +mov $1, %edx +mov $1, %dx +mov $1, %cl +movb $2, 0x100(%ebx,%edx,2) +movw $2, 0x100(%ebx,%edx,2) +movl $2, 0x100(%ebx,%edx,2) +movl %eax, 0x100(%ebx,%edx,2) +movl 0x100(%ebx,%edx,2), %edx +movw %ax, 0x100(%ebx,%edx,2) + +movw $0x1122,%si +movl $0x112233,%edx +movl $0x80000000, %esi +movl $-0x7fffffff, %edi +#ifdef __x86_64__ +mov $0x11223344,%rbx +movq $0x11223344,%rbx +mov $0x1122334455,%rbx +movq $0x1122334455,%rbx +movl $0x11334455,(%rbx) +#endif + +mov %eax, 0x12(,%edx,2) + +#ifdef __i386__ +mov %cr3, %edx +mov %ecx, %cr3 +movl %cr3, %eax +movl %tr3, %eax +movl %db3, %ebx +movl %dr6, %eax +#else +mov %cr3, %rdx +mov %rcx, %cr3 +movq %cr3, %rax +movq %db3, %rbx +movq %dr6, %rax +mov %cr8, %rsi +mov %rdi, %cr8 +#endif +movl %fs, %ecx +movl %ebx, %fs + +#ifdef __x86_64__ +movq %r8, %r9 +movq %r10, %r11 +movq %r12, %r13 +movq %r14, %r15 +movq %rax, %r9 +movq %r15, %rsi +inc %r9b +dec %r10w +not %r11d +negq %r12 +decb %r13b +incw %r14w +notl %r15d +#endif + + movsbl 0x1000, %eax + movsbw 0x1000, %ax + movswl 0x1000, %eax + + movzbl 0x1000, %eax + movzbw 0x1000, %ax + movzwl 0x1000, %eax + + movzb 0x1000, %eax + movzb 0x1000, %ax + + mov $0x12345678,%eax + +#ifdef __x86_64__ + movzb 0x1000, %rax + movzbq 0x1000, %rbx + movsbq 0x1000, %rdx + movzwq 0x1000, %rdi + movswq 0x1000, %rdx + movslq %eax, %rcx + mov $0x12345678,%rax + mov $0x12345678,%rdx + mov $0x12345678,%r10 + mov $0x123456789abcdef0,%rax + mov $0x123456789abcdef0,%rcx + mov $0x123456789abcdef0,%r11 +#endif + +#ifdef __i386__ + pushl %eax + push %eax + push %cs +#else + pushq %rax + push %rax +#endif + pushw %ax + push %gs + push $1 + push $100 + push 0x42(%eax) + pop 0x43(%esi) + +#ifdef __i386__ + popl %eax + pop %eax + pop %ds +#else + popq %rax + pop %rax +#endif + popw %ax + pop %fs + + xchg %eax, %ecx + xchg %edx, %eax + xchg %bx, 0x10000 + xchg 0x10000, %ebx + xchg 0x10000, %dl + + in $100, %al + in $100, %ax + in $100, %eax + in %dx, %al + in %dx, %ax + in %dx, %eax + inb %dx + inw %dx + inl %dx + + out %al, $100 + out %ax, $100 + out %eax, $100 + + /* NOTE: gas is bugged here, so size must be added */ + outb %al, %dx + outw %ax, %dx + outl %eax, %dx + + leal 0x1000(%ebx), %ecx + lea 0x1000(%ebx), %ecx + +#ifdef __i386__ + les 0x2000, %eax + lds 0x2000, %ebx + lss 0x2000, %edx +#endif + lfs 0x2000, %ecx + lgs 0x2000, %edx + +addl $0x123, %eax +add $0x123, %ebx +add $-16, %ecx +add $-0x123, %esi +add $1, %bx +add $1, %ebx +add $-1, %bx +add $-1, %ebx +add $127, %bx +addl $127, %ebx +addl $-128, %ebx +addl $-128, %ebx +addl $-129, %ebx +addl $128, %ebx +addl $255, %ebx +addl $256, %ebx +andb $0xf, %ah +andb $-15, %cl +xorb $127, %dh +cmpb $42, (%eax) +addl $0x123, 0x100 +addl $0x123, 0x100(%ebx) +addl $0x123, 0x100(%ebx,%edx,2) +addl $0x123, 0x100(%esp) +addl $0x123, (3*8)(%esp) +addl $0x123, (%ebp) +addl $0x123, (%esp) +cmpl $0x123, (%esp) + +#ifdef __x86_64__ +xor %bl,%ah +xor %bl,%r8b +xor %r9b,%bl +xor %sil,%cl +add %eax,(%r8d) +add %ebx,(%r9) +add %edx,(%r10d,%r11d) +add %ecx,(%r12,%r13) +add %esi,(%r14,%r15,4) +add %edi,0x1000(%rbx,%r12,8) +add %r11,0x1000(%ebp,%r9d,8) +movb $12, %ah +movb $13, %bpl +movb $14, %dil +movb $15, %r12b +#endif + +add %eax, (%ebx) +add (%ebx), %eax + +or %dx, (%ebx) +or (%ebx), %si + +add %cl, (%ebx) +add (%ebx), %dl + + inc %edx + incl 0x10000 + incb 0x10000 + dec %dx + + test $1, %al + test $1, %cl + + testl $1, 0x1000 + testb $1, 0x1000 + testw $1, 0x1000 + test %eax, %ebx + test %eax, 0x1000 + test 0x1000, %edx + + not %edx + notw 0x10000 + notl 0x10000 + notb 0x10000 + + neg %edx + negw 0x10000 + negl 0x10000 + negb 0x10000 + + imul %ecx + mul %edx + mulb %cl + + imul %eax, %ecx + imul 0x1000, %cx + imul $10, %eax, %ecx + imul $10, %ax, %cx + imul $10, %eax + imul $0x1100000, %eax + imul $1, %eax + + idivw 0x1000 + div %ecx + div %bl + div %ecx, %eax + +and $15,%bx +and $-20,%edx + +shl %edx +shl $10, %edx +shl %cl, %edx + +shld $1, %eax, %edx +shld %cl, %eax, %edx +shld %eax, %edx + +shrd $1, %eax, %edx +shrd %cl, %eax, %edx +shrd %eax, %edx + +L4: +call 0x1000 +call L4 +#ifdef __i386__ +call *%eax +#else +call *%rax +#endif +call *0x1000 +call func1 + +.global L5,L6 + +L5: +L6: + +#ifdef __i386__ +lcall $0x100, $0x1000 +#else +lcall *0x100 +lcall *(%rax) +#endif + +jmp 0x1000 +jmp *(%edi) +#ifdef __i386__ +jmp *%eax +#else +jmp *%rax +#endif +jmp *0x1000 + +#ifdef __i386__ +ljmp $0x100, $0x1000 +#else +ljmp *0x100 +ljmp *(%rdi) +ljmpl *(%esi) +ljmpw *(%esi) +#endif + +ret +ret $10 +#ifdef __i386__ +retl +retl $10 +#else +retq +retq $10 +#endif + +lret + +lret $10 + +enter $1234, $10 + +L3: + jo 0x1000 + jnp 0x1001 + jne 0x1002 + jg 0x1003 + + jo L3 + jnp L3 + jne L3 + jg L3 + + loopne L3 + loopnz L3 + loope L3 + loopz L3 + loop L3 + jecxz L3 + + + seto %al + setc %al + setcb %al + setnp 0x1000 + setl 0xaaaa + setg %dl + + fadd + fadd %st(1), %st + fadd %st(0), %st(1) + fadd %st(3) + + fmul %st(0),%st(0) + fmul %st(0),%st(1) + + faddp %st(5) + faddp + faddp %st(1), %st + + fadds 0x1000 + fiadds 0x1002 + faddl 0x1004 + fiaddl 0x1006 + + fmul + fmul %st(1), %st + fmul %st(3) + + fmulp %st(5) + fmulp + fmulp %st(1), %st + + fmuls 0x1000 + fimuls 0x1002 + fmull 0x1004 + fimull 0x1006 + + fsub + fsub %st(1), %st + fsub %st(3) + + fsubp %st(5) + fsubp + //fsubp %st(1), %st # not accepted by new GAS anymore + + fsubs 0x1000 + fisubs 0x1002 + fsubl 0x1004 + fisubl 0x1006 + + fsubr + fsubr %st(1), %st + fsubr %st(3) + + fsubrp %st(5) + fsubrp + //fsubrp %st(1), %st # not accepted by new GAS anymore + + fsubrs 0x1000 + fisubrs 0x1002 + fsubrl 0x1004 + fisubrl 0x1006 + + fdiv + fdiv %st(1), %st + fdiv %st(3) + + fdivp %st(5) + fdivp + //fdivp %st(1), %st # not accepted by new GAS anymore + + fdivs 0x1000 + fidivs 0x1002 + fdivl 0x1004 + fidivl 0x1006 + + fcom %st(3) + + fcoms 0x1000 + ficoms 0x1002 + fcoml 0x1004 + ficoml 0x1006 + + fcomp %st(5) + fcomp + fcompp + + fcomps 0x1000 + ficomps 0x1002 + fcompl 0x1004 + ficompl 0x1006 + + fld %st(5) + fldl 0x1000 + flds 0x1002 + fildl 0x1004 + fst %st(4) + fstp %st(6) + fstpt 0x1006 + fbstp 0x1008 + + fxch + fxch %st(4) + + fucom %st(6) + fucomp %st(3) + fucompp + + finit + fninit + fldcw 0x1000 + fnstcw 0x1002 + fstcw 0x1002 + fnstsw 0x1004 + fnstsw (%eax) + fstsw 0x1004 + fstsw (%eax) + fnclex + fclex + fnstenv 0x1000 + fstenv 0x1000 + fldenv 0x1000 + fnsave 0x1002 + fsave 0x1000 + frstor 0x1000 + ffree %st(7) + ffreep %st(6) + + ftst + fxam + fld1 + fldl2t + fldl2e + fldpi + fldlg2 + fldln2 + fldz + + f2xm1 + fyl2x + fptan + fpatan + fxtract + fprem1 + fdecstp + fincstp + fprem + fyl2xp1 + fsqrt + fsincos + frndint + fscale + fsin + fcos + fchs + fabs + fnop + fwait + +bswap %edx +bswapl %ecx +xadd %ecx, %edx +xaddb %dl, 0x1000 +xaddw %ax, 0x1000 +xaddl %eax, 0x1000 +cmpxchg %ecx, %edx +cmpxchgb %dl, 0x1000 +cmpxchgw %ax, 0x1000 +cmpxchgl %eax, 0x1000 +invlpg 0x1000 +cmpxchg8b 0x1002 +#ifdef __x86_64__ +cmpxchg16b (%rax) +cmpxchg16b (%r10,%r11) +#endif + +fcmovb %st(5), %st +fcmove %st(5), %st +fcmovbe %st(5), %st +fcmovu %st(5), %st +fcmovnb %st(5), %st +fcmovne %st(5), %st +fcmovnbe %st(5), %st +fcmovnu %st(5), %st +fcomi %st(5), %st +fucomi %st(5), %st +fcomip %st(5), %st +fucomip %st(5), %st + + + + cmovo 0x1000, %eax + cmovs 0x1000, %eax + cmovns %edx, %edi + cmovne %ax, %si + cmovbw %ax, %di + cmovnbel %edx, %ecx +#ifdef __x86_64__ + bswapq %rsi + bswapq %r10 + cmovz %rdi,%rbx + cmovpeq %rsi, %rdx +#endif + +int $3 +int $0x10 + +#ifdef __i386__ + pusha + popa +#endif + clc # another comment + cld # a comment with embedded ' tick + cli + clts + cmc + lahf + sahf +#ifdef __i386__ + pushfl + popfl +#else + pushfq + popfq +#endif + pushf + popf + stc + std + sti +#ifdef __i386__ + aaa + aas + daa + das + aad + aam + into +#endif + cbw + cwd + cwde + cdq + cbtw + cwtd + cwtl + cltd + leave + int3 + iret + iretw + iretl +#ifdef __x86_64__ + iretq +#endif + rsm + hlt + wait + nop + vmcall + vmlaunch + vmresume + vmxoff + + /* XXX: handle prefixes */ +#if 0 + aword + addr16 +#endif + lock + rep + repe + repz + repne + repnz + nop + + lock ;negl (%eax) + wait ;pushf + rep ;stosb + repe ;lodsb + repz ;cmpsb + repne;movsb + repnz;outsb + + /* handle one-line prefix + ops */ + lock negl (%eax) + wait pushf + rep stosb + repe lodsb + repz cmpsb + repne movsb + repnz outsb + + invd + wbinvd + cpuid + wrmsr + rdtsc + rdmsr + rdpmc + ud2 +#ifdef __x86_64__ + syscall + sysret + sysretq + lfence + mfence + sfence + prefetchnta 0x18(%rdx) + prefetcht0 (%rcx) + prefetcht1 (%rsi) + prefetcht2 (%rdi) + prefetchw (%rdi) + clflush 0x1000(%rax,%rcx) + fxsaveq (%rdx) + fxsaveq (%r11) + fxrstorq (%rcx) + fxrstorq (%r10) + movnti %ebx, (%rdi) + movntil %ecx, (%rdi) + movnti %rax, (%rdi) + movntiq %r8, (%rdi) + +#endif + + lar %ax,%dx + lar %eax,%dx + lar %ax,%edx + lar %eax,%edx +#ifdef __x86_64__ + lar %ax,%rdx + lar %eax,%rdx +#endif + emms + movd %edx, %mm3 + movd 0x1000, %mm2 + movd %mm4, %ecx + movd %mm5, 0x1000 + + movq 0x1000, %mm2 + movq %mm4, 0x1000 + + pand 0x1000, %mm3 + pand %mm4, %mm5 + + psllw $1, %mm6 + psllw 0x1000, %mm7 + psllw %mm2, %mm7 + + xlat + cmpsb + scmpw + insl + outsw + lodsb + slodl + movsb + movsl + smovb + scasb + sscaw + stosw + sstol + + bsf 0x1000, %ebx + bsr 0x1000, %ebx + bt %edx, 0x1000 + btl $2, 0x1000 + btc %edx, 0x1000 + btcl $2, 0x1000 + btr %edx, 0x1000 + btrl $2, 0x1000 + bts %edx, 0x1000 + btsl $2, 0x1000 + + popcnt %ax, %si + popcntw %ax, %si + popcnt 0x1000, %edx + popcntl 0x1000, %edx +#ifdef __x86_64__ + popcnt %rbx, %rdi + popcntq %rcx, %r8 +#endif + + lzcnt %cx, %ax + lzcntw %cx, %ax + lzcnt %edx, %ebx + lzcntl 8(%edi), %ecx +#ifdef __x86_64__ + lzcnt %rdi, %rdx + lzcntq %r12, %r15 + lzcnt 0x40(%rcx), %r11 + lzcntq (%r8), %rsi +#endif + + tzcnt %cx, %ax + tzcntw %cx, %ax + tzcnt %edx, %ebx + tzcntl -24(%edi), %ecx +#ifdef __x86_64__ + tzcnt %rbp, %rdx + tzcntq %rax, %r15 + tzcnt -8(%rbp), %rcx + tzcntq (%r8), %r12 +#endif + +#ifdef __i386__ + boundl %edx, 0x10000 + boundw %bx, 0x1000 + + arpl %bx, 0x1000 +#endif + lar 0x1000, %eax + lgdt 0x1000 + lidt 0x1000 + lldt 0x1000 + sgdt 0x1000 + sidt 0x1000 + sldt 0x1000 +#ifdef __x86_64__ + lgdtq 0x1000 + lidtq 0x1000 + sgdtq 0x1000 + sidtq 0x1000 + + swapgs + + /* Newer gas assemble 'str %rdx' as 'str %edx', based on the observation + that the 16bit value of the task register is zero-extended into the + destination anyway, and hence storing into %edx is the same as storing + into %rdx. TCC doesn't do that micro-optimization, hence just store + into the 32bit reg as well. */ + str %edx + str %r9d +#endif + + lmsw 0x1000 + lsl 0x1000, %ecx + ltr 0x1000 + ltr %si + smsw 0x1000 + str 0x1000 + str %ecx + str %dx + + verr 0x1000 + verw 0x1000 + +#ifdef __i386__ + push %ds + pushw %ds + pushl %ds + pop %ds + popw %ds + popl %ds +#endif + fxsave 1(%ebx) + fxrstor 1(%ecx) +#ifdef __i386__ + pushl $1 +#else + pushq $1 +#endif + pushw $1 + push $1 + +#ifdef __ASSEMBLER__ // should be defined, for S files + inc %eax +#endif + +#ifndef _WIN32 +ft1: ft2: ft3: ft4: ft5: ft6: ft7: ft8: ft9: + xor %eax, %eax + ret + +.type ft1,STT_FUNC +.type ft2,@STT_FUNC +.type ft3,%STT_FUNC +.type ft4,"STT_FUNC" +.type ft5,function +.type ft6,@function +.type ft7,%function +.type ft8,"function" +#endif + + pause +.rept 6 + nop +.endr +.fill 4,1,0x90 + +.section .text.one,"ax" +nop +.previous +.pushsection .text.one,"ax" +nop +.pushsection .text.two,"ax" +nop +.popsection +.popsection + +1: ud2 +.pushsection __bug_table,"a" +.align 8 +2: .long 1b - 2b + .long 0x600000 - 2b + .long 1b + 42 + .long 43 + 1b + .long 2b + 144 + .long 145 + 2b + .word 164, 0 + .org 2b+32 +#ifdef __x86_64__ + .quad 1b +#else + .long 1b +#endif +.popsection +3: mov %eax,%ecx +4: +.pushsection .text.three, "ax" +nop +.skip (-((4b-3b) > 0) * 2) , 0x90 +.popsection + +.globl overrideme +.weak overrideme + nop +.globl notimplemented +notimplemented: + ret +.set overrideme, notimplemented +overrideme = notimplemented +overrideme: + ret + + movd %esi, %mm1 + movd %edi, %xmm2 + movd (%ebx), %mm3 + movd (%ebx), %xmm3 + movd %mm1, %esi + movd %xmm2, %edi + movd %mm3, (%edx) + movd %xmm3, (%edx) +#ifdef __x86_64__ + movd %rsi, %mm1 + movd %rdi, %xmm2 + movd (%rbx), %mm3 + movd (%rbx), %xmm3 + movd %mm1, %r12 + movd %xmm2, %rdi + movd %mm3, (%r8) + movd %xmm3, (%r13) +#endif + + movq (%ebp), %mm1 + movq %mm2, (%edi) + movq (%edi), %xmm3 + movq %mm4, %mm5 +#ifdef __x86_64__ + movq %rcx, %mm1 + movq %rdx, %xmm2 + movq %r13, %xmm3 + /* movq mem64->xmm is encoded as f30f7e by GAS, but as + 660f6e by tcc (which really is a movd and would need + a REX.W prefix to be movq). */ + movq (%rsi), %xmm3 + movq %mm1, %rdx + movq %xmm3, %rcx + movq %xmm4, (%rsi) +#endif + +#define TEST_MMX_SSE(insn) \ + insn %mm1, %mm2; \ + insn %xmm2, %xmm3; \ + insn (%ebx), %xmm3; +#define TEST_MMX_SSE_I8(insn) \ + TEST_MMX_SSE(insn) \ + insn $0x42, %mm4; \ + insn $0x42, %xmm4; + + TEST_MMX_SSE(packssdw) + TEST_MMX_SSE(packsswb) + TEST_MMX_SSE(packuswb) + TEST_MMX_SSE(paddb) + TEST_MMX_SSE(paddw) + TEST_MMX_SSE(paddd) + TEST_MMX_SSE(paddsb) + TEST_MMX_SSE(paddsw) + TEST_MMX_SSE(paddusb) + TEST_MMX_SSE(paddusw) + TEST_MMX_SSE(pand) + TEST_MMX_SSE(pandn) + TEST_MMX_SSE(pcmpeqb) + TEST_MMX_SSE(pcmpeqw) + TEST_MMX_SSE(pcmpeqd) + TEST_MMX_SSE(pcmpgtb) + TEST_MMX_SSE(pcmpgtw) + TEST_MMX_SSE(pcmpgtd) + TEST_MMX_SSE(pmaddwd) + TEST_MMX_SSE(pmulhw) + TEST_MMX_SSE(pmullw) + TEST_MMX_SSE(por) + TEST_MMX_SSE(psllw) +TEST_MMX_SSE_I8(psllw) + TEST_MMX_SSE(pslld) +TEST_MMX_SSE_I8(pslld) + TEST_MMX_SSE(psllq) +TEST_MMX_SSE_I8(psllq) + TEST_MMX_SSE(psraw) +TEST_MMX_SSE_I8(psraw) + TEST_MMX_SSE(psrad) +TEST_MMX_SSE_I8(psrad) + TEST_MMX_SSE(psrlw) +TEST_MMX_SSE_I8(psrlw) + TEST_MMX_SSE(psrld) +TEST_MMX_SSE_I8(psrld) + TEST_MMX_SSE(psrlq) +TEST_MMX_SSE_I8(psrlq) + TEST_MMX_SSE(psubb) + TEST_MMX_SSE(psubw) + TEST_MMX_SSE(psubd) + TEST_MMX_SSE(psubsb) + TEST_MMX_SSE(psubsw) + TEST_MMX_SSE(psubusb) + TEST_MMX_SSE(psubusw) + TEST_MMX_SSE(punpckhbw) + TEST_MMX_SSE(punpckhwd) + TEST_MMX_SSE(punpckhdq) + TEST_MMX_SSE(punpcklbw) + TEST_MMX_SSE(punpcklwd) + TEST_MMX_SSE(punpckldq) + TEST_MMX_SSE(pxor) + + cvtpi2ps %mm1, %xmm2 + cvtpi2ps (%ebx), %xmm2 + TEST_MMX_SSE(pmaxsw) + TEST_MMX_SSE(pmaxub) + TEST_MMX_SSE(pminsw) + TEST_MMX_SSE(pminub) diff --git a/lib/tinycc/tests/boundtest.c b/lib/tinycc/tests/boundtest.c new file mode 100644 index 000000000..e4b2ab1c2 --- /dev/null +++ b/lib/tinycc/tests/boundtest.c @@ -0,0 +1,309 @@ +#include +#include +#include + +#define NB_ITS 1000000 +//#define NB_ITS 1 +#define TAB_SIZE 100 + +int tab[TAB_SIZE]; +int ret_sum; +char tab3[256]; + +int test1(void) +{ + int i, sum = 0; + for(i=0;i= 2) + index = atoi(argv[1]) - 1; + + if ((index < 0) || (index >= index_max)) { + printf("N is outside of the valid range (%d)\n", index); + exit(2); + } + + /* well, we also use bounds on this ! */ + ftest = table_test[index]; + ftest(); + + return 0; +} + +/* + * without bound 0.77 s + * with bounds 4.73 + */ diff --git a/lib/tinycc/tests/bug.c b/lib/tinycc/tests/bug.c new file mode 100644 index 000000000..b0bc2d547 --- /dev/null +++ b/lib/tinycc/tests/bug.c @@ -0,0 +1,35 @@ +#include +#include + +int compile_errors(void) +{ +#if TEST == 1 + { + /* Not constant */ + static int i = (&"Foobar"[1] - &"Foobar"[0]); + } +#endif +#if TEST == 2 + { + /* Not constant */ + struct{int c;}v; + static long i=((char*)&(v.c)-(char*)&v); + } +#endif +#if TEST == 3 + { + /* Not constant */ + static const short ar[] = { &&l1 - &&l1, &&l2 - &&l1 }; + void *p = &&l1 + ar[0]; + goto *p; + l1: return 1; + l2: return 2; + } +#endif + return 0; +} + +int +main(void) +{ +} diff --git a/lib/tinycc/tests/exec_section_in_asm.c b/lib/tinycc/tests/exec_section_in_asm.c new file mode 100644 index 000000000..671b776a6 --- /dev/null +++ b/lib/tinycc/tests/exec_section_in_asm.c @@ -0,0 +1,29 @@ +/* This test only works on x86-64. */ +/* Previously in TinyCC, ELF sections defined in assembly would always have the +execute bit not set, so you would get segmentation faults when code in these +sections was exectuted. This file is a minimal example of a file that will put +the resulting code in a non-executable section (and invoke it) prior to the fix. +*/ +#include + +void *memset(void *dst, int c, int len); + +__asm__ ( +".section .text.nolibc_memset\n" +".weak memset\n" +"memset:\n" + "xchgl %eax, %esi\n\t" + "movq %rdx, %rcx\n\t" + "pushq %rdi\n\t" + "rep stosb\n\t" + "popq %rax\n\t" + "retq\n" +); + +int main () { + char buf[10]; + memset(&buf[0], 'A', 9); + buf[9] = 0; + puts(buf); + return 0; +} diff --git a/lib/tinycc/tests/gcctestsuite.sh b/lib/tinycc/tests/gcctestsuite.sh new file mode 100755 index 000000000..b6f9ec213 --- /dev/null +++ b/lib/tinycc/tests/gcctestsuite.sh @@ -0,0 +1,151 @@ +#!/bin/sh + +if [ -z "$TESTSUITE_PATH" ] +then + if [ -d "$HOME/gcc/gcc-3.2/gcc/testsuite/gcc.c-torture" ] + then + TESTSUITE_PATH="$HOME/gcc/gcc-3.2/gcc/testsuite/gcc.c-torture" + fi +fi + +if [ -z "$TESTSUITE_PATH" ] +then + echo "gcc testsuite not found." + echo "define TESTSUITE_PATH to point to the gcc.c-torture directory" + exit 1 +fi + +if [ -z "$TCC_SOURCE_PATH" ] +then + if [ -f "include/tccdefs.h" ] + then + TCC_SOURCE_PATH="." + elif [ -f "../include/tccdefs.h" ] + then + TCC_SOURCE_PATH=".." + elif [ -f "../tinycc/include/tccdefs.h" ] + then + TCC_SOURCE_PATH="../tinycc" + fi +fi + +if [ -z "$RUNTIME_DIR" ] +then + RUNTIME_DIR=$XDG_RUNTIME_DIR +fi +if [ -z "$RUNTIME_DIR" ] +then + RUNTIME_DIR="/tmp" +fi + +if [ -z "$CC" ] +then + if [ -z "$TCC_SOURCE_PATH" ] + then + echo "tcc not found." + echo "define TCC_SOURCE_PATH to point to the tcc source path" + exit 1 + fi + + TCC="./tcc -B. -I$TCC_SOURCE_PATH/ -I$TCC_SOURCE_PATH/include -DNO_TRAMPOLINES" +else + TCC="$CC -O1 -Wno-implicit-int $CFLAGS" +fi + +rm -f tcc.sum tcc.fail +nb_ok="0" +nb_skipped="0" +nb_failed="0" +nb_exe_failed="0" + +# skip some failed tests not implemented in tcc +# builtin: gcc "__builtins_*" +# ieee: gcc "__builtins_*" in the ieee directory +# complex: C99 "_Complex" and gcc "__complex__" +# misc: stdc features, other arch, gcc extensions (example: gnu_inline in c89) +# + +old_pwd="`pwd`" +cd "$TESTSUITE_PATH" + +skip_builtin="`grep "_builtin_" compile/*.c execute/*.c execute/ieee/*.c | cut -d ':' -f1 | cut -d '/' -f2 | sort -u `" +skip_ieee="`grep "_builtin_" execute/ieee/*.c | cut -d ':' -f1 | cut -d '/' -f3 | sort -u `" +skip_complex="`grep -i "_Complex" compile/*.c execute/*.c execute/ieee/*.c | cut -d ':' -f1 | cut -d '/' -f2 | sort -u `" +skip_misc="20000120-2.c mipscop-1.c mipscop-2.c mipscop-3.c mipscop-4.c + fp-cmp-4f.c fp-cmp-4l.c fp-cmp-8f.c fp-cmp-8l.c pr38016.c " + +cd "$old_pwd" + +for src in $TESTSUITE_PATH/compile/*.c ; do + echo $TCC -o $RUNTIME_DIR/tst.o -c $src + $TCC -o $RUNTIME_DIR/tst.o -c $src >> tcc.fail 2>&1 + if [ "$?" = "0" ] ; then + result="PASS" + nb_ok=$(( $nb_ok + 1 )) + else + base=`basename "$src"` + skip_me="`echo $skip_builtin $skip_ieee $skip_complex $skip_misc | grep -w $base`" + + if [ -n "$skip_me" ] + then + result="SKIP" + nb_skipped=$(( $nb_skipped + 1 )) + else + result="FAIL" + nb_failed=$(( $nb_failed + 1 )) + fi + fi + echo "$result: $src" >> tcc.sum +done + +if [ -f "$RUNTIME_DIR/tst.o" ] +then + rm -f "$RUNTIME_DIR/tst.o" +fi + +for src in $TESTSUITE_PATH/execute/*.c $TESTSUITE_PATH/execute/ieee/*.c ; do + echo $TCC $src -o $RUNTIME_DIR/tst -lm + $TCC $src -o $RUNTIME_DIR/tst -lm >> tcc.fail 2>&1 + if [ "$?" = "0" ] ; then + result="PASS" + if $RUNTIME_DIR/tst >> tcc.fail 2>&1 + then + result="PASS" + nb_ok=$(( $nb_ok + 1 )) + else + result="FAILEXE" + nb_exe_failed=$(( $nb_exe_failed + 1 )) + fi + else + base=`basename "$src"` + skip_me="`echo $skip_builtin $skip_ieee $skip_complex $skip_misc | grep -w $base`" + + if [ -n "$skip_me" ] + then + result="SKIP" + nb_skipped=$(( $nb_skipped + 1 )) + else + result="FAIL" + nb_failed=$(( $nb_failed + 1 )) + fi + fi + echo "$result: $src" >> tcc.sum +done + +if [ -f "$RUNTIME_DIR/tst.o" ] +then + rm -f "$RUNTIME_DIR/tst.o" +fi +if [ -f "$RUNTIME_DIR/tst" ] +then + rm -f "$RUNTIME_DIR/tst" +fi + +echo "$nb_ok test(s) ok." >> tcc.sum +echo "$nb_ok test(s) ok." +echo "$nb_skipped test(s) skipped." >> tcc.sum +echo "$nb_skipped test(s) skipped." +echo "$nb_failed test(s) failed." >> tcc.sum +echo "$nb_failed test(s) failed." +echo "$nb_exe_failed test(s) exe failed." >> tcc.sum +echo "$nb_exe_failed test(s) exe failed." diff --git a/lib/tinycc/tests/libtcc_test.c b/lib/tinycc/tests/libtcc_test.c new file mode 100644 index 000000000..1428b1eab --- /dev/null +++ b/lib/tinycc/tests/libtcc_test.c @@ -0,0 +1,103 @@ +/* + * Simple Test program for libtcc + * + * libtcc can be useful to use tcc as a "backend" for a code generator. + */ +#include +#include +#include +#include "libtcc.h" + +void handle_error(void *opaque, const char *msg) +{ + fprintf(opaque, "%s\n", msg); +} + +/* this function is called by the generated code */ +int add(int a, int b) +{ + return a + b; +} + +/* this strinc is referenced by the generated code */ +const char hello[] = "Hello World!"; + +char my_program[] = +"#include \n" /* include the "Simple libc header for TCC" */ +"extern int add(int a, int b);\n" +"#ifdef _WIN32\n" /* dynamically linked data needs 'dllimport' */ +" __attribute__((dllimport))\n" +"#endif\n" +"extern const char hello[];\n" +"int fib(int n)\n" +"{\n" +" if (n <= 2)\n" +" return 1;\n" +" else\n" +" return fib(n-1) + fib(n-2);\n" +"}\n" +"\n" +"int foo(int n)\n" +"{\n" +" printf(\"%s\\n\", hello);\n" +" printf(\"fib(%d) = %d\\n\", n, fib(n));\n" +" printf(\"add(%d, %d) = %d\\n\", n, 2 * n, add(n, 2 * n));\n" +" return 0;\n" +"}\n"; + +int main(int argc, char **argv) +{ + TCCState *s; + int i; + int (*func)(int); + + s = tcc_new(); + if (!s) { + fprintf(stderr, "Could not create tcc state\n"); + exit(1); + } + + /* set custom error/warning printer */ + tcc_set_error_func(s, stderr, handle_error); + + /* if tcclib.h and libtcc1.a are not installed, where can we find them */ + for (i = 1; i < argc; ++i) { + char *a = argv[i]; + if (a[0] == '-') { + if (a[1] == 'B') + tcc_set_lib_path(s, a+2); + else if (a[1] == 'I') + tcc_add_include_path(s, a+2); + else if (a[1] == 'L') + tcc_add_library_path(s, a+2); + } + } + + /* MUST BE CALLED before any compilation */ + tcc_set_output_type(s, TCC_OUTPUT_MEMORY); + + if (tcc_compile_string(s, my_program) == -1) + return 1; + + /* as a test, we add symbols that the compiled program can use. + You may also open a dll with tcc_add_dll() and use symbols from that */ + tcc_add_symbol(s, "add", add); + tcc_add_symbol(s, "hello", hello); + + /* relocate the code */ + if (tcc_relocate(s) < 0) + return 1; + + /* get entry symbol */ + func = tcc_get_symbol(s, "foo"); + if (!func) + return 1; + + /* run the code */ + func(32); + + /* delete the state */ + tcc_delete(s); + + return 0; +} diff --git a/lib/tinycc/tests/libtcc_test_mt.c b/lib/tinycc/tests/libtcc_test_mt.c new file mode 100644 index 000000000..f9c90bd6d --- /dev/null +++ b/lib/tinycc/tests/libtcc_test_mt.c @@ -0,0 +1,354 @@ +/* + * Multi-thread Test for libtcc + */ + +#ifndef FIB +#include +#include +#include +#include +#include "libtcc.h" + +#define M 20 /* number of states */ +#define F(n) (n % 20 + 2) /* fib argument */ + +#ifdef _WIN32 +#include +#define TF_TYPE(func, param) DWORD WINAPI func(void *param) +typedef TF_TYPE(ThreadFunc, x); +HANDLE hh[M]; +void create_thread(ThreadFunc f, int n) +{ + DWORD tid; + hh[n] = CreateThread(NULL, 0, f, (void*)(size_t)n, 0, &tid); +} +void wait_threads(int n) +{ + WaitForMultipleObjects(n, hh, TRUE, INFINITE); + while (n) + CloseHandle(hh[--n]); +} +void sleep_ms(unsigned n) +{ + Sleep(n); +} +#else +#include +#include +#include +#define TF_TYPE(func, param) void* func(void *param) +typedef TF_TYPE(ThreadFunc, x); +pthread_t hh[M]; +void create_thread(ThreadFunc f, int n) +{ + pthread_create(&hh[n], NULL, f, (void*)(size_t)n); +} +void wait_threads(int n) +{ + while (n) + pthread_join(hh[--n], NULL); + +} +void sleep_ms(unsigned n) +{ + usleep(n * 1000); +} +#endif + +void handle_error(void *opaque, const char *msg) +{ + fprintf(opaque, "%s\n", msg); +} + +/* this function is called by the generated code */ +int add(int a, int b) +{ + return a + b; +} + +#define _str(s) #s +#define str(s) _str(s) +/* as a trick, prepend #line directive for better error/warning messages */ +#define PROG(lbl) \ + char lbl[] = "#line " str(__LINE__) " " str(__FILE__) "\n\n" + +PROG(my_program) +"#include \n" /* include the "Simple libc header for TCC" */ +"int add(int a, int b);\n" +"int fib(int n)\n" +"{\n" +" if (n <= 2)\n" +" return 1;\n" +" else\n" +" return add(fib(n-1),fib(n-2));\n" +"}\n" +"\n" +"void bar(void) { *(void**)0 = 0; }\n" +"\n" +"int foo(int n)\n" +"{\n" +" printf(\" %d\", fib(n));\n" +" if (n >= N_CRASH && n < N_CRASH + 8)\n" +" bar();\n" +" return 0;\n" +"# warning is this the correct file:line...\n" +"}\n"; + +int g_argc; char **g_argv; + +void parse_args(TCCState *s) +{ + int i; + /* if tcclib.h and libtcc1.a are not installed, where can we find them */ + for (i = 1; i < g_argc; ++i) { + char *a = g_argv[i]; + if (a[0] == '-') { + if (a[1] == 'B') + tcc_set_lib_path(s, a+2); + else if (a[1] == 'I') + tcc_add_include_path(s, a+2); + else if (a[1] == 'L') + tcc_add_library_path(s, a+2); + else if (a[1] == 'D') + tcc_define_symbol(s, a+2, NULL); + } + } +} + +int backtrace_func( + void *ud, + void *pc, + const char *file, + int line, + const char *func, + const char *msg) +{ +#if 0 + printf("\n *** %p %s %s:%d in '%s'", + pc, + msg ? "at" : "by", + file ? file : "?", + line, + func ? func : "?"); + return 1; // want more backtrace levels +#else + //printf(" [%d]", *(int*)ud); + printf("!"); + return 0; // cancel backtrace +#endif +} + +TCCState *new_state(int w) +{ + TCCState *s = tcc_new(); + if (!s) { + fprintf(stderr, __FILE__ ": could not create tcc state\n"); + exit(1); + } + tcc_set_error_func(s, stdout, handle_error); + parse_args(s); + if (0 == (w & 1)) + tcc_set_options(s, "-w"); + if (w & 2) { + tcc_set_options(s, "-bt"); + tcc_define_symbol(s, "N_CRASH", str(M/2)); + } else + tcc_define_symbol(s, "N_CRASH", "-1000"); + tcc_set_output_type(s, TCC_OUTPUT_MEMORY); + return s; +} + +void *reloc_state(TCCState *s, const char *entry) +{ + void *func; + tcc_add_symbol(s, "add", add); + if (tcc_relocate(s) < 0) { + fprintf(stderr, __FILE__ ": could not relocate tcc state.\n"); + return NULL; + } + func = tcc_get_symbol(s, entry); + if (!func) + fprintf(stderr, __FILE__ ": could not get entry symbol.\n"); + return func; +} + +/* work with several states at the same time */ +int state_test(int w) +{ + TCCState *s[M]; + int (*funcs[M])(int); + int n; + jmp_buf jb; + + for (n = 0; n < M + 4; ++n) { + unsigned a = n, b = n - 1, c = n - 2, d = n - 3, e = n - 4; + if (a < M) + s[a] = new_state(w); + if (b < M) + if (tcc_compile_string(s[b], my_program) == -1) + break; + if (c < M) + funcs[c] = reloc_state(s[c], "foo"); + if (d < M && funcs[d]) { + tcc_set_backtrace_func(s[d], &d, backtrace_func); + if (0 == tcc_setjmp(s[d], jb, funcs[d])) + funcs[d](F(d)); + } + if (e < M) + tcc_delete(s[e]); + } + return 0; +} + +/* simple compilation in threads */ +TF_TYPE(thread_test_simple, vn) +{ + TCCState *s; + int (*func)(int); + int ret; + int n = (size_t)vn; + jmp_buf jb; + + s = new_state(0); /* '2' for exceptions */ + sleep_ms(1); + ret = tcc_compile_string(s, my_program); + sleep_ms(1); + if (ret >= 0) { + func = reloc_state(s, "foo"); + tcc_set_backtrace_func(s, &n, backtrace_func); + if (func) { + if (0 == tcc_setjmp(s, jb, func)) + func(F(n)); + } + } + tcc_delete(s); + return 0; +} + +/* more complex compilation in threads */ +TF_TYPE(thread_test_complex, vn) +{ + TCCState *s; + int ret; + int n = (size_t)vn; + char *argv[30], b[10]; + int argc = 0, i; + + sprintf(b, "%d", F(n)); + + for (i = 1; i < g_argc; ++i) argv[argc++] = g_argv[i]; +#if 0 + argv[argc++] = "-run"; + for (i = 1; i < g_argc; ++i) argv[argc++] = g_argv[i]; +#endif + argv[argc++] = "-DFIB"; + argv[argc++] = "-run"; + argv[argc++] = __FILE__; + argv[argc++] = b; + argv[argc] = NULL; + + s = new_state(1); + sleep_ms(2); + ret = tcc_add_file(s, argv[0]); + sleep_ms(3); + if (ret == 0) + tcc_run(s, argc, argv); + tcc_delete(s); + fflush(stdout); + return 0; +} + +void time_tcc(int n, const char *src) +{ + TCCState *s; + int ret, i = 0; + while (i++ < n) { + s = new_state(1); + printf(" %d", i), fflush(stdout); + ret = tcc_add_file(s, src); + tcc_delete(s); + if (ret < 0) + exit(1); + } +} + +static unsigned getclock_ms(void) +{ +#ifdef _WIN32 + return GetTickCount(); +#else + struct timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_sec*1000 + (tv.tv_usec+500)/1000; +#endif +} + +int main(int argc, char **argv) +{ + int n; + unsigned t; + + g_argc = argc; + g_argv = argv; + + if (argc < 2) { + fprintf(stderr, "usage: libtcc_test_mt tcc.c \n"); + return 1; + } + +#if 1 + printf("running fib with mixed calls\n "), fflush(stdout); + t = getclock_ms(); + state_test(0); + printf("\n (%u ms)\n", getclock_ms() - t); +#endif +#if 1 + printf("producing some exceptions (!)\n "), fflush(stdout); + t = getclock_ms(); + state_test(2); + printf("\n (%u ms)\n", getclock_ms() - t); +#endif +#if 1 + //{ int i; for (i = 0; i < 100; ++i) { printf("(%d) ", i); + printf("running fib in threads\n "), fflush(stdout); + t = getclock_ms(); + for (n = 0; n < M; ++n) + create_thread(thread_test_simple, n); + wait_threads(n); + printf("\n (%u ms)\n", getclock_ms() - t); + //}} +#endif +#if 1 + printf("running tcc.c in threads to run fib\n "), fflush(stdout); + t = getclock_ms(); + for (n = 0; n < M; ++n) + create_thread(thread_test_complex, n); + wait_threads(n); + printf("\n (%u ms)\n", getclock_ms() - t); +#endif +#if 1 + printf("compiling tcc.c 10 times\n "), fflush(stdout); + t = getclock_ms(); + time_tcc(10, argv[1]); + printf("\n (%u ms)\n", getclock_ms() - t), fflush(stdout); +#endif + return 0; +} + +#else +#include + +unsigned int sleep(unsigned int seconds); + +int fib(n) +{ + return (n <= 2) ? 1 : fib(n-1) + fib(n-2); +} + +int main(int argc, char **argv) +{ + sleep(1); + printf(" %d", fib(atoi(argv[1]))); + return 0; +} +#endif diff --git a/lib/tinycc/tests/pp/01.c b/lib/tinycc/tests/pp/01.c new file mode 100644 index 000000000..2fc3d7960 --- /dev/null +++ b/lib/tinycc/tests/pp/01.c @@ -0,0 +1,6 @@ +#define hash_hash # ## # +#define mkstr(a) # a +#define in_between(a) mkstr(a) +#define join(c, d) in_between(c hash_hash d) +char p[] = join(x, y); +// char p[] = "x ## y"; diff --git a/lib/tinycc/tests/pp/01.expect b/lib/tinycc/tests/pp/01.expect new file mode 100644 index 000000000..cf5b15340 --- /dev/null +++ b/lib/tinycc/tests/pp/01.expect @@ -0,0 +1 @@ +char p[] = "x ## y"; diff --git a/lib/tinycc/tests/pp/02.c b/lib/tinycc/tests/pp/02.c new file mode 100644 index 000000000..feb1254e3 --- /dev/null +++ b/lib/tinycc/tests/pp/02.c @@ -0,0 +1,28 @@ +#define x 3 +#define f(a) f(x * (a)) +#undef x +#define x 2 +#define g f +#define z z[0] +#define h g(~ +#define m(a) a(w) +#define w 0,1 +#define t(a) a +#define p() int +#define q(x) x +#define r(x,y) x ## y +#define str(x) # x +f(y+1) + f(f(z)) % t(t(g)(0) + t)(1); +g(x+(3,4)-w) | h 5) & m +(f)^m(m); +char c[2][6] = { str(hello), str() }; +/* + * f(2 * (y+1)) + f(2 * (f(2 * (z[0])))) % f(2 * (0)) + t(1); + * f(2 * (2+(3,4)-0,1)) | f(2 * (~ 5)) & f(2 * (0,1))^m(0,1); + * char c[2][6] = { "hello", "" }; + */ +#define L21 f(y+1) + f(f(z)) % t(t(g)(0) + t)(1); +#define L22 g(x+(3,4)-w) | h 5) & m\ +(f)^m(m); +L21 +L22 diff --git a/lib/tinycc/tests/pp/02.expect b/lib/tinycc/tests/pp/02.expect new file mode 100644 index 000000000..8ae2eb9ea --- /dev/null +++ b/lib/tinycc/tests/pp/02.expect @@ -0,0 +1,5 @@ +f(2 * (y+1)) + f(2 * (f(2 * (z[0])))) % f(2 * (0)) + t(1); +f(2 * (2 +(3,4)-0,1)) | f(2 * (~ 5)) & f(2 * (0,1))^m(0,1); +char c[2][6] = { "hello", "" }; +f(2 * (y+1)) + f(2 * (f(2 * (z[0])))) % f(2 * (0)) + t(1); +f(2 * (2 +(3,4)-0,1)) | f(2 * (~ 5)) & f(2 * (0,1))^m(0,1); diff --git a/lib/tinycc/tests/pp/03.c b/lib/tinycc/tests/pp/03.c new file mode 100644 index 000000000..a659245ec --- /dev/null +++ b/lib/tinycc/tests/pp/03.c @@ -0,0 +1,15 @@ +#define str(s) # s +#define xstr(s) str(s) +#define debug(s, t) printf("x" # s "= %d, x" # t "= %s", \ + x ## s, x ## t) +#define INCFILE(n) vers ## n +#define glue(a, b) a ## b +#define xglue(a, b) glue(a, b) +#define HIGHLOW "hello" +#define LOW LOW ", world" +debug(1, 2); +fputs(str(strncmp("abc\0d", "abc", '\4') // this goes away + == 0) str(: @\n), s); +\#include xstr(INCFILE(2).h) +glue(HIGH, LOW); +xglue(HIGH, LOW) diff --git a/lib/tinycc/tests/pp/03.expect b/lib/tinycc/tests/pp/03.expect new file mode 100644 index 000000000..44aad0ae1 --- /dev/null +++ b/lib/tinycc/tests/pp/03.expect @@ -0,0 +1,5 @@ +printf("x" "1" "= %d, x" "2" "= %s", x1, x2); +fputs("strncmp(\"abc\\0d\", \"abc\", '\\4') == 0" ": @\n", s); +\#include "vers2.h" +"hello"; +"hello" ", world" diff --git a/lib/tinycc/tests/pp/04.c b/lib/tinycc/tests/pp/04.c new file mode 100644 index 000000000..0068f3751 --- /dev/null +++ b/lib/tinycc/tests/pp/04.c @@ -0,0 +1,4 @@ +#define foobar 1 +#define C(x,y) x##y +#define D(x) (C(x,bar)) +D(foo) diff --git a/lib/tinycc/tests/pp/04.expect b/lib/tinycc/tests/pp/04.expect new file mode 100644 index 000000000..7c67b0104 --- /dev/null +++ b/lib/tinycc/tests/pp/04.expect @@ -0,0 +1 @@ +(1) diff --git a/lib/tinycc/tests/pp/05.c b/lib/tinycc/tests/pp/05.c new file mode 100644 index 000000000..72749416c --- /dev/null +++ b/lib/tinycc/tests/pp/05.c @@ -0,0 +1,7 @@ +#define t(x,y,z) x ## y ## z +#define xxx(s) int s[] = { t(1,2,3), t(,4,5), t(6,,7), t(8,9,), \ + t(10,,), t(,11,), t(,,12), t(,,) }; + +int j[] = { t(1,2,3), t(,4,5), t(6,,7), t(8,9,), + t(10,,), t(,11,), t(,,12), t(,,) }; +xxx(j) diff --git a/lib/tinycc/tests/pp/05.expect b/lib/tinycc/tests/pp/05.expect new file mode 100644 index 000000000..9f9be378f --- /dev/null +++ b/lib/tinycc/tests/pp/05.expect @@ -0,0 +1,3 @@ +int j[] = { 123, 45, 67, 89, + 10, 11, 12, }; +int j[] = { 123, 45, 67, 89, 10, 11, 12, }; diff --git a/lib/tinycc/tests/pp/06.c b/lib/tinycc/tests/pp/06.c new file mode 100644 index 000000000..28cfddece --- /dev/null +++ b/lib/tinycc/tests/pp/06.c @@ -0,0 +1,5 @@ +#define X(a,b, \ + c,d) \ + foo + +X(1,2,3,4) diff --git a/lib/tinycc/tests/pp/06.expect b/lib/tinycc/tests/pp/06.expect new file mode 100644 index 000000000..257cc5642 --- /dev/null +++ b/lib/tinycc/tests/pp/06.expect @@ -0,0 +1 @@ +foo diff --git a/lib/tinycc/tests/pp/07.c b/lib/tinycc/tests/pp/07.c new file mode 100644 index 000000000..b22b22bbc --- /dev/null +++ b/lib/tinycc/tests/pp/07.c @@ -0,0 +1,4 @@ +#define a() YES +#define b() a +b() +b()() diff --git a/lib/tinycc/tests/pp/07.expect b/lib/tinycc/tests/pp/07.expect new file mode 100644 index 000000000..ad0e20a66 --- /dev/null +++ b/lib/tinycc/tests/pp/07.expect @@ -0,0 +1,2 @@ +a +YES diff --git a/lib/tinycc/tests/pp/08.c b/lib/tinycc/tests/pp/08.c new file mode 100644 index 000000000..93018e11f --- /dev/null +++ b/lib/tinycc/tests/pp/08.c @@ -0,0 +1,4 @@ +// test macro expansion in arguments +#define s_pos s_s.s_pos +#define foo(x) (x) +foo(hej.s_pos) diff --git a/lib/tinycc/tests/pp/08.expect b/lib/tinycc/tests/pp/08.expect new file mode 100644 index 000000000..2b2e3eebd --- /dev/null +++ b/lib/tinycc/tests/pp/08.expect @@ -0,0 +1 @@ +(hej.s_s.s_pos) diff --git a/lib/tinycc/tests/pp/09.c b/lib/tinycc/tests/pp/09.c new file mode 100644 index 000000000..315b297cd --- /dev/null +++ b/lib/tinycc/tests/pp/09.c @@ -0,0 +1,4 @@ +#define C(a,b,c) a##b##c +#define N(x,y) C(x,_,y) +#define A_O aaaaoooo +N(A,O) diff --git a/lib/tinycc/tests/pp/09.expect b/lib/tinycc/tests/pp/09.expect new file mode 100644 index 000000000..adce0f95e --- /dev/null +++ b/lib/tinycc/tests/pp/09.expect @@ -0,0 +1 @@ +aaaaoooo diff --git a/lib/tinycc/tests/pp/10.c b/lib/tinycc/tests/pp/10.c new file mode 100644 index 000000000..f180eff1e --- /dev/null +++ b/lib/tinycc/tests/pp/10.c @@ -0,0 +1,10 @@ +#define f(x) x +#define g(x) f(x) f(x +#define i(x) g(x)) g(x +#define h(x) i(x))) i(x +#define k(x) i(x))) i(x)))) +f(x) +g(x)) +i(x))) +h(x)))) +k(x)))) diff --git a/lib/tinycc/tests/pp/10.expect b/lib/tinycc/tests/pp/10.expect new file mode 100644 index 000000000..bd18e18e5 --- /dev/null +++ b/lib/tinycc/tests/pp/10.expect @@ -0,0 +1,5 @@ +x +x x +x x x x +x x x x x x x x +x x x x x x x x)))) diff --git a/lib/tinycc/tests/pp/11.c b/lib/tinycc/tests/pp/11.c new file mode 100644 index 000000000..d6ba7a96e --- /dev/null +++ b/lib/tinycc/tests/pp/11.c @@ -0,0 +1,36 @@ +#define D1(s, ...) s +#define D2(s, ...) s D1(__VA_ARGS__) +#define D3(s, ...) s D2(__VA_ARGS__) +#define D4(s, ...) s D3(__VA_ARGS__) + +D1(a) +D2(a, b) +D3(a, b, c) +D4(a, b, c, d) + +x D4(a, b, c, d) y +x D4(a, b, c) y +x D4(a, b) y +x D4(a) y +x D4() y + +#define GNU_COMMA(X,Y...) X,##Y + +x GNU_COMMA(A,B,C) y +x GNU_COMMA(A,B) y +x GNU_COMMA(A) y +x GNU_COMMA() y + +#define __sun_attr___noreturn__ __attribute__((__noreturn__)) +#define ___sun_attr_inner(__a) __sun_attr_##__a +#define __sun_attr__(__a) ___sun_attr_inner __a +#define __NORETURN __sun_attr__((__noreturn__)) +__NORETURN +#define X(...) +#define Y(...) 1 __VA_ARGS__ 2 +Y(X X() ()) + +#define DDD(A, B) D_ ## B ## _D_ ## A +#define CCC(X, ...) DDD(X,## __VA_ARGS__) +/* must be D_B_D_A (not D_B _D_A) */ +CCC(A,B) diff --git a/lib/tinycc/tests/pp/11.expect b/lib/tinycc/tests/pp/11.expect new file mode 100644 index 000000000..c1c99fef4 --- /dev/null +++ b/lib/tinycc/tests/pp/11.expect @@ -0,0 +1,16 @@ +a +a b +a b c +a b c d +x a b c d y +x a b c y +x a b y +x a y +x y +x A,B,C y +x A,B y +x A y +x y +__attribute__((__noreturn__)) +1 2 +D_B_D_A diff --git a/lib/tinycc/tests/pp/12.S b/lib/tinycc/tests/pp/12.S new file mode 100644 index 000000000..597ccb4cb --- /dev/null +++ b/lib/tinycc/tests/pp/12.S @@ -0,0 +1,8 @@ +#define SRC(y...) \ + 9999: y; \ + .section __ex_table, "a"; \ + .long 9999b, 6001f ; \ + // .previous + + SRC(1: movw (%esi), %bx) +6001: diff --git a/lib/tinycc/tests/pp/12.expect b/lib/tinycc/tests/pp/12.expect new file mode 100644 index 000000000..17a861c25 --- /dev/null +++ b/lib/tinycc/tests/pp/12.expect @@ -0,0 +1,2 @@ + 9999: 1: movw (%esi), %bx; .section __ex_table, "a"; .long 9999b, 6001f ; +6001: diff --git a/lib/tinycc/tests/pp/13.S b/lib/tinycc/tests/pp/13.S new file mode 100644 index 000000000..bf0b525f9 --- /dev/null +++ b/lib/tinycc/tests/pp/13.S @@ -0,0 +1,6 @@ +# `modelist' label. Each video mode record looks like: +#ifdef AAA +# modelist' label. Each video mode record looks like: +#endif +.text +endtext: diff --git a/lib/tinycc/tests/pp/13.expect b/lib/tinycc/tests/pp/13.expect new file mode 100644 index 000000000..c7a32305f --- /dev/null +++ b/lib/tinycc/tests/pp/13.expect @@ -0,0 +1,2 @@ +.text +endtext: diff --git a/lib/tinycc/tests/pp/14.c b/lib/tinycc/tests/pp/14.c new file mode 100644 index 000000000..e15468c5f --- /dev/null +++ b/lib/tinycc/tests/pp/14.c @@ -0,0 +1,13 @@ +#define W Z +#define Z(X) W(X,2) +#define Y(X) Z(X) +#define X Y +return X(X(1)); + +#define P Q +#define Q(n) P(n,2) +return P(1); + +#define A (B * B) +#define B (A + A) +return A + B; diff --git a/lib/tinycc/tests/pp/14.expect b/lib/tinycc/tests/pp/14.expect new file mode 100644 index 000000000..37860440c --- /dev/null +++ b/lib/tinycc/tests/pp/14.expect @@ -0,0 +1,3 @@ +return Z(Z(1,2),2); +return Q(1,2); +return ((A + A) * (A + A)) + ((B * B) + (B * B)); diff --git a/lib/tinycc/tests/pp/15.c b/lib/tinycc/tests/pp/15.c new file mode 100644 index 000000000..cf13f9a89 --- /dev/null +++ b/lib/tinycc/tests/pp/15.c @@ -0,0 +1,18 @@ +// insert a space between two tokens if otherwise they +// would form a single token when read back + +#define n(x) x + +return (n(long)n(double))d; +return n(A)n(++)n(+)n(B); +return n(A)n(+)n(++)n(B); +return n(A)n(++)n(+)n(+)n(B); + +// not a hex float +return n(0x1E)n(-1); + +// unlike gcc but correct +// XXX: return n(x)+n(x)-n(1)+n(1)-2; + +// unlike gcc, but cannot appear in valid C +// XXX: return n(x)n(x)n(1)n(2)n(x); diff --git a/lib/tinycc/tests/pp/15.expect b/lib/tinycc/tests/pp/15.expect new file mode 100644 index 000000000..b4f885e95 --- /dev/null +++ b/lib/tinycc/tests/pp/15.expect @@ -0,0 +1,5 @@ +return (long double)d; +return A+++B; +return A+ ++B; +return A+++ +B; +return 0x1E -1; diff --git a/lib/tinycc/tests/pp/16.c b/lib/tinycc/tests/pp/16.c new file mode 100644 index 000000000..8b5b6428c --- /dev/null +++ b/lib/tinycc/tests/pp/16.c @@ -0,0 +1,3 @@ +/* The following should warn */ +#define A ... +#define A <<= diff --git a/lib/tinycc/tests/pp/16.expect b/lib/tinycc/tests/pp/16.expect new file mode 100644 index 000000000..695d6d41c --- /dev/null +++ b/lib/tinycc/tests/pp/16.expect @@ -0,0 +1,2 @@ + +16.c:3: warning: A redefined diff --git a/lib/tinycc/tests/pp/17.c b/lib/tinycc/tests/pp/17.c new file mode 100644 index 000000000..f12196fe8 --- /dev/null +++ b/lib/tinycc/tests/pp/17.c @@ -0,0 +1,14 @@ +#define STR1(u) # u +#define pass(a) a +#define __ASM_REG(reg) STR1(one##reg) +#define _ASM_DX __ASM_REG(tok) +X162 pass(__ASM_REG(tok)) +X161 pass(_ASM_DX) +X163 pass(STR1(one##tok)) + +X170 pass(x ## y) +X171 pass(x pass(##) y) + +#define Y(x) Z(x) +#define X Y +X180 return X(X(1)); diff --git a/lib/tinycc/tests/pp/17.expect b/lib/tinycc/tests/pp/17.expect new file mode 100644 index 000000000..e95aafef8 --- /dev/null +++ b/lib/tinycc/tests/pp/17.expect @@ -0,0 +1,6 @@ +X162 "onetok" +X161 "onetok" +X163 "one##tok" +X170 x ## y +X171 x ## y +X180 return Z(Z(1)); diff --git a/lib/tinycc/tests/pp/18.c b/lib/tinycc/tests/pp/18.c new file mode 100644 index 000000000..de47790ea --- /dev/null +++ b/lib/tinycc/tests/pp/18.c @@ -0,0 +1,30 @@ +#define M_RETI_ARG27(x,y,z,aa, ...) aa +#define M_RET_ARG27(...) M_RETI_ARG27(__VA_ARGS__) +#define M_COMMA_P(...) M_RET_ARG27(__VA_ARGS__, 1, 1, 0, useless) +#define M_EMPTYI_DETECT(...) 0, 1, +#define M_EMPTYI_P_C1(...) M_COMMA_P(M_EMPTYI_DETECT __VA_ARGS__ () ) +#define EX +#define empty(x) +#define fnlike(x) yeah x +/* If the following macro is called with empty arg (X183), the use + of 'x' between fnlike and '(' doesn't hinder the recognition of this + being a further fnlike macro invocation. */ +#define usefnlike(x) fnlike x (x) +X181 M_EMPTYI_P_C1() +X182 M_EMPTYI_P_C1(x) +X183 usefnlike() + +#define ABC(x) ABC : x +#define A(a,b,c) a ## b ## c +#define B(a,b,c) A(a,b,c) +#define C(a,b,c) a b c +B( + C(A,C(,,),), + C(B(,,),B,B(,,)), + C(B(,,),B(,,),C) + )/* */(a b c) + +#define TEST(x) TEST : x +#define K(a,b) a ## b +#define L(a,b) K( TE a , b ST ) +L(,)(t e s t) diff --git a/lib/tinycc/tests/pp/18.expect b/lib/tinycc/tests/pp/18.expect new file mode 100644 index 000000000..a8d1a4c27 --- /dev/null +++ b/lib/tinycc/tests/pp/18.expect @@ -0,0 +1,5 @@ +X181 1 +X182 0 +X183 yeah +ABC : a b c +TEST : t e s t diff --git a/lib/tinycc/tests/pp/19.c b/lib/tinycc/tests/pp/19.c new file mode 100644 index 000000000..aa91abe0d --- /dev/null +++ b/lib/tinycc/tests/pp/19.c @@ -0,0 +1,101 @@ +#define M_C2I(a, ...) a ## __VA_ARGS__ +#define M_C(a, ...) M_C2I(a, __VA_ARGS__) +#define M_C3I(a, b, ...) a ## b ## __VA_ARGS__ +#define M_C3(a, b, ...) M_C3I(a ,b, __VA_ARGS__) + +#define M_RETI_ARG2(a, b, ...) b +#define M_RET_ARG2(...) M_RETI_ARG2(__VA_ARGS__) +#define M_RETI_ARG27(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,aa, ...) aa +#define M_RET_ARG27(...) M_RETI_ARG27(__VA_ARGS__) + +#define M_TOBOOLI_0 1, 0, +#define M_BOOL(x) M_RET_ARG2(M_C(M_TOBOOLI_, x), 1, useless) + +#define M_IFI_0(true_macro, ...) __VA_ARGS__ +#define M_IFI_1(true_macro, ...) true_macro +#define M_IF(c) M_C(M_IFI_, M_BOOL(c)) + +#define M_FLAT(...) __VA_ARGS__ +#define M_INVI_0 1 +#define M_INVI_1 0 +#define M_INV(x) M_C(M_INVI_, x) + +#define M_ANDI_00 0 +#define M_ANDI_01 0 +#define M_ANDI_10 0 +#define M_ANDI_11 1 +#define M_AND(x,y) M_C3(M_ANDI_, x, y) + +#define M_ORI_00 0 +#define M_ORI_01 1 +#define M_ORI_10 1 +#define M_ORI_11 1 +#define M_OR(x,y) M_C3(M_ORI_, x, y) + +#define M_COMMA_P(...) M_RET_ARG27(__VA_ARGS__, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, useless) + +#define M_EMPTYI_DETECT(...) 0, 1, +#define M_EMPTYI_P_C1(...) M_COMMA_P(M_EMPTYI_DETECT __VA_ARGS__ ()) +#define M_EMPTYI_P_C2(...) M_COMMA_P(M_EMPTYI_DETECT __VA_ARGS__) +#define M_EMPTYI_P_C3(...) M_COMMA_P(__VA_ARGS__ () ) +#define M_EMPTY_P(...) M_AND(M_EMPTYI_P_C1(__VA_ARGS__), M_INV(M_OR(M_OR(M_EMPTYI_P_C2(__VA_ARGS__), M_COMMA_P(__VA_ARGS__)),M_EMPTYI_P_C3(__VA_ARGS__)))) +#define M_APPLY_FUNC2B(func, arg1, arg2) \ + M_IF(M_EMPTY_P(arg2))(,func(arg1, arg2)) +#define M_MAP2B_0(func, data, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z,...) \ + M_APPLY_FUNC2B(func, data, a) M_APPLY_FUNC2B(func, data, b) M_APPLY_FUNC2B(func, data, c) \ + M_APPLY_FUNC2B(func, data, d) M_APPLY_FUNC2B(func, data, e) M_APPLY_FUNC2B(func, data, f) \ + M_APPLY_FUNC2B(func, data, g) M_APPLY_FUNC2B(func, data, h) M_APPLY_FUNC2B(func, data, i) \ + M_APPLY_FUNC2B(func, data, j) M_APPLY_FUNC2B(func, data, k) M_APPLY_FUNC2B(func, data, l) \ + M_APPLY_FUNC2B(func, data, m) M_APPLY_FUNC2B(func, data, n) M_APPLY_FUNC2B(func, data, o) \ + M_APPLY_FUNC2B(func, data, p) M_APPLY_FUNC2B(func, data, q) M_APPLY_FUNC2B(func, data, r) \ + M_APPLY_FUNC2B(func, data, s) M_APPLY_FUNC2B(func, data, t) M_APPLY_FUNC2B(func, data, u) \ + M_APPLY_FUNC2B(func, data, v) M_APPLY_FUNC2B(func, data, w) M_APPLY_FUNC2B(func, data, x) \ + M_APPLY_FUNC2B(func, data, y) M_APPLY_FUNC2B(func, data, z) +#define M_MAP2B(f, ...) M_MAP2B_0(f, __VA_ARGS__, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ) +#define M_INIT_INIT(a) ,a, + +#define M_GET_METHOD(method, method_default, ...) \ + M_RET_ARG2 (M_MAP2B(M_C, M_C3(M_, method, _), __VA_ARGS__), method_default,) + +#define M_TEST_METHOD_P(method, oplist) \ + M_BOOL(M_GET_METHOD (method, 0, M_FLAT oplist)) + +#define TRUE 1 +#define TEST1(n) \ + M_IF(n)(ok,nok) +#define TEST2(op) \ + M_TEST_METHOD_P(INIT, op) +#define TEST3(op) \ + M_IF(M_TEST_METHOD_P(INIT, op))(ok, nok) +#define TEST4(op) \ + TEST1(TEST2(op)) +#define KO(a) ((void)1) + +/* This checks that the various expansions that ultimately lead to + something like 'KO(arg,arg)', where 'KO' comes from a macro + expansion reducing from a large macro chain do not are regarded + as funclike macro invocation of KO. E.g. X93 and X94 expand to 'KO', + but X95 must not consume the (a,b) arguments outside the M_IF() + invocation to reduce the 'KO' macro to an invocation. Instead + X95 should reduce via M_IF(KO)(a,b) to 'a'. + + The other lines here are variations on this scheme, with X1 to + X6 coming from the bug report at + http://lists.nongnu.org/archive/html/tinycc-devel/2017-07/msg00017.html */ +X92 M_IF(KO) +X93 M_GET_METHOD(INIT, 0, INIT(KO)) +X94 M_GET_METHOD(INIT, 0, M_FLAT (INIT(KO))) +X95 M_IF(M_GET_METHOD(INIT, 0, INIT(KO)))(a,b) +X96 M_IF(M_GET_METHOD(INIT, 0, M_FLAT (INIT(KO)))) +X97 M_IF(M_GET_METHOD(INIT, 0, M_FLAT (INIT(KO))))(ok,nok) +X98 (M_TEST_METHOD_P(INIT, (INIT(KO))))(ok, nok) +X99 M_IF(M_TEST_METHOD_P(INIT, (INIT(KO))))(ok, nok) +// test begins +X1 TEST1(TRUE) // ==> expect ok, get ok +// First test with a token which is not a macro +X2 TEST2((INIT(ok))) // ==> expect 1, get 1 +X3 TEST3((INIT(ok))) // ==> expect ok, get ok +// Then test with a token which is a macro, but should not be expanded. +X4 TEST2((INIT(KO))) // ==> expect 1, get 1 +X5 TEST4(INIT(KO)) +X6 TEST3((INIT(KO))) // ==> expect ok, get "error: macro 'KO' used with too many args" diff --git a/lib/tinycc/tests/pp/19.expect b/lib/tinycc/tests/pp/19.expect new file mode 100644 index 000000000..08c08581e --- /dev/null +++ b/lib/tinycc/tests/pp/19.expect @@ -0,0 +1,14 @@ +X92 M_IFI_1 +X93 KO +X94 KO +X95 a +X96 M_IFI_1 +X97 ok +X98 (1)(ok, nok) +X99 ok +X1 ok +X2 1 +X3 ok +X4 1 +X5 nok +X6 ok diff --git a/lib/tinycc/tests/pp/20.c b/lib/tinycc/tests/pp/20.c new file mode 100644 index 000000000..7944d62bc --- /dev/null +++ b/lib/tinycc/tests/pp/20.c @@ -0,0 +1,13 @@ +/* Various things I encountered while hacking the pre processor */ +#define wrap(x) x +#define pr_warning(fmt, ...) printk(KERN_WARNING fmt, ##__VA_ARGS__) +#define pr_warn(x,y) pr_warning(x,y) +#define net_ratelimited_function(function, ...) function(__VA_ARGS__) +X1 net_ratelimited_function(pr_warn, "pipapo", bla); +X2 net_ratelimited_function(wrap(pr_warn), "bla", foo); +#define two m n +#define chain4(a,b,c,d) a ## b ## c ## d +X2 chain4(two,o,p,q) +X3 chain4(o,two,p,q) +X4 chain4(o,p,two,q) +X5 chain4(o,p,q,two) diff --git a/lib/tinycc/tests/pp/20.expect b/lib/tinycc/tests/pp/20.expect new file mode 100644 index 000000000..d19405d74 --- /dev/null +++ b/lib/tinycc/tests/pp/20.expect @@ -0,0 +1,6 @@ +X1 printk(KERN_WARNING "pipapo",bla); +X2 printk(KERN_WARNING "bla",foo); +X2 twoopq +X3 otwopq +X4 optwoq +X5 opqtwo diff --git a/lib/tinycc/tests/pp/21.c b/lib/tinycc/tests/pp/21.c new file mode 100644 index 000000000..c28988d4f --- /dev/null +++ b/lib/tinycc/tests/pp/21.c @@ -0,0 +1,41 @@ +/* accept 'defined' as result of substitution */ + +----- 1 ------ +#define AAA 2 +#define BBB +#define CCC (defined ( AAA ) && AAA > 1 && !defined BBB) +#if !CCC +OK +#else +NOT OK +#endif + +----- 2 ------ +#undef BBB +#if CCC +OK +#else +NOT OK +#endif + +----- 3 ------ +#define DEFINED defined +#define DDD (DEFINED ( AAA ) && AAA > 1 && !DEFINED BBB) +#if (DDD) +OK +#else +NOT OK +#endif + +----- 4 ------ +#undef AAA +#if !(DDD) +OK +#else +NOT OK +#endif + +----- 5 ------ +line __LINE__ +#define __LINE__ # ## # +line __LINE__ diff --git a/lib/tinycc/tests/pp/21.expect b/lib/tinycc/tests/pp/21.expect new file mode 100644 index 000000000..297b4d4c5 --- /dev/null +++ b/lib/tinycc/tests/pp/21.expect @@ -0,0 +1,11 @@ +----- 1 ------ +OK +----- 2 ------ +OK +----- 3 ------ +OK +----- 4 ------ +OK +----- 5 ------ +line 39 +line ## diff --git a/lib/tinycc/tests/pp/22.c b/lib/tinycc/tests/pp/22.c new file mode 100644 index 000000000..76e23154b --- /dev/null +++ b/lib/tinycc/tests/pp/22.c @@ -0,0 +1,12 @@ +#define TRACE(a,b,c) X a X b X c X +#define rettrue(x) 1 +A rettrue(bla) B +TRACE( + ARG_1, +#if rettrue(bla) + ARG_2, +#else + ARG_2_wrong, +#endif + ARG_3 +); diff --git a/lib/tinycc/tests/pp/22.expect b/lib/tinycc/tests/pp/22.expect new file mode 100644 index 000000000..ceaea0301 --- /dev/null +++ b/lib/tinycc/tests/pp/22.expect @@ -0,0 +1,2 @@ +A 1 B +X ARG_1 X ARG_2 X ARG_3 X; diff --git a/lib/tinycc/tests/pp/Makefile b/lib/tinycc/tests/pp/Makefile new file mode 100644 index 000000000..7e989c99f --- /dev/null +++ b/lib/tinycc/tests/pp/Makefile @@ -0,0 +1,55 @@ +# +# credits: 01..13.c from the pcc cpp-tests suite +# + +TOP = ../.. +include $(TOP)/Makefile +SRC = $(TOPSRC)/tests/pp +VPATH = $(SRC) + +files = $(patsubst %.$1,%.test,$(notdir $(wildcard $(SRC)/*.$1))) +TESTS = $(call files,c) $(call files,S) + +all test testspp.all: $(sort $(TESTS)) + +DIFF_OPTS = -Nu -b + +# Filter source directory in warnings/errors (out-of-tree builds) +FILTER = 2>&1 | sed 's,$(SRC)/,,g' + +%.test: %.c %.expect + @echo PPTest $* ... + -@$(TCC) -E -P $< $(FILTER) >$*.output 2>&1 ; \ + diff $(DIFF_OPTS) $(SRC)/$*.expect $*.output \ + && rm -f $*.output + +%.test: %.S %.expect + @echo PPTest $* ... + -@$(TCC) -E -P $< $(FILTER) >$*.output 2>&1 ; \ + diff $(DIFF_OPTS) $(SRC)/$*.expect $*.output \ + && rm -f $*.output + +testspp.%: %.test ; + +# generate .expect file with tcc, e.g. "make testspp.17+" +testspp.%+: %.c + $(TCC) -E -P $*.[cS] -o $*.expect + +# automatically generate .expect files with gcc: +%.expect: # %.c + gcc -E -P $*.[cS] >$*.expect 2>&1 + +# tell make not to delete +.PRECIOUS: %.expect + +clean: + rm -f *.output + +02.test : DIFF_OPTS += -w +# 15.test : DIFF_OPTS += -I"^XXX:" + +# diff options: +# -b ighore space changes +# -w ighore all whitespace +# -B ignore blank lines +# -I ignore lines matching RE diff --git a/lib/tinycc/tests/pp/pp-counter.c b/lib/tinycc/tests/pp/pp-counter.c new file mode 100644 index 000000000..3978e1a7e --- /dev/null +++ b/lib/tinycc/tests/pp/pp-counter.c @@ -0,0 +1,27 @@ +X1 __COUNTER__ +X2 __COUNTER__ +#if __COUNTER__ +X3 __COUNTER__ +#endif +#define pass(x) x +#define a x __COUNTER__ y +#define a2 pass(__COUNTER__) +#define f(c) c __COUNTER__ +#define apply(d) d d __COUNTER__ x2 f(d) y2 __COUNTER__ +#define _paste(a,b) a ## b +#define paste(a,b) _paste(a,b) +#define _paste3(a,b,c) a ## b ## c +#define doublepaste(a,b) _paste3(a,b,b) +#define str(x) #x +X4 a +X5 f(a) +X6 f(b) +X7 f(__COUNTER__) +X8 apply(a) +X9 apply(f(a)) +X10 apply(__COUNTER__) +X11 apply(a2) +X12 str(__COUNTER__) +X13 paste(x,__COUNTER__) +X14 _paste(x,__COUNTER__) +X15 doublepaste(x,__COUNTER__) diff --git a/lib/tinycc/tests/pp/pp-counter.expect b/lib/tinycc/tests/pp/pp-counter.expect new file mode 100644 index 000000000..02fc535bc --- /dev/null +++ b/lib/tinycc/tests/pp/pp-counter.expect @@ -0,0 +1,15 @@ +X1 0 +X2 1 +X3 3 +X4 x 4 y +X5 x 5 y 6 +X6 b 7 +X7 8 9 +X8 x 10 y x 10 y 11 x2 x 10 y 12 y2 13 +X9 x 14 y 15 x 14 y 15 16 x2 x 14 y 15 17 y2 18 +X10 19 19 20 x2 19 21 y2 22 +X11 23 23 24 x2 23 25 y2 26 +X12 "__COUNTER__" +X13 x27 +X14 x__COUNTER__ +X15 x2828 diff --git a/lib/tinycc/tests/tcctest.c b/lib/tinycc/tests/tcctest.c new file mode 100644 index 000000000..279e35c15 --- /dev/null +++ b/lib/tinycc/tests/tcctest.c @@ -0,0 +1,4498 @@ +/* + * TCC auto test program + */ +#include "config.h" + +/* identify the configured reference compiler in use */ +#define CC_gcc 1 +#define CC_clang 2 +#define CC_tcc 3 + +/* Unfortunately, gcc version < 3 does not handle that! */ +#define ALL_ISOC99 + +/* only gcc 3 handles _Bool correctly */ +#define BOOL_ISOC99 + +/* __VA_ARGS__ and __func__ support */ +#define C99_MACROS + +#ifndef __TINYC__ +typedef __SIZE_TYPE__ uintptr_t; +#endif + +#if defined(_WIN32) \ + || (defined(__arm__) \ + && (defined(__FreeBSD__) \ + || defined(__OpenBSD__) \ + || defined(__NetBSD__) \ + || defined __ANDROID__)) +#define LONG_LONG_FORMAT "%lld" +#define ULONG_LONG_FORMAT "%llu" +#define XLONG_LONG_FORMAT "%llx" +#else +#define LONG_LONG_FORMAT "%Ld" +#define ULONG_LONG_FORMAT "%Lu" +#define XLONG_LONG_FORMAT "%Lx" +#endif + +// MinGW has 80-bit rather than 64-bit long double which isn't compatible with TCC or MSVC +#if defined(_WIN32) && defined(__GNUC__) +#define LONG_DOUBLE double +#define LONG_DOUBLE_LITERAL(x) x +#else +#define LONG_DOUBLE long double +#define LONG_DOUBLE_LITERAL(x) x ## L +#endif + +/* test various include syntaxes */ + +#define TCCLIB_INC +#define TCCLIB_INC1 +#define TCCLIB_INC3 "tcclib.h" + +#include TCCLIB_INC + +#include TCCLIB_INC1.TCCLIB_INC2 + +#include TCCLIB_INC1.h> + +#include TCCLIB_INC3 + +#include + +#include "tcclib.h" + +#include "tcctest.h" + +/* Test two more ways to include a file named like a pp-number */ +#define INC(name) +#define funnyname 42test.h +#define incdir tests/ +#ifdef __clang__ +/* clang's preprocessor is broken in this regard and adds spaces + to the tokens 'incdir' and 'funnyname' when expanding */ +#define incname +#else +#define incname < incdir funnyname > +#endif +#define __stringify(x) #x +#define stringify(x) __stringify(x) +#include INC(42test) +#include incname +#include stringify(funnyname) + +int puts(const char *s); +void *alloca(size_t size); + +int fib(int n); +void num(int n); +void forward_ref(void); +int isid(int c); + +/* Line joining happens before tokenization, so the following + must be parsed as ellipsis. */ +void funny_line_continuation (int, ..\ +. ); + +#define A 2 +#define N 1234 + A +#define pf printf +#define M1(a, b) (a) + (b) + +#define str\ +(s) # s +#define glue(a, b) a ## b +#define xglue(a, b) glue(a, b) +#define HIGHLOW "hello" +#define LOW LOW ", world" + +static int onetwothree = 123; +#define onetwothree4 onetwothree +#define onetwothree xglue(onetwothree,4) + +#define min(a, b) ((a) < (b) ? (a) : (b)) + +#ifdef C99_MACROS +#define dprintf(level,...) printf(__VA_ARGS__) +#endif + +/* gcc vararg macros */ +#define dprintf1(level, fmt, args...) printf(fmt, ## args) + +#define MACRO_NOARGS() + +#define TEST_CALL(f, ...) f(__VA_ARGS__) +#define TEST_CONST() 123 + +#define AAA 3 +#undef AAA +#define AAA 4 + +#if 1 +#define B3 1 +#elif 1 +#define B3 2 +#elif 0 +#define B3 3 +#else +#define B3 4 +#endif + +#define __INT64_C(c) c ## LL +#define INT64_MIN (-__INT64_C(9223372036854775807)-1) + +int qq(int x) +{ + return x + 40; +} +#define qq(x) x + +#define spin_lock(lock) do { } while (0) +#define wq_spin_lock spin_lock +#define TEST2() wq_spin_lock(a) + +void macro_test(void) +{ + pf("N=%d\n", N); + printf("aaa=%d\n", AAA); + + printf("min=%d\n", min(1, min(2, -1))); + + printf("s1=%s\n", glue(HIGH, LOW)); + printf("s2=%s\n", xglue(HIGH, LOW)); + printf("s3=%s\n", str("c")); + printf("s4=%s\n", str(a1)); + printf("B3=%d\n", B3); + + printf("onetwothree=%d\n", onetwothree); + +#ifdef A + printf("A defined\n"); +#endif +#ifdef B + printf("B defined\n"); +#endif +#ifdef A + printf("A defined\n"); +#else + printf("A not defined\n"); +#endif +#ifdef B + printf("B defined\n"); +#else + printf("B not defined\n"); +#endif + +#ifdef A + printf("A defined\n"); +#ifdef B + printf("B1 defined\n"); +#else + printf("B1 not defined\n"); +#endif +#else + printf("A not defined\n"); +#ifdef B + printf("B2 defined\n"); +#else + printf("B2 not defined\n"); +#endif +#endif + +#if 1+1 + printf("test true1\n"); +#endif +#if 0 + printf("test true2\n"); +#endif +#if 1-1 + printf("test true3\n"); +#endif +#if defined(A) + printf("test trueA\n"); +#endif +#if defined(B) + printf("test trueB\n"); +#endif + +#if 0 + printf("test 0\n"); +#elif 0 + printf("test 1\n"); +#elif 2 + printf("test 2\n"); +#else + printf("test 3\n"); +#endif + + MACRO_NOARGS(); + + printf("%d\n", TEST_CALL(TEST_CONST)); + + /* not strictly preprocessor, but we test it there */ +#ifdef C99_MACROS + printf("__func__ = %s\n", __func__); + dprintf(1, "vaarg=%d\n", 1); +#endif + dprintf1(1, "vaarg1\n"); + dprintf1(1, "vaarg1=%d\n", 2); + dprintf1(1, "vaarg1=%d %d\n", 1, 2); + + /* gcc extension */ + printf("func='%s'\n", __FUNCTION__); + + /* complicated macros in glibc */ + printf("INT64_MIN=" LONG_LONG_FORMAT "\n", INT64_MIN); + { + int a; + a = 1; + glue(a+, +); + printf("a=%d\n", a); + glue(a <, <= 2); + printf("a=%d\n", a); + } + + /* macro function with argument outside the macro string */ +#define MF_s MF_hello +#define MF_hello(msg) printf("%s\n",msg) + +#define MF_t printf("tralala\n"); MF_hello + + MF_s("hi"); + MF_t("hi"); + + /* test macro substitution inside args (should not eat stream) */ + printf("qq=%d\n", qq(qq)(2)); + + /* test zero argument case. NOTE: gcc 2.95.x does not accept a + null argument without a space. gcc 3.2 fixes that. */ + +#define qq1(x) 1 + printf("qq1=%d\n", qq1( )); + + /* comment with stray handling *\ +/ + /* this is a valid *\/ comment */ + /* this is a valid comment *\*/ + // this is a valid\ +comment + + /* test function macro substitution when the function name is + substituted */ + TEST2(); + + /* And again when the name and parentheses are separated by a + comment. */ + TEST2 /* the comment */ (); + + printf("basefromheader %s\n", get_basefile_from_header()); + printf("base %s\n", __BASE_FILE__); + { + /* Some compilers (clang) prepend './' to __FILE__ from included + files. */ + const char *fn = get_file_from_header(); + if (fn[0] == '.' && fn[1] == '/') + fn += 2; + printf("filefromheader %s\n", fn); + } + printf("file %s\n", __FILE__); + + /* Check that funnily named include was in fact included */ + have_included_42test_h = 1; + have_included_42test_h_second = 1; + have_included_42test_h_third = 1; + + /* Check that we don't complain about stray \ here */ + printf("print a backslash: %s\n", stringify(\\)); +} + + +static void print_num(char *fn, int line, int num) { + printf("fn %s, line %d, num %d\n", fn, line, num); +} + +void recursive_macro_test(void) +{ + +#define ELF32_ST_TYPE(val) ((val) & 0xf) +#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) +#define STB_WEAK 2 /* Weak symbol */ +#define ELFW(type) ELF##32##_##type + printf("%d\n", ELFW(ST_INFO)(STB_WEAK, ELFW(ST_TYPE)(123))); + +#define WRAP(x) x + +#define print_num(x) print_num(__FILE__,__LINE__,x) + print_num(123); + WRAP(print_num(123)); + WRAP(WRAP(print_num(123))); + +static struct recursive_macro { int rm_field; } G; +#define rm_field (G.rm_field) + printf("rm_field = %d\n", rm_field); + printf("rm_field = %d\n", WRAP(rm_field)); + WRAP((printf("rm_field = %d %d\n", rm_field, WRAP(rm_field)))); +} + +#if __TINYC__ +int op(a, b) +{ + return a / b; +} + +int ret(a) +{ + if (a == 2) + return 1; + if (a == 3) + return 2; + return 0; +} +#endif + +#if !defined(__TINYC__) && (__GNUC__ >= 8) +/* Old GCCs don't regard "foo"[1] as constant, even in GNU dialect. */ +#define CONSTANTINDEXEDSTRLIT +#endif +char str_ag1[] = "b"; +char str_ag2[] = { "b" }; +/*char str_bg1[] = ("cccc"); GCC accepts this with pedantic warning, TCC not */ +#ifdef CONSTANTINDEXEDSTRLIT +char str_ag3[] = { "ab"[1], 0 }; +char str_x[2] = { "xy" "z"[2], 0 }; +#endif +char *str_ar[] = { "one", "two" }; +struct str_SS {unsigned char a[3], b; }; +struct str_SS str_sinit15 = { "r" }; +struct str_SS str_sinit16[] = { { "q" }, 2 }; + +static void string_test2() +{ + char *p = "hello"; + char a3[2] = { "p" }; + char a4[2] = { "ab" "c"[2], 0 }; + char *pa1 = "def" + 1; + char *pa2 = { "xyz" + 1 }; + int i = 0; + struct str_SS ss = { { [0 ... 1] = 'a' }, 0 }; +#ifndef CONSTANTINDEXEDSTRLIT + char str_ag3[] = { "ab"[1], 0 }; + char str_x[2] = { "xy" "z"[2], 0 }; +#endif + puts("string_test2"); + puts(str_ag1); + puts(str_ag2); + /*puts(str_bg1);*/ + puts(str_ag3); + puts(str_x); + puts(str_sinit15.a); + puts(str_sinit16[0].a); + puts(a3); + puts(a4); + puts(p); + puts("world"); + printf("%s\n", "bla"); + puts(str_ar[0]); + puts(str_ar[1]); + puts(ss.a); + puts(i >= 0 ? "one" : "two"); + puts(pa1); + puts(pa2); +} + +void ps(const char *s) +{ + int c; + while (1) { + c = *s; + if (c == 0) + break; + printf("%c", c); + s++; + } +} + +const char foo1_string[] = "\ +bar\n\ +test\14\ +1"; + +void string_test() +{ + unsigned int b; + printf("string:\n"); + printf("\141\1423\143\n");/* dezdez test */ + printf("\x41\x42\x43\x3a\n"); + printf("c=%c\n", 'r'); + printf("wc=%C 0x%lx %C\n", L'a', L'\x1234', L'c'); + printf("foo1_string='%s'\n", foo1_string); +#if 0 + printf("wstring=%S\n", L"abc"); + printf("wstring=%S\n", L"abc" L"def" "ghi"); + printf("'\\377'=%d '\\xff'=%d\n", '\377', '\xff'); + printf("L'\\377'=%d L'\\xff'=%d\n", L'\377', L'\xff'); +#endif + ps("test\n"); + b = 32; + while ((b = b + 1) < 96) { + printf("%c", b); + } + printf("\n"); + printf("fib=%d\n", fib(33)); + b = 262144; + while (b != 0x80000000) { + num(b); + b = b * 2; + } + string_test2(); +} + + +void if1t(int n, int a, int b, int c) +{ + if (a && b) printf("if1t: %d 1 %d %d\n", n, a, b); + if (a && !b) printf("if1t: %d 2 %d %d\n", n, a, b); + if (!a && b) printf("if1t: %d 3 %d %d\n", n, a, b); + if (!a && !b) printf("if1t: %d 4 %d %d\n", n, a, b); + if (a || b) printf("if1t: %d 5 %d %d\n", n, a, b); + if (a || !b) printf("if1t: %d 6 %d %d\n", n, a, b); + if (!a || b) printf("if1t: %d 7 %d %d\n", n, a, b); + if (!a || !b) printf("if1t: %d 8 %d %d\n", n, a, b); + if (a && b || c) printf("if1t: %d 9 %d %d %d\n", n, a, b, c); + if (a || b && c) printf("if1t: %d 10 %d %d %d\n", n, a, b, c); + if (a > b - 1 && c) printf("if1t: %d 11 %d %d %d\n", n, a, b, c); + if (a > b - 1 || c) printf("if1t: %d 12 %d %d %d\n", n, a, b, c); + if (a > 0 && 1) printf("if1t: %d 13 %d %d %d\n", n, a, b, c); + if (a > 0 || 0) printf("if1t: %d 14 %d %d %d\n", n, a, b, c); +} + +void if2t(void) +{ + if (0 && 1 || printf("if2t:ok\n") || 1) + printf("if2t:ok2\n"); + printf("if2t:ok3\n"); +} + +void if3t(void) +{ + volatile long long i = 1; + if (i <= 18446744073709551615ULL) + ; + else + printf ("if3t:wrong 1\n"); +} + +void if_test(void) +{ + if1t(1, 0, 0, 0); + if1t(2, 0, 3, 0); + if1t(3, 2, 0, 0); + if1t(4, 2, 3, 0); + if2t(); + if3t(); +} + +void loop_test() +{ + int i; + i = 0; + while (i < 10) + printf("%d", i++); + printf("\n"); + for(i = 0; i < 10;i++) + printf("%d", i); + printf("\n"); + i = 0; + do { + printf("%d", i++); + } while (i < 10); + printf("\n"); + + char count = 123; + /* c99 for loop init test */ + for (size_t count = 1; count < 3; count++) + printf("count=%d\n", count); + printf("count = %d\n", count); + + /* break/continue tests */ + i = 0; + while (1) { + if (i == 6) + break; + i++; + if (i == 3) + continue; + printf("%d", i); + } + printf("\n"); + + /* break/continue tests */ + i = 0; + do { + if (i == 6) + break; + i++; + if (i == 3) + continue; + printf("%d", i); + } while(1); + printf("\n"); + + for(i = 0;i < 10;i++) { + if (i == 3) + continue; + printf("%d", i); + } + printf("\n"); +} + +typedef int typedef_and_label; + +void goto_test() +{ + int i; + static void *label_table[3] = { &&label1, &&label2, &&label3 }; + struct { + int bla; + /* This needs to parse as typedef, not as label. */ + typedef_and_label : 32; + } y = {1}; + + printf("\ngoto:\n"); + i = 0; + /* This is a normal decl. */ + typedef_and_label x; + /* This needs to parse as label, not as start of decl. */ + typedef_and_label: + s_loop: + if (i >= 10) + goto s_end; + printf("%d", i); + i++; + goto s_loop; + s_end: + printf("\n"); + + /* we also test computed gotos (GCC extension) */ + for(i=0;i<3;i++) { + goto *label_table[i]; + label1: + printf("label1\n"); + goto next; + label2: + printf("label2\n"); + goto next; + label3: + printf("label3\n"); + next: ; + } +} + +enum { + E0, + E1 = 2, + E2 = 4, + E3, + E4, +}; + +enum test { + E5 = 1000, +}; + +struct S_enum { + enum {E6 = 42, E7, E8} e:8; +}; + +enum ELong { + /* This is either 0 on L32 machines, or a large number + on L64 machines. We should be able to store this. */ + EL_large = ((unsigned long)0xf000 << 31) << 1, +}; + +enum { BIASU = -1U<<31 }; +enum { BIASS = -1 << 31 }; + +static int getint(int i) +{ + if (i) + return 0; + else + return (int)(-1U << 31); +} + +void enum_test() +{ + enum test b1; + /* The following should give no warning */ + unsigned *p = &b1; + struct S_enum s = {E7}; + printf("%d %d %d %d %d %d %d\n", s.e, + E0, E1, E2, E3, E4, E5); + b1 = 1; + printf("b1=%d\n", b1); + printf("enum large: %ld\n", EL_large); + + if (getint(0) == BIASU) + printf("enum unsigned: ok\n"); + else + printf("enum unsigned: wrong\n"); + if (getint(0) == BIASS) + printf("enum unsigned: ok\n"); + else + printf("enum unsigned: wrong\n"); +} + +typedef int *my_ptr; + +typedef int mytype1; +typedef int mytype2; + +void typedef_test() +{ + my_ptr a; + mytype1 mytype2; + int b; + + a = &b; + *a = 1234; + printf("a=%d\n", *a); + mytype2 = 2; + printf("mytype2=%d\n", mytype2); +} + +void forward_test() +{ + forward_ref(); + forward_ref(); +} + + +void forward_ref(void) +{ + printf("forward ok\n"); +} + +typedef struct struct1 { + int f1; + int f2, f3; + union union1 { + int v1; + int v2; + } u; + char str[3]; +} struct1; + +struct struct2 { + int a; + char b; +}; + +union union2 { + int w1; + int w2; +}; + +struct struct1 st1, st2; + +struct empty_mem { + /* nothing */ ; + int x; +}; + +int tab[3]; +int tab2[3][2]; + +int g; + +void f1(int g) +{ + printf("g1=%d\n", g); +} + +void scope_test() +{ + g = 2; + f1(1); + printf("g2=%d\n", g); + { + int g; + g = 3; + printf("g3=%d\n", g); + { + int g; + g = 4; + printf("g4=%d\n", g); + } + } + printf("g5=%d\n", g); +} + +int st2_i; +int *st2_p = &st2_i; +void scope2_test() +{ + char a[50]; + st2_i = 42; + for (int st2_i = 1; st2_i < 10; st2_i++) { + extern int st2_i; + st2_i++; + printf("exloc: %d\n", st2_i); + } + printf("exloc: %d\n", *st2_p); +} + +/* C has tentative definition, and they may be repeated. */ +extern int st_global1; +int st_global1=42; +extern int st_global1; +int st_global1; +extern int st_global2; +int st_global2; +extern int st_global2; +int st_global2; + +void array_test() +{ + int i, j, a[4]; + + printf("sizeof(a) = %d\n", sizeof(a)); + printf("sizeof(\"a\") = %d\n", sizeof("a")); +#ifdef C99_MACROS + printf("sizeof(__func__) = %d\n", sizeof(__func__)); +#endif + printf("sizeof tab %d\n", sizeof(tab)); + printf("sizeof tab2 %d\n", sizeof tab2); + tab[0] = 1; + tab[1] = 2; + tab[2] = 3; + printf("%d %d %d\n", tab[0], tab[1], tab[2]); + for(i=0;i<3;i++) + for(j=0;j<2;j++) + tab2[i][j] = 10 * i + j; + for(i=0;i<3*2;i++) { + printf(" %3d", ((int *)tab2)[i]); + } + printf("\n"); + printf("sizeof(size_t)=%d\n", sizeof(size_t)); + printf("sizeof(ptrdiff_t)=%d\n", sizeof(ptrdiff_t)); +} + +void expr_test() +{ + int a, b; + a = 0; + printf("%d\n", a += 1); + printf("%d\n", a -= 2); + printf("%d\n", a *= 31232132); + printf("%d\n", a /= 4); + printf("%d\n", a %= 20); + printf("%d\n", a &= 6); + printf("%d\n", a ^= 7); + printf("%d\n", a |= 8); + printf("%d\n", a >>= 3); + printf("%d\n", a <<= 4); + + a = 22321; + b = -22321; + printf("%d\n", a + 1); + printf("%d\n", a - 2); + printf("%d\n", a * 312); + printf("%d\n", a / 4); + printf("%d\n", b / 4); + printf("%d\n", (unsigned)b / 4); + printf("%d\n", a % 20); + printf("%d\n", b % 20); + printf("%d\n", (unsigned)b % 20); + printf("%d\n", a & 6); + printf("%d\n", a ^ 7); + printf("%d\n", a | 8); + printf("%d\n", a >> 3); + printf("%d\n", b >> 3); + printf("%d\n", (unsigned)b >> 3); + printf("%d\n", a << 4); + printf("%d\n", ~a); + printf("%d\n", -a); + printf("%d\n", +a); + + printf("%d\n", 12 + 1); + printf("%d\n", 12 - 2); + printf("%d\n", 12 * 312); + printf("%d\n", 12 / 4); + printf("%d\n", 12 % 20); + printf("%d\n", 12 & 6); + printf("%d\n", 12 ^ 7); + printf("%d\n", 12 | 8); + printf("%d\n", 12 >> 2); + printf("%d\n", 12 << 4); + printf("%d\n", ~12); + printf("%d\n", -12); + printf("%d\n", +12); + printf("%d %d %d %d\n", + isid('a'), + isid('g'), + isid('T'), + isid('(')); +} + +int isid(int c) +{ + return (c >= 'a' & c <= 'z') | (c >= 'A' & c <= 'Z') | c == '_'; +} + +/**********************/ + +int vstack[10], *vstack_ptr; + +void vpush(int vt, int vc) +{ + *vstack_ptr++ = vt; + *vstack_ptr++ = vc; +} + +void vpop(int *ft, int *fc) +{ + *fc = *--vstack_ptr; + *ft = *--vstack_ptr; +} + +void expr2_test() +{ + int a, b; + + vstack_ptr = vstack; + vpush(1432432, 2); + vstack_ptr[-2] &= ~0xffffff80; + vpop(&a, &b); + printf("res= %d %d\n", a, b); +} + +int const_len_ar[sizeof(1/0)]; /* div-by-zero, but in unevaluated context */ + +void constant_expr_test() +{ + int a; + a = 3; + printf("%d\n", a * 16); + printf("%d\n", a * 1); + printf("%d\n", a + 0); + printf("%d\n", sizeof(const_len_ar)); +} + +int tab4[10]; + +void expr_ptr_test() +{ + int arr[10], *p, *q; + int i = -1; + + p = tab4; + q = tab4 + 10; + printf("diff=%d\n", q - p); + p++; + printf("inc=%d\n", p - tab4); + p--; + printf("dec=%d\n", p - tab4); + ++p; + printf("inc=%d\n", p - tab4); + --p; + printf("dec=%d\n", p - tab4); + printf("add=%d\n", p + 3 - tab4); + printf("add=%d\n", 3 + p - tab4); + + /* check if 64bit support is ok */ + q = p = 0; + q += i; + printf("%p %p %ld\n", q, p, p-q); + printf("%d %d %d %d %d %d\n", + p == q, p != q, p < q, p <= q, p >= q, p > q); + i = 0xf0000000; + p += i; + printf("%p %p %ld\n", q, p, p-q); + printf("%d %d %d %d %d %d\n", + p == q, p != q, p < q, p <= q, p >= q, p > q); + p = (int *)((char *)p + 0xf0000000); + printf("%p %p %ld\n", q, p, p-q); + printf("%d %d %d %d %d %d\n", + p == q, p != q, p < q, p <= q, p >= q, p > q); + p += 0xf0000000; + printf("%p %p %ld\n", q, p, p-q); + printf("%d %d %d %d %d %d\n", + p == q, p != q, p < q, p <= q, p >= q, p > q); + { + struct size12 { + int i, j, k; + }; + struct size12 s[2], *sp = s; + int i, j; + sp->i = 42; + sp++; + j = -1; + printf("%d\n", sp[j].i); + } +#ifdef __LP64__ + i = 1; + p = (int*)0x100000000UL + i; + i = ((long)p) >> 32; + printf("largeptr: %p %d\n", p, i); +#endif + p = &arr[0]; + q = p + 3; + printf ("%d\n", (int)((p - q) / 3)); +} + +void expr_cmp_test() +{ + int a, b; + a = -1; + b = 1; + printf("%d\n", a == a); + printf("%d\n", a != a); + + printf("%d\n", a < b); + printf("%d\n", a <= b); + printf("%d\n", a <= a); + printf("%d\n", b >= a); + printf("%d\n", a >= a); + printf("%d\n", b > a); + + printf("%d\n", (unsigned)a < b); + printf("%d\n", (unsigned)a <= b); + printf("%d\n", (unsigned)a <= a); + printf("%d\n", (unsigned)b >= a); + printf("%d\n", (unsigned)a >= a); + printf("%d\n", (unsigned)b > a); +} + +struct empty { +}; + +struct aligntest1 { + char a[10]; +}; + +struct aligntest2 { + int a; + char b[10]; +}; + +struct aligntest3 { + double a, b; +}; + +struct aligntest4 { + double a[0]; +}; + +struct __attribute__((aligned(16))) aligntest5 +{ + int i; +}; +struct aligntest6 +{ + int i; +} __attribute__((aligned(16))); +struct aligntest7 +{ + int i; +}; +struct aligntest5 altest5[2]; +struct aligntest6 altest6[2]; +int pad1; +/* altest7 is correctly aligned to 16 bytes also with TCC, + but __alignof__ returns the wrong result (4) because we + can't store the alignment yet when specified on symbols + directly (it's stored in the type so we'd need to make + a copy of it). -- FIXED */ +struct aligntest7 altest7[2] __attribute__((aligned(16))); + +struct aligntest8 +{ + int i; +} __attribute__((aligned(4096))); + +struct Large { + unsigned long flags; + union { + void *u1; + int *u2; + }; + + struct { + union { + unsigned long index; + void *freelist; + }; + union { + unsigned long counters; + struct { + int bla; + }; + }; + }; + + union { + struct { + long u3; + long u4; + }; + void *u5; + struct { + unsigned long compound_head; + unsigned int compound_dtor; + unsigned int compound_order; + }; + }; +} __attribute__((aligned(2 * sizeof(long)))); + +typedef unsigned long long __attribute__((aligned(4))) unaligned_u64; + +struct aligntest9 { + unsigned int buf_nr; + unaligned_u64 start_lba; +}; + +struct aligntest10 { + unsigned int buf_nr; + unsigned long long start_lba; +}; + +void struct_test() +{ + struct1 *s; + union union2 u; + struct Large ls; + + printf("sizes: %d %d %d %d\n", + sizeof(struct struct1), + sizeof(struct struct2), + sizeof(union union1), + sizeof(union union2)); + printf("offsets: %d\n", (int)((char*)&st1.u.v1 - (char*)&st1)); + st1.f1 = 1; + st1.f2 = 2; + st1.f3 = 3; + printf("st1: %d %d %d\n", + st1.f1, st1.f2, st1.f3); + st1.u.v1 = 1; + st1.u.v2 = 2; + printf("union1: %d\n", st1.u.v1); + u.w1 = 1; + u.w2 = 2; + printf("union2: %d\n", u.w1); + s = &st2; + s->f1 = 3; + s->f2 = 2; + s->f3 = 1; + printf("st2: %d %d %d\n", + s->f1, s->f2, s->f3); + printf("str_addr=%x\n", (int)(uintptr_t)st1.str - (int)(uintptr_t)&st1.f1); + + /* align / size tests */ + printf("aligntest1 sizeof=%d alignof=%d\n", + sizeof(struct aligntest1), __alignof__(struct aligntest1)); + printf("aligntest2 sizeof=%d alignof=%d\n", + sizeof(struct aligntest2), __alignof__(struct aligntest2)); + printf("aligntest3 sizeof=%d alignof=%d\n", + sizeof(struct aligntest3), __alignof__(struct aligntest3)); + printf("aligntest4 sizeof=%d alignof=%d\n", + sizeof(struct aligntest4), __alignof__(struct aligntest4)); + printf("aligntest5 sizeof=%d alignof=%d\n", + sizeof(struct aligntest5), __alignof__(struct aligntest5)); + printf("aligntest6 sizeof=%d alignof=%d\n", + sizeof(struct aligntest6), __alignof__(struct aligntest6)); + printf("aligntest7 sizeof=%d alignof=%d\n", + sizeof(struct aligntest7), __alignof__(struct aligntest7)); + printf("aligntest8 sizeof=%d alignof=%d\n", + sizeof(struct aligntest8), __alignof__(struct aligntest8)); + printf("aligntest9 sizeof=%d alignof=%d\n", + sizeof(struct aligntest9), __alignof__(struct aligntest9)); + printf("aligntest10 sizeof=%d alignof=%d\n", + sizeof(struct aligntest10), __alignof__(struct aligntest10)); + printf("altest5 sizeof=%d alignof=%d\n", + sizeof(altest5), __alignof__(altest5)); + printf("altest6 sizeof=%d alignof=%d\n", + sizeof(altest6), __alignof__(altest6)); + printf("altest7 sizeof=%d alignof=%d\n", + sizeof(altest7), __alignof__(altest7)); + + /* empty structures (GCC extension) */ + printf("sizeof(struct empty) = %d\n", sizeof(struct empty)); + printf("alignof(struct empty) = %d\n", __alignof__(struct empty)); + + printf("Large: sizeof=%d\n", sizeof(ls)); + memset(&ls, 0, sizeof(ls)); + ls.compound_head = 42; + printf("Large: offsetof(compound_head)=%d\n", (int)((char*)&ls.compound_head - (char*)&ls)); +} + +/* simulate char/short return value with undefined upper bits */ +static int __csf(int x) { return x; } +static void *_csf = __csf; +#define csf(t,n) ((t(*)(int))_csf)(n) + +/* XXX: depend on endianness */ +void char_short_test() +{ + int var1, var2; + signed char var3; + long long var4; + + var1 = 0x01020304; + var2 = 0xfffefdfc; + printf("s8=%d %d\n", + *(signed char *)&var1, *(signed char *)&var2); + printf("u8=%d %d\n", + *(unsigned char *)&var1, *(unsigned char *)&var2); + printf("s16=%d %d\n", + *(short *)&var1, *(short *)&var2); + printf("u16=%d %d\n", + *(unsigned short *)&var1, *(unsigned short *)&var2); + printf("s32=%d %d\n", + *(int *)&var1, *(int *)&var2); + printf("u32=%d %d\n", + *(unsigned int *)&var1, *(unsigned int *)&var2); + *(signed char *)&var1 = 0x08; + printf("var1=%x\n", var1); + *(short *)&var1 = 0x0809; + printf("var1=%x\n", var1); + *(int *)&var1 = 0x08090a0b; + printf("var1=%x\n", var1); + + var1 = 0x778899aa; + var4 = 0x11223344aa998877ULL; + var1 = var3 = var1 + 1; + var4 = var3 = var4 + 1; + printf("promote char/short assign %d "LONG_LONG_FORMAT"\n", var1, var4); + var1 = 0x778899aa; + var4 = 0x11223344aa998877ULL; + printf("promote char/short assign VA %d %d\n", var3 = var1 + 1, var3 = var4 + 1); + printf("promote char/short cast VA %d %d\n", (signed char)(var1 + 1), (signed char)(var4 + 1)); +#if !defined(__arm__) + /* We can't really express GCC behaviour of return type promotion in + the presence of undefined behaviour (like __csf is). */ + var1 = csf(unsigned char,0x89898989); + var4 = csf(signed char,0xabababab); + printf("promote char/short funcret %d "LONG_LONG_FORMAT"\n", var1, var4); + printf("promote char/short fumcret VA %d %d %d %d\n", + csf(unsigned short,0xcdcdcdcd), + csf(short,0xefefefef), + csf(_Bool,0x33221100), + csf(_Bool,0x33221101)); +#endif + var3 = -10; + var1 = (signed char)(unsigned char)(var3 + 1); + var4 = (signed char)(unsigned char)(var3 + 1); + printf("promote multicast (char)(unsigned char) %d "LONG_LONG_FORMAT"\n", var1, var4); + var4 = 0x11223344aa998877ULL; + var4 = (unsigned)(int)(var4 + 1); + printf("promote multicast (unsigned)(int) "LONG_LONG_FORMAT"\n", var4); + var4 = 0x11223344bbaa9988ULL; + var4 = (unsigned)(signed char)(var4 + 1); + printf("promote multicast (unsigned)(char) "LONG_LONG_FORMAT"\n", var4); +} + +/******************/ + +typedef struct Sym { + int v; + int t; + int c; + struct Sym *next; + struct Sym *prev; +} Sym; + +#define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) + +static int toupper1(int a) +{ + return TOUPPER(a); +} + +static unsigned int calc_vm_flags(unsigned int prot) +{ + unsigned int prot_bits; + /* This used to segfault in some revisions: */ + prot_bits = ((0x1==0x00000001)?(prot&0x1):(prot&0x1)?0x00000001:0); + return prot_bits; +} + +enum cast_enum { FIRST, LAST }; + +static void tst_cast(enum cast_enum ce) +{ + printf("%d\n", ce); +} + +void bool_test() +{ + int *s, a, b, t, f, i; + + a = 0; + s = (void*)0; + printf("!s=%d\n", !s); + + if (!s || !s[0]) + a = 1; + printf("a=%d\n", a); + + printf("a=%d %d %d\n", 0 || 0, 0 || 1, 1 || 1); + printf("a=%d %d %d\n", 0 && 0, 0 && 1, 1 && 1); + printf("a=%d %d\n", 1 ? 1 : 0, 0 ? 1 : 0); +#if 1 && 1 + printf("a1\n"); +#endif +#if 1 || 0 + printf("a2\n"); +#endif +#if 1 ? 0 : 1 + printf("a3\n"); +#endif +#if 0 ? 0 : 1 + printf("a4\n"); +#endif + + a = 4; + printf("b=%d\n", a + (0 ? 1 : a / 2)); + + /* test register spilling */ + a = 10; + b = 10; + a = (a + b) * ((a < b) ? + ((b - a) * (a - b)): a + b); + printf("a=%d\n", a); + + /* test complex || or && expressions */ + t = 1; + f = 0; + a = 32; + printf("exp=%d\n", f == (32 <= a && a <= 3)); + printf("r=%d\n", (t || f) + (t && f)); + + /* check that types of casted &&/|| are preserved (here the unsignedness) */ + t = 1; + printf("type of bool: %d\n", (int) ( (~ ((unsigned int) (t && 1))) / 2) ); + tst_cast(t >= 0 ? FIRST : LAST); + + printf("type of cond: %d\n", (~(t ? 0U : (unsigned int)0)) / 2 ); + /* test ? : cast */ + { + int aspect_on; + int aspect_native = 65536; + double bfu_aspect = 1.0; + int aspect; + for(aspect_on = 0; aspect_on < 2; aspect_on++) { + aspect=aspect_on?(aspect_native*bfu_aspect+0.5):65535UL; + printf("aspect=%d\n", aspect); + } + } + + /* test ? : GCC extension */ + { + static int v1 = 34 ? : -1; /* constant case */ + static int v2 = 0 ? : -1; /* constant case */ + int a = 30; + + printf("%d %d\n", v1, v2); + printf("%d %d\n", a - 30 ? : a * 2, a + 1 ? : a * 2); + } + + /* again complex expression */ + for(i=0;i<256;i++) { + if (toupper1 (i) != TOUPPER (i)) + printf("error %d\n", i); + } + printf ("bits = 0x%x\n", calc_vm_flags (0x1)); +} + +extern int undefined_function(void); +extern int defined_function(void); + +#ifdef __clang__ +int undefined_function(void) {} +#endif + +static inline void refer_to_undefined(void) +{ + undefined_function(); +} + +void optimize_out_test(void) +{ + int i = 0 ? undefined_function() : defined_function(); + printf ("oo:%d\n", i); + int j = 1 ? defined_function() : undefined_function(); + printf ("oo:%d\n", j); + if (0) + printf("oo:%d\n", undefined_function()); + else + printf("oo:%d\n", defined_function()); + if (1) + printf("oo:%d\n", defined_function()); + else + printf("oo:%d\n", undefined_function()); + while (1) { + printf("oow:%d\n", defined_function()); + break; + printf("oow:%d\n", undefined_function()); + } + j = 1; + /* Following is a switch without {} block intentionally. */ + switch (j) + case 1: break; + printf ("oos:%d\n", defined_function()); + /* The following break shouldn't lead to disabled code after + the while. */ + while (1) + break; + printf ("ool1:%d\n", defined_function()); + /* Same for the other types of loops. */ + do + break; + while (1); + printf ("ool2:%d\n", defined_function()); + for (;;) + break; + printf ("ool3:%d\n", defined_function()); + /* Normal {} blocks without controlling statements + shouldn't reactivate code emission */ + while (1) { + { + break; + } + printf ("ool4:%d\n", undefined_function()); + } + j = 1; + while (j) { + if (j == 0) + break; /* this break shouldn't disable code outside the if. */ + printf("ool5:%d\n", defined_function()); + j--; + } + + j = 1; + while (j) { + if (1) + j--; + else + breakhere: break; + printf("ool6:%d\n", defined_function()); + goto breakhere; + } + j = 1; + while (j) { + j--; + continue; + printf("ool7:%d\n", undefined_function()); + } + + /* Test that constants in logical && are optimized: */ + i = 0 && undefined_function(); + i = defined_function() && 0 && undefined_function(); + if (0 && undefined_function()) + undefined_function(); + if (defined_function() && 0) + undefined_function(); + if (0 && 0) + undefined_function(); + if (defined_function() && 0 && undefined_function()) + undefined_function(); + /* The same for || : */ + i = 1 || undefined_function(); + i = defined_function() || 1 || undefined_function(); + if (1 || undefined_function()) + ; + else + undefined_function(); + if (defined_function() || 1) + ; + else + undefined_function(); + if (1 || 1) + ; + else + undefined_function(); + if (defined_function() || 1 || undefined_function()) + ; + else + undefined_function(); + + if (defined_function() && 0) + refer_to_undefined(); + + if (0) { + (void)sizeof( ({ + do { } while (0); + 0; + }) ); + undefined_function(); + } + + if (0) { + switch (defined_function()) { + case 0: undefined_function(); break; + default: undefined_function(); break; + } + } + + /* Leave the "if(1)return; printf()" in this order and last in the function */ + if (1) + return; + printf ("oor:%d\n", undefined_function()); +} + +int defined_function(void) +{ + static int i = 40; + return i++; +} + +/* GCC accepts that */ +static int tab_reinit[]; +static int tab_reinit[10]; + +static int tentative_ar[]; +static int tentative_ar[] = {1,2,3}; + +//int cinit1; /* a global variable can be defined several times without error ! */ +int cinit1; +int cinit1; +int cinit1 = 0; +int *cinit2 = (int []){3, 2, 1}; + +void compound_literal_test(void) +{ + int *p, i; + char *q, *q3; + + p = (int []){1, 2, 3}; + for(i=0;i<3;i++) + printf(" %d", p[i]); + printf("\n"); + + for(i=0;i<3;i++) + printf("%d", cinit2[i]); + printf("\n"); + + q = "tralala1"; + printf("q1=%s\n", q); + + q = (char *){ "tralala2" }; + printf("q2=%s\n", q); + + q3 = (char *){ q }; + printf("q3=%s\n", q3); + + q = (char []){ "tralala3" }; + printf("q4=%s\n", q); + +#ifdef ALL_ISOC99 + p = (int []){1, 2, cinit1 + 3}; + for(i=0;i<3;i++) + printf(" %d", p[i]); + printf("\n"); + + for(i=0;i<3;i++) { + p = (int []){1, 2, 4 + i}; + printf("%d %d %d\n", + p[0], + p[1], + p[2]); + } +#endif +} + + +#if __TINYC__ + +/* K & R protos */ + +kr_func1(a, b) +{ + return a + b; +} + +int kr_func2(a, b) +{ + return a + b; +} + +kr_test() +{ + printf("func1=%d\n", kr_func1(3, 4)); + printf("func2=%d\n", kr_func2(3, 4)); + return 0; +} + +/* We try to handle this syntax. Make at least sure it doesn't segfault. */ +char invalid_function_def()[] {return 0;} + +#else +# define kr_test() printf("func1=7\nfunc2=7\n") +#endif + +void num(int n) +{ + char *tab, *p; + tab = (char*)malloc(20); + p = tab; + while (1) { + *p = 48 + (n % 10); + p++; + n = n / 10; + if (n == 0) + break; + } + while (p != tab) { + p--; + printf("%c", *p); + } + printf("\n"); + free(tab); +} + +/* structure assignment tests */ +struct structa1 { + int f1; + char f2; +}; + +void struct_assign_test1(struct structa1 s1, int t, float f) +{ + printf("%d %d %d %f\n", s1.f1, s1.f2, t, f); +} + +struct structa1 struct_assign_test2(struct structa1 s1, int t) +{ + s1.f1 += t; + s1.f2 -= t; + return s1; +} + +void struct_assign_test(void) +{ + struct S { + struct structa1 lsta1, lsta2; + int i; + } s = {{1,2}, {3,4}}, *ps; + + ps = &s; + ps->i = 4; + + struct_assign_test1(ps->lsta2, 3, 4.5); + printf("before call: %d %d\n", s.lsta2.f1, s.lsta2.f2); + ps->lsta2 = struct_assign_test2(ps->lsta2, ps->i); + printf("after call: %d %d\n", ps->lsta2.f1, ps->lsta2.f2); + + static struct { + void (*elem)(); + } t[] = { + /* XXX: we should allow this even without braces */ + { struct_assign_test } + }; + printf("%d\n", struct_assign_test == t[0].elem); + + s.lsta1 = s.lsta2 = struct_assign_test2(s.lsta1, 1); + printf("%d %d\n", s.lsta1.f1, s.lsta1.f2); +} + +/* casts to short/char */ + +void cast1(char a, short b, unsigned char c, unsigned short d) +{ + printf("%d %d %d %d\n", a, b, c, d); +} + +char bcast; +short scast; + +void cast_test() +{ + int a; + char c; + char tab[10]; + unsigned b,d; + short s; + char *p = NULL; + unsigned long ul = 0x80000000UL; + p -= 0x700000000042; + + a = 0xfffff; + cast1(a, a, a, a); + a = 0xffffe; + printf("%d %d %d %d\n", + (char)(a + 1), + (short)(a + 1), + (unsigned char)(a + 1), + (unsigned short)(a + 1)); + printf("%d %d %d %d\n", + (char)0xfffff, + (short)0xfffff, + (unsigned char)0xfffff, + (unsigned short)0xfffff); + + a = (bcast = 128) + 1; + printf("%d\n", a); + a = (scast = 65536) + 1; + printf("%d\n", a); + + printf("sizeof(c) = %d, sizeof((int)c) = %d\n", sizeof(c), sizeof((int)c)); + + /* test cast from unsigned to signed short to int */ + b = 0xf000; + d = (short)b; + printf("((unsigned)(short)0x%08x) = 0x%08x\n", b, d); + b = 0xf0f0; + d = (char)b; + printf("((unsigned)(char)0x%08x) = 0x%08x\n", b, d); + + /* test implicit int casting for array accesses */ + c = 0; + tab[1] = 2; + tab[c] = 1; + printf("%d %d\n", tab[0], tab[1]); + + /* test implicit casting on some operators */ + printf("sizeof(+(char)'a') = %d\n", sizeof(+(char)'a')); + printf("sizeof(-(char)'a') = %d\n", sizeof(-(char)'a')); + printf("sizeof(~(char)'a') = %d\n", sizeof(-(char)'a')); + +#if CC_NAME != CC_clang /* clang doesn't support non-portable conversions */ + /* from pointer to integer types */ + printf("%d %d %ld %ld %lld %lld\n", + (int)p, (unsigned int)p, + (long)p, (unsigned long)p, + (long long)p, (unsigned long long)p); +#endif + + /* from integers to pointers */ + printf("%p %p %p %p\n", + (void *)a, (void *)b, (void *)c, (void *)d); + + /* int to int with sign set */ + printf("0x%lx\n", (unsigned long)(int)ul); +} + +/* initializers tests */ +struct structinit1 { + int f1; + char f2; + short f3; + int farray[3]; +}; + +int sinit1 = 2; +int sinit2 = { 3 }; +int sinit3[3] = { 1, 2, {{3}}, }; +int sinit4[3][2] = { {1, 2}, {3, 4}, {5, 6} }; +int sinit5[3][2] = { 1, 2, 3, 4, 5, 6 }; +int sinit6[] = { 1, 2, 3 }; +int sinit7[] = { [2] = 3, [0] = 1, 2 }; +char sinit8[] = "hello" "trala"; + +struct structinit1 sinit9 = { 1, 2, 3 }; +struct structinit1 sinit10 = { .f2 = 2, 3, .f1 = 1 }; +struct structinit1 sinit11 = { .f2 = 2, 3, .f1 = 1, +#ifdef ALL_ISOC99 + .farray[0] = 10, + .farray[1] = 11, + .farray[2] = 12, +#endif +}; + +char *sinit12 = "hello world"; +char *sinit13[] = { + "test1", + "test2", + "test3", +}; +char sinit14[10] = { "abc" }; +int sinit15[3] = { sizeof(sinit15), 1, 2 }; + +struct { int a[3], b; } sinit16[] = { { 1 }, 2 }; + +struct bar { + char *s; + int len; +} sinit17[] = { + "a1", 4, + "a2", 1 +}; + +int sinit18[10] = { + [2 ... 5] = 20, + 2, + [8] = 10, +}; + +struct complexinit0 { + int a; + int b; +}; + +struct complexinit { + int a; + const struct complexinit0 *b; +}; + +const static struct complexinit cix[] = { + [0] = { + .a = 2000, + .b = (const struct complexinit0[]) { + { 2001, 2002 }, + { 2003, 2003 }, + {} + } + } +}; + +struct complexinit2 { + int a; + int b[]; +}; + +struct complexinit2 cix20; + +struct complexinit2 cix21 = { + .a = 3000, + .b = { 3001, 3002, 3003 } +}; + +struct complexinit2 cix22 = { + .a = 4000, + .b = { 4001, 4002, 4003, 4004, 4005, 4006 } +}; + +typedef int arrtype1[]; +arrtype1 sinit19 = {1}; +arrtype1 sinit20 = {2,3}; +typedef int arrtype2[3]; +arrtype2 sinit21 = {4}; +arrtype2 sinit22 = {5,6,7}; + +/* Address comparisons of non-weak symbols with zero can be const-folded */ +int sinit23[2] = { "astring" ? sizeof("astring") : -1, + &sinit23 ? 42 : -1 }; + +int sinit24 = 2 || 1 / 0; /* exception in constant but unevaluated context */ + +/* bitfield init */ +struct bf_SS {unsigned int bit:1,bits31:31; }; +struct bf_SS bf_init = { .bit = 1 }; +struct bfn_SS {int a,b; struct bf_SS c; int d,e; }; +struct bfn_SS bfn_init = { .c.bit = 1 }; +struct bfa_SS {int a,b; struct bf_SS c[3]; int d,e; }; +struct bfa_SS bfa_init = { .c[1].bit = 1 }; +struct bf_SS bfaa_init[3] = { [1].bit = 1 }; +struct bf_SS bfaa_vinit[] = { [2].bit = 1 }; +struct b2_SS {long long int field : 52; long long int pad : 12; }; +struct b2_SS bf_init2 = {0xFFF000FFF000FLL, 0x123}; + +extern int external_inited = 42; + +void init_test(void) +{ + int linit1 = 2; + int linit2 = { 3 }; + int linit4[3][2] = { {1, 2}, {3, 4}, {5, 6} }; + int linit6[] = { 1, 2, 3 }; + int i, j; + char linit8[] = "hello" "trala"; + int linit12[10] = { 1, 2 }; + int linit13[10] = { 1, 2, [7] = 3, [3] = 4, }; + char linit14[10] = "abc"; + int linit15[10] = { linit1, linit1 + 1, [6] = linit1 + 2, }; + struct linit16 { int a1, a2, a3, a4; } linit16 = { 1, .a3 = 2 }; + int linit17 = sizeof(linit17); + int zero = 0; + /* Addresses on non-weak symbols are non-zero, but not the access itself */ + int linit18[2] = {&zero ? 1 : -1, zero ? -1 : 1 }; + struct bf_SS bf_finit = { .bit = 1 }; + struct bfn_SS bfn_finit = { .c.bit = 1 }; + struct bfa_SS bfa_finit = { .c[1].bit = 1 }; + struct bf_SS bfaa_finit[3] = { [1].bit = 1 }; + struct bf_SS bfaa_fvinit[] = { [2].bit = 1 }; + struct b2_SS bf_finit2 = {0xFFF000FFF000FLL, 0x123}; + + printf("sinit1=%d\n", sinit1); + printf("sinit2=%d\n", sinit2); + printf("sinit3=%d %d %d %d\n", + sizeof(sinit3), + sinit3[0], + sinit3[1], + sinit3[2] + ); + printf("sinit6=%d\n", sizeof(sinit6)); + printf("sinit7=%d %d %d %d\n", + sizeof(sinit7), + sinit7[0], + sinit7[1], + sinit7[2] + ); + printf("sinit8=%s\n", sinit8); + printf("sinit9=%d %d %d\n", + sinit9.f1, + sinit9.f2, + sinit9.f3 + ); + printf("sinit10=%d %d %d\n", + sinit10.f1, + sinit10.f2, + sinit10.f3 + ); + printf("sinit11=%d %d %d %d %d %d\n", + sinit11.f1, + sinit11.f2, + sinit11.f3, + sinit11.farray[0], + sinit11.farray[1], + sinit11.farray[2] + ); + + for(i=0;i<3;i++) + for(j=0;j<2;j++) + printf("[%d][%d] = %d %d %d\n", + i, j, sinit4[i][j], sinit5[i][j], linit4[i][j]); + printf("linit1=%d\n", linit1); + printf("linit2=%d\n", linit2); + printf("linit6=%d\n", sizeof(linit6)); + printf("linit8=%d %s\n", sizeof(linit8), linit8); + + printf("sinit12=%s\n", sinit12); + printf("sinit13=%d %s %s %s\n", + sizeof(sinit13), + sinit13[0], + sinit13[1], + sinit13[2]); + printf("sinit14=%s\n", sinit14); + + for(i=0;i<10;i++) printf(" %d", linit12[i]); + printf("\n"); + for(i=0;i<10;i++) printf(" %d", linit13[i]); + printf("\n"); + for(i=0;i<10;i++) printf(" %d", linit14[i]); + printf("\n"); + for(i=0;i<10;i++) printf(" %d", linit15[i]); + printf("\n"); + printf("%d %d %d %d\n", + linit16.a1, + linit16.a2, + linit16.a3, + linit16.a4); + /* test that initialisation is done after variable declare */ + printf("linit17=%d\n", linit17); + printf("sinit15=%d\n", sinit15[0]); + printf("sinit16=%d %d\n", sinit16[0].a[0], sinit16[1].a[0]); + printf("sinit17=%s %d %s %d\n", + sinit17[0].s, sinit17[0].len, + sinit17[1].s, sinit17[1].len); + for(i=0;i<10;i++) + printf("%x ", sinit18[i]); + printf("\n"); + /* complex init check */ + printf("cix: %d %d %d %d %d %d %d\n", + cix[0].a, + cix[0].b[0].a, cix[0].b[0].b, + cix[0].b[1].a, cix[0].b[1].b, + cix[0].b[2].a, cix[0].b[2].b); + printf("cix2: %d %d\n", cix21.b[2], cix22.b[5]); + printf("sizeof cix20 %d, cix21 %d, sizeof cix22 %d\n", sizeof cix20, sizeof cix21, sizeof cix22); + + printf("arrtype1: %d %d %d\n", sinit19[0], sinit20[0], sinit20[1]); + printf("arrtype2: %d %d\n", sizeof(sinit19), sizeof(sinit20)); + printf("arrtype3: %d %d %d\n", sinit21[0], sinit21[1], sinit21[2]); + printf("arrtype4: %d %d %d\n", sinit22[0], sinit22[1], sinit22[2]); + printf("arrtype5: %d %d\n", sizeof(sinit21), sizeof(sinit22)); + printf("arrtype6: %d\n", sizeof(arrtype2)); + + printf("sinit23= %d %d\n", sinit23[0], sinit23[1]); + printf("sinit24=%d\n", sinit24); + printf("linit18= %d %d\n", linit18[0], linit18[1]); + printf ("bf1: %u %u\n", bf_init.bit, bf_init.bits31); + printf ("bf2: %u %u\n", bf_finit.bit, bf_finit.bits31); + printf ("bf3: %u %u\n", bfn_init.c.bit, bfn_init.c.bits31); + printf ("bf4: %u %u\n", bfn_finit.c.bit, bfn_finit.c.bits31); + for (i = 0; i < 3; i++) + printf ("bf5[%d]: %u %u\n", i, bfa_init.c[i].bit, bfa_init.c[i].bits31); + for (i = 0; i < 3; i++) + printf ("bf6[%d]: %u %u\n", i, bfa_finit.c[i].bit, bfa_finit.c[i].bits31); + for (i = 0; i < 3; i++) + printf ("bf7[%d]: %u %u\n", i, bfaa_init[i].bit, bfaa_init[i].bits31); + for (i = 0; i < 3; i++) + printf ("bf8[%d]: %u %u\n", i, bfaa_finit[i].bit, bfaa_finit[i].bits31); + for (i = 0; i < 3; i++) + printf ("bf9[%d]: %u %u\n", i, bfaa_vinit[i].bit, bfaa_vinit[i].bits31); + for (i = 0; i < 3; i++) + printf ("bf10[%d]: %u %u\n", i, bfaa_fvinit[i].bit, bfaa_fvinit[i].bits31); +} + +void switch_uc(unsigned char uc) +{ + switch (uc) { + case 0xfb ... 0xfe: + printf("ucsw:1\n"); + break; + case 0xff: + printf("ucsw:2\n"); + break; + case 0 ... 5: + printf("ucsw:3\n"); + break; + default: + printf("ucsw: broken!\n"); + } +} + +void switch_sc(signed char sc) +{ + switch (sc) { + case -5 ... -2: + printf("scsw:1\n"); + break; + case -1: + printf("scsw:2\n"); + break; + case 0 ... 5: + printf("scsw:3\n"); + break; + default: + printf("scsw: broken!\n"); + } +} + +void switch_test() +{ + int i; + unsigned long long ull; + long long ll; + + for(i=0;i<15;i++) { + switch(i) { + case 0: + case 1: + printf("a"); + break; + default: + printf("%d", i); + break; + case 8 ... 12: + printf("c"); + break; + case 3: + printf("b"); + break; + case 0xc33c6b9fU: + case 0x7c9eeeb9U: + break; + } + } + printf("\n"); + + for (i = 1; i <= 5; i++) { + ull = (unsigned long long)i << 61; + switch (ull) { + case 1ULL << 61: + printf("ullsw:1\n"); + break; + case 2ULL << 61: + printf("ullsw:2\n"); + break; + case 3ULL << 61: + printf("ullsw:3\n"); + break; + case 4ULL << 61: + printf("ullsw:4\n"); + break; + case 5ULL << 61: + printf("ullsw:5\n"); + break; + default: + printf("ullsw: broken!\n"); + } + } + + for (i = 1; i <= 5; i++) { + ll = (long long)i << 61; + switch (ll) { + case 1LL << 61: + printf("llsw:1\n"); + break; + case 2LL << 61: + printf("llsw:2\n"); + break; + case 3LL << 61: + printf("llsw:3\n"); + break; + case 4LL << 61: + printf("llsw:4\n"); + break; + case 5LL << 61: + printf("llsw:5\n"); + break; + default: + printf("llsw: broken!\n"); + } + } + + for (i = -5; i <= 5; i++) { + switch_uc((unsigned char)i); + } + + for (i = -5; i <= 5; i++) { + switch_sc ((signed char)i); + } +} + +/* ISOC99 _Bool type */ +void c99_bool_test(void) +{ +#ifdef BOOL_ISOC99 + int a; + _Bool b, b2; + + printf("sizeof(_Bool) = %d\n", sizeof(_Bool)); + a = 3; + printf("cast: %d %d %d\n", (_Bool)10, (_Bool)0, (_Bool)a); + b = 3; + printf("b = %d\n", b); + b++; + printf("b = %d\n", b); + b2 = 0; + printf("sizeof(x ? _Bool : _Bool) = %d (should be sizeof int)\n", + sizeof ((volatile int)a ? b : b2)); +#endif +} + +void bitfield_test(void) +{ + int a; + short sa; + unsigned char ca; + struct sbf1 { + int f1 : 3; + int : 2; + int f2 : 1; + int : 0; + int f3 : 5; + int f4 : 7; + unsigned int f5 : 7; + } st1; + printf("sizeof(st1) = %d\n", sizeof(st1)); + + st1.f1 = 3; + st1.f2 = 1; + st1.f3 = 15; + a = 120; + st1.f4 = a; + st1.f5 = a; + st1.f5++; + printf("%d %d %d %d %d\n", + st1.f1, st1.f2, st1.f3, st1.f4, st1.f5); + sa = st1.f5; + ca = st1.f5; + printf("%d %d\n", sa, ca); + + st1.f1 = 7; + if (st1.f1 == -1) + printf("st1.f1 == -1\n"); + else + printf("st1.f1 != -1\n"); + if (st1.f2 == -1) + printf("st1.f2 == -1\n"); + else + printf("st1.f2 != -1\n"); + + struct sbf2 { + long long f1 : 45; + long long : 2; + long long f2 : 35; + unsigned long long f3 : 38; + } st2; + st2.f1 = 0x123456789ULL; + a = 120; + st2.f2 = (long long)a << 25; + st2.f3 = a; + st2.f2++; + printf("%lld %lld %lld\n", st2.f1, st2.f2, st2.f3); + +#if 0 + Disabled for now until further clarification re GCC compatibility + struct sbf3 { + int f1 : 7; + int f2 : 1; + char f3; + int f4 : 8; + int f5 : 1; + int f6 : 16; + } st3; + printf("sizeof(st3) = %d\n", sizeof(st3)); +#endif + + struct sbf4 { + int x : 31; + char y : 2; + } st4; + st4.y = 1; + printf("st4.y == %d\n", st4.y); + struct sbf5 { + int a; + char b; + int x : 12, y : 4, : 0, : 4, z : 3; + char c; + } st5 = { 1, 2, 3, 4, -3, 6 }; + printf("st5 = %d %d %d %d %d %d\n", st5.a, st5.b, st5.x, st5.y, st5.z, st5.c); + struct sbf6 { + short x : 12; + unsigned char y : 2; + } st6; + st6.y = 1; + printf("st6.y == %d\n", st6.y); +} + +#ifdef __x86_64__ +#define FLOAT_FMT "%f\n" +#else +/* x86's float isn't compatible with GCC */ +#define FLOAT_FMT "%.5f\n" +#endif + +/* declare strto* functions as they are C99 */ +double strtod(const char *nptr, char **endptr); + +#if defined(_WIN32) +float strtof(const char *nptr, char **endptr) {return (float)strtod(nptr, endptr);} +LONG_DOUBLE strtold(const char *nptr, char **endptr) {return (LONG_DOUBLE)strtod(nptr, endptr);} +#else +float strtof(const char *nptr, char **endptr); +LONG_DOUBLE strtold(const char *nptr, char **endptr); +#endif + +#if CC_NAME == CC_clang +/* In clang 0.0/0.0 is nan and not -nan. + Also some older clang version do v=-v + as v = -0 - v */ +static char enable_nan_test = 0; +#else +static char enable_nan_test = 1; +#endif + +#define FTEST(prefix, typename, type, fmt)\ +void prefix ## cmp(type a, type b)\ +{\ + printf("%d %d %d %d %d %d\n",\ + a == b,\ + a != b,\ + a < b,\ + a > b,\ + a >= b,\ + a <= b);\ + printf(fmt " " fmt " " fmt " " fmt " " fmt " " fmt " " fmt "\n",\ + a,\ + b,\ + a + b,\ + a - b,\ + a * b,\ + a / b,\ + -a);\ + printf(fmt "\n", ++a);\ + printf(fmt "\n", a++);\ + printf(fmt "\n", a);\ + b = 0;\ + printf("%d %d\n", !a, !b);\ +}\ +void prefix ## fcast(type a)\ +{\ + float fa;\ + double da;\ + LONG_DOUBLE la;\ + int ia;\ + long long llia;\ + unsigned int ua;\ + unsigned long long llua;\ + type b;\ + fa = a;\ + da = a;\ + la = a;\ + printf("ftof: %f %f %Lf\n", fa, da, la);\ + ia = (int)a;\ + llia = (long long)a;\ + a = (a >= 0) ? a : -a;\ + ua = (unsigned int)a;\ + llua = (unsigned long long)a;\ + printf("ftoi: %d %u %lld %llu\n", ia, ua, llia, llua);\ + ia = -1234;\ + ua = 0x81234500;\ + llia = -0x123456789012345LL;\ + llua = 0xf123456789012345LLU;\ + b = ia;\ + printf("itof: " fmt "\n", b);\ + b = ua;\ + printf("utof: " fmt "\n", b);\ + b = llia;\ + printf("lltof: " fmt "\n", b);\ + b = llua;\ + printf("ulltof: " fmt "\n", b);\ +}\ +\ +float prefix ## retf(type a) { return a; }\ +double prefix ## retd(type a) { return a; }\ +LONG_DOUBLE prefix ## retld(type a) { return a; }\ +\ +void prefix ## call(void)\ +{\ + printf("float: " FLOAT_FMT, prefix ## retf(42.123456789));\ + printf("double: %f\n", prefix ## retd(42.123456789));\ + printf("long double: %Lf\n", prefix ## retld(42.123456789));\ + printf("strto%s: %f\n", #prefix, (double)strto ## prefix("1.2", NULL));\ +}\ +\ +void prefix ## signed_zeros(void) \ +{\ + type x = 0.0, y = -0.0, n, p;\ + if (x == y)\ + printf ("Test 1.0 / x != 1.0 / y returns %d (should be 1).\n",\ + 1.0 / x != 1.0 / y);\ + else\ + printf ("x != y; this is wrong!\n");\ +\ + n = -x;\ + if (x == n)\ + printf ("Test 1.0 / x != 1.0 / -x returns %d (should be 1).\n",\ + 1.0 / x != 1.0 / n);\ + else\ + printf ("x != -x; this is wrong!\n");\ +\ + p = +y;\ + if (x == p)\ + printf ("Test 1.0 / x != 1.0 / +y returns %d (should be 1).\n",\ + 1.0 / x != 1.0 / p);\ + else\ + printf ("x != +y; this is wrong!\n");\ + p = -y;\ + if (x == p)\ + printf ("Test 1.0 / x != 1.0 / -y returns %d (should be 0).\n",\ + 1.0 / x != 1.0 / p);\ + else\ + printf ("x != -y; this is wrong!\n");\ +}\ +void prefix ## nan(void)\ +{\ + type nan = 0.0/0.0;\ + type nnan = -nan; \ + printf("nantest: " fmt " " fmt "\n", nan, nnan);\ +}\ +void prefix ## test(void)\ +{\ + printf("testing '%s'\n", #typename);\ + prefix ## cmp(1, 2.5);\ + prefix ## cmp(2, 1.5);\ + prefix ## cmp(1, 1);\ + prefix ## fcast(234.6);\ + prefix ## fcast(-2334.6);\ + prefix ## call();\ + prefix ## signed_zeros();\ + if (enable_nan_test) prefix ## nan();\ +} + +FTEST(f, float, float, "%f") +FTEST(d, double, double, "%f") +FTEST(ld, long double, LONG_DOUBLE, "%Lf") + +double ftab1[3] = { 1.2, 3.4, -5.6 }; + + +void float_test(void) +{ +#if !defined(__arm__) || defined(__ARM_PCS_VFP) || defined __ANDROID__ + volatile float fa, fb; + volatile 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; + volatile LONG_DOUBLE la; + + printf("sizeof(float) = %d\n", sizeof(float)); + printf("sizeof(double) = %d\n", sizeof(double)); + printf("sizeof(long double) = %d\n", sizeof(LONG_DOUBLE)); + ftest(); + dtest(); + ldtest(); + printf("%f %f %f\n", ftab1[0], ftab1[1], ftab1[2]); + printf("%f %f %f\n", 2.12, .5, 2.3e10); + // printf("%f %f %f\n", 0x1234p12, 0x1e23.23p10, 0x12dp-10); + da = 123; + printf("da=%f\n", da); + fa = 123; + printf("fa=%f\n", fa); + a = 4000000000; + da = a; + printf("da = %f\n", da); + b = 4000000000; + db = b; + printf("db = %f\n", db); + printf("nan != nan = %d, inf1 = %f, inf2 = %f\n", nan2 != nan2, inf1, inf2); + da = 0x0.88p-1022; /* a subnormal */ + la = da; + printf ("da subnormal = %a\n", da); + printf ("da subnormal = %.40g\n", da); + printf ("la subnormal = %La\n", la); + printf ("la subnormal = %.40Lg\n", la); + da /= 2; + la = da; + printf ("da/2 subnormal = %a\n", da); + printf ("da/2 subnormal = %.40g\n", da); + printf ("la/2 subnormal = %La\n", la); + printf ("la/2 subnormal = %.40Lg\n", la); + fa = 0x0.88p-126f; /* a subnormal */ + la = fa; + printf ("fa subnormal = %a\n", fa); + printf ("fa subnormal = %.40g\n", fa); + printf ("la subnormal = %La\n", la); + printf ("la subnormal = %.40Lg\n", la); + fa /= 2; + la = fa; + printf ("fa/2 subnormal = %a\n", fa); + printf ("fa/2 subnormal = %.40g\n", fa); + printf ("la/2 subnormal = %La\n", la); + printf ("la/2 subnormal = %.40Lg\n", la); +#endif +} + +int fib(int n) +{ + if (n <= 2) + return 1; + else + return fib(n-1) + fib(n-2); +} + +#if __GNUC__ == 3 || __GNUC__ == 4 +# define aligned_function 0 +#else +void __attribute__((aligned(16))) aligned_function(int i) {} +#endif + +void funcptr_test() +{ + void (*func)(int); + int a; + struct { + int dummy; + void (*func)(int); + } st1; + long diff; + + func = # + (*func)(12345); + func = num; + a = 1; + a = 1; + func(12345); + /* more complicated pointer computation */ + st1.func = num; + st1.func(12346); + printf("sizeof1 = %d\n", sizeof(funcptr_test)); + printf("sizeof2 = %d\n", sizeof funcptr_test); + printf("sizeof3 = %d\n", sizeof(&funcptr_test)); + printf("sizeof4 = %d\n", sizeof &funcptr_test); + a = 0; + func = num + a; + diff = func - num; + 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)(uintptr_t)func) & 15); +} + +void lloptest(long long a, long long b) +{ + unsigned long long ua, ub; + + ua = a; + ub = b; + /* arith */ + printf("arith: " LONG_LONG_FORMAT " " LONG_LONG_FORMAT " " LONG_LONG_FORMAT "\n", + a + b, + a - b, + a * b); + + if (b != 0) { + printf("arith1: " LONG_LONG_FORMAT " " LONG_LONG_FORMAT "\n", + a / b, + a % b); + } + + /* binary */ + printf("bin: " LONG_LONG_FORMAT " " LONG_LONG_FORMAT " " LONG_LONG_FORMAT "\n", + a & b, + a | b, + a ^ b); + + /* tests */ + printf("test: %d %d %d %d %d %d\n", + a == b, + a != b, + a < b, + a > b, + a >= b, + a <= b); + + printf("utest: %d %d %d %d %d %d\n", + ua == ub, + ua != ub, + ua < ub, + ua > ub, + ua >= ub, + ua <= ub); + + /* arith2 */ + a++; + b++; + printf("arith2: " LONG_LONG_FORMAT " " LONG_LONG_FORMAT "\n", a, b); + printf("arith2: " LONG_LONG_FORMAT " " LONG_LONG_FORMAT "\n", a++, b++); + printf("arith2: " LONG_LONG_FORMAT " " LONG_LONG_FORMAT "\n", --a, --b); + printf("arith2: " LONG_LONG_FORMAT " " LONG_LONG_FORMAT "\n", a, b); + b = ub = 0; + printf("not: %d %d %d %d\n", !a, !ua, !b, !ub); +} + +void llshift(long long a, int b) +{ + printf("shift: " LONG_LONG_FORMAT " " LONG_LONG_FORMAT " " LONG_LONG_FORMAT "\n", + (unsigned long long)a >> b, + a >> b, + a << b); + printf("shiftc: " LONG_LONG_FORMAT " " LONG_LONG_FORMAT " " LONG_LONG_FORMAT "\n", + (unsigned long long)a >> 3, + a >> 3, + a << 3); + printf("shiftc: " LONG_LONG_FORMAT " " LONG_LONG_FORMAT " " LONG_LONG_FORMAT "\n", + (unsigned long long)a >> 35, + a >> 35, + a << 35); +} + +void llfloat(void) +{ + float fa; + double da; + LONG_DOUBLE lda; + long long la, lb, lc; + unsigned long long ula, ulb, ulc; + la = 0x12345678; + ula = 0x72345678; + la = (la << 20) | 0x12345; + ula = ula << 33; + printf("la=" LONG_LONG_FORMAT " ula=" ULONG_LONG_FORMAT "\n", la, ula); + + fa = la; + da = la; + lda = la; + printf("lltof: %f %f %Lf\n", fa, da, lda); + + la = fa; + lb = da; + lc = lda; + printf("ftoll: " LONG_LONG_FORMAT " " LONG_LONG_FORMAT " " LONG_LONG_FORMAT "\n", la, lb, lc); + + fa = ula; + da = ula; + lda = ula; + printf("ulltof: %f %f %Lf\n", fa, da, lda); + + ula = fa; + ulb = da; + ulc = lda; + printf("ftoull: " ULONG_LONG_FORMAT " " ULONG_LONG_FORMAT " " ULONG_LONG_FORMAT "\n", ula, ulb, ulc); +} + +long long llfunc1(int a) +{ + return a * 2; +} + +struct S { + int id; + char item; +}; + +long long int value(struct S *v) +{ + return ((long long int)v->item); +} + +long long llfunc2(long long x, long long y, int z) +{ + return x * y * z; +} + +void check_opl_save_regs(char *a, long long b, int c) +{ + *a = b < 0 && !c; +} + +void longlong_test(void) +{ + long long a, b, c; + int ia; + unsigned int ua; + printf("sizeof(long long) = %d\n", sizeof(long long)); + ia = -1; + ua = -2; + a = ia; + b = ua; + printf(LONG_LONG_FORMAT " " LONG_LONG_FORMAT "\n", a, b); + printf(LONG_LONG_FORMAT " " LONG_LONG_FORMAT " " LONG_LONG_FORMAT " %Lx\n", + (long long)1, + (long long)-2, + 1LL, + 0x1234567812345679); + a = llfunc1(-3); + printf(LONG_LONG_FORMAT "\n", a); + + lloptest(1000, 23); + lloptest(0xff, 0x1234); + b = 0x72345678 << 10; + lloptest(-3, b); + llshift(0x123, 5); + llshift(-23, 5); + b = 0x72345678LL << 10; + llshift(b, 47); + + llfloat(); +#if 1 + b = 0x12345678; + a = -1; + c = a + b; + printf(XLONG_LONG_FORMAT"\n", c); +#endif + + /* long long reg spill test */ + { + struct S a; + + a.item = 3; + printf("%lld\n", value(&a)); + } + lloptest(0x80000000, 0); + + { + long long *p, v, **pp; + v = 1; + p = &v; + p[0]++; + printf("another long long spill test : %lld\n", *p); + pp = &p; + + v = llfunc2(**pp, **pp, ia); + printf("a long long function (arm-)reg-args test : %lld\n", v); + } + a = 68719476720LL; + b = 4294967295LL; + printf("%d %d %d %d\n", a > b, a < b, a >= b, a <= b); + + printf(LONG_LONG_FORMAT "\n", 0x123456789LLU); + + /* long long pointer deref in argument passing test */ + 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); + u = 0x11223344aa998877ULL; + u = (unsigned)(int)(u + 1); + printf("long long u=" ULONG_LONG_FORMAT "\n", u); + + /* was a problem with missing save_regs in gen_opl on 32-bit platforms */ + char cc = 78; + check_opl_save_regs(&cc, -1, 0); + printf("check_opl_save_regs: %d\n", cc); +} + +void manyarg_test(void) +{ + LONG_DOUBLE ld = 1234567891234LL; + printf("%d %d %d %d %d %d %d %d %f %f %f %f %f %f %f %f %f %f\n", + 1, 2, 3, 4, 5, 6, 7, 8, + 0.1, 1.2, 2.3, 3.4, 4.5, 5.6, 6.7, 7.8, 8.9, 9.0); + printf("%d %d %d %d %d %d %d %d %f %f %f %f %f %f %f %f %f %f " + LONG_LONG_FORMAT " " LONG_LONG_FORMAT " %f %f\n", + 1, 2, 3, 4, 5, 6, 7, 8, + 0.1, 1.2, 2.3, 3.4, 4.5, 5.6, 6.7, 7.8, 8.9, 9.0, + 1234567891234LL, 987654321986LL, + 42.0, 43.0); + printf("%Lf %d %d %d %d %d %d %d %d %f %f %f %f %f %f %f %f %f %f " + LONG_LONG_FORMAT " " LONG_LONG_FORMAT " %f %f\n", + ld, 1, 2, 3, 4, 5, 6, 7, 8, + 0.1, 1.2, 2.3, 3.4, 4.5, 5.6, 6.7, 7.8, 8.9, 9.0, + 1234567891234LL, 987654321986LL, + 42.0, 43.0); + printf("%d %d %d %d %d %d %d %d %Lf\n", + 1, 2, 3, 4, 5, 6, 7, 8, ld); + printf("%d %d %d %d %d %d %d %d %f %f %f %f %f %f %f %f %f %f " + LONG_LONG_FORMAT " " LONG_LONG_FORMAT "%f %f %Lf\n", + 1, 2, 3, 4, 5, 6, 7, 8, + 0.1, 1.2, 2.3, 3.4, 4.5, 5.6, 6.7, 7.8, 8.9, 9.0, + 1234567891234LL, 987654321986LL, + 42.0, 43.0, ld); + printf("%d %d %d %d %d %d %d %d %f %f %f %f %f %f %f %f %f %f " + "%Lf " LONG_LONG_FORMAT " " LONG_LONG_FORMAT " %f %f %Lf\n", + 1, 2, 3, 4, 5, 6, 7, 8, + 0.1, 1.2, 2.3, 3.4, 4.5, 5.6, 6.7, 7.8, 8.9, 9.0, + ld, 1234567891234LL, 987654321986LL, + 42.0, 43.0, ld); +} + +void* +va_arg_with_struct_ptr(va_list ap) { + /* + * This was a BUG identified with FFTW-3.3.8 on arm64. + * The test case only checks it compiles on all supported + * architectures. This function is not currently called. + */ + struct X { int _x; }; + struct X *x = va_arg(ap, struct X *); + return x; +} + +void vprintf1(const char *fmt, ...) +{ + va_list ap, aq; + const char *p; + int c, i; + double d; + long long ll; + LONG_DOUBLE ld; + + va_start(aq, fmt); + va_copy(ap, aq); + + p = fmt; + for(;;) { + c = *p; + if (c == '\0') + break; + p++; + if (c == '%') { + c = *p; + switch(c) { + case '\0': + goto the_end; + case 'd': + i = va_arg(ap, int); + printf("%d", i); + break; + case 'f': + d = va_arg(ap, double); + printf("%f", d); + break; + case 'l': + ll = va_arg(ap, long long); + printf(LONG_LONG_FORMAT, ll); + break; + case 'F': + ld = va_arg(ap, LONG_DOUBLE); + printf("%Lf", ld); + break; + } + p++; + } else { + putchar(c); + } + } + the_end: + va_end(aq); + va_end(ap); +} + +struct myspace { + short int profile; +}; +struct myspace2 { +#if CC_NAME == CC_clang /* clang7 doesn't support zero sized structs */ + char a[1]; +#else + char a[0]; +#endif +}; +struct myspace3 { + char a[1]; +}; +struct myspace4 { + char a[2]; +}; +struct mytest { + void *foo, *bar, *baz; +}; + +struct mytest stdarg_for_struct(struct myspace bob, ...) +{ + struct myspace george, bill; + struct myspace2 alex1; + struct myspace3 alex2; + struct myspace4 alex3; + va_list ap; + short int validate; + + va_start(ap, bob); + alex1 = va_arg(ap, struct myspace2); + alex2 = va_arg(ap, struct myspace3); + alex3 = va_arg(ap, struct myspace4); + bill = va_arg(ap, struct myspace); + george = va_arg(ap, struct myspace); + validate = va_arg(ap, int); + printf("stdarg_for_struct: %d %d %d %d %d %d %d\n", + alex2.a[0], alex3.a[0], alex3.a[1], + bob.profile, bill.profile, george.profile, validate); + va_end(ap); + return (struct mytest) {}; +} + +void stdarg_for_libc(const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + vprintf(fmt, args); + va_end(args); +} + +void stdarg_syntax(int n, ...) +{ + int i; + va_list ap; + if (1) + va_start(ap, n); + else + ; + i = va_arg(ap, int); + printf("stdarg_void_expr: %d\n", i); + (va_end(ap)); +} + +typedef struct{ + double x,y; +} point; +point pts[]={{1.0,2.0},{3.0,4.0},{5.0,6.0},{7.0,8.0},{9.0,10.0},{11.0,12.0}}; + +static void stdarg_double_struct(int nargs, int posd,...) +{ + int i; + double d; + point pi; + va_list args; + + printf ("stdarg_double_struct: %d\n", posd); + va_start(args,posd); + for(i = 0; i < nargs; i++) { + if (i == posd) { + d = va_arg (args, double); + printf ("d %d = %g\n", i, d); + } + else { + pi = va_arg (args, point); + printf ("pts[%d] = %g %g\n", i, pi.x, pi.y); + } + } + va_end(args); +} + +void stdarg_test(void) +{ + LONG_DOUBLE ld = 1234567891234LL; + struct myspace bob; + struct myspace2 bob2; + struct myspace3 bob3; + struct myspace4 bob4; + + vprintf1("%d %d %d\n", 1, 2, 3); + vprintf1("%f %d %f\n", 1.0, 2, 3.0); + vprintf1("%l %l %d %f\n", 1234567891234LL, 987654321986LL, 3, 1234.0); + vprintf1("%F %F %F\n", LONG_DOUBLE_LITERAL(1.2), LONG_DOUBLE_LITERAL(2.3), LONG_DOUBLE_LITERAL(3.4)); + vprintf1("%d %f %l %F %d %f %l %F\n", + 1, 1.2, 3LL, LONG_DOUBLE_LITERAL(4.5), 6, 7.8, 9LL, LONG_DOUBLE_LITERAL(0.1)); + vprintf1("%d %d %d %d %d %d %d %d %f %f %f %f %f %f %f %f\n", + 1, 2, 3, 4, 5, 6, 7, 8, + 0.1, 1.2, 2.3, 3.4, 4.5, 5.6, 6.7, 7.8); + vprintf1("%d %d %d %d %d %d %d %d %f %f %f %f %f %f %f %f %f %f\n", + 1, 2, 3, 4, 5, 6, 7, 8, + 0.1, 1.2, 2.3, 3.4, 4.5, 5.6, 6.7, 7.8, 8.9, 9.0); + vprintf1("%d %d %d %d %d %d %d %d %f %f %f %f %f %f %f %f %f %f " + "%l %l %f %f\n", + 1, 2, 3, 4, 5, 6, 7, 8, + 0.1, 1.2, 2.3, 3.4, 4.5, 5.6, 6.7, 7.8, 8.9, 9.0, + 1234567891234LL, 987654321986LL, + 42.0, 43.0); + vprintf1("%F %d %d %d %d %d %d %d %d %f %f %f %f %f %f %f %f %f %f " + "%l %l %f %f\n", + ld, 1, 2, 3, 4, 5, 6, 7, 8, + 0.1, 1.2, 2.3, 3.4, 4.5, 5.6, 6.7, 7.8, 8.9, 9.0, + 1234567891234LL, 987654321986LL, + 42.0, 43.0); + vprintf1("%d %d %d %d %d %d %d %d %F\n", + 1, 2, 3, 4, 5, 6, 7, 8, ld); + vprintf1("%d %d %d %d %d %d %d %d %f %f %f %f %f %f %f %f %f %f " + "%l %l %f %f %F\n", + 1, 2, 3, 4, 5, 6, 7, 8, + 0.1, 1.2, 2.3, 3.4, 4.5, 5.6, 6.7, 7.8, 8.9, 9.0, + 1234567891234LL, 987654321986LL, + 42.0, 43.0, ld); + vprintf1("%d %d %d %d %d %d %d %d %f %f %f %f %f %f %f %f %f %f " + "%F %l %l %f %f %F\n", + 1, 2, 3, 4, 5, 6, 7, 8, + 0.1, 1.2, 2.3, 3.4, 4.5, 5.6, 6.7, 7.8, 8.9, 9.0, + ld, 1234567891234LL, 987654321986LL, + 42.0, 43.0, ld); + + bob.profile = 42; + bob3.a[0] = 1; + bob4.a[0] = 2; + bob4.a[1] = 3; + stdarg_for_struct(bob, bob2, bob3, bob4, bob, bob, bob.profile); + stdarg_for_libc("stdarg_for_libc: %s %.2f %d\n", "string", 1.23, 456); + stdarg_syntax(1, 17); + stdarg_double_struct(6,-1,pts[0],pts[1],pts[2],pts[3],pts[4],pts[5]); + stdarg_double_struct(7,1,pts[0],-1.0,pts[1],pts[2],pts[3],pts[4],pts[5]); + stdarg_double_struct(7,2,pts[0],pts[1],-1.0,pts[2],pts[3],pts[4],pts[5]); + stdarg_double_struct(7,3,pts[0],pts[1],pts[2],-1.0,pts[3],pts[4],pts[5]); + stdarg_double_struct(7,4,pts[0],pts[1],pts[2],pts[3],-1.0,pts[4],pts[5]); + stdarg_double_struct(7,5,pts[0],pts[1],pts[2],pts[3],pts[4],-1.0,pts[5]); +} + +int reltab[3] = { 1, 2, 3 }; + +int *rel1 = &reltab[1]; +int *rel2 = &reltab[2]; + +void getmyaddress(void) +{ + printf("in getmyaddress\n"); +} + +#ifdef __LP64__ +long __pa_symbol(void) +{ + /* This 64bit constant was handled incorrectly, it was used as addend + (which can hold 64bit just fine) in connection with a symbol, + and TCC generates wrong code for that (displacements are 32bit only). + This effectively is "+ 0x80000000", and if addresses of globals + are below 2GB the result should be a number without high 32 bits set. */ + return ((long)(((unsigned long)(&rel1))) - (0xffffffff80000000UL)); +} +#endif + +uintptr_t theaddress = (uintptr_t)getmyaddress; +void relocation_test(void) +{ + void (*fptr)(void) = (void (*)(void))theaddress; + printf("*rel1=%d\n", *rel1); + printf("*rel2=%d\n", *rel2); + fptr(); +#ifdef __LP64__ + // compare 'addend' displacement versus conventional arithmetics + printf("pa_symbol: %d\n", (long)&rel1 == __pa_symbol() - 0x80000000); +#endif +} + +void old_style_f(a,b,c) + int a, b; + double c; +{ + printf("a=%d b=%d b=%f\n", a, b, c); +} + +void decl_func1(int cmpfn()) +{ + printf("cmpfn=%lx\n", (long)cmpfn); +} + +void decl_func2(cmpfn) +int cmpfn(); +{ + printf("cmpfn=%lx\n", (long)cmpfn); +} + +void old_style_function_test(void) +{ +#if CC_NAME == CC_clang + /* recent clang versions (at least 15.0) raise an error: + incompatible pointer to integer conversion passing 'void *' + For the purpose of this test, pass 1 instead. + */ + old_style_f(1, 2, 3.0); +#else + old_style_f((void *)1, 2, 3.0); +#endif + decl_func1(NULL); + decl_func2(NULL); +} + +void alloca_test() +{ +#if defined __i386__ || defined __x86_64__ || defined __arm__ + char *p = alloca(16); + strcpy(p,"123456789012345"); + printf("alloca: p is %s\n", p); + char *demo = "This is only a test.\n"; + /* Test alloca embedded in a larger expression */ + printf("alloca: %s\n", strcpy(alloca(strlen(demo)+1),demo) ); +#endif +} + +void *bounds_checking_is_enabled() +{ + char ca[10], *cp = ca-1; + return (ca != cp + 1) ? cp : NULL; +} + +typedef int constant_negative_array_size_as_compile_time_assertion_idiom[(1 ? 2 : 0) - 1]; + +void c99_vla_test_1(int size1, int size2) +{ + int size = size1 * size2; + int tab1[size][2], tab2[10][2]; + void *tab1_ptr, *tab2_ptr, *bad_ptr; + + /* "size" should have been 'captured' at tab1 declaration, + so modifying it should have no effect on VLA behaviour. */ + size = size-1; + + printf("Test C99 VLA 1 (sizeof): "); + printf("%s\n", (sizeof tab1 == size1 * size2 * 2 * sizeof(int)) ? "PASSED" : "FAILED"); + tab1_ptr = tab1; + tab2_ptr = tab2; + printf("Test C99 VLA 2 (ptrs subtract): "); + printf("%s\n", (tab2 - tab1 == (tab2_ptr - tab1_ptr) / (sizeof(int) * 2)) ? "PASSED" : "FAILED"); + printf("Test C99 VLA 3 (ptr add): "); + printf("%s\n", &tab1[5][1] == (tab1_ptr + (5 * 2 + 1) * sizeof(int)) ? "PASSED" : "FAILED"); + printf("Test C99 VLA 4 (ptr access): "); + tab1[size1][1] = 42; + printf("%s\n", (*((int *) (tab1_ptr + (size1 * 2 + 1) * sizeof(int))) == 42) ? "PASSED" : "FAILED"); + + printf("Test C99 VLA 5 (bounds checking (might be disabled)): "); + if (bad_ptr = bounds_checking_is_enabled()) { + int *t1 = &tab1[size1 * size2 - 1][3]; + int *t2 = &tab2[9][3]; + printf("%s ", bad_ptr == t1 ? "PASSED" : "FAILED"); + printf("%s ", bad_ptr == t2 ? "PASSED" : "FAILED"); + + char*c1 = 1 + sizeof(tab1) + (char*)tab1; + char*c2 = 1 + sizeof(tab2) + (char*)tab2; + printf("%s ", bad_ptr == c1 ? "PASSED" : "FAILED"); + printf("%s ", bad_ptr == c2 ? "PASSED" : "FAILED"); + + int *i1 = tab1[-1]; + int *i2 = tab2[-1]; + printf("%s ", bad_ptr == i1 ? "PASSED" : "FAILED"); + printf("%s ", bad_ptr == i2 ? "PASSED" : "FAILED"); + + int *x1 = tab1[size1 * size2 + 1]; + int *x2 = tab2[10 + 1]; + printf("%s ", bad_ptr == x1 ? "PASSED" : "FAILED"); + printf("%s ", bad_ptr == x2 ? "PASSED" : "FAILED"); + } else { + printf("PASSED PASSED PASSED PASSED PASSED PASSED PASSED PASSED "); + } + printf("\n"); +} + +void c99_vla_test_2(int d, int h, int w) +{ + int x, y, z; + int (*arr)[h][w] = malloc(sizeof(int) * d*h*w); + int c = 1; + static int (*starr)[h][w]; + + printf("Test C99 VLA 6 (pointer)\n"); + + for (z=0; z> 24) & 0xff) | + ((x >> 8) & 0xff00) | + ((x << 8) & 0xff0000) | + ((x << 24) & 0xff000000); +} +#else +static __inline__ __const__ unsigned int swab32(unsigned int x) +{ + __asm__("xchgb %b0,%h0\n\t" /* swap lower bytes */ + "rorl $16,%0\n\t" /* swap words */ + "xchgb %b0,%h0" /* swap higher bytes */ + :"=" "q" (x) + : "0" (x)); + return x; +} +#endif + +static __inline__ unsigned long long mul64(unsigned int a, unsigned int b) +{ + unsigned long long res; +#ifdef __x86_64__ + /* Using the A constraint is wrong (it means rdx:rax, which is too large) + but still test the 32bit->64bit mull. */ + unsigned int resh, resl; + __asm__("mull %2" : "=a" (resl), "=d" (resh) : "a" (a), "r" (b)); + res = ((unsigned long long)resh << 32) | resl; +#else + __asm__("mull %2" : "=A" (res) : "a" (a), "r" (b)); +#endif + return res; +} + +static __inline__ unsigned long long inc64(unsigned long long a) +{ + unsigned long long res; +#ifdef __x86_64__ + /* Using the A constraint is wrong, and increments are tested + elsewhere. */ + res = a + 1; +#else + __asm__("addl $1, %%eax ; adcl $0, %%edx" : "=A" (res) : "A" (a)); +#endif + return res; +} + +struct struct123 { + int a; + int b; +}; +struct struct1231 { + word addr; +}; + +word mconstraint_test(struct struct1231 *r) +{ + word ret; + unsigned int a[2]; + a[0] = 0; + __asm__ volatile ("lea %2,%0; movl 4(%0),%k0; addl %2,%k0; movl $51,%2; movl $52,4%2; movl $63,%1" + : "=&r" (ret), "=m" (a) + : "m" (*(struct struct123 *)r->addr)); + return ret + a[0]; +} + +#ifdef __x86_64__ +int fls64(unsigned long long x) +{ + int bitpos = -1; + asm("bsrq %1,%q0" + : "+r" (bitpos) + : "rm" (x)); + return bitpos + 1; +} +#endif + +void other_constraints_test(void) +{ + word ret; + int var; +#if CC_NAME != CC_clang + __asm__ volatile ("mov %P1,%0" : "=r" (ret) : "p" (&var)); + printf ("oc1: %d\n", ret == (word)&var); +#endif +} + +#ifndef _WIN32 +/* Test global asm blocks playing with aliases. */ +void base_func(void) +{ + printf ("asmc: base\n"); +} + +#ifndef __APPLE__ +extern void override_func1 (void); +extern void override_func2 (void); + +asm(".weak override_func1\n.set override_func1, base_func"); +asm(".set override_func1, base_func"); +asm(".set override_func2, base_func"); + +void override_func2 (void) +{ + printf ("asmc: override2\n"); +} + +/* This checks a construct used by the linux kernel to encode + references to strings by PC relative references. */ +extern int bug_table[] __attribute__((section("__bug_table"))); +char * get_asm_string (void) +{ + /* On i386 when -fPIC is enabled this would cause a compile error with GCC, + the problem being the "i" constraint used with a symbolic operand + resolving to a local label. That check is overly zealous as the code + within the asm makes sure to use it only in PIC-possible contexts, + but all GCC versions behave like so. We arrange for PIC to be disabled + for compiling tcctest.c in the Makefile. + + Additionally the usage of 'c' in "%c0" in the template is actually wrong, + as that would expect an operand that is a condition code. The operand + as is (a local label) is accepted by GCC in non-PIC mode, and on x86-64. + What the linux kernel really wanted is 'p' to disable the addition of '$' + to the printed operand (as in "$.LC0" where the template only wants the + bare operand ".LC0"). But the code below is what the linux kernel + happens to use and as such is the one we want to test. */ +#ifndef __clang__ + extern int some_symbol; + asm volatile (".globl some_symbol\n" + "jmp .+6\n" + "1:\n" + "some_symbol: .long 0\n" + ".pushsection __bug_table, \"a\"\n" + ".globl bug_table\n" + "bug_table:\n" + /* The first entry (1b-2b) is unused in this test, + but we include it to check if cross-section + PC-relative references work. */ + "2:\t.long 1b - 2b, %c0 - 2b\n" + ".popsection\n" : : "i" ("A string")); + char * str = ((char*)bug_table) + bug_table[1]; + return str; +#else + return (char *) "A string"; +#endif +} + +/* This checks another constructs with local labels. */ +extern unsigned char alld_stuff[]; +asm(".data\n" + ".byte 41\n" + "alld_stuff:\n" + "661:\n" + ".byte 42\n" + "662:\n" + ".pushsection .data.ignore\n" + ".long 661b - .\n" /* This reference to 661 generates an external sym + which shouldn't somehow overwrite the offset that's + already determined for it. */ + ".popsection\n" + ".byte 662b - 661b\n" /* So that this value is undeniably 1. */); + +void asm_local_label_diff (void) +{ + printf ("asm_local_label_diff: %d %d\n", alld_stuff[0], alld_stuff[1]); +} +#endif +#endif + +/* This checks that static local variables are available from assembler. */ +void asm_local_statics (void) +{ + static int localint = 41; + asm("incl %0" : "+m" (localint)); + printf ("asm_local_statics: %d\n", localint); +} + +static +unsigned int set; + +void fancy_copy (unsigned *in, unsigned *out) +{ + asm volatile ("" : "=r" (*out) : "0" (*in)); +} + +void fancy_copy2 (unsigned *in, unsigned *out) +{ + asm volatile ("mov %0,(%1)" : : "r" (*in), "r" (out) : "memory"); +} + +#if defined __x86_64__ +void clobber_r12(void) +{ + asm volatile("mov $1, %%r12" ::: "r12"); +} +#endif + +void test_high_clobbers_really(void) +{ +#if defined __x86_64__ + register word val asm("r12"); + word val2; + /* This tests if asm clobbers correctly save/restore callee saved + registers if they are clobbered and if it's the high 8 x86-64 + registers. This is fragile for GCC as the constraints do not + correctly capture the data flow, but good enough for us. */ + asm volatile("mov $0x4542, %%r12" : "=r" (val):: "memory"); + clobber_r12(); + asm volatile("mov %%r12, %0" : "=r" (val2) : "r" (val): "memory"); + printf("asmhc: 0x%x\n", val2); +#endif +} + +void test_high_clobbers(void) +{ +#if defined __x86_64__ + word x1, x2; + asm volatile("mov %%r12,%0" :: "m" (x1)); /* save r12 */ + test_high_clobbers_really(); + asm volatile("mov %%r12,%0" :: "m" (x2)); /* new r12 */ + asm volatile("mov %0,%%r12" :: "m" (x1)); /* restore r12 */ + /* should be 0 but tcc doesn't save r12 automatically, which has + bad effects when gcc helds TCCState *s in r12 in tcc.c:main */ + //printf("r12-clobber-diff: %lx\n", x2 - x1); +#endif +} + +static long cpu_number; +void trace_console(long len, long len2) +{ +#ifdef __x86_64__ + /* This generated invalid code when the emission of the switch + table isn't disabled. The asms are necessary to show the bug, + normal statements don't work (they need to generate some code + even under nocode_wanted, which normal statements don't do, + but asms do). Also at least these number of cases is necessary + to generate enough "random" bytes. They ultimately are enough + to create invalid instruction patterns to which the first + skip-to-decision-table jump jumps. If decision table emission + is disabled all of this is no problem. + + It also is necessary that the switches are in a statement expression + (which has the property of not being enterable from outside. no + matter what). */ + if (0 + && + ({ + long pscr_ret__; + switch(len) { + case 4: + { + long pfo_ret__; + switch (len2) { + case 8: printf("bla"); pfo_ret__ = 42; break; + } + pscr_ret__ = pfo_ret__; + } + break; + case 8: + { + long pfo_ret__; + switch (len2) { + case 1:asm("movq %1,%0": "=r" (pfo_ret__) : "m" (cpu_number)); break; + case 2:asm("movq %1,%0": "=r" (pfo_ret__) : "m" (cpu_number)); break; + case 4:asm("movq %1,%0": "=r" (pfo_ret__) : "m" (cpu_number)); break; + case 8:asm("movq %1,%0": "=r" (pfo_ret__) : "m" (cpu_number)); break; + default: printf("impossible\n"); + } + pscr_ret__ = pfo_ret__; + }; + break; + } + pscr_ret__; + })) + { + printf("huh?\n"); + } +#endif +} + +void test_asm_dead_code(void) +{ + word rdi; + /* Try to make sure that xdi contains a zero, and hence will + lead to a segfault if the next asm is evaluated without + arguments being set up. */ + asm volatile ("" : "=D" (rdi) : "0" (0)); + (void)sizeof (({ + int var; + /* This shouldn't trigger a segfault, either the argument + registers need to be set up and the asm emitted despite + this being in an unevaluated context, or both the argument + setup _and_ the asm emission need to be suppressed. The latter + is better. Disabling asm code gen when suppression is on + also fixes the above trace_console bug, but that came earlier + than asm suppression. */ + asm volatile ("movl $0,(%0)" : : "D" (&var) : "memory"); + var; + })); +} + +void test_asm_call(void) +{ +#if defined __x86_64__ && !defined _WIN64 && !defined(__APPLE__) + static char str[] = "PATH"; + char *s; + /* This tests if a reference to an undefined symbol from an asm + block, which isn't otherwise referenced in this file, is correctly + regarded as global symbol, so that it's resolved by other object files + or libraries. We chose getenv here, which isn't used anywhere else + in this file. (If we used e.g. printf, which is used we already + would have a global symbol entry, not triggering the bug which is + tested here). */ + /* two pushes so stack remains aligned */ + asm volatile ("push %%rdi; push %%rdi; mov %0, %%rdi;" +#if 1 && !defined(__TINYC__) && (defined(__PIC__) || defined(__PIE__)) + "call getenv@plt;" +#else + "call getenv;" +#endif + "pop %%rdi; pop %%rdi" + : "=a" (s) : "r" (str)); + printf("asmd: %s\n", s); +#endif +} + +#if defined __x86_64__ +# define RX "(%rip)" +#else +# define RX +#endif + +void asm_dot_test(void) +{ +#ifndef __APPLE__ + int x; + for (x = 1;; ++x) { + int r = x; + switch (x) { + case 1: + asm(".text; lea S"RX",%eax; lea ."RX",%ecx; sub %ecx,%eax; S=.; jmp p0"); + case 2: +#ifndef __clang__ + /* clangs internal assembler is broken */ + asm(".text; jmp .+6; .int 123; mov .-4"RX",%eax; jmp p0"); +#else + asm(".text; mov $123, %eax; jmp p0"); +#endif + case 3: +#if !defined(_WIN32) && !defined(__clang__) + asm(".pushsection \".data\"; Y=.; .int 999; X=Y; .int 456; X=.-4; .popsection"); +#else + asm(".data; Y=.; .int 999; X=Y; .int 456; X=.-4; .text"); +#endif + asm(".text; mov X"RX",%eax; jmp p0"); + case 4: +#ifdef __clang__ + /* Bah! Clang! Doesn't want to redefine 'X' */ + asm(".text; mov $789,%eax; jmp p0"); +#else +#ifndef _WIN32 + asm(".data; X=.; .int 789; Y=.; .int 999; .previous"); +#else + asm(".data; X=.; .int 789; Y=.; .int 999; .text"); +#endif + asm(".text; mov X"RX",%eax; X=Y; jmp p0"); +#endif + case 0: + asm(".text; p0=.; mov %%eax,%0;" : "=m"(r)); break; + } + if (r == x) + break; + printf("asm_dot_test %d: %d\n", x, r); + } +#endif +} + +void asm_pcrel_test(void) +{ + unsigned o1, o2; + /* subtract text-section label from forward or other-section label */ + asm("1: mov $2f-1b,%%eax; mov %%eax,%0" : "=m"(o1)); + /* verify ... */ + asm("2: lea 2b"RX",%eax; lea 1b"RX",%ecx; sub %ecx,%eax"); + asm("mov %%eax,%0" : "=m"(o2)); + printf("%s : %x\n", __FUNCTION__, o1 - o2); /* should be zero */ +} + +void asm_test(void) +{ + char buf[128]; + unsigned int val, val2; + struct struct123 s1; + struct struct1231 s2 = { (word)&s1 }; + /* Hide the outer base_func, but check later that the inline + asm block gets the outer one. */ + int base_func = 42; + void override_func3 (void); + word asmret; +#ifdef BOOL_ISOC99 + _Bool somebool; +#endif + register int regvar asm("%esi"); + + // parse 0x1E-1 as 3 tokens in asm mode + asm volatile ("mov $0x1E-1,%eax"); + + /* test the no operand case */ + asm volatile ("xorl %eax, %eax"); + + memcpy1(buf, "hello", 6); + strncat1(buf, " worldXXXXX", 3); + printf("%s\n", buf); + + memcpy2(buf, "hello", 6); + strncat2(buf, " worldXXXXX", 3); + printf("%s\n", buf); + + /* 'A' constraint test */ + printf("mul64=0x%Lx\n", mul64(0x12345678, 0xabcd1234)); + printf("inc64=0x%Lx\n", inc64(0x12345678ffffffff)); + + s1.a = 42; + s1.b = 43; + printf("mconstraint: %d", mconstraint_test(&s2)); + printf(" %d %d\n", s1.a, s1.b); + other_constraints_test(); + set = 0xff; + sigdelset1(&set, 2); + sigaddset1(&set, 16); + /* NOTE: we test here if C labels are correctly restored after the + asm statement */ + goto label1; + label2: + __asm__("btsl %1,%0" : "=m"(set) : "Ir"(20) : "cc"); + printf("set=0x%x\n", set); + val = 0x01020304; + printf("swab32(0x%08x) = 0x%0x\n", val, swab32(val)); +#ifndef _WIN32 +#ifndef __APPLE__ + override_func1(); + override_func2(); + /* The base_func ref from the following inline asm should find + the global one, not the local decl from this function. */ + asm volatile(".weak override_func3\n.set override_func3, base_func"); + override_func3(); + printf("asmstr: %s\n", get_asm_string()); + asm_local_label_diff(); +#endif +#endif + asm_local_statics(); +#ifndef __clang__ + /* clang can't deal with the type change */ + /* Check that we can also load structs of appropriate layout + into registers. */ + asm volatile("" : "=r" (asmret) : "0"(s2)); + if (asmret != s2.addr) + printf("asmstr: failed\n"); +#endif +#ifdef BOOL_ISOC99 + /* Check that the typesize correctly sets the register size to + 8 bit. */ + asm volatile("cmp %1,%2; sete %0" : "=a"(somebool) : "r"(1), "r"(2)); + if (!somebool) + printf("asmbool: failed\n"); +#endif + val = 43; + fancy_copy (&val, &val2); + printf ("fancycpy(%d)=%d\n", val, val2); + val = 44; + fancy_copy2 (&val, &val2); + printf ("fancycpy2(%d)=%d\n", val, val2); + asm volatile ("mov $0x4243, %%esi" : "=r" (regvar)); + printf ("regvar=%x\n", regvar); + test_high_clobbers(); + trace_console(8, 8); + test_asm_dead_code(); + test_asm_call(); + asm_dot_test(); + asm_pcrel_test(); + return; + label1: + goto label2; +} + +#else + +void asm_test(void) +{ +} + +#endif + +#define COMPAT_TYPE(type1, type2) \ +{\ + printf("__builtin_types_compatible_p(%s, %s) = %d\n", #type1, #type2, \ + __builtin_types_compatible_p (type1, type2));\ +} + +int constant_p_var; + +int func(void); + + +/* __builtin_clz and __builtin_ctz return random values for 0 */ +static void builtin_test_bits(unsigned long long x, int cnt[]) +{ +#if GCC_MAJOR >= 4 + cnt[0] += __builtin_ffs(x); + cnt[1] += __builtin_ffsl(x); + cnt[2] += __builtin_ffsll(x); + + if ((unsigned int) x) cnt[3] += __builtin_clz(x); + if ((unsigned long) x) cnt[4] += __builtin_clzl(x); + if ((unsigned long long) x) cnt[5] += __builtin_clzll(x); + + if ((unsigned int) x) cnt[6] += __builtin_ctz(x); + if ((unsigned long) x) cnt[7] += __builtin_ctzl(x); + if ((unsigned long long) x) cnt[8] += __builtin_ctzll(x); + +#if GCC_MAJOR >= 6 && (CC_NAME != CC_clang || GCC_MAJOR >= 11) +/* Apple clang 10 does not have __builtin_clrsb[l[l]] */ + cnt[9] += __builtin_clrsb(x); + cnt[10] += __builtin_clrsbl(x); + cnt[11] += __builtin_clrsbll(x); +#endif + + cnt[12] += __builtin_popcount(x); + cnt[13] += __builtin_popcountl(x); + cnt[14] += __builtin_popcountll(x); + + cnt[15] += __builtin_parity(x); + cnt[16] += __builtin_parityl(x); + cnt[17] += __builtin_parityll(x); +#endif +} + +void builtin_test(void) +{ + short s; + int i; + long long ll; +#if GCC_MAJOR >= 3 + COMPAT_TYPE(int, int); + COMPAT_TYPE(int, unsigned int); + COMPAT_TYPE(int, char); + COMPAT_TYPE(int, const int); + COMPAT_TYPE(int, volatile int); + COMPAT_TYPE(int *, int *); + COMPAT_TYPE(int *, void *); + COMPAT_TYPE(int *, const int *); + COMPAT_TYPE(char *, unsigned char *); + COMPAT_TYPE(char *, signed char *); + COMPAT_TYPE(char *, char *); + COMPAT_TYPE(char **, void *); +#endif + printf("res1 = %d\n", __builtin_constant_p(1)); + printf("res2 = %d\n", __builtin_constant_p(1 + 2)); + printf("res3 = %d\n", __builtin_constant_p(&constant_p_var)); + printf("res4 = %d\n", __builtin_constant_p(constant_p_var)); + printf("res5 = %d\n", __builtin_constant_p(100000 / constant_p_var)); + printf("res6 = %d\n", __builtin_constant_p(i && 1)); + printf("res7 = %d\n", __builtin_constant_p("hi")); + printf("res8 = %d\n", __builtin_constant_p(func())); +#ifndef __clang__ + printf("res10 = %d\n", __builtin_constant_p(i && 0)); + printf("res11 = %d\n", __builtin_constant_p(i * 0)); + printf("res12 = %d\n", __builtin_constant_p(i && 0 ? i : 34)); + printf("res13 = %d\n", __builtin_constant_p((1,7))); +#else + /* clang doesn't regard these as constant expression */ + printf("res10 = 1\n"); + printf("res11 = 1\n"); + printf("res12 = 1\n"); + printf("res13 = 0\n"); +#endif + + s = 1; + ll = 2; + i = __builtin_choose_expr (1 != 0, ll, s); + printf("bce: %d\n", i); + i = __builtin_choose_expr (1 != 1, ll, s); + printf("bce: %d\n", i); + i = sizeof (__builtin_choose_expr (1, ll, s)); + printf("bce: %d\n", i); + i = sizeof (__builtin_choose_expr (0, ll, s)); + printf("bce: %d\n", i); + + //printf("bera: %p\n", __builtin_extract_return_addr((void*)43)); + + { + int cnt[18]; + unsigned long long r = 0; + + memset(cnt, 0, sizeof(cnt)); + builtin_test_bits(0, cnt); + builtin_test_bits(0xffffffffffffffffull, cnt); + for (i = 0; i < 64; i++) + builtin_test_bits(1ull << i, cnt); + for (i = 0; i < 1000; i++) { + r = 0x5851f42d4c957f2dull * r + 0x14057b7ef767814full; + builtin_test_bits(r, cnt); + } + for (i = 0; i < 18; i++) + printf ("%d %d\n", i, cnt[i]); + } +} + +#if defined _WIN32 +void weak_test(void) {} +#else +extern int __attribute__((weak)) weak_f1(void); +extern int __attribute__((weak)) weak_f2(void); +extern int weak_f3(void); +extern int __attribute__((weak)) weak_v1; +extern int __attribute__((weak)) weak_v2; +extern int weak_v3; + +extern int (*weak_fpa)() __attribute__((weak)); +extern int __attribute__((weak)) (*weak_fpb)(); +extern __attribute__((weak)) int (*weak_fpc)(); + +extern int weak_asm_f1(void) asm("weak_asm_f1x") __attribute((weak)); +extern int __attribute((weak)) weak_asm_f2(void) asm("weak_asm_f2x") ; +extern int __attribute((weak)) weak_asm_f3(void) asm("weak_asm_f3x") __attribute((weak)); +extern int weak_asm_v1 asm("weak_asm_v1x") __attribute((weak)); +extern int __attribute((weak)) weak_asm_v2 asm("weak_asm_v2x") ; +extern int __attribute((weak)) weak_asm_v3(void) asm("weak_asm_v3x") __attribute((weak)); + +#ifndef __clang__ +static const size_t dummy = 0; +extern __typeof(dummy) weak_dummy1 __attribute__((weak, alias("dummy"))); +extern __typeof(dummy) __attribute__((weak, alias("dummy"))) weak_dummy2; +extern __attribute__((weak, alias("dummy"))) __typeof(dummy) weak_dummy3; +#endif + +int some_lib_func(void); +int dummy_impl_of_slf(void) { return 444; } +#ifndef __clang__ +int some_lib_func(void) __attribute__((weak, alias("dummy_impl_of_slf"))); +#endif + +int weak_toolate() __attribute__((weak)); +int weak_toolate() { return 0; } + +void __attribute__((weak)) weak_test(void) +{ + printf("weak_f1=%d\n", weak_f1 ? weak_f1() : 123); + printf("weak_f2=%d\n", weak_f2 ? weak_f2() : 123); + printf("weak_f3=%d\n", weak_f3 ? weak_f3() : 123); + printf("weak_v1=%d\n",&weak_v1 ? weak_v1 : 123); + printf("weak_v2=%d\n",&weak_v2 ? weak_v2 : 123); + printf("weak_v3=%d\n",&weak_v3 ? weak_v3 : 123); + + printf("weak_fpa=%d\n",&weak_fpa ? weak_fpa() : 123); + printf("weak_fpb=%d\n",&weak_fpb ? weak_fpb() : 123); + printf("weak_fpc=%d\n",&weak_fpc ? weak_fpc() : 123); + + printf("weak_asm_f1=%d\n", weak_asm_f1 != NULL); + printf("weak_asm_f2=%d\n", weak_asm_f2 != NULL); + printf("weak_asm_f3=%d\n", weak_asm_f3 != NULL); + printf("weak_asm_v1=%d\n",&weak_asm_v1 != NULL); + printf("weak_asm_v2=%d\n",&weak_asm_v2 != NULL); + printf("weak_asm_v3=%d\n",&weak_asm_v3 != NULL); +#ifdef __clang__ + printf("some_lib_func=444\n"); +#else + printf("some_lib_func=%d\n", &some_lib_func ? some_lib_func() : 0); +#endif +} + +int __attribute__((weak)) weak_f2() { return 222; } +int __attribute__((weak)) weak_f3() { return 333; } +int __attribute__((weak)) weak_v2 = 222; +int __attribute__((weak)) weak_v3 = 333; +#endif + +void const_func(const int a) +{ +} + +void const_warn_test(void) +{ + const_func(1); +} + +struct condstruct { + int i; +}; + +int getme (struct condstruct *s, int i) +{ + int i1 = (i == 0 ? 0 : s)->i; + int i2 = (i == 0 ? s : 0)->i; + int i3 = (i == 0 ? (void*)0 : s)->i; + int i4 = (i == 0 ? s : (void*)0)->i; + return i1 + i2 + i3 + i4; +} + +struct global_data +{ + int a[40]; + int *b[40]; +}; + +struct global_data global_data; + +int global_data_getstuff (int *, int); + +void global_data_callit (int i) +{ + *global_data.b[i] = global_data_getstuff (global_data.b[i], 1); +} + +int global_data_getstuff (int *p, int i) +{ + return *p + i; +} + +void global_data_test (void) +{ + global_data.a[0] = 42; + global_data.b[0] = &global_data.a[0]; + global_data_callit (0); + printf ("%d\n", global_data.a[0]); +} + +struct cmpcmpS +{ + unsigned char fill : 3; + unsigned char b1 : 1; + unsigned char b2 : 1; + unsigned char fill2 : 3; +}; + +int glob1, glob2, glob3; + +void compare_comparisons (struct cmpcmpS *s) +{ + if (s->b1 != (glob1 == glob2) + || (s->b2 != (glob1 == glob3))) + printf ("comparing comparisons broken\n"); +} + +void cmp_comparison_test(void) +{ + struct cmpcmpS s; + s.b1 = 1; + glob1 = 42; glob2 = 42; + s.b2 = 0; + glob3 = 43; + compare_comparisons (&s); +} + +int fcompare (double a, double b, int code) +{ + switch (code) { + case 0: return a == b; + case 1: return a != b; + case 2: return a < b; + case 3: return a >= b; + case 4: return a > b; + case 5: return a <= b; + } + return 0; +} + +void math_cmp_test(void) +{ + double nan = 0.0/0.0; + double one = 1.0; + double two = 2.0; + int comp = 0; + int v; +#define bug(a,b,op,iop,part) printf("Test broken: %s %s %s %s %d\n", #a, #b, #op, #iop, part) + + /* This asserts that "a op b" is _not_ true, but "a iop b" is true. + And it does this in various ways so that all code generation paths + are checked (generating inverted tests, or non-inverted tests, or + producing a 0/1 value without jumps (that's done in the fcompare + function). */ +#define FCMP(a,b,op,iop,code) \ + if (fcompare (a,b,code)) \ + bug (a,b,op,iop,1); \ + if (a op b) \ + bug (a,b,op,iop,2); \ + if (a iop b) \ + ; \ + else \ + bug (a,b,op,iop,3); \ + if ((a op b) || comp) \ + bug (a,b,op,iop,4); \ + if ((a iop b) || comp) \ + ; \ + else \ + bug (a,b,op,iop,5); \ + if (v = !(a op b), !v) bug(a,b,op,iop,7); + + /* Equality tests. */ + FCMP(nan, nan, ==, !=, 0); + FCMP(one, two, ==, !=, 0); + FCMP(one, one, !=, ==, 1); + /* Non-equality is a bit special. */ + if (!fcompare (nan, nan, 1)) + bug (nan, nan, !=, ==, 6); + + /* Relational tests on numbers. */ + FCMP(two, one, <, >=, 2); + FCMP(one, two, >=, <, 3); + FCMP(one, two, >, <=, 4); + FCMP(two, one, <=, >, 5); + + /* Relational tests on NaNs. Note that the inverse op here is + always !=, there's no operator in C that is equivalent to !(a < b), + when NaNs are involved, same for the other relational ops. */ + FCMP(nan, nan, <, !=, 2); + FCMP(nan, nan, >=, !=, 3); + FCMP(nan, nan, >, !=, 4); + FCMP(nan, nan, <=, !=, 5); +} + +double get100 () { return 100.0; } + +void callsave_test(void) +{ +#if defined __i386__ || defined __x86_64__ || defined __arm__ + int i, s; double *d; double t; + s = sizeof (double); + printf ("callsavetest: %d\n", s); + d = alloca (sizeof(double)); + d[0] = 10.0; + /* x86-64 had a bug were the next call to get100 would evict + the lvalue &d[0] as VT_LLOCAL, and the reload would be done + in int type, not pointer type. When alloca returns a pointer + with the high 32 bit set (which is likely on x86-64) the access + generates a segfault. */ + i = d[0] > get100 (); + printf ("%d\n", i); +#endif +} + + +void bfa3(ptrdiff_t str_offset) +{ + printf("bfa3: %s\n", (char *)__builtin_frame_address(3) + str_offset); +} +void bfa2(ptrdiff_t str_offset) +{ + printf("bfa2: %s\n", (char *)__builtin_frame_address(2) + str_offset); + bfa3(str_offset); +} +void bfa1(ptrdiff_t str_offset) +{ + printf("bfa1: %s\n", (char *)__builtin_frame_address(1) + str_offset); + bfa2(str_offset); +} + +void builtin_frame_address_test(void) +{ +/* builtin_frame_address fails on ARM with gcc which make test3 fail */ +#ifndef __arm__ + char str[] = "__builtin_frame_address"; + char *fp0 = __builtin_frame_address(0); + + printf("str: %s\n", str); +#ifndef __riscv // gcc dumps core. tcc, clang work + bfa1(str-fp0); +#endif +#endif +} + +char via_volatile (char i) +{ + char volatile vi; + vi = i; + return vi; +} + +void volatile_test(void) +{ + if (via_volatile (42) != 42) + printf (" broken\n"); + else + printf (" ok\n"); +} + +struct __attribute__((__packed__)) Spacked { + char a; + short b; + int c; +}; +struct Spacked spacked; +typedef struct __attribute__((__packed__)) { + char a; + short b; + int c; +} Spacked2; +Spacked2 spacked2; +typedef struct Spacked3_s { + char a; + short b; + int c; +} __attribute__((__packed__)) Spacked3; +Spacked3 spacked3; +struct gate_struct64 { + unsigned short offset_low; + unsigned short segment; + unsigned ist : 3, zero0 : 5, type : 5, dpl : 2, p : 1; + unsigned short offset_middle; + unsigned offset_high; + unsigned zero1; +} __attribute__((packed)); +typedef struct gate_struct64 gate_desc; +gate_desc a_gate_desc; +void attrib_test(void) +{ +#ifndef _WIN32 + printf("attr: %d %d %d %d\n", sizeof(struct Spacked), + sizeof(spacked), sizeof(Spacked2), sizeof(spacked2)); + printf("attr: %d %d\n", sizeof(Spacked3), sizeof(spacked3)); + printf("attr: %d %d\n", sizeof(gate_desc), sizeof(a_gate_desc)); +#endif +} +extern __attribute__((__unused__)) char * __attribute__((__unused__)) * +strange_attrib_placement (void); + +void * __attribute__((__unused__)) get_void_ptr (void *a) +{ + return a; +} + +/* This part checks for a bug in TOK_GET (used for inline expansion), + where the large long long constant left the the high bits set for + the integer constant token. */ +static inline +int __get_order(unsigned long long size) +{ + int order; + size -= 0xffff880000000000ULL; // this const left high bits set in the token + { + struct S { int i : 1; } s; // constructed for this '1' + } + order = size; + return order; +} + +/* This just forces the above inline function to be actually emitted. */ +int force_get_order(unsigned long s) +{ + return __get_order(s); +} + +#define pv(m) printf(sizeof (s->m + 0) == 8 ? "%016llx\n" : "%02x\n", s->m) + +/* Test failed when using bounds checking */ +void bounds_check1_test (void) +{ + struct s { + int x; + long long y; + } _s, *s = &_s; + s->x = 10; + s->y = 20; + pv(x); + pv(y); +} + +/* This failed on arm64/riscv64 */ +void map_add(int a, int b, int c, int d, int e, int f, int g, int h, int i) +{ + printf ("%d %d %d %d %d %d %d %d %d\n", a, b, c, d, e, f, g, h, i); +} + +void func_arg_test(void) +{ + int a = 0; + int b = 1; + map_add(0, 1, 2, 3, 4, 5, 6, 7, a && b); +} + +/* gcc 2.95.3 does not handle correctly CR in strings or after strays */ +#define CORRECT_CR_HANDLING + +/* deprecated and no longer supported in gcc 3.3 */ +/* no longer supported by default in TinyCC */ +#ifdef __TINYC__ +/* # define ACCEPT_LF_IN_STRINGS */ +#endif + +#define tcc_test() + +/* keep this as the last test because GCC messes up line-numbers + with the ^L^K^M characters below */ +void whitespace_test(void) +{ + char *str; + int tcc_test = 1; + + #if 1 + pri\ +ntf("whitspace:\n"); +#endif + pf("N=%d\n", 2); + +#ifdef CORRECT_CR_HANDLING + pri\ +ntf("aaa=%d\n", 3); +#endif + + pri\ +\ +ntf("min=%d\n", 4); + +#ifdef ACCEPT_LF_IN_STRINGS + printf("len1=%d\n", strlen(" +")); +#ifdef CORRECT_CR_HANDLING + str = " +"; + printf("len1=%d str[0]=%d\n", strlen(str), str[0]); +#endif + printf("len1=%d\n", strlen(" a +")); +#else + printf("len1=1\nlen1=1 str[0]=10\nlen1=3\n"); +#endif /* ACCEPT_LF_IN_STRINGS */ + +#ifdef __LINE__ + printf("__LINE__ defined\n"); +#endif + +#if 0 + /* wrong with GCC */ + printf("__LINE__=%d __FILE__=%s\n", __LINE__, __FILE__); +#line 1111 + printf("__LINE__=%d __FILE__=%s\n", __LINE__, __FILE__); +#line 2222 "test" + printf("__LINE__=%d __FILE__=%s\n", __LINE__, __FILE__); +#endif + + printf("\\ +"12\\ +063\\ +n 456\"\n"); + + printf ("%d\n", +#if 1 + tcc_test +#endif + ); + +} + +#define RUN(test) puts("---- " #test " ----"), test(), puts("") + +int main(int argc, char **argv) +{ + RUN(whitespace_test); + RUN(macro_test); + RUN(recursive_macro_test); + RUN(string_test); + RUN(expr_test); + RUN(scope_test); + RUN(scope2_test); + RUN(forward_test); + RUN(funcptr_test); + RUN(if_test); + RUN(loop_test); + RUN(switch_test); + RUN(goto_test); + RUN(enum_test); + RUN(typedef_test); + RUN(struct_test); + RUN(array_test); + RUN(expr_ptr_test); + RUN(bool_test); + RUN(optimize_out_test); + RUN(expr2_test); + RUN(constant_expr_test); + RUN(expr_cmp_test); + RUN(char_short_test); + RUN(init_test); + RUN(compound_literal_test); + RUN(kr_test); + RUN(struct_assign_test); + RUN(cast_test); + RUN(bitfield_test); + RUN(c99_bool_test); + RUN(float_test); + RUN(longlong_test); + RUN(manyarg_test); + RUN(stdarg_test); + RUN(relocation_test); + RUN(old_style_function_test); + RUN(alloca_test); + RUN(c99_vla_test); + RUN(sizeof_test); + RUN(typeof_test); + RUN(statement_expr_test); + RUN(local_label_test); + RUN(asm_test); + RUN(builtin_test); + RUN(weak_test); + RUN(global_data_test); + RUN(cmp_comparison_test); + RUN(math_cmp_test); + RUN(callsave_test); + RUN(builtin_frame_address_test); + RUN(volatile_test); + RUN(attrib_test); + RUN(bounds_check1_test); + RUN(func_arg_test); + + return 0; +} diff --git a/lib/tinycc/tests/tcctest.h b/lib/tinycc/tests/tcctest.h new file mode 100644 index 000000000..b301c7c16 --- /dev/null +++ b/lib/tinycc/tests/tcctest.h @@ -0,0 +1,9 @@ +static inline const char *get_basefile_from_header(void) +{ + return __BASE_FILE__; +} + +static inline const char *get_file_from_header(void) +{ + return __FILE__; +} diff --git a/lib/tinycc/tests/testfp.c b/lib/tinycc/tests/testfp.c new file mode 100644 index 000000000..63342b422 --- /dev/null +++ b/lib/tinycc/tests/testfp.c @@ -0,0 +1,510 @@ +/* + * Test 128-bit floating-point arithmetic on arm64: + * build with two different compilers and compare the output. + * + * Copyright (c) 2015 Edmund Grimley Evans + * + * Copying and distribution of this file, with or without modification, + * are permitted in any medium without royalty provided the copyright + * notice and this notice are preserved. This file is offered as-is, + * without any warranty. + */ + +#include +#include +#include +#include + +#define check(x) ((x) ? (void)0 : check_fail(#x, __FILE__, __LINE__)) + +void check_fail(const char *assertion, const char *file, unsigned int line) +{ + printf("%s:%d: Check (%s) failed.", file, line, assertion); + exit(1); +} + +typedef struct { + unsigned long long x0, x1; +} u128_t; + +float copy_fi(uint32_t x) +{ + float f; + memcpy(&f, &x, 4); + return f; +} + +double copy_di(uint64_t x) +{ + double f; + memcpy(&f, &x, 8); + return f; +} + +long double copy_ldi(u128_t x) +{ + long double f; + memcpy(&f, &x, 16); + return f; +} + +uint32_t copy_if(float f) +{ + uint32_t x; + memcpy(&x, &f, 4); + return x; +} + +uint64_t copy_id(double f) +{ + uint64_t x; + memcpy(&x, &f, 8); + return x; +} + +u128_t copy_ild(long double f) +{ + u128_t x; + memcpy(&x, &f, 16); + return x; +} + +long double make(int sgn, int exp, uint64_t high, uint64_t low) +{ + u128_t x = { low, + (0x0000ffffffffffff & high) | + (0x7fff000000000000 & (uint64_t)exp << 48) | + (0x8000000000000000 & (uint64_t)sgn << 63) }; + return copy_ldi(x); +} + +void cmp(long double a, long double b) +{ + u128_t ax = copy_ild(a); + u128_t bx = copy_ild(b); + int eq = (a == b); + int ne = (a != b); + int lt = (a < b); + int le = (a <= b); + int gt = (a > b); + int ge = (a >= b); + + check(eq == 0 || eq == 1); + check(lt == 0 || lt == 1); + check(gt == 0 || gt == 1); + check(ne == !eq && le == (lt | eq) && ge == (gt | eq)); + check(eq + lt + gt < 2); + + printf("cmp %016llx%016llx %016llx%016llx %d %d %d\n", + ax.x1, ax.x0, bx.x1, bx.x0, lt, eq, gt); +} + +void cmps(void) +{ + int i, j; + + for (i = 0; i < 2; i++) + for (j = 0; j < 2; j++) + cmp(make(i, 0, 0, 0), make(j, 0, 0, 0)); + + for (i = 0; i < 2; i++) { + for (j = 0; j < 64; j++) { + long double f1 = make(i, 32767, (uint64_t)1 << j, 0); + long double f2 = make(i, 32767, 0, (uint64_t)1 << j); + cmp(f1, 0); + cmp(f2, 0); + cmp(0, f1); + cmp(0, f2); + } + } + + for (i = 0; i < 6; i++) + for (j = 0; j < 6; j++) + cmp(make(i & 1, i >> 1, 0, 0), + make(j & 1, j >> 1, 0, 0)); + + for (i = 0; i < 2; i++) { + for (j = 0; j < 2; j++) { + int a, b; + for (a = 0; a < 2; a++) { + for (b = 0; b < 2; b++) { + cmp(make(i, j, a, b), make(i, j, 0, 0)); + cmp(make(i, j, 0, 0), make(i, j, a, b)); + } + } + } + } +} + +void xop(const char *name, long double a, long double b, long double c) +{ + u128_t ax = copy_ild(a); + u128_t bx = copy_ild(b); + u128_t cx = copy_ild(c); + printf("%s %016llx%016llx %016llx%016llx %016llx%016llx\n", + name, ax.x1, ax.x0, bx.x1, bx.x0, cx.x1, cx.x0); +} + +void fadd(long double a, long double b) +{ + xop("add", a, b, a + b); +} + +void fsub(long double a, long double b) +{ + xop("sub", a, b, a - b); +} + +void fmul(long double a, long double b) +{ + xop("mul", a, b, a * b); +} + +void fdiv(long double a, long double b) +{ + xop("div", a, b, a / b); +} + +void nanz(void) +{ + // Check NaNs: + { + long double x[7]; + int i, j, n = 0; + x[n++] = make(0, 32000, 0x95132b76effc, 0xd79035214b4f8d53); + x[n++] = make(1, 32001, 0xbe71d7a51587, 0x30601c6815d6c3ac); + x[n++] = make(0, 32767, 0, 1); + x[n++] = make(0, 32767, (uint64_t)1 << 46, 0); + x[n++] = make(1, 32767, (uint64_t)1 << 47, 0); + x[n++] = make(1, 32767, 0x7596c7099ad5, 0xe25fed2c58f73fc9); + x[n++] = make(0, 32767, 0x835d143360f9, 0x5e315efb35630666); + check(n == sizeof(x) / sizeof(*x)); + for (i = 0; i < n; i++) { + for (j = 0; j < n; j++) { + fadd(x[i], x[j]); + fsub(x[i], x[j]); + fmul(x[i], x[j]); + fdiv(x[i], x[j]); + } + } + } + + // Check infinities and zeroes: + { + long double x[6]; + int i, j, n = 0; + x[n++] = make(1, 32000, 0x62acda85f700, 0x47b6c9f35edc4044); + x[n++] = make(0, 32001, 0x94b7abf55af7, 0x9f425fe354428e19); + x[n++] = make(0, 32767, 0, 0); + x[n++] = make(1, 32767, 0, 0); + x[n++] = make(0, 0, 0, 0); + x[n++] = make(1, 0, 0, 0); + check(n == sizeof(x) / sizeof(*x)); + for (i = 0; i < n; i++) { + for (j = 0; j < n; j++) { + fadd(x[i], x[j]); + fsub(x[i], x[j]); + fmul(x[i], x[j]); + fdiv(x[i], x[j]); + } + } + } +} + +void adds(void) +{ + // Check shifting and add/sub: + { + int i; + for (i = -130; i <= 130; i++) { + int s1 = (uint32_t)i % 3 < 1; + int s2 = (uint32_t)i % 5 < 2; + fadd(make(s1, 16384 , 0x502c065e4f71a65d, 0xd2f9bdb031f4f031), + make(s2, 16384 + i, 0xae267395a9bc1033, 0xb56b5800da1ba448)); + } + } + + // Check normalisation: + { + uint64_t a0 = 0xc6bab0a6afbef5ed; + uint64_t a1 = 0x4f84136c4a2e9b52; + int ee[] = { 0, 1, 10000 }; + int e, i; + for (e = 0; e < sizeof(ee) / sizeof(*ee); e++) { + int exp = ee[e]; + fsub(make(0, exp, a1, a0), make(0, 0, 0, 0)); + for (i = 63; i >= 0; i--) + fsub(make(0, exp, a1 | (uint64_t)1 << i >> 1, a0), + make(0, exp, a1 >> i << i, 0)); + for (i = 63; i >=0; i--) + fsub(make(0, exp, a1, a0 | (uint64_t)1 << i >> 1), + make(0, exp, a1, a0 >> i << i)); + } + } + + // Carry/overflow from rounding: + { + fadd(make(0, 114, -1, -1), make(0, 1, 0, 0)); + fadd(make(0, 32766, -1, -1), make(0, 32653, 0, 0)); + fsub(make(1, 32766, -1, -1), make(0, 32653, 0, 0)); + } +} + +void muls(void) +{ + int i, j; + + { + long double max = make(0, 32766, -1, -1); + long double min = make(0, 0, 0, 1); + fmul(max, max); + fmul(max, min); + fmul(min, min); + } + + for (i = 117; i > 0; i--) + fmul(make(0, 16268, 0x643dcea76edc, 0xe0877a598403627a), + make(i & 1, i, 0, 0)); + + fmul(make(0, 16383, -1, -3), make(0, 16383, 0, 1)); + // Round to next exponent: + fmul(make(0, 16383, -1, -2), make(0, 16383, 0, 1)); + // Round from subnormal to normal: + fmul(make(0, 1, -1, -1), make(0, 16382, 0, 0)); + + for (i = 0; i < 2; i++) + for (j = 0; j < 112; j++) + fmul(make(0, 16383, (uint64_t)1 << i, 0), + make(0, 16383, + j < 64 ? 0 : (uint64_t)1 << (j - 64), + j < 64 ? (uint64_t)1 << j : 0)); +} + +void divs(void) +{ + int i; + + { + long double max = make(0, 32766, -1, -1); + long double min = make(0, 0, 0, 1); + fdiv(max, max); + fdiv(max, min); + fdiv(min, max); + fdiv(min, min); + } + + for (i = 0; i < 64; i++) + fdiv(make(0, 16383, -1, -1), make(0, 16383, -1, -(uint64_t)1 << i)); + for (i = 0; i < 48; i++) + fdiv(make(0, 16383, -1, -1), make(0, 16383, -(uint64_t)1 << i, 0)); +} + +void cvtlsw(int32_t a) +{ + long double f = a; + u128_t x = copy_ild(f); + printf("cvtlsw %08lx %016llx%016llx\n", (long)(uint32_t)a, x.x1, x.x0); +} + +void cvtlsx(int64_t a) +{ + long double f = a; + u128_t x = copy_ild(f); + printf("cvtlsx %016llx %016llx%016llx\n", + (long long)(uint64_t)a, x.x1, x.x0); +} + +void cvtluw(uint32_t a) +{ + long double f = a; + u128_t x = copy_ild(f); + printf("cvtluw %08lx %016llx%016llx\n", (long)a, x.x1, x.x0); +} + +void cvtlux(uint64_t a) +{ + long double f = a; + u128_t x = copy_ild(f); + printf("cvtlux %016llx %016llx%016llx\n", (long long)a, x.x1, x.x0); +} + +void cvtil(long double a) +{ + u128_t x = copy_ild(a); + int32_t b1 = a; + int64_t b2 = a; + uint32_t b3 = a; + uint64_t b4 = a; + printf("cvtswl %016llx%016llx %08lx\n", + x.x1, x.x0, (long)(uint32_t)b1); + printf("cvtsxl %016llx%016llx %016llx\n", + x.x1, x.x0, (long long)(uint64_t)b2); + printf("cvtuwl %016llx%016llx %08lx\n", + x.x1, x.x0, (long)b3); + printf("cvtuxl %016llx%016llx %016llx\n", + x.x1, x.x0, (long long)b4); +} + +void cvtlf(float a) +{ + uint32_t ax = copy_if(a); + long double b = a; + u128_t bx = copy_ild(b); + printf("cvtlf %08lx %016llx%016llx\n", (long)ax, bx.x1, bx.x0); +} + +void cvtld(double a) +{ + uint64_t ax = copy_id(a); + long double b = a; + u128_t bx = copy_ild(b); + printf("cvtld %016llx %016llx%016llx\n", (long long)ax, bx.x1, bx.x0); +} + +void cvtfl(long double a) +{ + u128_t ax = copy_ild(a); + float b = a; + uint32_t bx = copy_if(b); + printf("cvtfl %016llx%016llx %08lx\n", ax.x1, ax.x0, (long)bx); +} + +void cvtdl(long double a) +{ + u128_t ax = copy_ild(a); + double b = a; + uint64_t bx = copy_id(b); + printf("cvtdl %016llx%016llx %016llx\n", ax.x1, ax.x0, (long long)bx); +} + +void cvts(void) +{ + int i, j; + + { + uint32_t x = 0xad040c5b; + cvtlsw(0); + for (i = 0; i < 31; i++) + cvtlsw(x >> (31 - i)); + for (i = 0; i < 31; i++) + cvtlsw(-(x >> (31 - i))); + cvtlsw(0x80000000); + } + { + uint64_t x = 0xb630a248cad9afd2; + cvtlsx(0); + for (i = 0; i < 63; i++) + cvtlsx(x >> (63 - i)); + for (i = 0; i < 63; i++) + cvtlsx(-(x >> (63 - i))); + cvtlsx(0x8000000000000000); + } + { + uint32_t x = 0xad040c5b; + cvtluw(0); + for (i = 0; i < 32; i++) + cvtluw(x >> (31 - i)); + } + { + uint64_t x = 0xb630a248cad9afd2; + cvtlux(0); + for (i = 0; i < 64; i++) + cvtlux(x >> (63 - i)); + } + + for (i = 0; i < 2; i++) { + cvtil(make(i, 32767, 0, 1)); + cvtil(make(i, 32767, (uint64_t)1 << 47, 0)); + cvtil(make(i, 32767, 123, 456)); + cvtil(make(i, 32767, 0, 0)); + cvtil(make(i, 16382, -1, -1)); + cvtil(make(i, 16383, -1, -1)); + cvtil(make(i, 16384, 0x7fffffffffff, -1)); + cvtil(make(i, 16384, 0x800000000000, 0)); + for (j = 0; j < 68; j++) + cvtil(make(i, 16381 + j, 0xd4822c0a10ec, 0x1fe2f8b2669f5c9d)); + } + + cvtlf(copy_fi(0x00000000)); + cvtlf(copy_fi(0x456789ab)); + cvtlf(copy_fi(0x7f800000)); + cvtlf(copy_fi(0x7f923456)); + cvtlf(copy_fi(0x7fdbcdef)); + cvtlf(copy_fi(0x80000000)); + cvtlf(copy_fi(0xabcdef12)); + cvtlf(copy_fi(0xff800000)); + cvtlf(copy_fi(0xff923456)); + cvtlf(copy_fi(0xffdbcdef)); + + cvtld(copy_di(0x0000000000000000)); + cvtld(copy_di(0x456789abcdef0123)); + cvtld(copy_di(0x7ff0000000000000)); + cvtld(copy_di(0x7ff123456789abcd)); + cvtld(copy_di(0x7ffabcdef1234567)); + cvtld(copy_di(0x8000000000000000)); + cvtld(copy_di(0xcdef123456789abc)); + cvtld(copy_di(0xfff0000000000000)); + cvtld(copy_di(0xfff123456789abcd)); + cvtld(copy_di(0xfffabcdef1234567)); + + for (i = 0; i < 2; i++) { \ + cvtfl(make(i, 0, 0, 0)); + cvtfl(make(i, 16232, -1, -1)); + cvtfl(make(i, 16233, 0, 0)); + cvtfl(make(i, 16233, 0, 1)); + cvtfl(make(i, 16383, 0xab0ffd000000, 0)); + cvtfl(make(i, 16383, 0xab0ffd000001, 0)); + cvtfl(make(i, 16383, 0xab0ffeffffff, 0)); + cvtfl(make(i, 16383, 0xab0fff000000, 0)); + cvtfl(make(i, 16383, 0xab0fff000001, 0)); + cvtfl(make(i, 16510, 0xfffffeffffff, -1)); + cvtfl(make(i, 16510, 0xffffff000000, 0)); + cvtfl(make(i, 16511, 0, 0)); + cvtfl(make(i, 32767, 0, 0)); + cvtfl(make(i, 32767, 0, 1)); + cvtfl(make(i, 32767, 0x4cbe01ac5f40, 0x75cee3c6afbb00b5)); + cvtfl(make(i, 32767, 0x800000000000, 1)); + cvtfl(make(i, 32767, 0xa11caaaf6a52, 0x696033e871eab099)); + } + + for (i = 0; i < 2; i++) { + cvtdl(make(i, 0, 0, 0)); + cvtdl(make(i, 15307, -1, -1)); + cvtdl(make(i, 15308, 0, 0)); + cvtdl(make(i, 15308, 0, 1)); + cvtdl(make(i, 16383, 0xabc123abc0ff, 0xe800000000000000)); + cvtdl(make(i, 16383, 0xabc123abc0ff, 0xe800000000000001)); + cvtdl(make(i, 16383, 0xabc123abc0ff, 0xf7ffffffffffffff)); + cvtdl(make(i, 16383, 0xabc123abc0ff, 0xf800000000000000)); + cvtdl(make(i, 16383, 0xabc123abc0ff, 0xf800000000000001)); + cvtdl(make(i, 17406, 0xffffffffffff, 0xf7ffffffffffffff)); + cvtdl(make(i, 17406, 0xffffffffffff, 0xf800000000000000)); + cvtdl(make(i, 17407, 0, 0)); + cvtdl(make(i, 32767, 0, 0)); + cvtdl(make(i, 32767, 0, 1)); + cvtdl(make(i, 32767, 0x4cbe01ac5f40, 0x75cee3c6afbb00b5)); + cvtdl(make(i, 32767, 0x800000000000, 1)); + cvtdl(make(i, 32767, 0xa11caaaf6a52, 0x696033e871eab099)); + } +} + +void tests(void) +{ + cmps(); + nanz(); + adds(); + muls(); + divs(); + cvts(); +} + +int main() +{ +#ifdef __aarch64__ + tests(); +#else + printf("This test program is intended for a little-endian architecture\n" + "with an IEEE-standard 128-bit long double.\n"); +#endif + return 0; +} diff --git a/lib/tinycc/tests/tests2/00_assignment.c b/lib/tinycc/tests/tests2/00_assignment.c new file mode 100644 index 000000000..c96109fdc --- /dev/null +++ b/lib/tinycc/tests/tests2/00_assignment.c @@ -0,0 +1,18 @@ +#include + +int main() +{ + int a; + a = 42; + printf("%d\n", a); + + int b = 64; + printf("%d\n", b); + + int c = 12, d = 34; + printf("%d, %d\n", c, d); + + return 0; +} + +// vim: set expandtab ts=4 sw=3 sts=3 tw=80 : diff --git a/lib/tinycc/tests/tests2/00_assignment.expect b/lib/tinycc/tests/tests2/00_assignment.expect new file mode 100644 index 000000000..d4407f3fe --- /dev/null +++ b/lib/tinycc/tests/tests2/00_assignment.expect @@ -0,0 +1,3 @@ +42 +64 +12, 34 diff --git a/lib/tinycc/tests/tests2/01_comment.c b/lib/tinycc/tests/tests2/01_comment.c new file mode 100644 index 000000000..a2e6bc63d --- /dev/null +++ b/lib/tinycc/tests/tests2/01_comment.c @@ -0,0 +1,14 @@ +#include + +int main() +{ + printf("Hello\n"); + printf("Hello\n"); /* this is a comment */ printf("Hello\n"); + printf("Hello\n"); + // this is also a comment sayhello(); + printf("Hello\n"); + + return 0; +} + +// vim: set expandtab ts=4 sw=3 sts=3 tw=80 : diff --git a/lib/tinycc/tests/tests2/01_comment.expect b/lib/tinycc/tests/tests2/01_comment.expect new file mode 100644 index 000000000..b1387ad09 --- /dev/null +++ b/lib/tinycc/tests/tests2/01_comment.expect @@ -0,0 +1,5 @@ +Hello +Hello +Hello +Hello +Hello diff --git a/lib/tinycc/tests/tests2/02_printf.c b/lib/tinycc/tests/tests2/02_printf.c new file mode 100644 index 000000000..4c34dd874 --- /dev/null +++ b/lib/tinycc/tests/tests2/02_printf.c @@ -0,0 +1,18 @@ +#include + +int main() +{ + printf("Hello world\n"); + + int Count; + for (Count = -5; Count <= 5; Count++) + printf("Count = %d\n", Count); + + printf("String 'hello', 'there' is '%s', '%s'\n", "hello", "there"); + printf("Character 'A' is '%c'\n", 65); + printf("Character 'a' is '%c'\n", 'a'); + + return 0; +} + +// vim: set expandtab ts=4 sw=3 sts=3 tw=80 : diff --git a/lib/tinycc/tests/tests2/02_printf.expect b/lib/tinycc/tests/tests2/02_printf.expect new file mode 100644 index 000000000..f67a0f6e3 --- /dev/null +++ b/lib/tinycc/tests/tests2/02_printf.expect @@ -0,0 +1,15 @@ +Hello world +Count = -5 +Count = -4 +Count = -3 +Count = -2 +Count = -1 +Count = 0 +Count = 1 +Count = 2 +Count = 3 +Count = 4 +Count = 5 +String 'hello', 'there' is 'hello', 'there' +Character 'A' is 'A' +Character 'a' is 'a' diff --git a/lib/tinycc/tests/tests2/03_struct.c b/lib/tinycc/tests/tests2/03_struct.c new file mode 100644 index 000000000..fd7313383 --- /dev/null +++ b/lib/tinycc/tests/tests2/03_struct.c @@ -0,0 +1,38 @@ +extern int printf(const char*, ...); + +struct fred; + +void fred$(struct fred* this) +{ + printf("~fred()\n"); +} + +struct __attribute__((__cleanup__(fred$))) fred +{ + int boris; + int natasha; +}; + +int main() +{ + struct fred __attribute__((__cleanup__(fred$))) bloggs; + + bloggs.boris = 12; + bloggs.natasha = 34; + + printf("%d\n", bloggs.boris); + printf("%d\n", bloggs.natasha); + + struct fred jones[2]; + jones[0].boris = 12; + jones[0].natasha = 34; + jones[1].boris = 56; + jones[1].natasha = 78; + + printf("%d\n", jones[0].boris); + printf("%d\n", jones[0].natasha); + printf("%d\n", jones[1].boris); + printf("%d\n", jones[1].natasha); + + return 0; +} diff --git a/lib/tinycc/tests/tests2/03_struct.expect b/lib/tinycc/tests/tests2/03_struct.expect new file mode 100644 index 000000000..be8df373c --- /dev/null +++ b/lib/tinycc/tests/tests2/03_struct.expect @@ -0,0 +1,8 @@ +03_struct.c:14: warning: attribute '__cleanup__' ignored on type +12 +34 +12 +34 +56 +78 +~fred() diff --git a/lib/tinycc/tests/tests2/04_for.c b/lib/tinycc/tests/tests2/04_for.c new file mode 100644 index 000000000..312fed855 --- /dev/null +++ b/lib/tinycc/tests/tests2/04_for.c @@ -0,0 +1,15 @@ +#include + +int main() +{ + int Count; + + for (Count = 1; Count <= 10; Count++) + { + printf("%d\n", Count); + } + + return 0; +} + +// vim: set expandtab ts=4 sw=3 sts=3 tw=80 : diff --git a/lib/tinycc/tests/tests2/04_for.expect b/lib/tinycc/tests/tests2/04_for.expect new file mode 100644 index 000000000..f00c965d8 --- /dev/null +++ b/lib/tinycc/tests/tests2/04_for.expect @@ -0,0 +1,10 @@ +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 diff --git a/lib/tinycc/tests/tests2/05_array.c b/lib/tinycc/tests/tests2/05_array.c new file mode 100644 index 000000000..c218f3163 --- /dev/null +++ b/lib/tinycc/tests/tests2/05_array.c @@ -0,0 +1,21 @@ +#include + +int main() +{ + int Count; + int Array[10]; + + for (Count = 1; Count <= 10; Count++) + { + Array[Count-1] = Count * Count; + } + + for (Count = 0; Count < 10; Count++) + { + printf("%d\n", Array[Count]); + } + + return 0; +} + +// vim: set expandtab ts=4 sw=3 sts=3 tw=80 : diff --git a/lib/tinycc/tests/tests2/05_array.expect b/lib/tinycc/tests/tests2/05_array.expect new file mode 100644 index 000000000..bc7257c0f --- /dev/null +++ b/lib/tinycc/tests/tests2/05_array.expect @@ -0,0 +1,10 @@ +1 +4 +9 +16 +25 +36 +49 +64 +81 +100 diff --git a/lib/tinycc/tests/tests2/06_case.c b/lib/tinycc/tests/tests2/06_case.c new file mode 100644 index 000000000..c0191e2b0 --- /dev/null +++ b/lib/tinycc/tests/tests2/06_case.c @@ -0,0 +1,29 @@ +#include + +int main() +{ + int Count; + + for (Count = 0; Count < 4; Count++) + { + printf("%d\n", Count); + switch (Count) + { + case 1: + printf("%d\n", 1); + break; + + case 2: + printf("%d\n", 2); + break; + + default: + printf("%d\n", 0); + break; + } + } + + return 0; +} + +// vim: set expandtab ts=4 sw=3 sts=3 tw=80 : diff --git a/lib/tinycc/tests/tests2/06_case.expect b/lib/tinycc/tests/tests2/06_case.expect new file mode 100644 index 000000000..fab2c201a --- /dev/null +++ b/lib/tinycc/tests/tests2/06_case.expect @@ -0,0 +1,8 @@ +0 +0 +1 +1 +2 +2 +3 +0 diff --git a/lib/tinycc/tests/tests2/07_function.c b/lib/tinycc/tests/tests2/07_function.c new file mode 100644 index 000000000..006e0a7ad --- /dev/null +++ b/lib/tinycc/tests/tests2/07_function.c @@ -0,0 +1,35 @@ +#include + +int myfunc(int x) +{ + return x * x; +} + +void vfunc(int a) +{ + printf("a=%d\n", a); +} + +void qfunc() +{ + printf("qfunc()\n"); +} + +void zfunc() +{ + ((void (*)(void))0) (); +} + +int main() +{ + printf("%d\n", myfunc(3)); + printf("%d\n", myfunc(4)); + + vfunc(1234); + + qfunc(); + + return 0; +} + +// vim: set expandtab ts=4 sw=3 sts=3 tw=80 : diff --git a/lib/tinycc/tests/tests2/07_function.expect b/lib/tinycc/tests/tests2/07_function.expect new file mode 100644 index 000000000..8ffb0a702 --- /dev/null +++ b/lib/tinycc/tests/tests2/07_function.expect @@ -0,0 +1,4 @@ +9 +16 +a=1234 +qfunc() diff --git a/lib/tinycc/tests/tests2/08_while.c b/lib/tinycc/tests/tests2/08_while.c new file mode 100644 index 000000000..602ffc737 --- /dev/null +++ b/lib/tinycc/tests/tests2/08_while.c @@ -0,0 +1,24 @@ +#include + +int main() +{ + int a; + int p; + int t; + + a = 1; + p = 0; + t = 0; + + while (a < 100) + { + printf("%d\n", a); + t = a; + a = t + p; + p = t; + } + + return 0; +} + +// vim: set expandtab ts=4 sw=3 sts=3 tw=80 : diff --git a/lib/tinycc/tests/tests2/08_while.expect b/lib/tinycc/tests/tests2/08_while.expect new file mode 100644 index 000000000..702d4c0fc --- /dev/null +++ b/lib/tinycc/tests/tests2/08_while.expect @@ -0,0 +1,11 @@ +1 +1 +2 +3 +5 +8 +13 +21 +34 +55 +89 diff --git a/lib/tinycc/tests/tests2/09_do_while.c b/lib/tinycc/tests/tests2/09_do_while.c new file mode 100644 index 000000000..1d3315d3a --- /dev/null +++ b/lib/tinycc/tests/tests2/09_do_while.c @@ -0,0 +1,24 @@ +#include + +int main() +{ + int a; + int p; + int t; + + a = 1; + p = 0; + t = 0; + + do + { + printf("%d\n", a); + t = a; + a = t + p; + p = t; + } while (a < 100); + + return 0; +} + +// vim: set expandtab ts=4 sw=3 sts=3 tw=80 : diff --git a/lib/tinycc/tests/tests2/09_do_while.expect b/lib/tinycc/tests/tests2/09_do_while.expect new file mode 100644 index 000000000..702d4c0fc --- /dev/null +++ b/lib/tinycc/tests/tests2/09_do_while.expect @@ -0,0 +1,11 @@ +1 +1 +2 +3 +5 +8 +13 +21 +34 +55 +89 diff --git a/lib/tinycc/tests/tests2/100_c99array-decls.c b/lib/tinycc/tests/tests2/100_c99array-decls.c new file mode 100644 index 000000000..46950aa2a --- /dev/null +++ b/lib/tinycc/tests/tests2/100_c99array-decls.c @@ -0,0 +1,34 @@ +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; +} diff --git a/lib/tinycc/tests/tests2/100_c99array-decls.expect b/lib/tinycc/tests/tests2/100_c99array-decls.expect new file mode 100644 index 000000000..e69de29bb diff --git a/lib/tinycc/tests/tests2/101_cleanup.c b/lib/tinycc/tests/tests2/101_cleanup.c new file mode 100644 index 000000000..de5dca27a --- /dev/null +++ b/lib/tinycc/tests/tests2/101_cleanup.c @@ -0,0 +1,227 @@ +extern int printf(const char*, ...); +static int glob_i = 0; + +void incr_glob_i(int *i) +{ + glob_i += *i; +} + +#define INCR_GI { \ + int i __attribute__ ((__cleanup__(incr_glob_i))) = 1; \ + } + +#define INCR_GI0 INCR_GI INCR_GI INCR_GI INCR_GI +#define INCR_GI1 INCR_GI0 INCR_GI0 INCR_GI0 INCR_GI0 +#define INCR_GI2 INCR_GI1 INCR_GI1 INCR_GI1 INCR_GI1 +#define INCR_GI3 INCR_GI2 INCR_GI2 INCR_GI2 INCR_GI2 +#define INCR_GI4 INCR_GI3 INCR_GI3 INCR_GI3 INCR_GI3 +#define INCR_GI5 INCR_GI4 INCR_GI4 INCR_GI4 INCR_GI4 +#define INCR_GI6 INCR_GI5 INCR_GI5 INCR_GI5 INCR_GI5 +#define INCR_GI7 INCR_GI6 INCR_GI6 INCR_GI6 INCR_GI6 + + +void check2(char **hum); + +void check(int *j) +{ + char * __attribute__ ((cleanup(check2))) stop_that = "wololo"; + int chk = 0; + + { + char * __attribute__ ((cleanup(check2))) stop_that = "plop"; + + { + non_plopage: + printf("---- %d\n", chk); + } + if (!chk) { + chk = 1; + goto non_plopage; + } + } + + { + char * __attribute__ ((cleanup(check2))) stop_that = "tata !"; + + goto out; + stop_that = "titi"; + } + again: + chk = 2; + { + char * __attribute__ ((cleanup(check2))) cascade1 = "1"; + { + char * __attribute__ ((cleanup(check2))) cascade2 = "2"; + { + char * __attribute__ ((cleanup(check2))) cascade3 = "3"; + + goto out; + cascade3 = "nope"; + } + } + } + out: + if (chk != 2) + goto again; + { + { + char * __attribute__ ((cleanup(check2))) out = "last goto out"; + ++chk; + if (chk != 3) + goto out; + } + } + return; +} + +void check_oh_i(char *oh_i) +{ + printf("c: %c\n", *oh_i); +} + +void goto_hell(double *f) +{ + printf("oo: %f\n", *f); +} + +char *test() +{ + char *__attribute__ ((cleanup(check2))) str = "I don't think this should be print(but gcc got it wrong too)"; + + return str; +} + +void test_ret_subcall(char *that) +{ + printf("should be print before\n"); +} + +void test_ret() +{ + char *__attribute__ ((cleanup(check2))) that = "that"; + return test_ret_subcall(that); +} + +void test_ret2() +{ + char *__attribute__ ((cleanup(check2))) that = "-that"; + { + char *__attribute__ ((cleanup(check2))) that = "this should appear only once"; + } + { + char *__attribute__ ((cleanup(check2))) that = "-that2"; + return; + } +} + +void test2(void) { + int chk = 0; +again: + if (!chk) { + char * __attribute__ ((cleanup(check2))) stop_that = "test2"; + chk++; + goto again; + } +} + +int test3(void) { + char * __attribute__ ((cleanup(check2))) stop_that = "three"; + int chk = 0; + + if (chk) { + { + outside: + { + char * __attribute__ ((cleanup(check2))) stop_that = "two"; + printf("---- %d\n", chk); + } + } + } + if (!chk) + { + char * __attribute__ ((cleanup(check2))) stop_that = "one"; + + if (!chk) { + chk = 1; + goto outside; + } + } + return 0; +} + +void cl(int *ip) +{ + printf("%d\n", *ip); +} + +void loop_cleanups(void) +{ + __attribute__((cleanup(cl))) int l = 1000; + + printf("-- loop 0 --\n"); + for ( __attribute__((cleanup(cl))) int i = 0; i < 10; ++i) { + __attribute__((cleanup(cl))) int j = 100; + } + + printf("-- loop 1 --\n"); + for (__attribute__((cleanup(cl))) int i = 0; i < 10; ++i) { + __attribute__((cleanup(cl))) int j = 200; + continue; + } + + printf("-- loop 2 --\n"); + for (__attribute__((cleanup(cl))) int i = 0; i < 10; ++i) { + __attribute__((cleanup(cl))) int j = 300; + break; + } + + printf("-- loop 3 --\n"); + for (int i = 0; i < 2; ++i) { + __attribute__((cleanup(cl))) int j = 400; + switch (i) { + case 0: + continue; + default: + { + __attribute__((cleanup(cl))) int jj = 500; + break; + } + } + } + printf("after break\n"); +} + +int main() +{ + int i __attribute__ ((__cleanup__(check))) = 0, not_i; + int chk = 0; + (void)not_i; + + { + __attribute__ ((__cleanup__(check_oh_i))) char oh_i = 'o', o = 'a'; + } + + INCR_GI7; + printf("glob_i: %d\n", glob_i); + naaaaaaaa: + if (!chk) { + __attribute__ ((__cleanup__(check_oh_i))) char oh_i = 'f'; + double __attribute__ ((__cleanup__(goto_hell))) f = 2.6; + + chk = 1; + goto naaaaaaaa; + } + i = 105; + printf("because what if free was call inside cleanup function %s\n", test()); + test_ret(); + test_ret2(); + test2(); + test3(); + loop_cleanups(); + return i; +} + +void check2(char **hum) +{ + printf("str: %s\n", *hum); +} diff --git a/lib/tinycc/tests/tests2/101_cleanup.expect b/lib/tinycc/tests/tests2/101_cleanup.expect new file mode 100644 index 000000000..84960cd5f --- /dev/null +++ b/lib/tinycc/tests/tests2/101_cleanup.expect @@ -0,0 +1,59 @@ +c: a +c: o +glob_i: 65536 +oo: 2.600000 +c: f +str: I don't think this should be print(but gcc got it wrong too) +because what if free was call inside cleanup function I don't think this should be print(but gcc got it wrong too) +should be print before +str: that +str: this should appear only once +str: -that2 +str: -that +str: test2 +str: one +---- 1 +str: two +str: three +-- loop 0 -- +100 +100 +100 +100 +100 +100 +100 +100 +100 +100 +10 +-- loop 1 -- +200 +200 +200 +200 +200 +200 +200 +200 +200 +200 +10 +-- loop 2 -- +300 +0 +-- loop 3 -- +400 +500 +400 +after break +1000 +---- 0 +---- 1 +str: plop +str: tata ! +str: 3 +str: 2 +str: 1 +str: last goto out +str: wololo diff --git a/lib/tinycc/tests/tests2/102_alignas.c b/lib/tinycc/tests/tests2/102_alignas.c new file mode 100644 index 000000000..62d3ed249 --- /dev/null +++ b/lib/tinycc/tests/tests2/102_alignas.c @@ -0,0 +1,29 @@ +_Alignas(16) int i1; +int _Alignas(16) i2; +void _Alignas(16) *p2; +_Alignas(16) i3; +int _Alignas(double) i4; +int _Alignas(int) i5; +#if 0 +/* The following are currently wrongly accepted by TCC but really shouldn't. */ +int _Alignas(int _Alignas(16)) i6; //wrong, 'int _Alignas(16)' is no type-name +typedef int _Alignas(16) int16aligned_t; //wrong, _Alignas invalid on typedef +int16aligned_t i7; +#endif +/* i8 should get an alignment of 16, because unlike _Alignas the + corresponding attribute _does_ apply to type-name, though not in + some clang versions. */ +int _Alignas(int __attribute__((aligned(16)))) i8; +extern int printf(const char*, ...); +#ifdef _MSC_VER +#define alignof(x) (int)__alignof(x) +#else +#define alignof(x) (int)__alignof__(x) +#endif +int main() +{ + printf("%d %d %d %d\n", + alignof(i1) == 16, alignof(i4) == alignof(double), + alignof(i5) == alignof(int) , alignof(i8) == 16); + return 0; +} diff --git a/lib/tinycc/tests/tests2/102_alignas.expect b/lib/tinycc/tests/tests2/102_alignas.expect new file mode 100644 index 000000000..b458e0746 --- /dev/null +++ b/lib/tinycc/tests/tests2/102_alignas.expect @@ -0,0 +1,2 @@ +102_alignas.c:4: warning: type defaults to int +1 1 1 1 diff --git a/lib/tinycc/tests/tests2/103_implicit_memmove.c b/lib/tinycc/tests/tests2/103_implicit_memmove.c new file mode 100644 index 000000000..1592fb258 --- /dev/null +++ b/lib/tinycc/tests/tests2/103_implicit_memmove.c @@ -0,0 +1,20 @@ +/* Test that the memmove TCC is emitting for the struct copy + and hence implicitely declares can be declared properly also + later. */ +struct S { int a,b,c,d, e[1024];}; +int foo (struct S *a, struct S *b) +{ + *a = *b; + return 0; +} + +void *memmove(void*,const void*,__SIZE_TYPE__); +void foo2 (struct S *a, struct S *b) +{ + memmove(a, b, sizeof *a); +} + +int main() +{ + return 0; +} diff --git a/lib/tinycc/tests/tests2/103_implicit_memmove.expect b/lib/tinycc/tests/tests2/103_implicit_memmove.expect new file mode 100644 index 000000000..e69de29bb diff --git a/lib/tinycc/tests/tests2/104+_inline.c b/lib/tinycc/tests/tests2/104+_inline.c new file mode 100644 index 000000000..3c48eb83d --- /dev/null +++ b/lib/tinycc/tests/tests2/104+_inline.c @@ -0,0 +1,54 @@ + +#define GOT(f) \ + __attribute__((weak)) void f(void); \ + printf("%d %s\n", !!((__SIZE_TYPE__)f & ~0u), #f); + +int printf(const char*, ...); + +void check_exports() +{ + // 0 + GOT(inline_inline_2decl_only) + GOT(inline_inline_undeclared) + GOT(inline_inline_predeclared) + GOT(inline_inline_postdeclared) + GOT(inline_inline_prepostdeclared) + GOT(inline_inline_undeclared2) + GOT(inline_inline_predeclared2) + GOT(inline_inline_postdeclared2) + GOT(inline_inline_prepostdeclared2) + + // 1 + GOT(extern_extern_postdeclared) + GOT(extern_extern_postdeclared2) + GOT(extern_extern_predeclared) + GOT(extern_extern_predeclared2) + GOT(extern_extern_prepostdeclared) + GOT(extern_extern_prepostdeclared2) + GOT(extern_extern_undeclared) + GOT(extern_extern_undeclared2) + GOT(extern_postdeclared) + GOT(extern_postdeclared2) + GOT(extern_predeclared) + GOT(extern_predeclared2) + GOT(extern_prepostdeclared) + GOT(extern_undeclared) + GOT(extern_undeclared2) + GOT(inst2_extern_inline_postdeclared) + GOT(inst2_extern_inline_predeclared) + GOT(inst3_extern_inline_predeclared) + GOT(inst_extern_inline_postdeclared) + GOT(inst_extern_inline_predeclared) + GOT(main) + GOT(noinst_extern_inline_func) + GOT(noinst_extern_inline_postdeclared) + GOT(noinst_extern_inline_postdeclared2) + GOT(noinst_extern_inline_undeclared) + + // 0 + GOT(noinst_static_inline_postdeclared) + GOT(noinst2_static_inline_postdeclared) + GOT(noinst_static_inline_predeclared) + GOT(noinst2_static_inline_predeclared) + GOT(static_func) +} diff --git a/lib/tinycc/tests/tests2/104_inline.c b/lib/tinycc/tests/tests2/104_inline.c new file mode 100644 index 000000000..766f94a33 --- /dev/null +++ b/lib/tinycc/tests/tests2/104_inline.c @@ -0,0 +1,132 @@ +inline void inline_inline_2decl_only(void); +inline void inline_inline_2decl_only(void); + +inline void inline_inline_undeclared(void){} + +inline void inline_inline_predeclared(void); +inline void inline_inline_predeclared(void){} + +inline void inline_inline_postdeclared(void){} +inline void inline_inline_postdeclared(void); + +inline void inline_inline_prepostdeclared(void); +inline void inline_inline_prepostdeclared(void){} +inline void inline_inline_prepostdeclared(void); + +inline void inline_inline_undeclared2(void){} + +inline void inline_inline_predeclared2(void); +inline void inline_inline_predeclared2(void); +inline void inline_inline_predeclared2(void){} + +inline void inline_inline_postdeclared2(void){} +inline void inline_inline_postdeclared2(void); +inline void inline_inline_postdeclared2(void); + +inline void inline_inline_prepostdeclared2(void); +inline void inline_inline_prepostdeclared2(void); +inline void inline_inline_prepostdeclared2(void){} +inline void inline_inline_prepostdeclared2(void); +inline void inline_inline_prepostdeclared2(void); + +extern void extern_extern_undeclared(void){} + +extern void extern_extern_predeclared(void); +extern void extern_extern_predeclared(void){} + +extern void extern_extern_postdeclared(void){} +extern void extern_extern_postdeclared(void); + +extern void extern_extern_prepostdeclared(void); +extern void extern_extern_prepostdeclared(void){} +extern void extern_extern_prepostdeclared(void); + +extern void extern_extern_undeclared2(void){} + +extern void extern_extern_predeclared2(void); +extern void extern_extern_predeclared2(void); +extern void extern_extern_predeclared2(void){} + +extern void extern_extern_postdeclared2(void){} +extern void extern_extern_postdeclared2(void); +extern void extern_extern_postdeclared2(void); + +extern void extern_extern_prepostdeclared2(void); +extern void extern_extern_prepostdeclared2(void); +extern void extern_extern_prepostdeclared2(void){} +extern void extern_extern_prepostdeclared2(void); +extern void extern_extern_prepostdeclared2(void); + +void extern_undeclared(void){} + +void extern_predeclared(void); +void extern_predeclared(void){} + +void extern_postdeclared(void){} +void extern_postdeclared(void); + +void extern_prepostdeclared(void); +void extern_prepostdeclared(void){} +void extern_prepostdeclared(void); + +void extern_undeclared2(void){} + +void extern_predeclared2(void); +void extern_predeclared2(void); +void extern_predeclared2(void){} + +void extern_postdeclared2(void){} +void extern_postdeclared2(void); +void extern_postdeclared2(void); + + +extern inline void noinst_extern_inline_undeclared(void){} + +extern inline void noinst_extern_inline_postdeclared(void){} +inline void noinst_extern_inline_postdeclared(void); + +extern inline void noinst_extern_inline_postdeclared2(void){} +inline void noinst_extern_inline_postdeclared2(void); +inline void noinst_extern_inline_postdeclared2(void); + +extern inline void inst_extern_inline_postdeclared(void){} +extern inline void inst_extern_inline_postdeclared(void); +inline void inst2_extern_inline_postdeclared(void){} +void inst2_extern_inline_postdeclared(void); + +void inst_extern_inline_predeclared(void); +extern inline void inst_extern_inline_predeclared(void){} +void inst2_extern_inline_predeclared(void); +inline void inst2_extern_inline_predeclared(void){} +extern inline void inst3_extern_inline_predeclared(void); +inline void inst3_extern_inline_predeclared(void){} + +static inline void noinst_static_inline_postdeclared(void){} +static inline void noinst_static_inline_postdeclared(void); +static inline void noinst2_static_inline_postdeclared(void){} +static void noinst2_static_inline_postdeclared(void); + +static void noinst_static_inline_predeclared(void); +static inline void noinst_static_inline_predeclared(void){} +static void noinst2_static_inline_predeclared(void); +static inline void noinst2_static_inline_predeclared(void){} + +static void static_func(void); +void static_func(void) { } + +inline void noinst_extern_inline_func(void); +void noinst_extern_inline_func(void) { } + +int main() +{ + inline_inline_undeclared(); inline_inline_predeclared(); inline_inline_postdeclared(); + inline_inline_undeclared2(); inline_inline_predeclared2(); inline_inline_postdeclared2(); + noinst_static_inline_predeclared(); + noinst2_static_inline_predeclared(); + noinst_static_inline_predeclared(); + noinst2_static_inline_predeclared(); + + void check_exports(); + check_exports(); + return 0; +} diff --git a/lib/tinycc/tests/tests2/104_inline.expect b/lib/tinycc/tests/tests2/104_inline.expect new file mode 100644 index 000000000..bdb0994a2 --- /dev/null +++ b/lib/tinycc/tests/tests2/104_inline.expect @@ -0,0 +1,39 @@ +0 inline_inline_2decl_only +0 inline_inline_undeclared +0 inline_inline_predeclared +0 inline_inline_postdeclared +0 inline_inline_prepostdeclared +0 inline_inline_undeclared2 +0 inline_inline_predeclared2 +0 inline_inline_postdeclared2 +0 inline_inline_prepostdeclared2 +1 extern_extern_postdeclared +1 extern_extern_postdeclared2 +1 extern_extern_predeclared +1 extern_extern_predeclared2 +1 extern_extern_prepostdeclared +1 extern_extern_prepostdeclared2 +1 extern_extern_undeclared +1 extern_extern_undeclared2 +1 extern_postdeclared +1 extern_postdeclared2 +1 extern_predeclared +1 extern_predeclared2 +1 extern_prepostdeclared +1 extern_undeclared +1 extern_undeclared2 +1 inst2_extern_inline_postdeclared +1 inst2_extern_inline_predeclared +1 inst3_extern_inline_predeclared +1 inst_extern_inline_postdeclared +1 inst_extern_inline_predeclared +1 main +1 noinst_extern_inline_func +1 noinst_extern_inline_postdeclared +1 noinst_extern_inline_postdeclared2 +1 noinst_extern_inline_undeclared +0 noinst_static_inline_postdeclared +0 noinst2_static_inline_postdeclared +0 noinst_static_inline_predeclared +0 noinst2_static_inline_predeclared +0 static_func diff --git a/lib/tinycc/tests/tests2/105_local_extern.c b/lib/tinycc/tests/tests2/105_local_extern.c new file mode 100644 index 000000000..a248bb421 --- /dev/null +++ b/lib/tinycc/tests/tests2/105_local_extern.c @@ -0,0 +1,12 @@ +extern int printf(const char *, ...); +void f(void); +void bar(void) { void f(void); f(); } +void foo(void) { extern void f(void); f(); } +void f(void) { printf("f\n"); } + +int main() +{ + bar(); + foo(); + return 0; +} diff --git a/lib/tinycc/tests/tests2/105_local_extern.expect b/lib/tinycc/tests/tests2/105_local_extern.expect new file mode 100644 index 000000000..445ae7415 --- /dev/null +++ b/lib/tinycc/tests/tests2/105_local_extern.expect @@ -0,0 +1,2 @@ +f +f diff --git a/lib/tinycc/tests/tests2/106_versym.c b/lib/tinycc/tests/tests2/106_versym.c new file mode 100644 index 000000000..dcce5089a --- /dev/null +++ b/lib/tinycc/tests/tests2/106_versym.c @@ -0,0 +1,18 @@ +#include +#include +#include + +int +main(void) +{ + int ret; + pthread_condattr_t attr; + pthread_cond_t condition; + + /* This test fails if symbol versioning does not work */ + pthread_condattr_init (&attr); + pthread_condattr_setpshared (&attr, PTHREAD_PROCESS_SHARED); + printf ("%s\n", pthread_cond_init (&condition, &attr) ? "fail":"ok"); + pthread_condattr_destroy (&attr); + return 0; +} diff --git a/lib/tinycc/tests/tests2/106_versym.expect b/lib/tinycc/tests/tests2/106_versym.expect new file mode 100644 index 000000000..9766475a4 --- /dev/null +++ b/lib/tinycc/tests/tests2/106_versym.expect @@ -0,0 +1 @@ +ok diff --git a/lib/tinycc/tests/tests2/107_stack_safe.c b/lib/tinycc/tests/tests2/107_stack_safe.c new file mode 100644 index 000000000..479c84d37 --- /dev/null +++ b/lib/tinycc/tests/tests2/107_stack_safe.c @@ -0,0 +1,13 @@ +extern int printf(const char *, ...); + +static void func_ull_ull(unsigned long long l1,unsigned long long l2){ +} + +int main() +{ + int a,b,c,d; + a=1;b=2;c=3;d=4; + func_ull_ull((unsigned long long)a/1.0,(unsigned long long)b/1.0); + printf("%d %d %d %d",a,b,c,d); + return 0; +} diff --git a/lib/tinycc/tests/tests2/107_stack_safe.expect b/lib/tinycc/tests/tests2/107_stack_safe.expect new file mode 100644 index 000000000..e9e9cd732 --- /dev/null +++ b/lib/tinycc/tests/tests2/107_stack_safe.expect @@ -0,0 +1 @@ +1 2 3 4 \ No newline at end of file diff --git a/lib/tinycc/tests/tests2/108_constructor.c b/lib/tinycc/tests/tests2/108_constructor.c new file mode 100644 index 000000000..145d0da69 --- /dev/null +++ b/lib/tinycc/tests/tests2/108_constructor.c @@ -0,0 +1,20 @@ +extern int write (int fd, void *buf, int len); + +static void __attribute__ ((constructor)) +testc (void) +{ + write (1, "constructor\n", 12); +} + +static void __attribute__ ((destructor)) +testd (void) +{ + write (1, "destructor\n", 11); +} + +int +main (void) +{ + write (1, "main\n", 5); + return 0; +} diff --git a/lib/tinycc/tests/tests2/108_constructor.expect b/lib/tinycc/tests/tests2/108_constructor.expect new file mode 100644 index 000000000..167ca517d --- /dev/null +++ b/lib/tinycc/tests/tests2/108_constructor.expect @@ -0,0 +1,3 @@ +constructor +main +destructor diff --git a/lib/tinycc/tests/tests2/109_float_struct_calling.c b/lib/tinycc/tests/tests2/109_float_struct_calling.c new file mode 100644 index 000000000..90fc045b5 --- /dev/null +++ b/lib/tinycc/tests/tests2/109_float_struct_calling.c @@ -0,0 +1,24 @@ +#include + +/* This test used to fail on x86_64 on linux with sse registers */ + +struct Point { + float x; + float y; +}; + +struct Rect { + struct Point top_left; + struct Point size; +}; + +float foo(struct Point p, struct Rect r) { + return r.size.x; +} + +int main(int argc, char **argv) { + struct Point p = {1, 2}; + struct Rect r = {{3, 4}, {5, 6}}; + printf("%f\n", foo(p, r)); + return 0; +} diff --git a/lib/tinycc/tests/tests2/109_float_struct_calling.expect b/lib/tinycc/tests/tests2/109_float_struct_calling.expect new file mode 100644 index 000000000..eaa678729 --- /dev/null +++ b/lib/tinycc/tests/tests2/109_float_struct_calling.expect @@ -0,0 +1 @@ +5.000000 diff --git a/lib/tinycc/tests/tests2/10_pointer.c b/lib/tinycc/tests/tests2/10_pointer.c new file mode 100644 index 000000000..0177f4d81 --- /dev/null +++ b/lib/tinycc/tests/tests2/10_pointer.c @@ -0,0 +1,40 @@ +#include + +struct ziggy +{ + int a; + int b; + int c; +} bolshevic; + +int main() +{ + int a; + int *b; + int c; + + a = 42; + b = &a; + printf("a = %d\n", *b); + + bolshevic.a = 12; + bolshevic.b = 34; + bolshevic.c = 56; + + printf("bolshevic.a = %d\n", bolshevic.a); + printf("bolshevic.b = %d\n", bolshevic.b); + printf("bolshevic.c = %d\n", bolshevic.c); + + struct ziggy *tsar = &bolshevic; + + printf("tsar->a = %d\n", tsar->a); + printf("tsar->b = %d\n", tsar->b); + printf("tsar->c = %d\n", tsar->c); + + b = &(bolshevic.b); + printf("bolshevic.b = %d\n", *b); + + return 0; +} + +// vim: set expandtab ts=4 sw=3 sts=3 tw=80 : diff --git a/lib/tinycc/tests/tests2/10_pointer.expect b/lib/tinycc/tests/tests2/10_pointer.expect new file mode 100644 index 000000000..1e3c473f0 --- /dev/null +++ b/lib/tinycc/tests/tests2/10_pointer.expect @@ -0,0 +1,8 @@ +a = 42 +bolshevic.a = 12 +bolshevic.b = 34 +bolshevic.c = 56 +tsar->a = 12 +tsar->b = 34 +tsar->c = 56 +bolshevic.b = 34 diff --git a/lib/tinycc/tests/tests2/110_average.c b/lib/tinycc/tests/tests2/110_average.c new file mode 100644 index 000000000..273b51107 --- /dev/null +++ b/lib/tinycc/tests/tests2/110_average.c @@ -0,0 +1,27 @@ +#include + +typedef struct +{ + double average; + int count; +} +stats_type; + +static void +testc (stats_type *s, long long data) +{ + s->average = (s->average * s->count + data) / (s->count + 1); + s->count++; +} + +int main (void) +{ + stats_type s; + + s.average = 0; + s.count = 0; + testc (&s, 10); + testc (&s, 20); + printf ("%g %d\n", s.average, s.count); + return 0; +} diff --git a/lib/tinycc/tests/tests2/110_average.expect b/lib/tinycc/tests/tests2/110_average.expect new file mode 100644 index 000000000..4955335c0 --- /dev/null +++ b/lib/tinycc/tests/tests2/110_average.expect @@ -0,0 +1 @@ +15 2 diff --git a/lib/tinycc/tests/tests2/111_conversion.c b/lib/tinycc/tests/tests2/111_conversion.c new file mode 100644 index 000000000..c0815e1e3 --- /dev/null +++ b/lib/tinycc/tests/tests2/111_conversion.c @@ -0,0 +1,22 @@ +#include + +union u { + unsigned long ul; + long double ld; +}; + +void +conv (union u *p) +{ + p->ul = (unsigned int) p->ld; +} + +int main (void) +{ + union u v; + + v.ld = 42; + conv (&v); + printf ("%lu\n", v.ul); + return 0; +} diff --git a/lib/tinycc/tests/tests2/111_conversion.expect b/lib/tinycc/tests/tests2/111_conversion.expect new file mode 100644 index 000000000..d81cc0710 --- /dev/null +++ b/lib/tinycc/tests/tests2/111_conversion.expect @@ -0,0 +1 @@ +42 diff --git a/lib/tinycc/tests/tests2/112_backtrace.c b/lib/tinycc/tests/tests2/112_backtrace.c new file mode 100644 index 000000000..0b596d080 --- /dev/null +++ b/lib/tinycc/tests/tests2/112_backtrace.c @@ -0,0 +1,175 @@ +#include + +/* ------------------------------------------------------- */ +#if defined test_backtrace_1 + +void f3() +{ + printf("* f3()\n"), fflush(stdout); + *(void**)0 = 0; +} +void f2() +{ + printf("* f2()\n"), fflush(stdout); + f3(); +} +void f1() +{ + printf("* f1()\n"), fflush(stdout); + f2(); +} +int main(int argc, char **argv) +{ + printf("* main\n"), fflush(stdout); + f1(); + printf("* exit main\n"), fflush(stdout); + return 0; +} + +/* ------------------------------------------------------- */ +#elif defined test_bcheck_1 + +struct s { int a,b,c,d,e; }; +struct s s[3]; +struct s *ps = s; +void f1() +{ + printf("* f1()\n"), fflush(stdout); + ps[3] = ps[2]; +} +int main(int argc, char **argv) +{ + printf("* main\n"), fflush(stdout); + f1(); + printf("* exit main\n"), fflush(stdout); + return 0; +} + +/* ------------------------------------------------------- */ +#elif defined test_tcc_backtrace_2 + +/* test custom backtrace and 'exit()' redirection */ +int tcc_backtrace(const char *fmt, ...); +void exit(int); + +void f2() +{ + printf("* f2()\n"); + printf("* exit f2\n"), fflush(stdout); + exit(34); +} +void f1() +{ + printf("* f1()\n"), fflush(stdout); + tcc_backtrace("Hello from %s!", "f1"); + f2(); +} +int main(int argc, char **argv) +{ + printf("* main\n"), fflush(stdout); + f1(); + printf("* exit main\n"), fflush(stdout); + return 0; +} + +/* ------------------------------------------------------- */ +#elif defined test_tcc_backtrace_3 + +/* this test should be run despite of the exit(34) above */ +int main(int argc, char **argv) +{ + printf("* main\n"), fflush(stdout); + return 1; +} + +/* ------------------------------------------------------- */ +#else +#include +#include +char *strdup(); +int main() +{ + char pad1[10]; + char a[10]; + char pad2[10]; + char b[10]; + char pad3[10]; + memset (pad1, 0, sizeof(pad1)); + memset (pad2, 0, sizeof(pad2)); + memset (pad3, 0, sizeof(pad3)); + + memset (a, 'a', 10); + a[3] = 0; + a[9] = 0; + memset (b, 'b', 10); + +#if defined test_bcheck_100 + memcpy(&a[1],&b[0],10); +#elif defined test_bcheck_101 + memcpy(&a[0],&b[1],10); +#elif defined test_bcheck_102 + memcpy(&a[0],&a[3],4); +#elif defined test_bcheck_103 + memcpy(&a[3],&a[0],4); +#elif defined test_bcheck_104 + memcmp(&b[1],&b[0],10); +#elif defined test_bcheck_105 + memcmp(&b[0],&b[1],10); +#elif defined test_bcheck_106 + memmove(&b[1],&b[0],10); +#elif defined test_bcheck_107 + memmove(&b[0],&b[1],10); +#elif defined test_bcheck_108 + memset(&b[1],'b',10); +#elif defined test_bcheck_109 + strlen(&b[0]); +#elif defined test_bcheck_110 + strcpy(&a[7], &a[0]); +#elif defined test_bcheck_111 + strcpy(&a[0], &b[7]); +#elif defined test_bcheck_112 + strcpy(&a[0], &a[1]); +#elif defined test_bcheck_113 + strcpy(&a[2], &a[0]); +#elif defined test_bcheck_114 + strncpy(&a[7], &a[0], 10); +#elif defined test_bcheck_115 + strncpy(&a[0], &b[7], 10); +#elif defined test_bcheck_116 + strncpy(&a[0], &a[1], 10); +#elif defined test_bcheck_117 + strncpy(&a[2], &a[0], 10); +#elif defined test_bcheck_118 + strcmp(&b[2], &b[0]); +#elif defined test_bcheck_119 + strcmp(&b[0], &b[2]); +#elif defined test_bcheck_120 + strncmp(&b[5], &b[0], 10); +#elif defined test_bcheck_121 + strncmp(&b[0], &b[5], 10); +#elif defined test_bcheck_122 + strcat(&a[7], &a[0]); +#elif defined test_bcheck_123 + strcat(&a[0], &b[3]); +#elif defined test_bcheck_124 + strcat(&a[0], &a[4]); +#elif defined test_bcheck_125 + strcat(&a[3], &a[0]); +#elif defined test_bcheck_126 + strncat(&a[7], &a[0], 3); +#elif defined test_bcheck_127 + strncat(&a[0], &b[3], 8); +#elif defined test_bcheck_128 + strncat(&a[0], &a[4], 3); +#elif defined test_bcheck_129 + strncat(&a[3], &a[0], 10); +#elif defined test_bcheck_130 + strchr(&b[0], 'a'); +#elif defined test_bcheck_131 + strrchr(&b[0], 'a'); +#elif defined test_bcheck_132 + free(strdup(&b[0])); +#endif +} +/* ------------------------------------------------------- */ +#endif diff --git a/lib/tinycc/tests/tests2/112_backtrace.expect b/lib/tinycc/tests/tests2/112_backtrace.expect new file mode 100644 index 000000000..ec2c6b8e5 --- /dev/null +++ b/lib/tinycc/tests/tests2/112_backtrace.expect @@ -0,0 +1,162 @@ +[test_backtrace_1] +* main +* f1() +* f2() +* f3() +112_backtrace.c:9: at f3: RUNTIME ERROR: invalid memory access +112_backtrace.c:14: by f2 +112_backtrace.c:19: by f1 +112_backtrace.c:24: by main +[returns 255] + +[test_bcheck_1] +* main +* f1() +112_backtrace.c:38: at f1: BCHECK: invalid pointer ........, size 0x? in memmove dest +112_backtrace.c:43: by main +[returns 255] + +[test_tcc_backtrace_2] +* main +* f1() +112_backtrace.c:64: at f1: Hello from f1! +112_backtrace.c:70: by main +* f2() +* exit f2 +[returns 34] + +[test_tcc_backtrace_3] +* main +[returns 1] + +[test_bcheck_100] +112_backtrace.c:107: at main: BCHECK: invalid pointer ........, size 0x? in memcpy dest +[returns 255] + +[test_bcheck_101] +112_backtrace.c:109: at main: BCHECK: invalid pointer ........, size 0x? in memcpy src +[returns 255] + +[test_bcheck_102] +112_backtrace.c:111: at main: BCHECK: overlapping regions ........(0x?), ........(0x?) in memcpy +[returns 255] + +[test_bcheck_103] +112_backtrace.c:113: at main: BCHECK: overlapping regions ........(0x?), ........(0x?) in memcpy +[returns 255] + +[test_bcheck_104] +112_backtrace.c:115: at main: BCHECK: invalid pointer ........, size 0x? in memcmp s1 +[returns 255] + +[test_bcheck_105] +112_backtrace.c:117: at main: BCHECK: invalid pointer ........, size 0x? in memcmp s2 +[returns 255] + +[test_bcheck_106] +112_backtrace.c:119: at main: BCHECK: invalid pointer ........, size 0x? in memmove dest +[returns 255] + +[test_bcheck_107] +112_backtrace.c:121: at main: BCHECK: invalid pointer ........, size 0x? in memmove src +[returns 255] + +[test_bcheck_108] +112_backtrace.c:123: at main: BCHECK: invalid pointer ........, size 0x? in memset +[returns 255] + +[test_bcheck_109] +112_backtrace.c:125: at main: BCHECK: invalid pointer ........, size 0x? in strlen +[returns 255] + +[test_bcheck_110] +112_backtrace.c:127: at main: BCHECK: invalid pointer ........, size 0x? in strcpy dest +[returns 255] + +[test_bcheck_111] +112_backtrace.c:129: at main: BCHECK: invalid pointer ........, size 0x? in strcpy src +[returns 255] + +[test_bcheck_112] +112_backtrace.c:131: at main: BCHECK: overlapping regions ........(0x?), ........(0x?) in strcpy +[returns 255] + +[test_bcheck_113] +112_backtrace.c:133: at main: BCHECK: overlapping regions ........(0x?), ........(0x?) in strcpy +[returns 255] + +[test_bcheck_114] +112_backtrace.c:135: at main: BCHECK: invalid pointer ........, size 0x? in strncpy dest +[returns 255] + +[test_bcheck_115] +112_backtrace.c:137: at main: BCHECK: invalid pointer ........, size 0x? in strncpy src +[returns 255] + +[test_bcheck_116] +112_backtrace.c:139: at main: BCHECK: overlapping regions ........(0x?), ........(0x?) in strncpy +[returns 255] + +[test_bcheck_117] +112_backtrace.c:141: at main: BCHECK: overlapping regions ........(0x?), ........(0x?) in strncpy +[returns 255] + +[test_bcheck_118] +112_backtrace.c:143: at main: BCHECK: invalid pointer ........, size 0x? in strcmp s1 +[returns 255] + +[test_bcheck_119] +112_backtrace.c:145: at main: BCHECK: invalid pointer ........, size 0x? in strcmp s2 +[returns 255] + +[test_bcheck_120] +112_backtrace.c:147: at main: BCHECK: invalid pointer ........, size 0x? in strncmp s1 +[returns 255] + +[test_bcheck_121] +112_backtrace.c:149: at main: BCHECK: invalid pointer ........, size 0x? in strncmp s2 +[returns 255] + +[test_bcheck_122] +112_backtrace.c:151: at main: BCHECK: invalid pointer ........, size 0x? in strcat dest +[returns 255] + +[test_bcheck_123] +112_backtrace.c:153: at main: BCHECK: invalid pointer ........, size 0x? in strcat dest +[returns 255] + +[test_bcheck_124] +112_backtrace.c:155: at main: BCHECK: overlapping regions ........(0x?), ........(0x?) in strcat +[returns 255] + +[test_bcheck_125] +112_backtrace.c:157: at main: BCHECK: overlapping regions ........(0x?), ........(0x?) in strcat +[returns 255] + +[test_bcheck_126] +112_backtrace.c:159: at main: BCHECK: invalid pointer ........, size 0x? in strncat dest +[returns 255] + +[test_bcheck_127] +112_backtrace.c:161: at main: BCHECK: invalid pointer ........, size 0x? in strncat dest +[returns 255] + +[test_bcheck_128] +112_backtrace.c:163: at main: BCHECK: overlapping regions ........(0x?), ........(0x?) in strncat +[returns 255] + +[test_bcheck_129] +112_backtrace.c:165: at main: BCHECK: overlapping regions ........(0x?), ........(0x?) in strncat +[returns 255] + +[test_bcheck_130] +112_backtrace.c:167: at main: BCHECK: invalid pointer ........, size 0x? in strchr +[returns 255] + +[test_bcheck_131] +112_backtrace.c:169: at main: BCHECK: invalid pointer ........, size 0x? in strrchr +[returns 255] + +[test_bcheck_132] +112_backtrace.c:171: at main: BCHECK: invalid pointer ........, size 0x? in strdup +[returns 255] diff --git a/lib/tinycc/tests/tests2/113_btdll.c b/lib/tinycc/tests/tests2/113_btdll.c new file mode 100644 index 000000000..8ae898167 --- /dev/null +++ b/lib/tinycc/tests/tests2/113_btdll.c @@ -0,0 +1,43 @@ +int tcc_backtrace(const char*, ...); +#define hello() \ + tcc_backtrace("hello from %s() / %s:%d",__FUNCTION__,__FILE__,__LINE__) + +#ifndef _WIN32 +# define __declspec(n) +#endif + +#if DLL==1 +__declspec(dllexport) int f_1() +{ + hello(); + return 0; +} + + +#elif DLL==2 +__declspec(dllexport) int f_2() +{ + hello(); + return 0; +} + + +#else + +int f_1(); +int f_2(); +int f_main() +{ + hello(); + return 0; +} + +int main () +{ + f_1(); + f_2(); + f_main(); + return 0; +} + +#endif diff --git a/lib/tinycc/tests/tests2/113_btdll.expect b/lib/tinycc/tests/tests2/113_btdll.expect new file mode 100644 index 000000000..34de4811d --- /dev/null +++ b/lib/tinycc/tests/tests2/113_btdll.expect @@ -0,0 +1,6 @@ +113_btdll.c:12: at f_1: hello from f_1() / 113_btdll.c:12 +113_btdll.c:37: by main +113_btdll.c:20: at f_2: hello from f_2() / 113_btdll.c:20 +113_btdll.c:38: by main +113_btdll.c:31: at f_main: hello from f_main() / 113_btdll.c:31 +113_btdll.c:39: by main diff --git a/lib/tinycc/tests/tests2/114_bound_signal.c b/lib/tinycc/tests/tests2/114_bound_signal.c new file mode 100644 index 000000000..d11b14616 --- /dev/null +++ b/lib/tinycc/tests/tests2/114_bound_signal.c @@ -0,0 +1,143 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static volatile int run = 1; +static sem_t sem; +static sem_t sem_child; + +static void +add (int n) +{ + int i; + int arr[n]; + + for (i = 0; i < n; i++) { + arr[i]++; + } + memset (&arr[0], 0, n * sizeof(int)); +} + +static void * +high_load (void *unused) +{ + while (run) { + add(10); + add(20); + } + return NULL; +} + +static void * +do_signal (void *unused) +{ + while (run) { + kill (getpid(), SIGUSR1); + while (sem_wait(&sem) < 0 && errno == EINTR); + } + return NULL; +} + +static void * +do_fork (void *unused) +{ + pid_t pid; + + while (run) { + switch ((pid = fork())) { + case 0: + add(1000); + add(2000); + exit(0); + break; + case -1: + return NULL; + default: + while (sem_wait(&sem_child) < 0 && errno == EINTR); + wait(NULL); + break; + } + } + return NULL; +} + +static void signal_handler(int sig) +{ + add(10); + add(20); + sem_post (&sem); +} + +static void child_handler(int sig) +{ + add(10); + add(20); + sem_post (&sem_child); +} + +int +main (void) +{ + int i; + pthread_t id1, id2, id3; + struct sigaction act; + sigjmp_buf sj; + sigset_t m; + time_t end; + + memset (&act, 0, sizeof (act)); + act.sa_handler = signal_handler; + act.sa_flags = 0; + sigemptyset (&act.sa_mask); + sigaction (SIGUSR1, &act, NULL); + act.sa_handler = child_handler; + sigaction (SIGCHLD, &act, NULL); + + printf ("start\n"); fflush(stdout); + + sem_init (&sem, 0, 0); + sem_init (&sem_child, 0, 0); + pthread_create(&id1, NULL, high_load, NULL); + pthread_create(&id2, NULL, do_signal, NULL); +#if !defined(__APPLE__) + pthread_create(&id3, NULL, do_fork, NULL); +#endif + + /* sleep does not work !!! */ + end = time(NULL) + 2; + while (time(NULL) < end) ; + run = 0; + + pthread_join(id1, NULL); + pthread_join(id2, NULL); +#if !defined(__APPLE__) + pthread_join(id3, NULL); +#endif + sem_destroy (&sem); + sem_destroy (&sem_child); + + printf ("end\n"); fflush(stdout); + + sigemptyset (&m); + sigprocmask (SIG_SETMASK, &m, NULL); + if (sigsetjmp (sj, 0) == 0) + { + sigaddset (&m, SIGUSR1); + sigprocmask (SIG_SETMASK, &m, NULL); + siglongjmp (sj, 1); + printf ("failed"); + return 1; + } + sigprocmask (SIG_SETMASK, NULL, &m); + if (!sigismember (&m, SIGUSR1)) + printf ("failed"); + return 0; +} diff --git a/lib/tinycc/tests/tests2/114_bound_signal.expect b/lib/tinycc/tests/tests2/114_bound_signal.expect new file mode 100644 index 000000000..5d0fb3b2d --- /dev/null +++ b/lib/tinycc/tests/tests2/114_bound_signal.expect @@ -0,0 +1,2 @@ +start +end diff --git a/lib/tinycc/tests/tests2/115_bound_setjmp.c b/lib/tinycc/tests/tests2/115_bound_setjmp.c new file mode 100644 index 000000000..793db583f --- /dev/null +++ b/lib/tinycc/tests/tests2/115_bound_setjmp.c @@ -0,0 +1,172 @@ +#include +#include +#include + +#define TST int i, a[2], b[2]; \ + for (i = 0; i < 2; i++) a[i] = 0; \ + for (i = 0; i < 2; i++) b[i] = 0 + +static jmp_buf jmp; + +static void tst1 (void) +{ + TST; + longjmp(jmp, 1); +} + +static void tst2(void) +{ + jmp_buf jmp; + + setjmp (jmp); + TST; + tst1(); +} + +static void tst3 (jmp_buf loc) +{ + TST; + longjmp(loc, 1); +} + +static void tst4(jmp_buf loc) +{ + jmp_buf jmp; + + setjmp (jmp); + TST; + tst3(loc); +} + +static void tst (void) +{ + jmp_buf loc; + static int cnt; + + cnt = 0; + if (setjmp (jmp) == 0) { + TST; + tst2(); + } + else { + cnt++; + } + if (setjmp (loc) == 0) { + TST; + tst4(loc); + } + else { + cnt++; + } + if (cnt != 2) + printf ("incorrect cnt %d\n", cnt); +} + +static jmp_buf buf1; +static jmp_buf buf2; +static int *p; +static int n_x = 6; +static int g_counter; + +static void stack (void) +{ + static int counter; + static int way_point1; + static int way_point2; + + counter = 0; + way_point1 = 3; + way_point2 = 2; + g_counter = 0; + if (setjmp (buf1) != 101) { + int a[n_x]; + g_counter++; + p = &a[0]; + if (g_counter < 5) + longjmp (buf1, 2); + else if (g_counter == 5) + longjmp (buf1, 101); + else { + setjmp (buf2); + longjmp (buf1, 101); + } + } + + way_point1--; + + if (counter == 0) { + counter++; + { + int a[n_x]; + g_counter++; + p = &a[0]; + if (g_counter < 5) + longjmp (buf1, 2); + else if (g_counter == 5) + longjmp (buf1, 101); + else { + setjmp (buf2); + longjmp (buf1, 101); + } + } + } + + way_point2--; + + if (counter == 1) { + counter++; + longjmp (buf2, 2); + } + + if (!(way_point1 == 0 && way_point2 == 0 && + g_counter == 6 && counter == 2)) + printf ("Failed %d %d %d %d\n", + way_point1, way_point2, g_counter, counter); +} + +static jmp_buf env; +static int last_value; + +static void jump (int val) +{ + longjmp (env, val); +} + +static void check (void) +{ + int value; + + last_value = -1; + value = setjmp (env); + if (value != last_value + 1) { + printf ("incorrect value %d %d\n", + value, last_value + 1); + return; + } + last_value = value; + switch (value) { +#if !(defined(__FreeBSD__) || defined(__NetBSD__)) + /* longjmp(jmp_buf, 0) not supported */ + case 0: + jump (0); +#endif + default: + if (value < 10) + jump (value + 1); + } +} + +int +main (void) +{ + int i; + + for (i = 0; i < 10; i++) { + tst(); + stack(); + check(); + } + return 0; +} + + diff --git a/lib/tinycc/tests/tests2/115_bound_setjmp.expect b/lib/tinycc/tests/tests2/115_bound_setjmp.expect new file mode 100644 index 000000000..e69de29bb diff --git a/lib/tinycc/tests/tests2/116_bound_setjmp2.c b/lib/tinycc/tests/tests2/116_bound_setjmp2.c new file mode 100644 index 000000000..151114d9e --- /dev/null +++ b/lib/tinycc/tests/tests2/116_bound_setjmp2.c @@ -0,0 +1,84 @@ +#include +#include +#include +#if !defined(_WIN32) +#include +#else +#include +#endif + +#define SIZE 10 +#define COUNT 10 + +#define TST int i, a[2], b[2]; \ + for (i = 0; i < 2; i++) a[i] = 0; \ + for (i = 0; i < 2; i++) b[i] = 0 + +static int count[SIZE]; + +static void tst1 (jmp_buf loc) +{ + TST; + longjmp(loc, 1); +} + +static void tst2(jmp_buf loc) +{ + jmp_buf jmp; + + setjmp (jmp); + TST; + tst1(loc); +} + +static void *tst (void * index) +{ + jmp_buf loc; + int i = *(int *) index; + static int v[SIZE]; + + for (v[i] = 0; v[i] < COUNT; v[i]++) { + if (setjmp (loc) == 0) { + TST; + tst2(loc); + } + else { + count[i]++; + } + i = *(int *) index; + } + return NULL; +} + +int +main (void) +{ + int i; +#if !defined(_WIN32) + pthread_t id[SIZE]; +#else + HANDLE id[SIZE]; +#endif + int index[SIZE]; + + for (i = 0; i < SIZE; i++) { + index[i] = i; +#if !defined(_WIN32) + pthread_create (&id[i], NULL, tst, (void *) &index[i]); +#else + id[i] = CreateThread(NULL, 8192, (LPTHREAD_START_ROUTINE) tst, (void *) &index[i], 0, NULL); +#endif + } + for (i = 0; i < SIZE; i++) { +#if !defined(_WIN32) + pthread_join (id[i], NULL); +#else + WaitForSingleObject(id[i], INFINITE); +#endif + } + for (i = 0; i < SIZE; i++) { + if (count[i] != COUNT) + printf ("error: %d %d\n", i, count[i]); + } + return 0; +} diff --git a/lib/tinycc/tests/tests2/116_bound_setjmp2.expect b/lib/tinycc/tests/tests2/116_bound_setjmp2.expect new file mode 100644 index 000000000..e69de29bb diff --git a/lib/tinycc/tests/tests2/117_builtins.c b/lib/tinycc/tests/tests2/117_builtins.c new file mode 100644 index 000000000..b57a73ed8 --- /dev/null +++ b/lib/tinycc/tests/tests2/117_builtins.c @@ -0,0 +1,94 @@ +#include + +struct big_struct { char a[262144]; }; + +static const char str[] = "abcdefghijklmnopqrstuvwxyz"; + +int +main (void) +{ + char *p; + char tmp[100]; + int r = 0; + +#if defined __TCC_BCHECK__ + printf("BOUNDS ON:\n"); +#else + printf("BOUNDS OFF:\n"); +#endif + + if (r != 0) + __builtin_abort(); + + r = (__builtin_offsetof(struct big_struct, a) != 0); + printf(" 1:%d", !r); + + p = __builtin_memcpy (tmp, str, sizeof(str)); + r = (p != tmp); + printf(" 2:%d", !r); + + r = __builtin_memcmp (p, str, sizeof(str)); + printf(" 3:%d", !r); + + p = __builtin_memmove(tmp, str, sizeof(str)); + r = (__builtin_memcmp (p, str, sizeof(str))); + printf(" 4:%d", !r); + + p = __builtin_memset(tmp, 0, sizeof (tmp)); + r = (p != tmp || tmp[0] != 0 || tmp[99] != 0); + printf(" 5:%d", !r); + + r = (__builtin_strlen(str) != sizeof(str) - 1); + printf(" 6:%d", !r); + + p = __builtin_strcpy(tmp, str); + r = (__builtin_memcmp (p, str, sizeof(str))); + printf(" 7:%d", !r); + + p = __builtin_strncpy(tmp, str, sizeof(str)); + r = (__builtin_memcmp (p, str, sizeof(str))); + printf(" 8:%d", !r); + + r = (__builtin_strcmp (p, str)); + printf(" 9:%d", !r); + + r = (__builtin_strncmp (p, str, sizeof(str))); + printf(" 10:%d", !r); + + tmp[0] = '\0'; + p = __builtin_strcat(tmp, str); + r = (__builtin_memcmp (p, str, sizeof(str))); + printf(" 11:%d", !r); + + tmp[0] = '\0'; + p = __builtin_strncat(tmp, str, __builtin_strlen(str)); + r = (__builtin_memcmp (p, str, sizeof(str))); + printf(" 12:%d", !r); + + r = (__builtin_strchr(p, 'z') != &p[25]); + printf(" 13:%d", !r); + + r = (__builtin_strrchr(p, 'z') != &p[25]); + printf(" 14:%d", !r); + + p = __builtin_strdup (str); + r = (__builtin_memcmp (p, str, sizeof(str))); + printf(" 15:%d", !r); + __builtin_free(p); + + p = __builtin_malloc (100); + __builtin_memset(p, 0, 100); + p = __builtin_realloc (p, 1000); + __builtin_memset(p, 0, 1000); + __builtin_free(p); + + p = __builtin_calloc(10, 10); + __builtin_memset(p, 0, 100); + __builtin_free(p); + +#if defined(__i386__) || defined(__x86_64__) + p = __builtin_alloca(100); + __builtin_memset(p, 0, 100); +#endif + printf("\n"); +} diff --git a/lib/tinycc/tests/tests2/117_builtins.expect b/lib/tinycc/tests/tests2/117_builtins.expect new file mode 100644 index 000000000..f2c78ba79 --- /dev/null +++ b/lib/tinycc/tests/tests2/117_builtins.expect @@ -0,0 +1,4 @@ +BOUNDS OFF: + 1:1 2:1 3:1 4:1 5:1 6:1 7:1 8:1 9:1 10:1 11:1 12:1 13:1 14:1 15:1 +BOUNDS ON: + 1:1 2:1 3:1 4:1 5:1 6:1 7:1 8:1 9:1 10:1 11:1 12:1 13:1 14:1 15:1 diff --git a/lib/tinycc/tests/tests2/118_switch.c b/lib/tinycc/tests/tests2/118_switch.c new file mode 100644 index 000000000..789dd06c7 --- /dev/null +++ b/lib/tinycc/tests/tests2/118_switch.c @@ -0,0 +1,75 @@ +#include +#include +#include + +int ibdg(long long n) +{ + switch (n) { + case 1LL ... 9LL: return 1; + case 10LL ... 99LL: return 2; + case 100LL ... 999LL: return 3; + case 1000LL ... 9999LL: return 4; + case 10000LL ... 99999LL: return 5; + case 100000LL ... 999999LL: return 6; + case 1000000LL ... 9999999LL: return 7; + case 10000000LL ... 99999999LL: return 8; + case 100000000LL ... 999999999LL: return 9; + case 1000000000LL ... 9999999999LL: return 10; + case 10000000000LL ... 99999999999LL: return 11; + case 100000000000LL ... 999999999999LL: return 12; + case 1000000000000LL ... 9999999999999LL: return 13; + case 10000000000000LL ... 99999999999999LL: return 14; + case 100000000000000LL ... 999999999999999LL: return 15; + case 1000000000000000LL ... 9999999999999999LL: return 16; + case 10000000000000000LL ... 99999999999999999LL: return 17; + case 100000000000000000LL ... 999999999999999999LL: return 18; + case 1000000000000000000LL ... 9223372036854775807LL: return 19; + case -9223372036854775807LL-1LL ... -1LL: return 20; + } + return 0; +} + +int ubdg(unsigned long long n) +{ + switch (n) { + case 1ULL ... 9ULL: return 1; + case 10ULL ... 99ULL: return 2; + case 100ULL ... 999ULL: return 3; + case 1000ULL ... 9999ULL: return 4; + case 10000ULL ... 99999ULL: return 5; + case 100000ULL ... 999999ULL: return 6; + case 1000000ULL ... 9999999ULL: return 7; + case 10000000ULL ... 99999999ULL: return 8; + case 100000000ULL ... 999999999ULL: return 9; + case 1000000000ULL ... 9999999999ULL: return 10; + case 10000000000ULL ... 99999999999ULL: return 11; + case 100000000000ULL ... 999999999999ULL: return 12; + case 1000000000000ULL ... 9999999999999ULL: return 13; + case 10000000000000ULL ... 99999999999999ULL: return 14; + case 100000000000000ULL ... 999999999999999ULL: return 15; + case 1000000000000000ULL ... 9999999999999999ULL: return 16; + case 10000000000000000ULL ... 99999999999999999ULL: return 17; + case 100000000000000000ULL ... 999999999999999999ULL: return 18; + case 1000000000000000000ULL ... 9999999999999999999ULL: return 19; + case 10000000000000000000ULL ... 18446744073709551615ULL: return 20; + } + return 0; +} + +int main(int argc, char **argv) +{ + unsigned int i; + unsigned long long v = 1; + + v = 1; + for (i = 1; i <= 20; i++) { + printf("%lld : %d\n", (long long) v, ibdg((long long)v)); + v *= 10; + } + v = 1; + for (i = 1; i <= 20; i++) { + printf("%llu : %d\n", v, ubdg(v)); + v *= 10; + } + return 0; +} diff --git a/lib/tinycc/tests/tests2/118_switch.expect b/lib/tinycc/tests/tests2/118_switch.expect new file mode 100644 index 000000000..4155eb48a --- /dev/null +++ b/lib/tinycc/tests/tests2/118_switch.expect @@ -0,0 +1,40 @@ +1 : 1 +10 : 2 +100 : 3 +1000 : 4 +10000 : 5 +100000 : 6 +1000000 : 7 +10000000 : 8 +100000000 : 9 +1000000000 : 10 +10000000000 : 11 +100000000000 : 12 +1000000000000 : 13 +10000000000000 : 14 +100000000000000 : 15 +1000000000000000 : 16 +10000000000000000 : 17 +100000000000000000 : 18 +1000000000000000000 : 19 +-8446744073709551616 : 20 +1 : 1 +10 : 2 +100 : 3 +1000 : 4 +10000 : 5 +100000 : 6 +1000000 : 7 +10000000 : 8 +100000000 : 9 +1000000000 : 10 +10000000000 : 11 +100000000000 : 12 +1000000000000 : 13 +10000000000000 : 14 +100000000000000 : 15 +1000000000000000 : 16 +10000000000000000 : 17 +100000000000000000 : 18 +1000000000000000000 : 19 +10000000000000000000 : 20 diff --git a/lib/tinycc/tests/tests2/119_random_stuff.c b/lib/tinycc/tests/tests2/119_random_stuff.c new file mode 100644 index 000000000..5530c096c --- /dev/null +++ b/lib/tinycc/tests/tests2/119_random_stuff.c @@ -0,0 +1,141 @@ +#include + +struct big_struct { char a[262144]; }; + +static const char str[] = "abcdefghijklmnopqrstuvwxyz"; + +void tst_branch(void) +{ + printf("tst_branch --"); + goto *&&a; + printf (" dummy"); +a: ; + printf(" --\n"); +} + +void tst_void_ptr(void *pv, int i) +{ + i ? *pv : *pv; // dr106 +} + +void tst_shift(void) +{ + int i = 1; + long long l = 1; + i = i << 32; // illegal. just test + l = l << 64; // illegal. just test +} + +#if !defined(_WIN32) +#include + +void tst_const_addr(void) +{ + void *addr = mmap ((void *)0x20000000, 4096, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_ANONYMOUS, -1, 0); + if (addr != (void *) -1) { + *(int *)0x20000000 += 42; + munmap (addr, 4096); + } +} +#endif + +struct zero_struct {}; + +struct zero_struct tst_zero_struct(void) +{ + struct zero_struct ret; + return ret; +} + +struct big_struct tst_big(struct big_struct tst) +{ + return tst; +} + +void tst_adr (int (*fp)(char *, const char *, ...)) +{ + char buf[10]; + (*fp)(buf, "%.0f", 5.0); + printf("tst_adr %s\n", buf); +} + +int tst(void) +{ + long long value = 3; + return -value; +} + +void tst_compare(void) +{ + /* This failed on risc64 */ + printf ("tst_compare: %s\n", tst() > 0 ? "error" : "ok"); +} + +#pragma pack(1) +struct S { int d:24; int f:14; } i, j; +#pragma pack() + +void tst_pack (void) +{ + i.f = 5; j.f = 5; + printf("tst_pack: j.f = %d, i.f = %d\n", j.f, i.f); +} + +void tst_cast(void) +{ + signed char c = (signed char) 0xaaaaaaaa; + int r = (unsigned short) c ^ (signed char) 0x99999999; + printf ("schar to ushort cast: %x\n", r); +} + +struct { + int (*print)(const char *format, ...); +} tst_indir = { + printf +}; + +void tst_indir_func(void) +{ + tst_indir.print("tst_indir_func %d\n", 10); +} + +struct V { + int x, y, z; +}; + +struct V vec(void) +{ + return (struct V) { 1, 2, 3 }; +} + +void func(float f, struct V v) +{ + printf("%g\n", f); +} + +void tst_struct_return_align(void) +{ + float d = 5.0f; + func(d, vec()); +} + +int +main (void) +{ + struct big_struct big; + + tst_branch(); + tst_shift(); + tst_void_ptr(&big.a[0], 0); +#if !defined(_WIN32) + tst_const_addr(); +#endif + tst_zero_struct(); + tst_big(big); + tst_adr(&sprintf); + tst_compare(); + tst_pack(); + tst_cast(); + tst_indir_func(); + tst_struct_return_align(); +} diff --git a/lib/tinycc/tests/tests2/119_random_stuff.expect b/lib/tinycc/tests/tests2/119_random_stuff.expect new file mode 100644 index 000000000..02ce2282e --- /dev/null +++ b/lib/tinycc/tests/tests2/119_random_stuff.expect @@ -0,0 +1,7 @@ +tst_branch -- -- +tst_adr 5 +tst_compare: ok +tst_pack: j.f = 5, i.f = 5 +schar to ushort cast: ffff0033 +tst_indir_func 10 +5 diff --git a/lib/tinycc/tests/tests2/11_precedence.c b/lib/tinycc/tests/tests2/11_precedence.c new file mode 100644 index 000000000..845b6bf0b --- /dev/null +++ b/lib/tinycc/tests/tests2/11_precedence.c @@ -0,0 +1,41 @@ +//#include +extern int printf(const char *, ...); + +int main() +{ + int a; + int b; + int c; + int d; + int e; + int f; + int x; + int y; + + a = 12; + b = 34; + c = 56; + d = 78; + e = 0; + f = 1; + + printf("%d\n", c + d); + printf("%d\n", (y = c + d)); + printf("%d\n", e || e && f); + printf("%d\n", e || f && f); + printf("%d\n", e && e || f); + printf("%d\n", e && f || f); + printf("%d\n", a && f | f); + printf("%d\n", a | b ^ c & d); + printf("%d, %d\n", a == a, a == b); + printf("%d, %d\n", a != a, a != b); + printf("%d\n", a != b && c != d); + printf("%d\n", a + b * c / f); + printf("%d\n", a + b * c / f); + printf("%d\n", (4 << 4)); + printf("%d\n", (64 >> 4)); + + return 0; +} + +// vim: set expandtab ts=4 sw=3 sts=3 tw=80 : diff --git a/lib/tinycc/tests/tests2/11_precedence.expect b/lib/tinycc/tests/tests2/11_precedence.expect new file mode 100644 index 000000000..b6923966e --- /dev/null +++ b/lib/tinycc/tests/tests2/11_precedence.expect @@ -0,0 +1,15 @@ +134 +134 +0 +1 +1 +1 +1 +46 +1, 0 +0, 1 +1 +1916 +1916 +64 +4 diff --git a/lib/tinycc/tests/tests2/120+_alias.c b/lib/tinycc/tests/tests2/120+_alias.c new file mode 100644 index 000000000..56db69db8 --- /dev/null +++ b/lib/tinycc/tests/tests2/120+_alias.c @@ -0,0 +1,18 @@ +extern int printf (const char *, ...); +extern void target(void); +extern void alias_for_target(void); +extern void asm_for_target(void); +extern int g_int, alias_int; + +void inunit2(void); + +void inunit2(void) +{ + printf("in unit2:\n"); + target(); + alias_for_target(); + /* This symbol is not supposed to be available in this unit: + asm_for_target(); + */ + printf("g_int = %d\nalias_int = %d\n", g_int, alias_int); +} diff --git a/lib/tinycc/tests/tests2/120_alias.c b/lib/tinycc/tests/tests2/120_alias.c new file mode 100644 index 000000000..35bd44f8c --- /dev/null +++ b/lib/tinycc/tests/tests2/120_alias.c @@ -0,0 +1,37 @@ +/* Check semantics of various constructs to generate renamed symbols. */ + +extern int printf (const char *, ...); +void target(void); +void target(void) { + printf("in target function\n"); +} +void alias_for_target(void) __attribute__((alias("target"))); + +int g_int = 34; +int alias_int __attribute__((alias("g_int"))); + +#ifdef __leading_underscore +# define _ "_" +#else +# define _ +#endif + +void asm_for_target(void) __asm__(_"target"); +int asm_int __asm__(_"g_int"); + +/* This is not supposed to compile, alias targets must be defined in the + same unit. In TCC they even must be defined before the reference +void alias_for_undef(void) __attribute__((alias("undefined"))); +*/ + +extern void inunit2(void); + +int main(void) +{ + target(); + alias_for_target(); + asm_for_target(); + printf("g_int = %d\nalias_int = %d\nasm_int = %d\n", g_int, alias_int, asm_int); + inunit2(); + return 0; +} diff --git a/lib/tinycc/tests/tests2/120_alias.expect b/lib/tinycc/tests/tests2/120_alias.expect new file mode 100644 index 000000000..52099d0e4 --- /dev/null +++ b/lib/tinycc/tests/tests2/120_alias.expect @@ -0,0 +1,11 @@ +in target function +in target function +in target function +g_int = 34 +alias_int = 34 +asm_int = 34 +in unit2: +in target function +in target function +g_int = 34 +alias_int = 34 diff --git a/lib/tinycc/tests/tests2/121_struct_return.c b/lib/tinycc/tests/tests2/121_struct_return.c new file mode 100644 index 000000000..147761b1b --- /dev/null +++ b/lib/tinycc/tests/tests2/121_struct_return.c @@ -0,0 +1,35 @@ +#include + +typedef struct { + int data[4]; + double d1; + double d2; +} Node; + +Node init(Node self) { + self.data[0] = 0; + self.data[1] = 1; + self.data[2] = 2; + self.data[3] = 3; + self.d1 = 1234; + self.d2 = 2345; + return self; +} + +void dummy(Node self) { +} + +void print_data(Node data) { + printf ("%d %d %d %d %g %g\n", + data.data[0], data.data[1], data.data[2], data.data[3], + data.d1, data.d2); +} + +int main(void) { + /* This code resulted in a bounds checking error */ + Node data; + dummy (data); + char val; + data = init (data); + print_data(data); +} diff --git a/lib/tinycc/tests/tests2/121_struct_return.expect b/lib/tinycc/tests/tests2/121_struct_return.expect new file mode 100644 index 000000000..fa68b11d7 --- /dev/null +++ b/lib/tinycc/tests/tests2/121_struct_return.expect @@ -0,0 +1 @@ +0 1 2 3 1234 2345 diff --git a/lib/tinycc/tests/tests2/122_vla_reuse.c b/lib/tinycc/tests/tests2/122_vla_reuse.c new file mode 100644 index 000000000..feb47de50 --- /dev/null +++ b/lib/tinycc/tests/tests2/122_vla_reuse.c @@ -0,0 +1,31 @@ +#include + +int +main (void) +{ + int n = 0; + int first=1; + int *p[101]; + if (0) { + lab:; + } + int x[n % 100 + 1]; + if (first == 0) { + if (&x[0] != p[n % 100 + 1]) { + printf ("ERROR: %p %p\n", &x[0], p[n % 100 + 1]); + return(1); + } + } + else { + p[n % 100 + 1] = &x[0]; + first = n < 100; + } + x[0] = 1; + x[n % 100] = 2; + n++; + if (n < 100000) + goto lab; + printf ("OK\n"); + return 0; +} + diff --git a/lib/tinycc/tests/tests2/122_vla_reuse.expect b/lib/tinycc/tests/tests2/122_vla_reuse.expect new file mode 100644 index 000000000..d86bac9de --- /dev/null +++ b/lib/tinycc/tests/tests2/122_vla_reuse.expect @@ -0,0 +1 @@ +OK diff --git a/lib/tinycc/tests/tests2/123_vla_bug.c b/lib/tinycc/tests/tests2/123_vla_bug.c new file mode 100644 index 000000000..6d92c27cf --- /dev/null +++ b/lib/tinycc/tests/tests2/123_vla_bug.c @@ -0,0 +1,40 @@ +typedef __SIZE_TYPE__ size_t; +extern int printf(const char*, ...); +extern size_t strlen(const char*); +char str[] = "blabla"; +int g; +int main() +{ + //char helpme[strlen(str) + 1]; + int i = 0; +#if 0 + if (g) { + char buf[strlen(str) + 10]; + buf[0] = 0; + } +alabel: + printf("default: i = %d\n", i); +#else + for (i = 0; i < 5; i++) { + switch (i) { + case 10: + if (g) { + char buf[strlen(str) + 10]; + buf[0] = 0; + goto do_cmd; + } + break; + case 1: + printf("reached 3\n"); + do_cmd: + printf("after do_cmd"); + break; + default: + g++; + printf("default: i = %d\n", i); + break; + } + } +#endif + return 0; +} diff --git a/lib/tinycc/tests/tests2/123_vla_bug.expect b/lib/tinycc/tests/tests2/123_vla_bug.expect new file mode 100644 index 000000000..2468f809f --- /dev/null +++ b/lib/tinycc/tests/tests2/123_vla_bug.expect @@ -0,0 +1,5 @@ +default: i = 0 +reached 3 +after do_cmddefault: i = 2 +default: i = 3 +default: i = 4 diff --git a/lib/tinycc/tests/tests2/124_atomic_counter.c b/lib/tinycc/tests/tests2/124_atomic_counter.c new file mode 100644 index 000000000..67a500a7c --- /dev/null +++ b/lib/tinycc/tests/tests2/124_atomic_counter.c @@ -0,0 +1,152 @@ +#include +#include +#include +#include +#include +#include + +#define NR_THREADS 16 +#define NR_STEPS ((uint32_t)UINT16_MAX) + +#define BUG_ON(COND) \ + do { \ + if (!!(COND)) \ + abort(); \ + } while (0) + +#if defined __x86_64__ || defined __aarch64__ || defined __riscv +#define HAS_64BITS +#endif + +typedef struct { + atomic_flag flag; + atomic_uchar uc; + atomic_ushort us; + atomic_uint ui; +#ifdef HAS_64BITS + atomic_size_t ul; +#endif +} counter_type; + +static +void *adder_simple(void *arg) +{ + size_t step; + counter_type *counter = arg; + + for (step = 0; step < NR_STEPS; ++step) { + atomic_fetch_add_explicit(&counter->uc, 1, memory_order_relaxed); + atomic_fetch_add_explicit(&counter->us, 1, memory_order_relaxed); + atomic_fetch_add_explicit(&counter->ui, 1, memory_order_relaxed); +#ifdef HAS_64BITS + atomic_fetch_add_explicit(&counter->ul, 1, memory_order_relaxed); +#endif + } + + return NULL; +} + +static +void *adder_cmpxchg(void *arg) +{ + size_t step; + counter_type *counter = arg; + + for (step = 0; step < NR_STEPS; ++step) { + unsigned char xchgc; + unsigned short xchgs; + unsigned int xchgi; +#ifdef HAS_64BITS + size_t xchgl; +#endif + unsigned char cmpc = atomic_load_explicit(&counter->uc, memory_order_relaxed); + unsigned short cmps = atomic_load_explicit(&counter->us, memory_order_relaxed); + unsigned int cmpi = atomic_load_explicit(&counter->ui, memory_order_relaxed); +#ifdef HAS_64BITS + size_t cmpl = atomic_load_explicit(&counter->ul, memory_order_relaxed); +#endif + + do { + xchgc = (cmpc + 1); + } while (!atomic_compare_exchange_strong_explicit(&counter->uc, + &cmpc, xchgc, memory_order_relaxed, memory_order_relaxed)); + do { + xchgs = (cmps + 1); + } while (!atomic_compare_exchange_strong_explicit(&counter->us, + &cmps, xchgs, memory_order_relaxed, memory_order_relaxed)); + do { + xchgi = (cmpi + 1); + } while (!atomic_compare_exchange_strong_explicit(&counter->ui, + &cmpi, xchgi, memory_order_relaxed, memory_order_relaxed)); +#ifdef HAS_64BITS + do { + xchgl = (cmpl + 1); + } while (!atomic_compare_exchange_strong_explicit(&counter->ul, + &cmpl, xchgl, memory_order_relaxed, memory_order_relaxed)); +#endif + } + + return NULL; +} + +static +void *adder_test_and_set(void *arg) +{ + size_t step; + counter_type *counter = arg; + + for (step = 0; step < NR_STEPS; ++step) { + while (atomic_flag_test_and_set(&counter->flag)); + ++counter->uc; + ++counter->us; + ++counter->ui; +#ifdef HAS_64BITS + ++counter->ul; +#endif + atomic_flag_clear(&counter->flag); + } + + return NULL; +} + +static +void atomic_counter_test(void *(*adder)(void *arg)) +{ + size_t index; + counter_type counter; + pthread_t thread[NR_THREADS]; + + atomic_flag_clear(&counter.flag); + atomic_init(&counter.uc, 0); + atomic_init(&counter.us, 0); + atomic_init(&counter.ui, 0); +#ifdef HAS_64BITS + atomic_init(&counter.ul, 0); +#endif + + for (index = 0; index < NR_THREADS; ++index) + BUG_ON(pthread_create(&thread[index], NULL, adder, (void *)&counter)); + + for (index = 0; index < NR_THREADS; ++index) + BUG_ON(pthread_join(thread[index], NULL)); + + if (atomic_load(&counter.uc) == ((NR_THREADS * NR_STEPS) & 0xffu) + && atomic_load(&counter.us) == ((NR_THREADS * NR_STEPS) & 0xffffu) + && atomic_load(&counter.ui) == (NR_THREADS * NR_STEPS) +#ifdef HAS_64BITS + && atomic_load(&counter.ul) == (NR_THREADS * NR_STEPS) +#endif + ) + printf("SUCCESS\n"); + else + printf("FAILURE\n"); +} + +int main(void) +{ + atomic_counter_test(adder_simple); + atomic_counter_test(adder_cmpxchg); + atomic_counter_test(adder_test_and_set); + + return 0; +} diff --git a/lib/tinycc/tests/tests2/124_atomic_counter.expect b/lib/tinycc/tests/tests2/124_atomic_counter.expect new file mode 100644 index 000000000..21667a71d --- /dev/null +++ b/lib/tinycc/tests/tests2/124_atomic_counter.expect @@ -0,0 +1,3 @@ +SUCCESS +SUCCESS +SUCCESS diff --git a/lib/tinycc/tests/tests2/125_atomic_misc.c b/lib/tinycc/tests/tests2/125_atomic_misc.c new file mode 100644 index 000000000..2d1063169 --- /dev/null +++ b/lib/tinycc/tests/tests2/125_atomic_misc.c @@ -0,0 +1,227 @@ +#include +int printf(const char*,...); + +#if defined test_atomic_compare_exchange +int main() +{ + _Atomic int a = 12; + int b = 77; + int r; + + atomic_store(&a, b + 0); + r = atomic_compare_exchange_strong(&a, &b, 99); + printf("%d %d %d\n", r, a, b); + + atomic_store(&a, b + 3); + r = atomic_compare_exchange_strong(&a, &b, 99); + printf("%d %d %d\n", r, a, b); + + atomic_store(&a, b + 5); + r = atomic_exchange(&a, 33); + printf("%d %d %d\n", r, a, b); + + atomic_store(&a, b + 10); + r = atomic_exchange(&a, 66); + printf("%d %d %d\n", r, a, b); + + return 0; +} + +#elif defined test_atomic_store +int main() +{ + int _Atomic i; + int r; + atomic_store(&i, 12); + r = atomic_fetch_add(&i, i); + printf("r = %d, i = %d\n", r, i); +} + +#elif defined test_atomic_store_pointer +typedef struct { char c[4]; } c4; +int main() +{ + int i = 1; + int _Atomic *p = &i; + int k = 2; + atomic_store(&p, &k); + printf("*p = %d\n", *p); +} + +#elif defined test_atomic_store_struct +typedef struct { char c[4]; } c4; +int main() +{ + c4 _Atomic p; + c4 v = { 1,2,3,4 }; + atomic_store(&p, v); + printf("%d %d %d %d\n", p.c[0], p.c[1], p.c[2], p.c[3]); +} + +#elif defined test_atomic_op + +#define OP1(func, v, e1, e2) atomic_##func(&c, v) == e1 && c == e2 +#define OP2(func, v, e1, e2) atomic_##func(&s, v) == e1 && s == e2 +#define OP4(func, v, e1, e2) atomic_##func(&i, v) == e1 && i == e2 +#if defined __x86_64__ || defined __aarch64__ || defined __riscv +#define OP8(func, v, e1, e2) atomic_##func(&l, v) == e1 && l == e2 +#define HAS_64BITS +#else +#define OP8(func, v, e1, e2) 1 +#endif + +#define OP(func, v, e1, e2) printf ("%s: %s\n", #func, \ + OP1(func,v,e1,e2) && OP2(func,v,e1,e2) && \ + OP4(func,v,e1,e2) && OP8(func,v,e1,e2) \ + ? "SUCCESS" : "FAIL"); + +int main() +{ + atomic_char c; + atomic_short s; + atomic_int i; +#ifdef HAS_64BITS + atomic_size_t l; +#endif + + atomic_init(&c, 0); + atomic_init(&s, 0); + atomic_init(&i, 0); +#ifdef HAS_64BITS + atomic_init(&l, 0); +#endif + + OP(fetch_add, 10, 0, 10); + OP(fetch_sub, 5, 10, 5); + OP(fetch_or, 0x10, 5, 21); + OP(fetch_xor, 0x20, 21, 53); + OP(fetch_and, 0x0f, 53, 5); +} + +#elif defined test_atomic_op2 + +typedef __SIZE_TYPE__ size64_t; + +#define OP1(func, v, e1, e2) \ + __atomic_##func(&c, v, __ATOMIC_SEQ_CST) == e1 && c == e2 +#define OP2(func, v, e1, e2)\ + __atomic_##func(&s, v, __ATOMIC_SEQ_CST) == e1 && s == e2 +#define OP4(func, v, e1, e2)\ + __atomic_##func(&i, v, __ATOMIC_SEQ_CST) == e1 && i == e2 +#if defined __x86_64__ || defined __aarch64__ || defined __riscv +#define OP8(func, v, e1, e2)\ + __atomic_##func(&l, v, __ATOMIC_SEQ_CST) == e1 && l == e2 +#define HAS_64BITS +#else +#define OP8(func, v, e1, e2) 1 +#endif + +#define OP(func, v, e1, e2) printf ("%s: %s\n", #func, \ + OP1(func,v,e1,e2) && OP2(func,v,e1,e2) && \ + OP4(func,v,e1,e2) && OP8(func,v,e1,e2) \ + ? "SUCCESS" : "FAIL"); + +int main() +{ + signed char c; + short s; + int i; +#ifdef HAS_64BITS + size64_t l; +#endif + + atomic_init(&c, 0); + atomic_init(&s, 0); + atomic_init(&i, 0); +#ifdef HAS_64BITS + atomic_init(&l, 0); +#endif + + OP(fetch_add, 10, 0, 10); + OP(fetch_sub, 5, 10, 5); + OP(fetch_or, 0x10, 5, 21); + OP(fetch_xor, 0x20, 21, 53); + OP(fetch_and, 0x0f, 53, 5); + OP(fetch_nand, 0x01, 5, -2); + + atomic_init(&c, 0); + atomic_init(&s, 0); + atomic_init(&i, 0); +#ifdef HAS_64BITS + atomic_init(&l, 0); +#endif + + OP(add_fetch, 10, 10, 10); + OP(sub_fetch, 5, 5, 5); + OP(or_fetch, 0x10, 21, 21); + OP(xor_fetch, 0x20, 53, 53); + OP(and_fetch, 0x0f, 5, 5); + OP(nand_fetch, 0x01, -2, -2); +} + +#elif defined test_atomic_thread_signal +int main() +{ + int c; + + atomic_thread_fence(__ATOMIC_SEQ_CST); + atomic_signal_fence(__ATOMIC_SEQ_CST); + printf ("%d\n", atomic_is_lock_free(&c)); +} + +#elif defined test_atomic_error_1 +int main() +{ + int _Atomic i; + atomic_load(i); +} + +#elif defined test_atomic_error_2 +int main() +{ + struct { char c[3]; } _Atomic c3; + atomic_load(&c3); +} + +#elif defined test_atomic_error_3 +int main() +{ + _Atomic int *p = 0; + atomic_fetch_add(&p, 1); +} + +#elif defined test_atomic_error_4 +int main() +{ + int _Atomic i = 1; + char c = 2; + atomic_compare_exchange_strong(&i, &c, 0); +} + +#elif defined test_atomic_warn_1 +int main() +{ + size_t _Atomic i = 1; + /* assignment to integer from pointer */ + atomic_store(&i, &i); +} + +#elif defined test_atomic_warn_2 +int main() +{ + int i = 1; + char c = 2; + int _Atomic *p = &i; + /* assignment from incompatible pointer */ + atomic_store(&p, &c); +} + +#elif defined test_atomic_warn_3 +int main() +{ + int const i = 1; + /* assignment to read-only -location */ + atomic_fetch_add(&i, 2); +} + +#endif diff --git a/lib/tinycc/tests/tests2/125_atomic_misc.expect b/lib/tinycc/tests/tests2/125_atomic_misc.expect new file mode 100644 index 000000000..61bd29f4e --- /dev/null +++ b/lib/tinycc/tests/tests2/125_atomic_misc.expect @@ -0,0 +1,59 @@ +[test_atomic_compare_exchange] +1 99 77 +0 80 80 +85 33 80 +90 66 80 + +[test_atomic_store] +r = 12, i = 24 + +[test_atomic_store_pointer] +*p = 2 + +[test_atomic_store_struct] +1 2 3 4 + +[test_atomic_op] +fetch_add: SUCCESS +fetch_sub: SUCCESS +fetch_or: SUCCESS +fetch_xor: SUCCESS +fetch_and: SUCCESS + +[test_atomic_op2] +fetch_add: SUCCESS +fetch_sub: SUCCESS +fetch_or: SUCCESS +fetch_xor: SUCCESS +fetch_and: SUCCESS +fetch_nand: SUCCESS +add_fetch: SUCCESS +sub_fetch: SUCCESS +or_fetch: SUCCESS +xor_fetch: SUCCESS +and_fetch: SUCCESS +nand_fetch: SUCCESS + +[test_atomic_thread_signal] +1 + +[test_atomic_error_1] +125_atomic_misc.c:176: error: pointer expected + +[test_atomic_error_2] +125_atomic_misc.c:183: error: integral or integer-sized pointer target type expected + +[test_atomic_error_3] +125_atomic_misc.c:190: error: integral or integer-sized pointer target type expected + +[test_atomic_error_4] +125_atomic_misc.c:198: error: pointer target type mismatch in argument 2 + +[test_atomic_warn_1] +125_atomic_misc.c:206: warning: assignment makes integer from pointer without a cast + +[test_atomic_warn_2] +125_atomic_misc.c:216: warning: assignment from incompatible pointer type + +[test_atomic_warn_3] +125_atomic_misc.c:224: warning: assignment of read-only location diff --git a/lib/tinycc/tests/tests2/126_bound_global.c b/lib/tinycc/tests/tests2/126_bound_global.c new file mode 100644 index 000000000..d3a5c3b4f --- /dev/null +++ b/lib/tinycc/tests/tests2/126_bound_global.c @@ -0,0 +1,13 @@ +/* test bound checking code without -run */ + +int arr[10]; + +int +main(int argc, char **argv) +{ + int i; + + for (i = 0; i <= sizeof(arr)/sizeof(arr[0]); i++) + arr[i] = 0; + return 0; +} diff --git a/lib/tinycc/tests/tests2/126_bound_global.expect b/lib/tinycc/tests/tests2/126_bound_global.expect new file mode 100644 index 000000000..fcdea9002 --- /dev/null +++ b/lib/tinycc/tests/tests2/126_bound_global.expect @@ -0,0 +1,2 @@ +126_bound_global.c:11: at main: BCHECK: ........ is outside of the region +126_bound_global.c:11: at main: RUNTIME ERROR: invalid memory access diff --git a/lib/tinycc/tests/tests2/127_asm_goto.c b/lib/tinycc/tests/tests2/127_asm_goto.c new file mode 100644 index 000000000..de631aa32 --- /dev/null +++ b/lib/tinycc/tests/tests2/127_asm_goto.c @@ -0,0 +1,62 @@ +static int simple_jump(void) +{ + asm goto ("jmp %l[label]" : : : : label); + return 0; +label: + return 1; +} + +static int three_way_jump(int val, int *addr) +{ + *addr = 42; + asm goto ("cmp $0, %1\n\t" + "jg %l[larger]\n\t" + "jl %l[smaller]\n\t" + "incl %0\n\t" + : "=m" (*addr) + : "r" (val) + : + : smaller, larger); + return 1; +smaller: + return 2; +larger: + return 3; +} + +static int another_jump(void) +{ + asm goto ("jmp %l[label]" : : : : label); + return 70; + /* Use the same label name as in simple_jump to check that + that doesn't confuse our C/ASM symbol tables */ +label: + return 71; +} + +extern int printf (const char *, ...); +int main(void) +{ + int i; + if (simple_jump () == 1) + printf ("simple_jump: okay\n"); + else + printf ("simple_jump: wrong\n"); + if (another_jump () == 71) + printf ("another_jump: okay\n"); + else + printf ("another_jump: wrong\n"); + if (three_way_jump(0, &i) == 1 && i == 43) + printf ("three_way_jump(0): okay\n"); + else + printf ("three_way_jump(0): wrong (i=%d)\n", i); + if (three_way_jump(1, &i) == 3 && i == 42) + printf ("three_way_jump(1): okay\n"); + else + printf ("three_way_jump(1): wrong (i=%d)\n", i); + if (three_way_jump(-1, &i) == 2 && i == 42) + printf ("three_way_jump(-1): okay\n"); + else + printf ("three_way_jump(-1): wrong (i=%d)\n", i); + return 0; +} diff --git a/lib/tinycc/tests/tests2/127_asm_goto.expect b/lib/tinycc/tests/tests2/127_asm_goto.expect new file mode 100644 index 000000000..e1b716996 --- /dev/null +++ b/lib/tinycc/tests/tests2/127_asm_goto.expect @@ -0,0 +1,5 @@ +simple_jump: okay +another_jump: okay +three_way_jump(0): okay +three_way_jump(1): okay +three_way_jump(-1): okay diff --git a/lib/tinycc/tests/tests2/128_run_atexit.c b/lib/tinycc/tests/tests2/128_run_atexit.c new file mode 100644 index 000000000..3c7cfbb8f --- /dev/null +++ b/lib/tinycc/tests/tests2/128_run_atexit.c @@ -0,0 +1,59 @@ +#include + +int atexit(void (*function)(void)); +int on_exit(void (*function)(int, void *), void *arg); +void exit(int status); + +void __attribute((constructor)) startup5(void) +{ + printf ("startup5\n"); +} + +void cleanup1(void) +{ + printf ("cleanup1\n"); + fflush(stdout); +} + +void cleanup2(void) +{ + printf ("cleanup2\n"); +} + +void cleanup3(int ret, void *arg) +{ + printf ("%d %s\n", ret, (char *) arg); +} + +void cleanup4(int ret, void *arg) +{ + printf ("%d %s\n", ret, (char *) arg); +} + +void __attribute((destructor)) cleanup5(void) +{ + printf ("cleanup5\n"); +} + +void test(void) +{ + atexit(cleanup1); + atexit(cleanup2); + on_exit(cleanup3, "cleanup3"); + on_exit(cleanup4, "cleanup4"); +} + +#if defined test_128_return +int main(int argc, char **argv) +{ + test(); + return 1; +} + +#elif defined test_128_exit +int main(int argc, char **argv) +{ + test(); + exit(2); +} +#endif diff --git a/lib/tinycc/tests/tests2/128_run_atexit.expect b/lib/tinycc/tests/tests2/128_run_atexit.expect new file mode 100644 index 000000000..fda764cea --- /dev/null +++ b/lib/tinycc/tests/tests2/128_run_atexit.expect @@ -0,0 +1,17 @@ +[test_128_return] +startup5 +cleanup5 +1 cleanup4 +1 cleanup3 +cleanup2 +cleanup1 +[returns 1] + +[test_128_exit] +startup5 +cleanup5 +2 cleanup4 +2 cleanup3 +cleanup2 +cleanup1 +[returns 2] diff --git a/lib/tinycc/tests/tests2/129_scopes.c b/lib/tinycc/tests/tests2/129_scopes.c new file mode 100644 index 000000000..b63b68229 --- /dev/null +++ b/lib/tinycc/tests/tests2/129_scopes.c @@ -0,0 +1,43 @@ +#include +enum{ in = 0}; +#define myassert(X) do{ if(!X) printf("%d: assertion failed\n", __LINE__); }while(0) +int main(){ + { + myassert(!in); + if(sizeof(enum{in=1})) myassert(in); + myassert(!in); //OOPS + } + { + myassert(!in); + switch(sizeof(enum{in=1})) { default: myassert(in); } + myassert(!in); //OOPS + } + { + myassert(!in); + while(sizeof(enum{in=1})) { myassert(in); break; } + myassert(!in); //OOPS + } + { + myassert(!in); + do{ myassert(!in);}while(0*sizeof(enum{in=1})); + myassert(!in); //OOPS + } + + { + myassert(!in); + for(sizeof(enum{in=1});;){ myassert(in); break; } + myassert(!in); //OK + } + { + myassert(!in); + for(;;sizeof(enum{in=1})){ myassert(in); break; } + myassert(!in); //OK + } + { + myassert(!in); + for(;sizeof(enum{in=1});){ myassert(in); break; } + myassert(!in); //OK + } + +} + diff --git a/lib/tinycc/tests/tests2/129_scopes.expect b/lib/tinycc/tests/tests2/129_scopes.expect new file mode 100644 index 000000000..e69de29bb diff --git a/lib/tinycc/tests/tests2/12_hashdefine.c b/lib/tinycc/tests/tests2/12_hashdefine.c new file mode 100644 index 000000000..5c521e02b --- /dev/null +++ b/lib/tinycc/tests/tests2/12_hashdefine.c @@ -0,0 +1,14 @@ +#include + +#define FRED 12 +#define BLOGGS(x) (12*(x)) + +int main() +{ + printf("%d\n", FRED); + printf("%d, %d, %d\n", BLOGGS(1), BLOGGS(2), BLOGGS(3)); + + return 0; +} + +// vim: set expandtab ts=4 sw=3 sts=3 tw=80 : diff --git a/lib/tinycc/tests/tests2/12_hashdefine.expect b/lib/tinycc/tests/tests2/12_hashdefine.expect new file mode 100644 index 000000000..99f2ed5d9 --- /dev/null +++ b/lib/tinycc/tests/tests2/12_hashdefine.expect @@ -0,0 +1,2 @@ +12 +12, 24, 36 diff --git a/lib/tinycc/tests/tests2/130_large_argument.c b/lib/tinycc/tests/tests2/130_large_argument.c new file mode 100644 index 000000000..8415c85e9 --- /dev/null +++ b/lib/tinycc/tests/tests2/130_large_argument.c @@ -0,0 +1,41 @@ +#include + +struct large1 { + int a[768]; +}; + +struct large2 { + int a[1920]; +}; + +void pass_large_struct1(struct large1 in) +{ + printf("%d %d\n", in.a[200], in.a[767]); + return; +} + +void pass_large_struct2(struct large2 in) +{ + printf("%d %d %d\n", in.a[200], in.a[1023], in.a[1919]); + return; +} + +void pass_many_args(int a, int b, int c, int d, int e, int f, int g, int h, int i, + int j, int k, int l, int m) +{ + printf("%d %d %d %d %d %d %d %d %d %d %d %d %d\n", a, b, c, d, e, f, g, h, i, + j, k, l, m); + return; +} + +struct large1 l1 = { .a = { [200] = 1, [767] = 2 } }; +struct large2 l2 = { .a = { [200] = 3, [1023] = 4, [1919] = 5} }; + +int main(void) +{ + pass_large_struct1(l1); + pass_large_struct2(l2); + pass_many_args(13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1); + + return 0; +} diff --git a/lib/tinycc/tests/tests2/130_large_argument.expect b/lib/tinycc/tests/tests2/130_large_argument.expect new file mode 100644 index 000000000..8c5d9cd78 --- /dev/null +++ b/lib/tinycc/tests/tests2/130_large_argument.expect @@ -0,0 +1,3 @@ +1 2 +3 4 5 +13 12 11 10 9 8 7 6 5 4 3 2 1 diff --git a/lib/tinycc/tests/tests2/131_return_struct_in_reg.c b/lib/tinycc/tests/tests2/131_return_struct_in_reg.c new file mode 100644 index 000000000..2cb00b53a --- /dev/null +++ b/lib/tinycc/tests/tests2/131_return_struct_in_reg.c @@ -0,0 +1,70 @@ +#include + +struct s1 { + unsigned char a:4, b:4; +} g1 = { 0x05, 0x0a }; + +struct s2 { + unsigned char a, b; +} g2 = { 0x12, 0x34 }; + +struct s4 { + unsigned short a, b; +} g4 = { 0x1245, 0x5678 }; + +struct s8 { + unsigned a, b; +} g8 = { 0x12345678, 0x9abcdef0 }; + +/* returned in 2 registers on riscv64 */ +struct s16 { + unsigned long long a, b; +} g16 = { 0x123456789abcdef0ULL, 0xfedcba9876543210ULL }; + +/* Homogeneous float aggregate on ARM hard-float */ +struct s_f4 { + double a, b, c, d; +} g_f4 = { 1,2,3,4 }; + +#define def(S) \ +struct s##S f##S(int x) \ +{ \ + struct s##S l##S = g##S, *p##S = &l##S; \ + if (x == 0) \ + return g##S; \ + else if (x == 1) \ + return l##S; \ + else \ + return *p##S; \ +} + +def(1) +def(2) +def(4) +def(8) +def(16) +def(_f4) + +#define chk(S,x) \ + struct s##S l##S = f##S(x); \ + printf("%02llx %02llx\n", \ + (unsigned long long)l##S.a, \ + (unsigned long long)l##S.b \ + ); + +int main() +{ + for (int x = 0;;) { + chk(1,x); + chk(2,x); + chk(4,x); + chk(8,x); + chk(16,x); + struct s_f4 l_f4 = f_f4(x); + printf("%.1f %.1f %.1f %.1f\n", l_f4.a, l_f4.b, l_f4.c, l_f4.d); + if (++x > 2) + break; + printf("\n"); + } + return 0; +} diff --git a/lib/tinycc/tests/tests2/131_return_struct_in_reg.expect b/lib/tinycc/tests/tests2/131_return_struct_in_reg.expect new file mode 100644 index 000000000..2341c57c3 --- /dev/null +++ b/lib/tinycc/tests/tests2/131_return_struct_in_reg.expect @@ -0,0 +1,20 @@ +05 0a +12 34 +1245 5678 +12345678 9abcdef0 +123456789abcdef0 fedcba9876543210 +1.0 2.0 3.0 4.0 + +05 0a +12 34 +1245 5678 +12345678 9abcdef0 +123456789abcdef0 fedcba9876543210 +1.0 2.0 3.0 4.0 + +05 0a +12 34 +1245 5678 +12345678 9abcdef0 +123456789abcdef0 fedcba9876543210 +1.0 2.0 3.0 4.0 diff --git a/lib/tinycc/tests/tests2/132_bound_test.c b/lib/tinycc/tests/tests2/132_bound_test.c new file mode 100644 index 000000000..4898e8d72 --- /dev/null +++ b/lib/tinycc/tests/tests2/132_bound_test.c @@ -0,0 +1,29 @@ +#include +#include + +union ieee_double_extract +{ + struct { + unsigned int manl:32; + unsigned int manh:20; + unsigned int exp:11; + unsigned int sig:1; + } s; + double d; +}; + +double scale(double d) +{ + union ieee_double_extract x; + + x.d = d; + x.d *= 1000; + return x.d; +} + +int +main(void) +{ + printf("%g\n", scale(42)); + return 0; +} diff --git a/lib/tinycc/tests/tests2/132_bound_test.expect b/lib/tinycc/tests/tests2/132_bound_test.expect new file mode 100644 index 000000000..6096bd1be --- /dev/null +++ b/lib/tinycc/tests/tests2/132_bound_test.expect @@ -0,0 +1 @@ +42000 diff --git a/lib/tinycc/tests/tests2/133_exec_section_in_c.c b/lib/tinycc/tests/tests2/133_exec_section_in_c.c new file mode 100644 index 000000000..fea8e2f96 --- /dev/null +++ b/lib/tinycc/tests/tests2/133_exec_section_in_c.c @@ -0,0 +1,17 @@ +#include + +/* Previously in TinyCC, ELF sections defined in attributes would always have +the execute bit not set, so you would get segmentation faults when code in these +sections was exectuted. This file is a minimal example of a file that will put +the resulting code in a non-executable section (and invoke it) prior to the fix. +*/ +__attribute__((section(".text.wumbo"))) +int wumbo (int arg) { + return arg * 2; +} + +int main () { + wumbo(2); + puts("hi"); + return 0; +} diff --git a/lib/tinycc/tests/tests2/133_exec_section_in_c.expect b/lib/tinycc/tests/tests2/133_exec_section_in_c.expect new file mode 100644 index 000000000..45b983be3 --- /dev/null +++ b/lib/tinycc/tests/tests2/133_exec_section_in_c.expect @@ -0,0 +1 @@ +hi diff --git a/lib/tinycc/tests/tests2/13_integer_literals.c b/lib/tinycc/tests/tests2/13_integer_literals.c new file mode 100644 index 000000000..7cee98b1f --- /dev/null +++ b/lib/tinycc/tests/tests2/13_integer_literals.c @@ -0,0 +1,20 @@ +#include + +int main() +{ + int a = 24680; + int b = 01234567; + int c = 0x2468ac; + int d = 0x2468AC; + int e = 0b010101010101; + + printf("%d\n", a); + printf("%d\n", b); + printf("%d\n", c); + printf("%d\n", d); + printf("%d\n", e); + + return 0; +} + +// vim: set expandtab ts=4 sw=3 sts=3 tw=80 : diff --git a/lib/tinycc/tests/tests2/13_integer_literals.expect b/lib/tinycc/tests/tests2/13_integer_literals.expect new file mode 100644 index 000000000..f5aca06f7 --- /dev/null +++ b/lib/tinycc/tests/tests2/13_integer_literals.expect @@ -0,0 +1,5 @@ +24680 +342391 +2386092 +2386092 +1365 diff --git a/lib/tinycc/tests/tests2/14_if.c b/lib/tinycc/tests/tests2/14_if.c new file mode 100644 index 000000000..2bd255051 --- /dev/null +++ b/lib/tinycc/tests/tests2/14_if.c @@ -0,0 +1,21 @@ +#include + +int main() +{ + int a = 1; + + if (a) + printf("a is true\n"); + else + printf("a is false\n"); + + int b = 0; + if (b) + printf("b is true\n"); + else + printf("b is false\n"); + + return 0; +} + +// vim: set expandtab ts=4 sw=3 sts=3 tw=80 : diff --git a/lib/tinycc/tests/tests2/14_if.expect b/lib/tinycc/tests/tests2/14_if.expect new file mode 100644 index 000000000..c32c4159c --- /dev/null +++ b/lib/tinycc/tests/tests2/14_if.expect @@ -0,0 +1,2 @@ +a is true +b is false diff --git a/lib/tinycc/tests/tests2/15_recursion.c b/lib/tinycc/tests/tests2/15_recursion.c new file mode 100644 index 000000000..f79a00df5 --- /dev/null +++ b/lib/tinycc/tests/tests2/15_recursion.c @@ -0,0 +1,21 @@ +#include + +int factorial(int i) +{ + if (i < 2) + return i; + else + return i * factorial(i - 1); +} + +int main() +{ + int Count; + + for (Count = 1; Count <= 10; Count++) + printf("%d\n", factorial(Count)); + + return 0; +} + +/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/ diff --git a/lib/tinycc/tests/tests2/15_recursion.expect b/lib/tinycc/tests/tests2/15_recursion.expect new file mode 100644 index 000000000..db47b283d --- /dev/null +++ b/lib/tinycc/tests/tests2/15_recursion.expect @@ -0,0 +1,10 @@ +1 +2 +6 +24 +120 +720 +5040 +40320 +362880 +3628800 diff --git a/lib/tinycc/tests/tests2/16_nesting.c b/lib/tinycc/tests/tests2/16_nesting.c new file mode 100644 index 000000000..2b72cc028 --- /dev/null +++ b/lib/tinycc/tests/tests2/16_nesting.c @@ -0,0 +1,21 @@ +#include + +int main() +{ + int x, y, z; + + for (x = 0; x < 2; x++) + { + for (y = 0; y < 3; y++) + { + for (z = 0; z < 3; z++) + { + printf("%d %d %d\n", x, y, z); + } + } + } + + return 0; +} + +/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/ diff --git a/lib/tinycc/tests/tests2/16_nesting.expect b/lib/tinycc/tests/tests2/16_nesting.expect new file mode 100644 index 000000000..5a3431ee0 --- /dev/null +++ b/lib/tinycc/tests/tests2/16_nesting.expect @@ -0,0 +1,18 @@ +0 0 0 +0 0 1 +0 0 2 +0 1 0 +0 1 1 +0 1 2 +0 2 0 +0 2 1 +0 2 2 +1 0 0 +1 0 1 +1 0 2 +1 1 0 +1 1 1 +1 1 2 +1 2 0 +1 2 1 +1 2 2 diff --git a/lib/tinycc/tests/tests2/17_enum.c b/lib/tinycc/tests/tests2/17_enum.c new file mode 100644 index 000000000..e2bc73629 --- /dev/null +++ b/lib/tinycc/tests/tests2/17_enum.c @@ -0,0 +1,72 @@ +#include + +enum fred +{ + a, + b, + c, + d, + e = 54, + f = 73, + g, + h +}; + +/* All following uses of enum efoo should compile + without warning. While forward enums aren't ISO C, + it's accepted by GCC also in strict mode, and only warned + about with -pedantic. This happens in the real world. */ +/* Strict ISO C doesn't allow this kind of forward declaration of + enums, but GCC accepts it (and gives only pedantic warning), and + it occurs in the wild. */ +enum efoo; +struct Sforward_use { + int (*fmember) (enum efoo x); +}; + +extern enum efoo it_real_fn(void); +enum efoo { + ONE, + TWO, +}; +struct S2 { + enum efoo (*f2) (void); +}; +void should_compile(struct S2 *s) +{ + s->f2 = it_real_fn; +} + +enum efoo it_real_fn(void) +{ + return TWO; +} + +static unsigned int deref_uintptr(unsigned int *p) +{ + return *p; +} + +enum Epositive { + epos_one, epos_two +}; + +int main() +{ + enum fred frod; + enum Epositive epos = epos_two; + + printf("%d %d %d %d %d %d %d %d\n", a, b, c, d, e, f, g, h); + /* printf("%d\n", frod); */ + frod = 12; + printf("%d\n", frod); + frod = e; + printf("%d\n", frod); + + /* Following should compile without warning. */ + printf ("enum to int: %u\n", deref_uintptr(&epos)); + + return 0; +} + +/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/ diff --git a/lib/tinycc/tests/tests2/17_enum.expect b/lib/tinycc/tests/tests2/17_enum.expect new file mode 100644 index 000000000..d453a617b --- /dev/null +++ b/lib/tinycc/tests/tests2/17_enum.expect @@ -0,0 +1,4 @@ +0 1 2 3 54 73 74 75 +12 +54 +enum to int: 1 diff --git a/lib/tinycc/tests/tests2/18_include.c b/lib/tinycc/tests/tests2/18_include.c new file mode 100644 index 000000000..9ff60c96f --- /dev/null +++ b/lib/tinycc/tests/tests2/18_include.c @@ -0,0 +1,47 @@ +#include + +int main() +{ + printf("including\n"); +#include "18_include.h" +#define test_missing_nl + printf("done\n"); + +#define INC "18_include.h" + +#ifdef __has_include +#if defined __has_include +#if __has_include("18_include.h") + printf("has_include\n"); +#endif +#if __has_include(INC) + printf("has_include\n"); +#endif +#if __has_include("not_found_18_include.h") + printf("has_include not found\n"); +#endif +#endif +#endif + +#ifdef __has_include_next +#if defined __has_include_next +#if __has_include_next("18_include.h") + printf("has_include_next\n"); +#endif +#if __has_include_next(INC) + printf("has_include_next\n"); +#endif +#if __has_include_next("not_found_18_include.h") + printf("has_include_next not found\n"); +#endif +#endif +#endif + +#include "18_include2.h" +#include "./18_include2.h" +#include "../tests2/18_include2.h" + + return 0; +} + +/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/ diff --git a/lib/tinycc/tests/tests2/18_include.expect b/lib/tinycc/tests/tests2/18_include.expect new file mode 100644 index 000000000..fbc6d1342 --- /dev/null +++ b/lib/tinycc/tests/tests2/18_include.expect @@ -0,0 +1,8 @@ +including +included +done +has_include +has_include +has_include_next +has_include_next +counter 0 diff --git a/lib/tinycc/tests/tests2/18_include.h b/lib/tinycc/tests/tests2/18_include.h new file mode 100644 index 000000000..cad2433fd --- /dev/null +++ b/lib/tinycc/tests/tests2/18_include.h @@ -0,0 +1,5 @@ +printf("included\n"); +/* test file with missing newline */ +#ifndef INCLUDE +#define INCLUDE +#endif /* INCLUDE */ \ No newline at end of file diff --git a/lib/tinycc/tests/tests2/18_include2.h b/lib/tinycc/tests/tests2/18_include2.h new file mode 100644 index 000000000..2a89c3d1f --- /dev/null +++ b/lib/tinycc/tests/tests2/18_include2.h @@ -0,0 +1,2 @@ +#pragma once +printf ("counter %d\n", __COUNTER__); diff --git a/lib/tinycc/tests/tests2/19_pointer_arithmetic.c b/lib/tinycc/tests/tests2/19_pointer_arithmetic.c new file mode 100644 index 000000000..aff65e5b5 --- /dev/null +++ b/lib/tinycc/tests/tests2/19_pointer_arithmetic.c @@ -0,0 +1,28 @@ +#include + +int main() +{ + int a; + int *b; + int *c; + + a = 42; + b = &a; + c = NULL; + + printf("%d\n", *b); + + if (b == NULL) + printf("b is NULL\n"); + else + printf("b is not NULL\n"); + + if (c == NULL) + printf("c is NULL\n"); + else + printf("c is not NULL\n"); + + return 0; +} + +/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/ diff --git a/lib/tinycc/tests/tests2/19_pointer_arithmetic.expect b/lib/tinycc/tests/tests2/19_pointer_arithmetic.expect new file mode 100644 index 000000000..0cf781b9e --- /dev/null +++ b/lib/tinycc/tests/tests2/19_pointer_arithmetic.expect @@ -0,0 +1,3 @@ +42 +b is not NULL +c is NULL diff --git a/lib/tinycc/tests/tests2/20_pointer_comparison.c b/lib/tinycc/tests/tests2/20_pointer_comparison.c new file mode 100644 index 000000000..825f7787d --- /dev/null +++ b/lib/tinycc/tests/tests2/20_pointer_comparison.c @@ -0,0 +1,24 @@ +#include + +int main() +{ + int a; + int b; + int *d; + int *e; + d = &a; + e = &b; + a = 12; + b = 34; + printf("%d\n", *d); + printf("%d\n", *e); + printf("%d\n", d == e); + printf("%d\n", d != e); + d = e; + printf("%d\n", d == e); + printf("%d\n", d != e); + + return 0; +} + +/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/ diff --git a/lib/tinycc/tests/tests2/20_pointer_comparison.expect b/lib/tinycc/tests/tests2/20_pointer_comparison.expect new file mode 100644 index 000000000..5d1e5f5c7 --- /dev/null +++ b/lib/tinycc/tests/tests2/20_pointer_comparison.expect @@ -0,0 +1,6 @@ +12 +34 +0 +1 +1 +0 diff --git a/lib/tinycc/tests/tests2/21_char_array.c b/lib/tinycc/tests/tests2/21_char_array.c new file mode 100644 index 000000000..f22f5275c --- /dev/null +++ b/lib/tinycc/tests/tests2/21_char_array.c @@ -0,0 +1,33 @@ +#include + +int main() +{ + int x = 'a'; + char y = x; + + char *a = "hello"; + + printf("%s\n", a); + + int c; + c = *a; + + char *b; + for (b = a; *b != 0; b++) + printf("%c: %d\n", *b, *b); + + char destarray[10]; + char *dest = &destarray[0]; + char *src = a; + + while (*src != 0) + *dest++ = *src++; + + *dest = 0; + + printf("copied string is %s\n", destarray); + + return 0; +} + +/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/ diff --git a/lib/tinycc/tests/tests2/21_char_array.expect b/lib/tinycc/tests/tests2/21_char_array.expect new file mode 100644 index 000000000..dbc60683c --- /dev/null +++ b/lib/tinycc/tests/tests2/21_char_array.expect @@ -0,0 +1,7 @@ +hello +h: 104 +e: 101 +l: 108 +l: 108 +o: 111 +copied string is hello diff --git a/lib/tinycc/tests/tests2/22_floating_point.c b/lib/tinycc/tests/tests2/22_floating_point.c new file mode 100644 index 000000000..d6d4028f9 --- /dev/null +++ b/lib/tinycc/tests/tests2/22_floating_point.c @@ -0,0 +1,124 @@ +#include +#include + +float fd; + +int +test() +{ + // was an internal tcc compiler error with arm64 backend until 2019-11-08 + if (fd < 5.5) { + return 1; + } else { + return 0; + } +} + +float f1 = 12.34f, f2 = 56.78f; +double d1 = 12.34, d2 = 56.78; +long double ld1 = 12.34l, ld2 = 56.78l; + +float tf = 12.34f + 56.78f - 12.34f * 56.78f + 12.34f / 56.78f; +double td = 12.34 + 56.78 - 12.34 * 56.78 + 12.34 / 56.78; +long double tld = 12.34l + 56.78l - 12.34l * 56.78l + 12.34l / 56.78l; + +int main() +{ + static int e1 = -1.0 == 0.0; + static int e2 = -1.0 != 0.0; + static int e3 = -1.0 < 0.0; + static int e4 = -1.0 >= 0.0; + static int e5 = -1.0 <= 0.0; + static int e6 = -1.0 > 0.0; + // variables + float af = 12.34f + 56.78f; + double ad = 12.34 + 56.78; + long double ald = 12.34l + 56.78l; + printf("%f %f \n", af, tf); + printf("%g %g\n", ad, td); + printf("%Lf %Lf\n", ald, tld); + + // infix operators + printf("%f %f %f %f\n", 12.34f + 56.78f, 12.34f - 56.78f, 12.34f * 56.78f, 12.34f / 56.78f); + printf("%g %g %g %g\n", 12.34 + 56.78, 12.34 - 56.78, 12.34 * 56.78, 12.34 / 56.78); + printf("%Lf %Lf %Lf %Lf\n", 12.34l + 56.78l, 12.34l - 56.78l, 12.34l * 56.78l, 12.34l / 56.78l); +#ifdef __i386__ + // gcc/clang -m32 -mno-sse and tcc all fail for + and * but all have the same value + printf("%f %f %f %f\n", 12.34f + 56.78f, f1 - f2, 12.34f * 56.78f, f1 / f2); +#else + printf("%f %f %f %f\n", f1 + f2, f1 - f2, f1 * f2, f1 / f2); +#endif + printf("%g %g %g %g\n", d1 + d2, d1 - d2, d1 * d2, d1 / d2); + printf("%Lf %Lf %Lf %Lf\n", ld1 + ld2, ld1 - ld2, ld1 * ld2, ld1 / ld2); + + // comparison operators + printf("%d %d %d %d %d %d\n", 12.34f < 56.78f, 12.34f <= 56.78f, 12.34f == 56.78f, 12.34f >= 56.78f, 12.34f > 56.78f, 12.34f != 56.78f); + printf("%d %d %d %d %d %d\n", 12.34f < 12.34f, 12.34f <= 12.34f, 12.34f == 12.34f, 12.34f >= 12.34f, 12.34f > 12.34f, 12.34f != 12.34f); + printf("%d %d %d %d %d %d\n", 56.78f < 12.34f, 56.78f <= 12.34f, 56.78f == 12.34f, 56.78f >= 12.34f, 56.78f > 12.34f, 56.78f != 12.34f); + printf("%d %d %d %d %d %d\n", 12.34 < 56.78, 12.34 <= 56.78, 12.34 == 56.78, 12.34 >= 56.78, 12.34 > 56.78, 12.34 != 56.78); + printf("%d %d %d %d %d %d\n", 12.34 < 12.34, 12.34 <= 12.34, 12.34 == 12.34, 12.34 >= 12.34, 12.34 > 12.34, 12.34 != 12.34); + printf("%d %d %d %d %d %d\n", 56.78 < 12.34, 56.78 <= 12.34, 56.78 == 12.34, 56.78 >= 12.34, 56.78 > 12.34, 56.78 != 12.34); + printf("%d %d %d %d %d %d\n", 12.34l < 56.78l, 12.34l <= 56.78l, 12.34l == 56.78l, 12.34l >= 56.78l, 12.34l > 56.78l, 12.34l != 56.78l); + printf("%d %d %d %d %d %d\n", 12.34l < 12.34l, 12.34l <= 12.34l, 12.34l == 12.34l, 12.34l >= 12.34l, 12.34l > 12.34l, 12.34l != 12.34l); + printf("%d %d %d %d %d %d\n", 56.78l < 12.34l, 56.78l <= 12.34l, 56.78l == 12.34l, 56.78l >= 12.34l, 56.78l > 12.34l, 56.78l != 12.34l); + printf("%d %d %d %d %d %d\n", f1 < f2, f1 <= f2, f1 == f2, f1 >= f2, f1 > f2, f1 != f2); + printf("%d %d %d %d %d %d\n", f1 < f1, f1 <= f1, f1 == f1, f1 >= f1, f1 > f1, f1 != f1); + printf("%d %d %d %d %d %d\n", f2 < f1, f2 <= f1, f2 == f1, f2 >= f1, f2 > f1, f2 != f1); + printf("%d %d %d %d %d %d\n", d1 < d2, d1 <= d2, d1 == d2, d1 >= d2, d1 > d2, d1 != d2); + printf("%d %d %d %d %d %d\n", d1 < d1, d1 <= d1, d1 == d1, d1 >= d1, d1 > d1, d1 != d1); + printf("%d %d %d %d %d %d\n", d2 < d1, d2 <= d1, d2 == d1, d2 >= d1, d2 > d1, d2 != d1); + printf("%d %d %d %d %d %d\n", ld1 < ld2, ld1 <= ld2, ld1 == ld2, ld1 >= ld2, ld1 > ld2, ld1 != ld2); + printf("%d %d %d %d %d %d\n", ld1 < ld1, ld1 <= ld1, ld1 == ld1, ld1 >= ld1, ld1 > ld1, ld1 != ld1); + printf("%d %d %d %d %d %d\n", ld2 < ld1, ld2 <= ld1, ld2 == ld1, ld2 >= ld1, ld2 > ld1, ld2 != ld1); + printf("%d %d %d %d %d %d\n", e1, e2, e3, e4, e5, e6); + + // assignment operators + af = 12.34f; ad = 12.34; ald = 12.34l; + af += 56.78f; ad += 56.78; ald += 56.78l; + printf("%f %g %Lf\n", af, ad, ald); +#ifdef __i386__ + printf("%f %g %Lf\n", af, ad, ald); +#else + af = f1; ad = d1; ald = ld1; + af += f2; ad += d2; ald += ld2; + printf("%f %g %Lf\n", af, ad, ald); +#endif + + af = 12.34f; ad = 12.34; ald = 12.34l; + af -= 56.78f; ad -= 56.78; ald -= 56.78l; + printf("%f %g %Lf\n", af, ad, ald); + af = f1; ad = d1; ald = ld1; + af -= f2; ad -= d2; ald -= ld2; + printf("%f %g %Lf\n", af, ad, ald); + + af = 12.34f; ad = 12.34; ald = 12.34l; + af *= 56.78f; ad *= 56.78; ald *= 56.78l; + printf("%f %g %Lf\n", af, ad, ald); +#ifdef __i386__ + printf("%f %g %Lf\n", af, ad, ald); +#else + af = f1; ad = d1; ald = ld1; + af *= f2; ad *= d2; ald *= ld2; + printf("%f %g %Lf\n", af, ad, ald); +#endif + + af = 12.34f; ad = 12.34; ald = 12.34l; + af /= 56.78f; ad /= 56.78; ald /= 56.78l; + printf("%f %g %Lf\n", af, ad, ald); + af = f1; ad = d1; ald = ld1; + af /= f2; ad /= d2; ald /= ld2; + printf("%f %g %Lf\n", af, ad, ald); + + // prefix operators + printf("%f %g %Lf\n", +12.34f, +12.34, +12.34l); + printf("%f %g %Lf\n", -12.34f, -12.34, -12.34l); + + // type coercion + af = 2; + printf("%f\n", af); + printf("%f\n", sin(2)); + + return 0; +} + +/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/ diff --git a/lib/tinycc/tests/tests2/22_floating_point.expect b/lib/tinycc/tests/tests2/22_floating_point.expect new file mode 100644 index 000000000..d9c803e08 --- /dev/null +++ b/lib/tinycc/tests/tests2/22_floating_point.expect @@ -0,0 +1,40 @@ +69.119995 -631.327881 +69.12 -631.328 +69.120000 -631.327870 +69.119995 -44.439999 700.665222 0.217330 +69.12 -44.44 700.665 0.21733 +69.120000 -44.440000 700.665200 0.217330 +69.119995 -44.439999 700.665222 0.217330 +69.12 -44.44 700.665 0.21733 +69.120000 -44.440000 700.665200 0.217330 +1 1 0 0 0 1 +0 1 1 1 0 0 +0 0 0 1 1 1 +1 1 0 0 0 1 +0 1 1 1 0 0 +0 0 0 1 1 1 +1 1 0 0 0 1 +0 1 1 1 0 0 +0 0 0 1 1 1 +1 1 0 0 0 1 +0 1 1 1 0 0 +0 0 0 1 1 1 +1 1 0 0 0 1 +0 1 1 1 0 0 +0 0 0 1 1 1 +1 1 0 0 0 1 +0 1 1 1 0 0 +0 0 0 1 1 1 +0 1 1 0 1 0 +69.119995 69.12 69.120000 +69.119995 69.12 69.120000 +-44.439999 -44.44 -44.440000 +-44.439999 -44.44 -44.440000 +700.665222 700.665 700.665200 +700.665222 700.665 700.665200 +0.217330 0.21733 0.217330 +0.217330 0.21733 0.217330 +12.340000 12.34 12.340000 +-12.340000 -12.34 -12.340000 +2.000000 +0.909297 diff --git a/lib/tinycc/tests/tests2/23_type_coercion.c b/lib/tinycc/tests/tests2/23_type_coercion.c new file mode 100644 index 000000000..1fcc33519 --- /dev/null +++ b/lib/tinycc/tests/tests2/23_type_coercion.c @@ -0,0 +1,54 @@ +#include + +void charfunc(char a) +{ + printf("char: %c\n", a); +} + +void intfunc(int a) +{ + printf("int: %d\n", a); +} + +void floatfunc(float a) +{ + printf("float: %f\n", a); +} + +int main() +{ + charfunc('a'); + charfunc(98); + charfunc(99.0); + + intfunc('a'); + intfunc(98); + intfunc(99.0); + + floatfunc('a'); + floatfunc(98); + floatfunc(99.0); + + /* printf("%c %d %f\n", 'a', 'b', 'c'); */ + /* printf("%c %d %f\n", 97, 98, 99); */ + /* printf("%c %d %f\n", 97.0, 98.0, 99.0); */ + + char b = 97; + char c = 97.0; + + printf("%d %d\n", b, c); + + int d = 'a'; + int e = 97.0; + + printf("%d %d\n", d, e); + + float f = 'a'; + float g = 97; + + printf("%f %f\n", f, g); + + return 0; +} + +/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/ diff --git a/lib/tinycc/tests/tests2/23_type_coercion.expect b/lib/tinycc/tests/tests2/23_type_coercion.expect new file mode 100644 index 000000000..d9076f018 --- /dev/null +++ b/lib/tinycc/tests/tests2/23_type_coercion.expect @@ -0,0 +1,12 @@ +char: a +char: b +char: c +int: 97 +int: 98 +int: 99 +float: 97.000000 +float: 98.000000 +float: 99.000000 +97 97 +97 97 +97.000000 97.000000 diff --git a/lib/tinycc/tests/tests2/24_math_library.c b/lib/tinycc/tests/tests2/24_math_library.c new file mode 100644 index 000000000..514a25f63 --- /dev/null +++ b/lib/tinycc/tests/tests2/24_math_library.c @@ -0,0 +1,30 @@ +#define _ISOC99_SOURCE 1 + +#include +#include + +int main() +{ + printf("%f\n", sin(0.12)); + printf("%f\n", cos(0.12)); + printf("%f\n", tan(0.12)); + printf("%f\n", asin(0.12)); + printf("%f\n", acos(0.12)); + printf("%f\n", atan(0.12)); + printf("%f\n", sinh(0.12)); + printf("%f\n", cosh(0.12)); + printf("%f\n", tanh(0.12)); + printf("%f\n", exp(0.12)); + printf("%f\n", fabs(-0.12)); + printf("%f\n", log(0.12)); + printf("%f\n", log10(0.12)); + printf("%f\n", pow(0.12, 0.12)); + printf("%f\n", sqrt(0.12)); + printf("%f\n", round(12.34)); + printf("%f\n", ceil(12.34)); + printf("%f\n", floor(12.34)); + + return 0; +} + +/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/ diff --git a/lib/tinycc/tests/tests2/24_math_library.expect b/lib/tinycc/tests/tests2/24_math_library.expect new file mode 100644 index 000000000..99f7299cc --- /dev/null +++ b/lib/tinycc/tests/tests2/24_math_library.expect @@ -0,0 +1,18 @@ +0.119712 +0.992809 +0.120579 +0.120290 +1.450506 +0.119429 +0.120288 +1.007209 +0.119427 +1.127497 +0.120000 +-2.120264 +-0.920819 +0.775357 +0.346410 +12.000000 +13.000000 +12.000000 diff --git a/lib/tinycc/tests/tests2/25_quicksort.c b/lib/tinycc/tests/tests2/25_quicksort.c new file mode 100644 index 000000000..5cc08bd9d --- /dev/null +++ b/lib/tinycc/tests/tests2/25_quicksort.c @@ -0,0 +1,83 @@ +#include + +int array[16]; + +//Swap integer values by array indexes +void swap(int a, int b) +{ + int tmp = array[a]; + array[a] = array[b]; + array[b] = tmp; +} + +//Partition the array into two halves and return the +//index about which the array is partitioned +int partition(int left, int right) +{ + int pivotIndex = left; + int pivotValue = array[pivotIndex]; + int index = left; + int i; + + swap(pivotIndex, right); + for(i = left; i < right; i++) + { + if(array[i] < pivotValue) + { + swap(i, index); + index += 1; + } + } + swap(right, index); + + return index; +} + +//Quicksort the array +void quicksort(int left, int right) +{ + if(left >= right) + return; + + int index = partition(left, right); + quicksort(left, index - 1); + quicksort(index + 1, right); +} + +int main() +{ + int i; + + array[0] = 62; + array[1] = 83; + array[2] = 4; + array[3] = 89; + array[4] = 36; + array[5] = 21; + array[6] = 74; + array[7] = 37; + array[8] = 65; + array[9] = 33; + array[10] = 96; + array[11] = 38; + array[12] = 53; + array[13] = 16; + array[14] = 74; + array[15] = 55; + + for (i = 0; i < 16; i++) + printf("%d ", array[i]); + + printf("\n"); + + quicksort(0, 15); + + for (i = 0; i < 16; i++) + printf("%d ", array[i]); + + printf("\n"); + + return 0; +} + +/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/ diff --git a/lib/tinycc/tests/tests2/25_quicksort.expect b/lib/tinycc/tests/tests2/25_quicksort.expect new file mode 100644 index 000000000..2d39cd327 --- /dev/null +++ b/lib/tinycc/tests/tests2/25_quicksort.expect @@ -0,0 +1,2 @@ +62 83 4 89 36 21 74 37 65 33 96 38 53 16 74 55 +4 16 21 33 36 37 38 53 55 62 65 74 74 83 89 96 diff --git a/lib/tinycc/tests/tests2/26_character_constants.c b/lib/tinycc/tests/tests2/26_character_constants.c new file mode 100644 index 000000000..95c442371 --- /dev/null +++ b/lib/tinycc/tests/tests2/26_character_constants.c @@ -0,0 +1,17 @@ +#include + +int main() +{ + printf("%d\n", '\1'); + printf("%d\n", '\10'); + printf("%d\n", '\100'); + printf("%d\n", '\x01'); + printf("%d\n", '\x0e'); + printf("%d\n", '\x10'); + printf("%d\n", '\x40'); + printf("test \x40\n"); + + return 0; +} + +/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/ diff --git a/lib/tinycc/tests/tests2/26_character_constants.expect b/lib/tinycc/tests/tests2/26_character_constants.expect new file mode 100644 index 000000000..8f8bfa48c --- /dev/null +++ b/lib/tinycc/tests/tests2/26_character_constants.expect @@ -0,0 +1,8 @@ +1 +8 +64 +1 +14 +16 +64 +test @ diff --git a/lib/tinycc/tests/tests2/27_sizeof.c b/lib/tinycc/tests/tests2/27_sizeof.c new file mode 100644 index 000000000..5ae0ede54 --- /dev/null +++ b/lib/tinycc/tests/tests2/27_sizeof.c @@ -0,0 +1,18 @@ +#include + +int main() +{ + char a; + int b; + double c; + + printf("%d\n", sizeof(a)); + printf("%d\n", sizeof(b)); + printf("%d\n", sizeof(c)); + + printf("%d\n", sizeof(!a)); + + return 0; +} + +/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/ diff --git a/lib/tinycc/tests/tests2/27_sizeof.expect b/lib/tinycc/tests/tests2/27_sizeof.expect new file mode 100644 index 000000000..a47ea3a40 --- /dev/null +++ b/lib/tinycc/tests/tests2/27_sizeof.expect @@ -0,0 +1,4 @@ +1 +4 +8 +4 diff --git a/lib/tinycc/tests/tests2/28_strings.c b/lib/tinycc/tests/tests2/28_strings.c new file mode 100644 index 000000000..2db22986e --- /dev/null +++ b/lib/tinycc/tests/tests2/28_strings.c @@ -0,0 +1,45 @@ +#include +#include + +int main() +{ + char a[10]; + + strcpy(a, "hello"); + printf("%s\n", a); + + strncpy(a, "gosh", 2); + printf("%s\n", a); + + printf("%d\n", strcmp(a, "apple") > 0); + printf("%d\n", strcmp(a, "goere") > 0); + printf("%d\n", strcmp(a, "zebra") < 0); + + printf("%d\n", strlen(a)); + + strcat(a, "!"); + printf("%s\n", a); + + printf("%d\n", strncmp(a, "apple", 2) > 0); + printf("%d\n", strncmp(a, "goere", 2) == 0); + printf("%d\n", strncmp(a, "goerg", 2) == 0); + printf("%d\n", strncmp(a, "zebra", 2) < 0); + + printf("%s\n", strchr(a, 'o')); + printf("%s\n", strrchr(a, 'l')); + printf("%d\n", strrchr(a, 'x') == NULL); + + memset(&a[1], 'r', 4); + printf("%s\n", a); + + memcpy(&a[2], a, 2); + printf("%s\n", a); + + printf("%d\n", memcmp(a, "apple", 4) > 0); + printf("%d\n", memcmp(a, "grgr", 4) == 0); + printf("%d\n", memcmp(a, "zebra", 4) < 0); + + return 0; +} + +/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/ diff --git a/lib/tinycc/tests/tests2/28_strings.expect b/lib/tinycc/tests/tests2/28_strings.expect new file mode 100644 index 000000000..fd9217a22 --- /dev/null +++ b/lib/tinycc/tests/tests2/28_strings.expect @@ -0,0 +1,19 @@ +hello +gollo +1 +1 +1 +5 +gollo! +1 +1 +1 +1 +ollo! +lo! +1 +grrrr! +grgrr! +1 +1 +1 diff --git a/lib/tinycc/tests/tests2/29_array_address.c b/lib/tinycc/tests/tests2/29_array_address.c new file mode 100644 index 000000000..bda5ddde2 --- /dev/null +++ b/lib/tinycc/tests/tests2/29_array_address.c @@ -0,0 +1,13 @@ +#include +#include + +int main() +{ + char a[10]; + strcpy(a, "abcdef"); + printf("%s\n", &a[1]); + + return 0; +} + +/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/ diff --git a/lib/tinycc/tests/tests2/29_array_address.expect b/lib/tinycc/tests/tests2/29_array_address.expect new file mode 100644 index 000000000..9bc868324 --- /dev/null +++ b/lib/tinycc/tests/tests2/29_array_address.expect @@ -0,0 +1 @@ +bcdef diff --git a/lib/tinycc/tests/tests2/30_hanoi.c b/lib/tinycc/tests/tests2/30_hanoi.c new file mode 100644 index 000000000..7c0893b1a --- /dev/null +++ b/lib/tinycc/tests/tests2/30_hanoi.c @@ -0,0 +1,122 @@ +/* example from http://barnyard.syr.edu/quickies/hanoi.c */ + +/* hanoi.c: solves the tower of hanoi problem. (Programming exercise.) */ +/* By Terry R. McConnell (12/2/97) */ +/* Compile: cc -o hanoi hanoi.c */ + +/* This program does no error checking. But then, if it's right, + it's right ... right ? */ + + +/* The original towers of hanoi problem seems to have been originally posed + by one M. Claus in 1883. There is a popular legend that goes along with + it that has been often repeated and paraphrased. It goes something like this: + In the great temple at Benares there are 3 golden spikes. On one of them, + God placed 64 disks increasing in size from bottom to top, at the beginning + of time. Since then, and to this day, the priest on duty constantly transfers + disks, one at a time, in such a way that no larger disk is ever put on top + of a smaller one. When the disks have been transferred entirely to another + spike the Universe will come to an end in a large thunderclap. + + This paraphrases the original legend due to DeParville, La Nature, Paris 1884, + Part I, 285-286. For this and further information see: Mathematical + Recreations & Essays, W.W. Rouse Ball, MacMillan, NewYork, 11th Ed. 1967, + 303-305. + * + * + */ + +#include +#include + +#define TRUE 1 +#define FALSE 0 + +/* This is the number of "disks" on tower A initially. Taken to be 64 in the + * legend. The number of moves required, in general, is 2^N - 1. For N = 64, + * this is 18,446,744,073,709,551,615 */ +#define N 4 + +/* These are the three towers. For example if the state of A is 0,1,3,4, that + * means that there are three discs on A of sizes 1, 3, and 4. (Think of right + * as being the "down" direction.) */ +int A[N], B[N], C[N]; + +void Hanoi(int,int*,int*,int*); + +/* Print the current configuration of A, B, and C to the screen */ +void PrintAll() +{ + int i; + + printf("A: "); + for(i=0;i + +int main(int argc, char **argv) +{ + int Count; + + printf("hello world %d\n", argc); + for (Count = 1; Count < argc; Count++) + printf("arg %d: %s\n", Count, argv[Count]); + + return 0; +} + +/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/ diff --git a/lib/tinycc/tests/tests2/31_args.expect b/lib/tinycc/tests/tests2/31_args.expect new file mode 100644 index 000000000..8c60bfc5b --- /dev/null +++ b/lib/tinycc/tests/tests2/31_args.expect @@ -0,0 +1,6 @@ +hello world 6 +arg 1: arg1 +arg 2: arg2 +arg 3: arg3 +arg 4: arg4 +arg 5: arg5 diff --git a/lib/tinycc/tests/tests2/32_led.c b/lib/tinycc/tests/tests2/32_led.c new file mode 100644 index 000000000..5596cbfd3 --- /dev/null +++ b/lib/tinycc/tests/tests2/32_led.c @@ -0,0 +1,266 @@ +/* example from http://barnyard.syr.edu/quickies/led.c */ + +/* led.c: print out number as if on 7 line led display. I.e., write integer + given on command line like this: + _ _ _ + | _| _| |_| |_ + | |_ _| | _| etc. + + We assume the terminal behaves like a classical teletype. So the top + lines of all digits have to be printed first, then the middle lines of + all digits, etc. + + By Terry R. McConnell + +compile: cc -o led led.c + +If you just want to link in the subroutine print_led that does all the +work, compile with -DNO_MAIN, and declare the following in any source file +that uses the call: + +extern void print_led(unsigned long x, char *buf); + +Bug: you cannot call repeatedly to print more than one number to a line. +That would require curses or some other terminal API that allows moving the +cursor to a previous line. + +*/ + + + +#include +#include + +#define MAX_DIGITS 32 +#define NO_MAIN + + +/* Print the top line of the digit d into buffer. + Does not null terminate buffer. */ + +void topline(int d, char *p){ + + *p++ = ' '; + switch(d){ + + /* all these have _ on top line */ + + case 0: + case 2: + case 3: + case 5: + case 7: + case 8: + case 9: + *p++ = '_'; + break; + default: + *p++=' '; + + } + *p++=' '; +} + +/* Print the middle line of the digit d into the buffer. + Does not null terminate. */ + +void midline(int d, char *p){ + + switch(d){ + + /* those that have leading | on middle line */ + + case 0: + case 4: + case 5: + case 6: + case 8: + case 9: + *p++='|'; + break; + default: + *p++=' '; + } + switch(d){ + + /* those that have _ on middle line */ + + case 2: + case 3: + case 4: + case 5: + case 6: + case 8: + case 9: + *p++='_'; + break; + default: + *p++=' '; + + } + switch(d){ + + /* those that have closing | on middle line */ + + case 0: + case 1: + case 2: + case 3: + case 4: + case 7: + case 8: + case 9: + *p++='|'; + break; + default: + *p++=' '; + + } +} + +/* Print the bottom line of the digit d. Does not null terminate. */ + +void botline(int d, char *p){ + + + switch(d){ + + /* those that have leading | on bottom line */ + + case 0: + case 2: + case 6: + case 8: + *p++='|'; + break; + default: + *p++=' '; + } + switch(d){ + + /* those that have _ on bottom line */ + + case 0: + case 2: + case 3: + case 5: + case 6: + case 8: + *p++='_'; + break; + default: + *p++=' '; + + } + switch(d){ + + /* those that have closing | on bottom line */ + + case 0: + case 1: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + *p++='|'; + break; + default: + *p++=' '; + + } +} + +/* Write the led representation of integer to string buffer. */ + +void print_led(unsigned long x, char *buf) +{ + + int i=0,n; + static int d[MAX_DIGITS]; + + + /* extract digits from x */ + + n = ( x == 0L ? 1 : 0 ); /* 0 is a digit, hence a special case */ + + while(x){ + d[n++] = (int)(x%10L); + if(n >= MAX_DIGITS)break; + x = x/10L; + } + + /* print top lines of all digits */ + + for(i=n-1;i>=0;i--){ + topline(d[i],buf); + buf += 3; + *buf++=' '; + } + *buf++='\n'; /* move teletype to next line */ + + /* print middle lines of all digits */ + + for(i=n-1;i>=0;i--){ + midline(d[i],buf); + buf += 3; + *buf++=' '; + } + *buf++='\n'; + + /* print bottom lines of all digits */ + + for(i=n-1;i>=0;i--){ + botline(d[i],buf); + buf += 3; + *buf++=' '; + } + *buf++='\n'; + *buf='\0'; +} + +int main() +{ + char buf[5*MAX_DIGITS]; + print_led(1234567, buf); + printf("%s\n",buf); + + return 0; +} + +#ifndef NO_MAIN +int main(int argc, char **argv) +{ + + int i=0,n; + long x; + static int d[MAX_DIGITS]; + char buf[5*MAX_DIGITS]; + + if(argc != 2){ + fprintf(stderr,"led: usage: led integer\n"); + return 1; + } + + /* fetch argument from command line */ + + x = atol(argv[1]); + + /* sanity check */ + + if(x<0){ + fprintf(stderr,"led: %d must be non-negative\n",x); + return 1; + } + + print_led(x,buf); + printf("%s\n",buf); + + return 0; + +} +#endif + +/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/ diff --git a/lib/tinycc/tests/tests2/32_led.expect b/lib/tinycc/tests/tests2/32_led.expect new file mode 100644 index 000000000..c53b58ae0 --- /dev/null +++ b/lib/tinycc/tests/tests2/32_led.expect @@ -0,0 +1,4 @@ + _ _ _ _ + | _| _| |_| |_ |_ | + | |_ _| | _| |_| | + diff --git a/lib/tinycc/tests/tests2/33_ternary_op.c b/lib/tinycc/tests/tests2/33_ternary_op.c new file mode 100644 index 000000000..8305438c4 --- /dev/null +++ b/lib/tinycc/tests/tests2/33_ternary_op.c @@ -0,0 +1,119 @@ +#include +extern int printf(const char*, ...); + +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); + + /* The following line causes a warning */ + void *xx = fp?f:1; +} + +struct condstruct { + int i; +}; + +static int getme(struct condstruct* s, int i) +{ + int i1 = (i != 0 ? 0 : s)->i; + int i2 = (i == 0 ? s : 0)->i; + int i3 = (i != 0 ? (void*)0 : s)->i; + int i4 = (i == 0 ? s : (void*)0)->i; + return i1 + i2 + i3 + i4; +} + +int someglobal; + +void constantcond(void) +{ + /* This was broken by 8227db3a2, it saved/restored the CODE_OFF state + during the expression and that bled out to the outer one disabling + codegen for if-body. */ + if (( (someglobal ? 0 : 0) ? 8 : 9)) + printf("okay\n"); +} + +unsigned short tf_4_var_2 = 29886; +const unsigned short tf_4_var_34 = 54077; +const unsigned short tf_4_var_86 = 1129; +long int tf_4_var_98 = -4448775496354969734L; + +unsigned short tf_4_array_8 [9] = + {52593, 34626, 28127, 8124, 11473, 14634, 8370, 31153, 31060}; +unsigned short tf_4_array_2 [6] = + {7493, 64504, 22566, 54931, 44752, 18026}; +unsigned short tf_4_array_3 [9] = + {22671, 46595, 24007, 22460, 12020, 19732, 46148, 3906, 26139}; +unsigned short tf_4_array_7 [9] = + {24530, 26236, 61122, 9019, 26099, 31028, 1078, 27042, 36756}; +unsigned short tf_4_array_4 [9] = + {32711, 2853, 55531, 52731, 6621, 38797, 23543, 64627, 55640}; + +long int tf_4_var_132 = -6396431410421938408L; + +static void tst_yarpgen(void) +{ + /* generated by yarpgen */ + tf_4_var_132 = (long int) (((unsigned long long int) (((((((int) (tf_4_var_86)) && ((int) (tf_4_array_8 [0]))) ? (((int) (tf_4_var_2)) || ((int) (8))) : (((int) (tf_4_array_2 [0])) || (-4096)))) || ((((int) (tf_4_array_3 [6])) || ((int) (tf_4_var_34))) && (((int) (tf_4_array_3 [7])) || ((int) (tf_4_var_98))))) % ((+((int) ((unsigned short) (-6)))) && ((((int) (tf_4_array_7 [5])) & ((int) (tf_4_array_7 [1]))) | (((int) (tf_4_array_4 [0])) & ((int) (tf_4_array_4 [0]))))))) <= (((unsigned long long int) ((int) ((unsigned short) (((7192886880476152731ULL) * (7192886880476152731ULL)) * ((unsigned long long int) (((-9223372036854775807L - 1L)) * ((long int) ((int) (0))))))))) * (((unsigned long long int) (((-6) * ((int) (3))) * (-((int) (4))))) * (((8ULL) * (4ULL)) * ((unsigned long long int) (((long int) (-6)) * (-3L))))))); + printf("%ld\n", tf_4_var_132); +} + +int main() +{ + int Count; + + for (Count = 0; Count < 10; Count++) + { + 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'}; + static const struct stru2 { int x; } d = { 'D' }; + 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); + ASSERT(sizeof(int) == sizeof(0 ? 'a' : c)); + ASSERT(sizeof(double) == sizeof(0 ? 'a' : 1.0)); + ASSERT(sizeof(double) == sizeof(0 ? 0.0 : 'a')); + ASSERT(sizeof(float) == sizeof(0 ? 'a' : 1.0f)); + ASSERT(sizeof(double) == sizeof(0 ? 0.0 : 1.0f)); + struct condstruct cs = { 38 }; + printf("%d\n", getme(&cs, 0)); + + // the following lines contain type mismatch errors in every ternary expression + //printf("comparing double with pointer : size = %d\n", sizeof(0 ? &c : 0.0)); + //printf("'%c' <> '%c'\n", (0 ? a : d).x, (1 ? a : d).x); + //0 ? a : 0.0; + } + + constantcond(); + + tst_yarpgen(); + + return 0; +} + +/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/ diff --git a/lib/tinycc/tests/tests2/33_ternary_op.expect b/lib/tinycc/tests/tests2/33_ternary_op.expect new file mode 100644 index 000000000..c21f5fbb8 --- /dev/null +++ b/lib/tinycc/tests/tests2/33_ternary_op.expect @@ -0,0 +1,14 @@ +33_ternary_op.c:26: warning: pointer/integer mismatch in conditional expression +0 +1 +4 +9 +16 +15 +18 +21 +24 +27 +152 +okay +1 diff --git a/lib/tinycc/tests/tests2/34_array_assignment.c b/lib/tinycc/tests/tests2/34_array_assignment.c new file mode 100644 index 000000000..5885c9732 --- /dev/null +++ b/lib/tinycc/tests/tests2/34_array_assignment.c @@ -0,0 +1,23 @@ +#include + +int main() +{ + int a[4]; + + a[0] = 12; + a[1] = 23; + a[2] = 34; + a[3] = 45; + + printf("%d %d %d %d\n", a[0], a[1], a[2], a[3]); + + int b[4]; + + b = a; + + printf("%d %d %d %d\n", b[0], b[1], b[2], b[3]); + + return 0; +} + +/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/ diff --git a/lib/tinycc/tests/tests2/34_array_assignment.expect b/lib/tinycc/tests/tests2/34_array_assignment.expect new file mode 100644 index 000000000..9736bf508 --- /dev/null +++ b/lib/tinycc/tests/tests2/34_array_assignment.expect @@ -0,0 +1,2 @@ +12 23 34 45 +12 23 34 45 diff --git a/lib/tinycc/tests/tests2/35_sizeof.c b/lib/tinycc/tests/tests2/35_sizeof.c new file mode 100644 index 000000000..672e87e7f --- /dev/null +++ b/lib/tinycc/tests/tests2/35_sizeof.c @@ -0,0 +1,14 @@ +#include + +int main() +{ + char a; + short b; + + printf("%d %d\n", sizeof(char), sizeof(a)); + printf("%d %d\n", sizeof(short), sizeof(b)); + + return 0; +} + +/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/ diff --git a/lib/tinycc/tests/tests2/35_sizeof.expect b/lib/tinycc/tests/tests2/35_sizeof.expect new file mode 100644 index 000000000..534fb831b --- /dev/null +++ b/lib/tinycc/tests/tests2/35_sizeof.expect @@ -0,0 +1,2 @@ +1 1 +2 2 diff --git a/lib/tinycc/tests/tests2/36_array_initialisers.c b/lib/tinycc/tests/tests2/36_array_initialisers.c new file mode 100644 index 000000000..ac56f5ad9 --- /dev/null +++ b/lib/tinycc/tests/tests2/36_array_initialisers.c @@ -0,0 +1,25 @@ +#include + +extern int Array3[10]; +int Array3[] = { 12, 34, }; +int main() +{ + int Count; + + int Array[10] = { 12, 34, 56, 78, 90, 123, 456, 789, 8642, 9753 }; + + for (Count = 0; Count < 10; Count++) + printf("%d: %d\n", Count, Array[Count]); + + int Array2[10] = { 12, 34, 56, 78, 90, 123, 456, 789, 8642, 9753, }; + + for (Count = 0; Count < 10; Count++) + printf("%d: %d\n", Count, Array2[Count]); + + for (Count = 0; Count < 10; Count++) + printf("%d: %d\n", Count, Array3[Count]); + + return 0; +} + +/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/ diff --git a/lib/tinycc/tests/tests2/36_array_initialisers.expect b/lib/tinycc/tests/tests2/36_array_initialisers.expect new file mode 100644 index 000000000..4bb5ab7c0 --- /dev/null +++ b/lib/tinycc/tests/tests2/36_array_initialisers.expect @@ -0,0 +1,30 @@ +0: 12 +1: 34 +2: 56 +3: 78 +4: 90 +5: 123 +6: 456 +7: 789 +8: 8642 +9: 9753 +0: 12 +1: 34 +2: 56 +3: 78 +4: 90 +5: 123 +6: 456 +7: 789 +8: 8642 +9: 9753 +0: 12 +1: 34 +2: 0 +3: 0 +4: 0 +5: 0 +6: 0 +7: 0 +8: 0 +9: 0 diff --git a/lib/tinycc/tests/tests2/37_sprintf.c b/lib/tinycc/tests/tests2/37_sprintf.c new file mode 100644 index 000000000..1dd1dce28 --- /dev/null +++ b/lib/tinycc/tests/tests2/37_sprintf.c @@ -0,0 +1,17 @@ +#include + +int main() +{ + char Buf[100]; + int Count; + + for (Count = 1; Count <= 20; Count++) + { + sprintf(Buf, "->%02d<-\n", Count); + printf("%s", Buf); + } + + return 0; +} + +/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/ diff --git a/lib/tinycc/tests/tests2/37_sprintf.expect b/lib/tinycc/tests/tests2/37_sprintf.expect new file mode 100644 index 000000000..a643da842 --- /dev/null +++ b/lib/tinycc/tests/tests2/37_sprintf.expect @@ -0,0 +1,20 @@ +->01<- +->02<- +->03<- +->04<- +->05<- +->06<- +->07<- +->08<- +->09<- +->10<- +->11<- +->12<- +->13<- +->14<- +->15<- +->16<- +->17<- +->18<- +->19<- +->20<- diff --git a/lib/tinycc/tests/tests2/38_multiple_array_index.c b/lib/tinycc/tests/tests2/38_multiple_array_index.c new file mode 100644 index 000000000..4e1868efe --- /dev/null +++ b/lib/tinycc/tests/tests2/38_multiple_array_index.c @@ -0,0 +1,32 @@ +#include + +int main() +{ + int a[4][4]; + int b = 0; + int x; + int y; + + for (x = 0; x < 4; x++) + { + for (y = 0; y < 4; y++) + { + b++; + a[x][y] = b; + } + } + + for (x = 0; x < 4; x++) + { + printf("x=%d: ", x); + for (y = 0; y < 4; y++) + { + printf("%d ", a[x][y]); + } + printf("\n"); + } + + return 0; +} + +/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/ diff --git a/lib/tinycc/tests/tests2/38_multiple_array_index.expect b/lib/tinycc/tests/tests2/38_multiple_array_index.expect new file mode 100644 index 000000000..747ad751d --- /dev/null +++ b/lib/tinycc/tests/tests2/38_multiple_array_index.expect @@ -0,0 +1,4 @@ +x=0: 1 2 3 4 +x=1: 5 6 7 8 +x=2: 9 10 11 12 +x=3: 13 14 15 16 diff --git a/lib/tinycc/tests/tests2/39_typedef.c b/lib/tinycc/tests/tests2/39_typedef.c new file mode 100644 index 000000000..da73f71e6 --- /dev/null +++ b/lib/tinycc/tests/tests2/39_typedef.c @@ -0,0 +1,65 @@ +#include + +typedef int MyInt; + +struct FunStruct +{ + int i; + int j; +}; + +typedef struct FunStruct MyFunStruct; + +typedef MyFunStruct *MoreFunThanEver; + +int main() +{ + MyInt a = 1; + printf("%d\n", a); + + MyFunStruct b; + b.i = 12; + b.j = 34; + printf("%d,%d\n", b.i, b.j); + + MoreFunThanEver c = &b; + printf("%d,%d\n", c->i, c->j); + + return 0; +} + +/* "If the specification of an array type includes any type qualifiers, + the element type is so-qualified, not the array type." */ + +typedef int A[3]; +extern A const ca; +extern const A ca; +extern const int ca[3]; + +typedef A B[1][2]; +extern B const cb; +extern const B cb; +extern const int cb[1][2][3]; + +extern B b; +extern int b[1][2][3]; + +/* Funny but valid function declaration. */ +typedef int functype (int); +extern functype func; +int func(int i) +{ + return i + 1; +} + +/* Even funnier function decl and definition using typeof. */ +int set_anon_super(void); +int set_anon_super(void) +{ + return 42; +} +typedef int sas_type (void); +extern typeof(set_anon_super) set_anon_super; +extern sas_type set_anon_super; + +/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/ diff --git a/lib/tinycc/tests/tests2/39_typedef.expect b/lib/tinycc/tests/tests2/39_typedef.expect new file mode 100644 index 000000000..b9050a9b6 --- /dev/null +++ b/lib/tinycc/tests/tests2/39_typedef.expect @@ -0,0 +1,3 @@ +1 +12,34 +12,34 diff --git a/lib/tinycc/tests/tests2/40_stdio.c b/lib/tinycc/tests/tests2/40_stdio.c new file mode 100644 index 000000000..b98609302 --- /dev/null +++ b/lib/tinycc/tests/tests2/40_stdio.c @@ -0,0 +1,52 @@ +#include + +int main() +{ + FILE *f = fopen("fred.txt", "w"); + fwrite("hello\nhello\n", 1, 12, f); + fclose(f); + + char freddy[7]; + f = fopen("fred.txt", "r"); + if (fread(freddy, 1, 6, f) != 6) + printf("couldn't read fred.txt\n"); + + freddy[6] = '\0'; + fclose(f); + + printf("%s", freddy); + + int InChar; + char ShowChar; + f = fopen("fred.txt", "r"); + while ( (InChar = fgetc(f)) != EOF) + { + ShowChar = InChar; + if (ShowChar < ' ') + ShowChar = '.'; + + printf("ch: %d '%c'\n", InChar, ShowChar); + } + fclose(f); + + f = fopen("fred.txt", "r"); + while ( (InChar = getc(f)) != EOF) + { + ShowChar = InChar; + if (ShowChar < ' ') + ShowChar = '.'; + + printf("ch: %d '%c'\n", InChar, ShowChar); + } + fclose(f); + + f = fopen("fred.txt", "r"); + while (fgets(freddy, sizeof(freddy), f) != NULL) + printf("x: %s", freddy); + + fclose(f); + + return 0; +} + +/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/ diff --git a/lib/tinycc/tests/tests2/40_stdio.expect b/lib/tinycc/tests/tests2/40_stdio.expect new file mode 100644 index 000000000..e08167a6e --- /dev/null +++ b/lib/tinycc/tests/tests2/40_stdio.expect @@ -0,0 +1,27 @@ +hello +ch: 104 'h' +ch: 101 'e' +ch: 108 'l' +ch: 108 'l' +ch: 111 'o' +ch: 10 '.' +ch: 104 'h' +ch: 101 'e' +ch: 108 'l' +ch: 108 'l' +ch: 111 'o' +ch: 10 '.' +ch: 104 'h' +ch: 101 'e' +ch: 108 'l' +ch: 108 'l' +ch: 111 'o' +ch: 10 '.' +ch: 104 'h' +ch: 101 'e' +ch: 108 'l' +ch: 108 'l' +ch: 111 'o' +ch: 10 '.' +x: hello +x: hello diff --git a/lib/tinycc/tests/tests2/41_hashif.c b/lib/tinycc/tests/tests2/41_hashif.c new file mode 100644 index 000000000..cb37b9eb0 --- /dev/null +++ b/lib/tinycc/tests/tests2/41_hashif.c @@ -0,0 +1,85 @@ +#include + +int main() +{ + printf("#include test\n"); + +#if 1 +#if 0 + printf("a\n"); +#else + printf("b\n"); +#endif +#else +#if 0 + printf("c\n"); +#else + printf("d\n"); +#endif +#endif + +#if 0 +#if 1 + printf("e\n"); +#else + printf("f\n"); +#endif +#else +#if 1 + printf("g\n"); +#else + printf("h\n"); +#endif +#endif + +#define DEF + +#ifdef DEF +#ifdef DEF + printf("i\n"); +#else + printf("j\n"); +#endif +#else +#ifdef DEF + printf("k\n"); +#else + printf("l\n"); +#endif +#endif + +#ifndef DEF +#ifndef DEF + printf("m\n"); +#else + printf("n\n"); +#endif +#else +#ifndef DEF + printf("o\n"); +#else + printf("p\n"); +#endif +#endif + +#define ONE 1 +#define ZERO 0 + +#if ONE +#if ZERO + printf("q\n"); +#else + printf("r\n"); +#endif +#else +#if ZERO + printf("s\n"); +#else + printf("t\n"); +#endif +#endif + + return 0; +} + +/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/ diff --git a/lib/tinycc/tests/tests2/41_hashif.expect b/lib/tinycc/tests/tests2/41_hashif.expect new file mode 100644 index 000000000..5fd414bd0 --- /dev/null +++ b/lib/tinycc/tests/tests2/41_hashif.expect @@ -0,0 +1,6 @@ +#include test +b +g +i +p +r diff --git a/lib/tinycc/tests/tests2/42_function_pointer.c b/lib/tinycc/tests/tests2/42_function_pointer.c new file mode 100644 index 000000000..697bd79a6 --- /dev/null +++ b/lib/tinycc/tests/tests2/42_function_pointer.c @@ -0,0 +1,22 @@ +#include + +int fred(int p) +{ + printf("yo %d\n", p); + return 42; +} + +int (*f)(int) = &fred; + +/* To test what this is supposed to test the destination function + (fprint here) must not be called directly anywhere in the test. */ +int (*fprintfptr)(FILE *, const char *, ...) = &fprintf; + +int main() +{ + fprintfptr(stdout, "%d\n", (*f)(24)); + + return 0; +} + +/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/ diff --git a/lib/tinycc/tests/tests2/42_function_pointer.expect b/lib/tinycc/tests/tests2/42_function_pointer.expect new file mode 100644 index 000000000..6c8b6ce45 --- /dev/null +++ b/lib/tinycc/tests/tests2/42_function_pointer.expect @@ -0,0 +1,2 @@ +yo 24 +42 diff --git a/lib/tinycc/tests/tests2/43_void_param.c b/lib/tinycc/tests/tests2/43_void_param.c new file mode 100644 index 000000000..de17098b2 --- /dev/null +++ b/lib/tinycc/tests/tests2/43_void_param.c @@ -0,0 +1,15 @@ +#include + +void fred(void) +{ + printf("yo\n"); +} + +int main() +{ + fred(); + + return 0; +} + +/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/ diff --git a/lib/tinycc/tests/tests2/43_void_param.expect b/lib/tinycc/tests/tests2/43_void_param.expect new file mode 100644 index 000000000..092bfb9bd --- /dev/null +++ b/lib/tinycc/tests/tests2/43_void_param.expect @@ -0,0 +1 @@ +yo diff --git a/lib/tinycc/tests/tests2/44_scoped_declarations.c b/lib/tinycc/tests/tests2/44_scoped_declarations.c new file mode 100644 index 000000000..f38664fc5 --- /dev/null +++ b/lib/tinycc/tests/tests2/44_scoped_declarations.c @@ -0,0 +1,17 @@ +#include + +int main() +{ + int a; + + for (a = 0; a < 2; a++) + { + int b = a; + } + + printf("it's all good\n"); + + return 0; +} + +/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/ diff --git a/lib/tinycc/tests/tests2/44_scoped_declarations.expect b/lib/tinycc/tests/tests2/44_scoped_declarations.expect new file mode 100644 index 000000000..231ccc0c5 --- /dev/null +++ b/lib/tinycc/tests/tests2/44_scoped_declarations.expect @@ -0,0 +1 @@ +it's all good diff --git a/lib/tinycc/tests/tests2/45_empty_for.c b/lib/tinycc/tests/tests2/45_empty_for.c new file mode 100644 index 000000000..7cef513f8 --- /dev/null +++ b/lib/tinycc/tests/tests2/45_empty_for.c @@ -0,0 +1,18 @@ +#include + +int main() +{ + int Count = 0; + + for (;;) + { + Count++; + printf("%d\n", Count); + if (Count >= 10) + break; + } + + return 0; +} + +/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/ diff --git a/lib/tinycc/tests/tests2/45_empty_for.expect b/lib/tinycc/tests/tests2/45_empty_for.expect new file mode 100644 index 000000000..f00c965d8 --- /dev/null +++ b/lib/tinycc/tests/tests2/45_empty_for.expect @@ -0,0 +1,10 @@ +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 diff --git a/lib/tinycc/tests/tests2/46_grep.c b/lib/tinycc/tests/tests2/46_grep.c new file mode 100644 index 000000000..acda79307 --- /dev/null +++ b/lib/tinycc/tests/tests2/46_grep.c @@ -0,0 +1,570 @@ +/* + * 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 +#include +#include // 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 */ + } + if (e = pmatch(l, p)) + return(e); + 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 :*/ diff --git a/lib/tinycc/tests/tests2/46_grep.expect b/lib/tinycc/tests/tests2/46_grep.expect new file mode 100644 index 000000000..e8a67916b --- /dev/null +++ b/lib/tinycc/tests/tests2/46_grep.expect @@ -0,0 +1,3 @@ +File 46_grep.c: +/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/ + diff --git a/lib/tinycc/tests/tests2/47_switch_return.c b/lib/tinycc/tests/tests2/47_switch_return.c new file mode 100644 index 000000000..1ec7924c4 --- /dev/null +++ b/lib/tinycc/tests/tests2/47_switch_return.c @@ -0,0 +1,24 @@ +#include + +void fred(int x) +{ + switch (x) + { + case 1: printf("1\n"); return; + case 2: printf("2\n"); break; + case 3: printf("3\n"); return; + } + + printf("out\n"); +} + +int main() +{ + fred(1); + fred(2); + fred(3); + + return 0; +} + +/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/ diff --git a/lib/tinycc/tests/tests2/47_switch_return.expect b/lib/tinycc/tests/tests2/47_switch_return.expect new file mode 100644 index 000000000..b6deb7e9e --- /dev/null +++ b/lib/tinycc/tests/tests2/47_switch_return.expect @@ -0,0 +1,4 @@ +1 +2 +out +3 diff --git a/lib/tinycc/tests/tests2/48_nested_break.c b/lib/tinycc/tests/tests2/48_nested_break.c new file mode 100644 index 000000000..5bc5ba47f --- /dev/null +++ b/lib/tinycc/tests/tests2/48_nested_break.c @@ -0,0 +1,26 @@ +#include + +int main() +{ + int a; + char b; + + a = 0; + while (a < 2) + { + printf("%d", a++); + break; + + b = 'A'; + while (b < 'C') + { + printf("%c", b++); + } + printf("e"); + } + printf("\n"); + + return 0; +} + +/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/ diff --git a/lib/tinycc/tests/tests2/48_nested_break.expect b/lib/tinycc/tests/tests2/48_nested_break.expect new file mode 100644 index 000000000..573541ac9 --- /dev/null +++ b/lib/tinycc/tests/tests2/48_nested_break.expect @@ -0,0 +1 @@ +0 diff --git a/lib/tinycc/tests/tests2/49_bracket_evaluation.c b/lib/tinycc/tests/tests2/49_bracket_evaluation.c new file mode 100644 index 000000000..0cbe57d62 --- /dev/null +++ b/lib/tinycc/tests/tests2/49_bracket_evaluation.c @@ -0,0 +1,23 @@ +#include + +struct point +{ + double x; + double y; +}; + +struct point point_array[100]; + +int main() +{ + int my_point = 10; + + point_array[my_point].x = 12.34; + point_array[my_point].y = 56.78; + + printf("%f, %f\n", point_array[my_point].x, point_array[my_point].y); + + return 0; +} + +/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/ diff --git a/lib/tinycc/tests/tests2/49_bracket_evaluation.expect b/lib/tinycc/tests/tests2/49_bracket_evaluation.expect new file mode 100644 index 000000000..1da66dbeb --- /dev/null +++ b/lib/tinycc/tests/tests2/49_bracket_evaluation.expect @@ -0,0 +1 @@ +12.340000, 56.780000 diff --git a/lib/tinycc/tests/tests2/50_logical_second_arg.c b/lib/tinycc/tests/tests2/50_logical_second_arg.c new file mode 100644 index 000000000..ddec08c87 --- /dev/null +++ b/lib/tinycc/tests/tests2/50_logical_second_arg.c @@ -0,0 +1,29 @@ +#include + +int fred() +{ + printf("fred\n"); + return 0; +} + +int joe() +{ + printf("joe\n"); + return 1; +} + +int main() +{ + printf("%d\n", fred() && joe()); + printf("%d\n", fred() || joe()); + printf("%d\n", joe() && fred()); + printf("%d\n", joe() || fred()); + printf("%d\n", fred() && (1 + joe())); + printf("%d\n", fred() || (0 + joe())); + printf("%d\n", joe() && (0 + fred())); + printf("%d\n", joe() || (1 + fred())); + + return 0; +} + +/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/ diff --git a/lib/tinycc/tests/tests2/50_logical_second_arg.expect b/lib/tinycc/tests/tests2/50_logical_second_arg.expect new file mode 100644 index 000000000..d6174ae7d --- /dev/null +++ b/lib/tinycc/tests/tests2/50_logical_second_arg.expect @@ -0,0 +1,20 @@ +fred +0 +fred +joe +1 +joe +fred +0 +joe +1 +fred +0 +fred +joe +1 +joe +fred +0 +joe +1 diff --git a/lib/tinycc/tests/tests2/51_static.c b/lib/tinycc/tests/tests2/51_static.c new file mode 100644 index 000000000..d6c0917cf --- /dev/null +++ b/lib/tinycc/tests/tests2/51_static.c @@ -0,0 +1,30 @@ +#include + +static int fred = 1234; +static int joe; + +void henry() +{ + static int fred = 4567; + + printf("%d\n", fred); + fred++; +} + +int main() +{ + printf("%d\n", fred); + henry(); + henry(); + henry(); + henry(); + printf("%d\n", fred); + fred = 8901; + joe = 2345; + printf("%d\n", fred); + printf("%d\n", joe); + + return 0; +} + +/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/ diff --git a/lib/tinycc/tests/tests2/51_static.expect b/lib/tinycc/tests/tests2/51_static.expect new file mode 100644 index 000000000..18224fa3e --- /dev/null +++ b/lib/tinycc/tests/tests2/51_static.expect @@ -0,0 +1,8 @@ +1234 +4567 +4568 +4569 +4570 +1234 +8901 +2345 diff --git a/lib/tinycc/tests/tests2/52_unnamed_enum.c b/lib/tinycc/tests/tests2/52_unnamed_enum.c new file mode 100644 index 000000000..d0395b202 --- /dev/null +++ b/lib/tinycc/tests/tests2/52_unnamed_enum.c @@ -0,0 +1,27 @@ +#include + +enum fred { a, b, c }; + +int main() +{ + printf("a=%d\n", a); + printf("b=%d\n", b); + printf("c=%d\n", c); + + enum fred d; + + typedef enum { e, f, g } h; + typedef enum { i, j, k } m; + + printf("e=%d\n", e); + printf("f=%d\n", f); + printf("g=%d\n", g); + + printf("i=%d\n", i); + printf("j=%d\n", j); + printf("k=%d\n", k); + + return 0; +} + +/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/ diff --git a/lib/tinycc/tests/tests2/52_unnamed_enum.expect b/lib/tinycc/tests/tests2/52_unnamed_enum.expect new file mode 100644 index 000000000..84f2ac846 --- /dev/null +++ b/lib/tinycc/tests/tests2/52_unnamed_enum.expect @@ -0,0 +1,9 @@ +a=0 +b=1 +c=2 +e=0 +f=1 +g=2 +i=0 +j=1 +k=2 diff --git a/lib/tinycc/tests/tests2/54_goto.c b/lib/tinycc/tests/tests2/54_goto.c new file mode 100644 index 000000000..2e151bb76 --- /dev/null +++ b/lib/tinycc/tests/tests2/54_goto.c @@ -0,0 +1,56 @@ +#include + +void fred() +{ + printf("In fred()\n"); + goto done; + printf("In middle\n"); +done: + printf("At end\n"); +} + +void joe() +{ + int b = 5678; + + printf("In joe()\n"); + + { + int c = 1234; + printf("c = %d\n", c); + goto outer; + printf("uh-oh\n"); + } + +outer: + + printf("done\n"); +} + +void henry() +{ + int a; + + printf("In henry()\n"); + goto inner; + + { + int b; +inner: + b = 1234; + printf("b = %d\n", b); + } + + printf("done\n"); +} + +int main() +{ + fred(); + joe(); + henry(); + + return 0; +} + +/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/ diff --git a/lib/tinycc/tests/tests2/54_goto.expect b/lib/tinycc/tests/tests2/54_goto.expect new file mode 100644 index 000000000..8e553fa62 --- /dev/null +++ b/lib/tinycc/tests/tests2/54_goto.expect @@ -0,0 +1,8 @@ +In fred() +At end +In joe() +c = 1234 +done +In henry() +b = 1234 +done diff --git a/lib/tinycc/tests/tests2/55_lshift_type.c b/lib/tinycc/tests/tests2/55_lshift_type.c new file mode 100644 index 000000000..aa3e51a16 --- /dev/null +++ b/lib/tinycc/tests/tests2/55_lshift_type.c @@ -0,0 +1,52 @@ +/* $Id: lshift-type.c 53089 2012-07-06 11:18:26Z vinc17/ypig $ + +Tests on left-shift type, written by Vincent Lefevre . + +ISO C99 TC3 says: [6.5.7#3] "The integer promotions are performed on +each of the operands. The type of the result is that of the promoted +left operand." +*/ + +#include + +#define PTYPE(M) ((M) < 0 || -(M) < 0 ? -1 : 1) * (int) sizeof((M)+0) +#define CHECK(X,T) check(#X, PTYPE(X), PTYPE((X) << (T) 1)) +#define TEST1(X,T) do { CHECK(X,T); CHECK(X,unsigned T); } while (0) +#define TEST2(X) \ + do \ + { \ + TEST1((X),short); \ + TEST1((X),int); \ + TEST1((X),long); \ + TEST1((X),long long); \ + } \ + while (0) +#define TEST3(X,T) do { TEST2((T)(X)); TEST2((unsigned T)(X)); } while (0) +#define TEST4(X) \ + do \ + { \ + TEST3((X),short); \ + TEST3((X),int); \ + TEST3((X),long); \ + TEST3((X),long long); \ + } \ + while (0) + +static int debug, nfailed = 0; + +static void check (const char *s, int arg1, int shift) +{ + int failed = arg1 != shift; + if (debug || failed) + printf ("%s %d %d\n", s, arg1, shift); + nfailed += failed; +} + +int main (int argc, char **argv) +{ + debug = argc > 1; + TEST4(1); + TEST4(-1); + printf ("%d test(s) failed\n", nfailed); + return nfailed != 0; +} diff --git a/lib/tinycc/tests/tests2/55_lshift_type.expect b/lib/tinycc/tests/tests2/55_lshift_type.expect new file mode 100644 index 000000000..8523767af --- /dev/null +++ b/lib/tinycc/tests/tests2/55_lshift_type.expect @@ -0,0 +1 @@ +0 test(s) failed diff --git a/lib/tinycc/tests/tests2/60_errors_and_warnings.c b/lib/tinycc/tests/tests2/60_errors_and_warnings.c new file mode 100644 index 000000000..434c46b79 --- /dev/null +++ b/lib/tinycc/tests/tests2/60_errors_and_warnings.c @@ -0,0 +1,493 @@ +#if defined test_56_btype_excess_1 +struct A {} int i; + +#elif defined test_57_btype_excess_2 +char int i; + +#elif defined test_58_function_redefinition +int f(void) { return 0; } +int f(void) { return 1; } + +#elif defined test_global_redefinition +int xxx = 1; +int xxx; +int xxx = 2; + +#elif defined test_59_function_array +int (*fct)[42](int x); + +#elif defined test_60_enum_redefinition +enum color { RED, GREEN, BLUE }; +enum color { R, G, B }; +enum color c; + +#elif defined test_62_enumerator_redefinition +enum color { RED, GREEN, BLUE }; +enum rgb { RED, G, B}; +enum color c = RED; + +#elif defined test_63_local_enumerator_redefinition +enum { + FOO, + BAR +}; + +int main(void) +{ + enum { + FOO = 2, + BAR + }; + + return BAR - FOO; +} + +#elif defined test_61_undefined_enum +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_enum_compat_2 +enum e6 { E1 = -1, E0 }; +void f3(enum e6); +void f3(int); // should work as int and e6 are compatible +void f4(enum e6 e); +void f4(unsigned e); // should error as unsigned and e6 are incompatible + +#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); } +#elif defined test_duplicate_def_1 +static enum myenum { L = -1 } L; +#elif defined test_duplicate_def_2 +void foo(void) { +static enum myenum { L = -1 } L; +} +#elif defined test_abstract_decls +int bar(const char *()); // abstract declarator here is okay +int bar (const char *(*g)()) // should match this 'g' argument +{ + g(); + return 42; +} +int foo(int ()) // abstract decl is wrong in definitions +{ + return 0; +#elif defined test_invalid_1 +void f(char*); +void g(void) { + f((char[]){1, ,}); +} +#elif defined test_invalid_2 +int ga = 0.42 { 2 }; +#elif defined test_invalid_3 +struct S { int a, b; }; +struct T { struct S x; }; +struct T gt = { 42 a: 1, 43 }; +#elif defined test_invalid_4 +enum E { + x = 1 / 0 +}; +#elif defined test_conflicting_types +int i; +void foo(void) { + int i; + { + extern double i; + i = 42.2; + } +} +#elif defined test_nested_types +union u { + union u { + int i; + } m; +}; +#elif defined test_vla_1 +int X=1; + +int main(void) { + int t[][][X]; +} +#elif defined test_invalid_alignas +/* _Alignas is no type qualifier */ +void * _Alignas(16) p1; + +#elif defined test_static_assert + +#define ONE 0 + _Static_assert(ONE == 0, "don't show me this"); + struct x{ _Static_assert(ONE == 1, "ONE is not 1"); }; + +#elif defined test_static_assert_2 + _Static_assert(1, "1"" is 1"); +struct y { _Static_assert(0, "0"" is 0"); }; + +#elif defined test_static_assert_c2x + _Static_assert(1); +struct z { _Static_assert(0); } + +#elif defined test_static_assert_empty_string + _Static_assert(0,""); + +#elif defined test_void_array + void t[3]; + +#elif defined test_incomplete_enum_array + enum e t[3]; + +#elif defined test_incomplete_struct_array + struct s t[3]; + +#elif defined test_const_fun_array + typedef void f(void); + const f t[3]; + +#elif defined test_incomplete_array_array + int t[][3]; // gr: not an error, see below + +/******************************************************************/ +#elif defined test_extern_array +int iii[] = { 1,2,3 }; +extern int iii[]; +int x[]; +int x[2]; +int x[]; +int x[2]; +int x[]; +extern int x[2]; +extern int x[]; +int x[3]; + +/******************************************************************/ +#elif defined test_func_1 \ + || defined test_func_2 \ + || defined test_func_3 \ + || defined test_func_4 \ + || defined test_func_5 \ + || defined test_func_6 +#if defined test_func_1 +int hello(int); +#elif defined test_func_4 +static int hello(int); +#endif +int main () { +#if defined test_func_6 + static +#endif + int hello(int); + hello(123); + return 0; +} +int printf(const char*, ...); +#if defined test_func_3 +static int hello(int a) +#elif defined test_func_5 +int hello(int a, int b) +#else +int hello(int a) +#endif +{ printf("%s: a = %d\n", __FUNCTION__, a); return 0; } + +/******************************************************************/ +#elif defined test_var_1 \ + || defined test_var_2 \ + || defined test_var_3 +#define P(n,v) printf("%-5s: %d ; %d\n", __FUNCTION__, n, v) +#if defined test_var_1 +int xxx[]; +#endif +int bar(); +int printf(const char*, ...); +int main () +{ +#if !defined test_var_3 + int xxx = 2; +#endif + { + extern int xxx[ +#if defined test_var_3 + 2 +#endif + ]; + P(1, xxx[0]); + xxx[0] += 2; + } +#if !defined test_var_3 + P(2, xxx); +#endif + bar(123); + return 0; +} +int xxx[1] = {1}; +int bar() { P(3, xxx[0]); return 0; } + +#elif defined test_var_4 +struct yyy { int y; }; +struct zzz; +void f1() { + extern char *x; + extern char **xx; + extern struct yyy y; + extern struct yyy *yy; + extern struct zzz z; + extern struct zzz *zz; +} +void f2() { + extern char *x; + extern char **xx; + extern struct yyy y; + extern struct yyy *yy; + extern struct zzz z; + extern struct zzz *zz; +} +struct yyy y, *yy; +struct zzz { int z; } z, *zz; + +/******************************************************************/ +#elif defined test_long_double_type_for_win32 + +int main() +{ + double *a = 0; + long double *b = a; + int n = _Generic(*a, double:0, long double:1); +} + +#elif defined test_stray_backslash +#define x \a +x + +#elif defined test_stray_backslash2 +int printf(const char*, ...); +int main() +{ +#define _S(x) #x +#define S(x) _S(x) + printf("%sn\n", S(\\)); +} + +/******************************************************************/ +#elif defined test_var_array + +static struct var_len { int i; const char str[]; } var_array[] = +{ { 1, "abcdefghijklmnopqrstuvwxyz" }, + { 2, "longlonglonglonglong" }, + { 3, "tst3" } }; + +#elif defined test_var_array2 + +struct c1 { int a; int b[]; }; +struct c1 c1 = { 1, { 2, 3, 4 } }; + +struct c2 { int c; struct c1 c1; }; +struct c2 c2 = { 1, { 2, { 3, 4, 5 }}}; + +#elif defined test_var_array3 +/* similar to test_var_array2 but with string initializers */ +struct A { int a; char b[]; }; +struct A a = { 1, "1" }; +struct B { struct A a; }; +struct B b = { { 1, "1" } }; +/******************************************************************/ +#elif defined test_default_int_type +n; // warn +f(); // don't warn + +#elif defined test_invalid_global_stmtexpr +n[sizeof({3;})]; // crashed in block() due to missing local scope + +#elif defined test_invalid_tokckill +f(){"12"3;} // second const token killed the value of the first + +/******************************************************************/ +#elif defined test_duplicate_member +struct S { + int a, a; +}; +#elif defined test_duplicate_member_anon +struct S1 { + int b; + struct { + int b; + } c; +}; +struct S2 { + int d; + struct { + int d; + }; +}; + +/******************************************************************/ +#elif defined test_conflicting_array_definition +extern int array[2]; +int array[] = { 1, 2, 3 }; + +#elif defined test_incompatible_local_redef +void foo (void) +{ + typedef int localfunctype (int); + extern localfunctype func2; + typedef void localfunctype (int, int); +} + +#elif defined test_cast_from_void +void v() {} +int f() { return v(); } + +#elif defined test_switch_W1 || defined test_switch_W2 \ + || defined test_switch_W3 || defined test_switch_W4 +#if defined test_switch_W1 +#pragma comment(option, "-Wall") +#elif defined test_switch_W2 +#pragma comment(option, "-Wunsupported -Wno-implicit-function-declaration -Wstuff") +#elif defined test_switch_W3 +#pragma comment(option, "-Wwrite-strings -Werror=discarded-qualifiers") +#elif defined test_switch_W4 +#pragma comment(option, "-Wunsupported -Wno-error=implicit-function-declaration -Werror") +#endif +void func() +{ + char *ccp = "123"; + fink(); +} +__attribute__((stuff)) int fink() {return 0;} + +#elif defined test_invalid_funcparam_1 +void func(int a, int b, int a); + +#elif defined test_invalid_funcparam_2 +void func(int a, int if); + +#elif defined test_array_funcparam +int amain(int argc, char *argv[static argc + 1]) +{ + int i; + int printf(const char*, ...); + for (i = 0; i < argc; ++i) + printf("arg[%d] = \"%s\"\n", i, argv[i]); + return 0; +} +int main() +{ + return amain(2, (char *[]){ "X", "Y", 0 }); +} + +#elif defined test_return_from_statement_expr +int f() { ({ return 78; }); } +int main() { return f(); } + +/******************************************************************/ + +#elif defined test_illegal_unicode +int main() { + char *str = "\Uffffffff"; +} + +#elif defined test_error_string +#error \123\\ +456 + +#elif defined test_error_incomplete_type +struct A; +void f(struct A *); + +int main() +{ + f(&(struct A){}); +} + +struct A { + int x; +}; + +#elif defined test_pp_error_1 +# if //no expression +# endif +#elif defined test_pp_error_2 +# if X(1,2) //undefined function macro +# endif + +#elif defined test_pointer_plus_double + +int *invalid_operation(int *p, double d) +{ + return p + d; +} + +#endif diff --git a/lib/tinycc/tests/tests2/60_errors_and_warnings.expect b/lib/tinycc/tests/tests2/60_errors_and_warnings.expect new file mode 100644 index 000000000..a8ef81941 --- /dev/null +++ b/lib/tinycc/tests/tests2/60_errors_and_warnings.expect @@ -0,0 +1,242 @@ +[test_56_btype_excess_1] +60_errors_and_warnings.c:2: error: too many basic types + +[test_57_btype_excess_2] +60_errors_and_warnings.c:5: error: too many basic types + +[test_58_function_redefinition] +60_errors_and_warnings.c:9: error: redefinition of 'f' + +[test_global_redefinition] +60_errors_and_warnings.c:14: error: redefinition of 'xxx' + +[test_59_function_array] +60_errors_and_warnings.c:17: error: declaration of an array of functions + +[test_60_enum_redefinition] +60_errors_and_warnings.c:21: error: struct/union/enum already defined + +[test_62_enumerator_redefinition] +60_errors_and_warnings.c:26: error: redefinition of enumerator 'RED' + +[test_63_local_enumerator_redefinition] +[returns 1] + +[test_61_undefined_enum] +60_errors_and_warnings.c:46: error: initialization of incomplete type + +[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_enum_compat_2] +60_errors_and_warnings.c:126: error: incompatible types for redefinition of 'f4' + +[test_ptr_to_str] +60_errors_and_warnings.c:129: error: type 'const int **' does not match any association + +[test_fnptr_to_str] +60_errors_and_warnings.c:131: error: type 'int (*(*)(float, char))(double, int)' does not match any association + +[test_array_to_str] +60_errors_and_warnings.c:133: error: type 'int (*)[3]' does not match any association + +[test_duplicate_def_1] +60_errors_and_warnings.c:135: error: redefinition of 'L' + +[test_duplicate_def_2] +60_errors_and_warnings.c:138: error: redeclaration of 'L' + +[test_abstract_decls] +60_errors_and_warnings.c:148: error: identifier expected + +[test_invalid_1] +60_errors_and_warnings.c:153: error: expression expected before ',' + +[test_invalid_2] +60_errors_and_warnings.c:156: error: ';' expected (got "{") + +[test_invalid_3] +60_errors_and_warnings.c:160: error: ',' expected (got "a") + +[test_invalid_4] +60_errors_and_warnings.c:164: error: division by zero in constant + +[test_conflicting_types] +60_errors_and_warnings.c:170: error: incompatible types for redefinition of 'i' + +[test_nested_types] +60_errors_and_warnings.c:177: error: struct/union/enum already defined + +[test_vla_1] +60_errors_and_warnings.c:184: error: need explicit inner array size in VLAs + +[test_invalid_alignas] +60_errors_and_warnings.c:188: error: identifier expected + +[test_static_assert] +60_errors_and_warnings.c:194: error: ONE is not 1 + +[test_static_assert_2] +60_errors_and_warnings.c:198: error: 0 is 0 + +[test_static_assert_c2x] +60_errors_and_warnings.c:202: error: _Static_assert fail + +[test_static_assert_empty_string] +60_errors_and_warnings.c:205: error: + +[test_void_array] +60_errors_and_warnings.c:208: error: declaration of an array of incomplete type elements + +[test_incomplete_enum_array] +60_errors_and_warnings.c:211: error: declaration of an array of incomplete type elements + +[test_incomplete_struct_array] +60_errors_and_warnings.c:214: error: declaration of an array of incomplete type elements + +[test_const_fun_array] +60_errors_and_warnings.c:218: error: declaration of an array of functions + +[test_incomplete_array_array] + +[test_extern_array] +60_errors_and_warnings.c:234: error: incompatible types for redefinition of 'x' + +[test_func_1] +hello: a = 123 + +[test_func_2] +hello: a = 123 + +[test_func_3] +60_errors_and_warnings.c:264: warning: static storage ignored for redefinition of 'hello' +hello: a = 123 + +[test_func_4] +hello: a = 123 + +[test_func_5] +60_errors_and_warnings.c:264: error: incompatible types for redefinition of 'hello' + +[test_func_6] +60_errors_and_warnings.c:252: error: function without file scope cannot be static + +[test_var_1] +main : 1 ; 1 +main : 2 ; 2 +bar : 3 ; 3 + +[test_var_2] +main : 1 ; 1 +main : 2 ; 2 +bar : 3 ; 3 + +[test_var_3] +60_errors_and_warnings.c:296: error: incompatible types for redefinition of 'xxx' + +[test_var_4] + +[test_long_double_type_for_win32] +60_errors_and_warnings.c:327: warning: assignment from incompatible pointer type + +[test_stray_backslash] +60_errors_and_warnings.c:333: error: stray '\' in program + +[test_stray_backslash2] +\n + +[test_var_array] +60_errors_and_warnings.c:348: error: flexible array has zero size in this context + +[test_var_array2] +60_errors_and_warnings.c:358: error: flexible array has zero size in this context + +[test_var_array3] +60_errors_and_warnings.c:365: error: flexible array has zero size in this context + +[test_default_int_type] +60_errors_and_warnings.c:368: warning: type defaults to int + +[test_invalid_global_stmtexpr] +60_errors_and_warnings.c:372: error: statement expression outside of function + +[test_invalid_tokckill] +60_errors_and_warnings.c:375: error: ';' expected (got "3") + +[test_duplicate_member] +60_errors_and_warnings.c:381: error: duplicate member 'a' + +[test_duplicate_member_anon] +60_errors_and_warnings.c:394: error: duplicate member 'd' + +[test_conflicting_array_definition] +60_errors_and_warnings.c:399: error: incompatible types for redefinition of 'array' + +[test_incompatible_local_redef] +60_errors_and_warnings.c:406: error: incompatible redefinition of 'localfunctype' + +[test_cast_from_void] +60_errors_and_warnings.c:411: error: cannot convert 'void' to 'int' + +[test_switch_W1] +60_errors_and_warnings.c:427: warning: implicit declaration of function 'fink' + +[test_switch_W2] +60_errors_and_warnings.c:418: warning: unsupported option '-Wstuff' +60_errors_and_warnings.c:429: warning: 'stuff' attribute ignored + +[test_switch_W3] +60_errors_and_warnings.c:426: error: assignment discards qualifiers from pointer target type + +[test_switch_W4] +60_errors_and_warnings.c:427: warning: implicit declaration of function 'fink' +60_errors_and_warnings.c:429: error: 'stuff' attribute ignored + +[test_invalid_funcparam_1] +60_errors_and_warnings.c:432: error: redeclaration of 'a' + +[test_invalid_funcparam_2] +60_errors_and_warnings.c:435: error: identifier expected + +[test_array_funcparam] +arg[0] = "X" +arg[1] = "Y" + +[test_return_from_statement_expr] +[returns 78] + +[test_illegal_unicode] +60_errors_and_warnings.c:459: error: 0xffffffff is not a valid universal character + +[test_error_string] +60_errors_and_warnings.c:464: error: #error \123\456 + +[test_error_incomplete_type] +60_errors_and_warnings.c:472: error: initialization of incomplete type + +[test_pp_error_1] +60_errors_and_warnings.c:480: error: #if with no expression + +[test_pp_error_2] +60_errors_and_warnings.c:483: error: bad preprocessor expression: #if 0 ( 1 , 2 ) + +[test_pointer_plus_double] +60_errors_and_warnings.c:490: error: invalid operand types for binary operation diff --git a/lib/tinycc/tests/tests2/61_integers.c b/lib/tinycc/tests/tests2/61_integers.c new file mode 100644 index 000000000..de29b3ce3 --- /dev/null +++ b/lib/tinycc/tests/tests2/61_integers.c @@ -0,0 +1,70 @@ +#include + +/* This was first introduced to test the ARM port */ + +#define UINT_MAX ((unsigned) -1) + +int main() +{ + printf("18/21=%u\n", 18/21); + printf("18%%21=%u\n", 18%21); + printf("41/21=%u\n", 41/21); + printf("41%%21=%u\n", 41%21); + printf("42/21=%u\n", 42/21); + printf("42%%21=%u\n", 42%21); + printf("43/21=%u\n", 43/21); + printf("43%%21=%u\n", 43%21); + printf("126/21=%u\n", 126/21); + printf("126%%21=%u\n", 126%21); + printf("131/21=%u\n", 131/21); + printf("131%%21=%u\n", 131%21); + printf("(UINT_MAX/2+3)/2=%u\n", (UINT_MAX/2+3)/2); + printf("(UINT_MAX/2+3)%%2=%u\n", (UINT_MAX/2+3)%2); + + printf("18/-21=%u\n", 18/-21); + printf("18%%-21=%u\n", 18%-21); + printf("41/-21=%u\n", 41/-21); + printf("41%%-21=%u\n", 41%-21); + printf("42/-21=%u\n", 42/-21); + printf("42%%-21=%u\n", 42%-21); + printf("43/-21=%u\n", 43/-21); + printf("43%%-21=%u\n", 43%-21); + printf("126/-21=%u\n", 126/-21); + printf("126%%-21=%u\n", 126%-21); + printf("131/-21=%u\n", 131/-21); + printf("131%%-21=%u\n", 131%-21); + printf("(UINT_MAX/2+3)/-2=%u\n", (UINT_MAX/2+3)/-2); + printf("(UINT_MAX/2+3)%%-2=%u\n", (UINT_MAX/2+3)%-2); + + printf("-18/21=%u\n", -18/21); + printf("-18%%21=%u\n", -18%21); + printf("-41/21=%u\n", -41/21); + printf("-41%%21=%u\n", -41%21); + printf("-42/21=%u\n", -42/21); + printf("-42%%21=%u\n", -42%21); + printf("-43/21=%u\n", -43/21); + printf("-43%%21=%u\n", -43%21); + printf("-126/21=%u\n", -126/21); + printf("-126%%21=%u\n", -126%21); + printf("-131/21=%u\n", -131/21); + printf("-131%%21=%u\n", -131%21); + printf("-(UINT_MAX/2+3)/2=%u\n", (0-(UINT_MAX/2+3))/2); + printf("-(UINT_MAX/2+3)%%2=%u\n", (0-(UINT_MAX/2+3))%2); + + printf("-18/-21=%u\n", -18/-21); + printf("-18%%-21=%u\n", -18%-21); + printf("-41/-21=%u\n", -41/-21); + printf("-41%%-21=%u\n", -41%-21); + printf("-42/-21=%u\n", -42/-21); + printf("-42%%-21=%u\n", -42%-21); + printf("-43/-21=%u\n", -43/-21); + printf("-43%%-21=%u\n", -43%-21); + printf("-126/-21=%u\n", -126/-21); + printf("-126%%-21=%u\n", -126%-21); + printf("-131/-21=%u\n", -131/-21); + printf("-131%%-21=%u\n", -131%-21); + printf("-(UINT_MAX/2+3)/-2=%u\n", (0-(UINT_MAX/2+3))/-2); + printf("-(UINT_MAX/2+3)%%-2=%u\n", (0-(UINT_MAX/2+3))%-2); + + return 0; +} diff --git a/lib/tinycc/tests/tests2/61_integers.expect b/lib/tinycc/tests/tests2/61_integers.expect new file mode 100644 index 000000000..22c8d1b9b --- /dev/null +++ b/lib/tinycc/tests/tests2/61_integers.expect @@ -0,0 +1,56 @@ +18/21=0 +18%21=18 +41/21=1 +41%21=20 +42/21=2 +42%21=0 +43/21=2 +43%21=1 +126/21=6 +126%21=0 +131/21=6 +131%21=5 +(UINT_MAX/2+3)/2=1073741825 +(UINT_MAX/2+3)%2=0 +18/-21=0 +18%-21=18 +41/-21=4294967295 +41%-21=20 +42/-21=4294967294 +42%-21=0 +43/-21=4294967294 +43%-21=1 +126/-21=4294967290 +126%-21=0 +131/-21=4294967290 +131%-21=5 +(UINT_MAX/2+3)/-2=0 +(UINT_MAX/2+3)%-2=2147483650 +-18/21=0 +-18%21=4294967278 +-41/21=4294967295 +-41%21=4294967276 +-42/21=4294967294 +-42%21=0 +-43/21=4294967294 +-43%21=4294967295 +-126/21=4294967290 +-126%21=0 +-131/21=4294967290 +-131%21=4294967291 +-(UINT_MAX/2+3)/2=1073741823 +-(UINT_MAX/2+3)%2=0 +-18/-21=0 +-18%-21=4294967278 +-41/-21=1 +-41%-21=4294967276 +-42/-21=2 +-42%-21=0 +-43/-21=2 +-43%-21=4294967295 +-126/-21=6 +-126%-21=0 +-131/-21=6 +-131%-21=4294967291 +-(UINT_MAX/2+3)/-2=0 +-(UINT_MAX/2+3)%-2=2147483646 diff --git a/lib/tinycc/tests/tests2/64_macro_nesting.c b/lib/tinycc/tests/tests2/64_macro_nesting.c new file mode 100644 index 000000000..676e5d3ef --- /dev/null +++ b/lib/tinycc/tests/tests2/64_macro_nesting.c @@ -0,0 +1,12 @@ +#include // printf() + +#define CAT2(a,b) a##b +#define CAT(a,b) CAT2(a,b) +#define AB(x) CAT(x,y) + +int main(void) +{ + int xy = 42; + printf("%d\n", CAT(A,B)(x)); + return 0; +} diff --git a/lib/tinycc/tests/tests2/64_macro_nesting.expect b/lib/tinycc/tests/tests2/64_macro_nesting.expect new file mode 100644 index 000000000..d81cc0710 --- /dev/null +++ b/lib/tinycc/tests/tests2/64_macro_nesting.expect @@ -0,0 +1 @@ +42 diff --git a/lib/tinycc/tests/tests2/67_macro_concat.c b/lib/tinycc/tests/tests2/67_macro_concat.c new file mode 100644 index 000000000..c580d3a64 --- /dev/null +++ b/lib/tinycc/tests/tests2/67_macro_concat.c @@ -0,0 +1,14 @@ +#include + +#define P(A,B) A ## B ; bob +#define Q(A,B) A ## B+ + +int main(void) +{ + int bob, jim = 21; + bob = P(jim,) *= 2; + printf("jim: %d, bob: %d\n", jim, bob); + jim = 60 Q(+,)3; + printf("jim: %d\n", jim); + return 0; +} diff --git a/lib/tinycc/tests/tests2/67_macro_concat.expect b/lib/tinycc/tests/tests2/67_macro_concat.expect new file mode 100644 index 000000000..8386c2d6c --- /dev/null +++ b/lib/tinycc/tests/tests2/67_macro_concat.expect @@ -0,0 +1,2 @@ +jim: 21, bob: 42 +jim: 63 diff --git a/lib/tinycc/tests/tests2/70_floating_point_literals.c b/lib/tinycc/tests/tests2/70_floating_point_literals.c new file mode 100644 index 000000000..012fb4fab --- /dev/null +++ b/lib/tinycc/tests/tests2/70_floating_point_literals.c @@ -0,0 +1,77 @@ +#include + +int main() +{ + /* decimal floating constant */ + float fa0 = .123f; + float fa1 = .123E12F; + float fa2 = .123e-12f; + float fa3 = .123e+12f; + printf("%f\n%f\n%f\n%f\n\n", fa0, fa1, fa2, fa3); + + float fb0 = 123.123f; + float fb1 = 123.123E12F; + float fb2 = 123.123e-12f; + float fb3 = 123.123e+12f; + printf("%f\n%f\n%f\n%f\n\n", fb0, fb1, fb2, fb3); + + float fc0 = 123.f; + float fc1 = 123.E12F; + float fc2 = 123.e-12f; + float fc3 = 123.e+12f; + printf("%f\n%f\n%f\n%f\n\n", fc0, fc1, fc2, fc3); + + float fd0 = 123E12F; + float fd1 = 123e-12f; + float fd2 = 123e+12f; + printf("%f\n%f\n%f\n\n", fd0, fd1, fd2); + printf("\n"); + + /* hexadecimal floating constant */ + double da0 = 0X.1ACP12; + double da1 = 0x.1acp-12; + double da2 = 0x.1acp+12; + printf("%f\n%f\n%f\n\n", da0, da1, da2); + + double db0 = 0X1AC.BDP12; + double db1 = 0x1ac.bdp-12; + double db2 = 0x1ac.dbp+12; + printf("%f\n%f\n%f\n\n", db0, db1, db2); + + double dc0 = 0X1AC.P12; + double dc1 = 0x1ac.p-12; + double dc2 = 0x1ac.p+12; + printf("%f\n%f\n%f\n\n", dc0, dc1, dc2); + + double dd0 = 0X1ACP12; + double dd1 = 0x1acp-12; + double dd2 = 0x1acp+12; + printf("%f\n%f\n%f\n\n", dd0, dd1, dd2); + printf("\n"); + +#ifdef __TINYC__ + /* TCC extension + binary floating constant */ + long double la0 = 0B.110101100P12L; + long double la1 = 0b.110101100p-12l; + long double la2 = 0b.110101100p+12l; + printf("%Lf\n%Lf\n%Lf\n\n", la0, la1, la2); + + long double lb0 = 0B110101100.10111101P12L; + long double lb1 = 0b110101100.10111101p-12l; + long double lb2 = 0b110101100.10111101p+12l; + printf("%Lf\n%Lf\n%Lf\n\n", lb0, lb1, lb2); + + long double lc0 = 0B110101100.P12L; + long double lc1 = 0b110101100.p-12l; + long double lc2 = 0b110101100.p+12l; + printf("%Lf\n%Lf\n%Lf\n\n", lc0, lc1, lc2); + + long double ld0 = 0B110101100P12L; + long double ld1 = 0b110101100p-12l; + long double ld2 = 0b110101100p+12l; + printf("%Lf\n%Lf\n%Lf\n\n", ld0, ld1, ld2); +#endif + + return 0; +} diff --git a/lib/tinycc/tests/tests2/70_floating_point_literals.expect b/lib/tinycc/tests/tests2/70_floating_point_literals.expect new file mode 100644 index 000000000..7eb1efb9e --- /dev/null +++ b/lib/tinycc/tests/tests2/70_floating_point_literals.expect @@ -0,0 +1,53 @@ +0.123000 +122999996416.000000 +0.000000 +122999996416.000000 + +123.123001 +123122997002240.000000 +0.000000 +123122997002240.000000 + +123.000000 +123000003231744.000000 +0.000000 +123000003231744.000000 + +123000003231744.000000 +0.000000 +123000003231744.000000 + + +428.000000 +0.000026 +428.000000 + +1756112.000000 +0.104672 +1756592.000000 + +1753088.000000 +0.104492 +1753088.000000 + +1753088.000000 +0.104492 +1753088.000000 + + +3424.000000 +0.000204 +3424.000000 + +1756112.000000 +0.104672 +1756112.000000 + +1753088.000000 +0.104492 +1753088.000000 + +1753088.000000 +0.104492 +1753088.000000 + diff --git a/lib/tinycc/tests/tests2/71_macro_empty_arg.c b/lib/tinycc/tests/tests2/71_macro_empty_arg.c new file mode 100644 index 000000000..f0d3511b9 --- /dev/null +++ b/lib/tinycc/tests/tests2/71_macro_empty_arg.c @@ -0,0 +1,9 @@ +#include + +#define T(a,b,c) a b c + +int main(void) +{ + printf("%d", T(1,+,2) T(+,,) T(,2,*) T(,7,) T(,,)); + return 0; +} diff --git a/lib/tinycc/tests/tests2/71_macro_empty_arg.expect b/lib/tinycc/tests/tests2/71_macro_empty_arg.expect new file mode 100644 index 000000000..98d9bcb75 --- /dev/null +++ b/lib/tinycc/tests/tests2/71_macro_empty_arg.expect @@ -0,0 +1 @@ +17 diff --git a/lib/tinycc/tests/tests2/72_long_long_constant.c b/lib/tinycc/tests/tests2/72_long_long_constant.c new file mode 100644 index 000000000..66082133d --- /dev/null +++ b/lib/tinycc/tests/tests2/72_long_long_constant.c @@ -0,0 +1,19 @@ +#include + +int main() +{ + long long int res = 0; + + if (res < -2147483648LL) { + printf("Error: 0 < -2147483648\n"); + return 1; + } + else + if (2147483647LL < res) { + printf("Error: 2147483647 < 0\n"); + return 2; + } + else + printf("long long constant test ok.\n"); + return 0; +} diff --git a/lib/tinycc/tests/tests2/72_long_long_constant.expect b/lib/tinycc/tests/tests2/72_long_long_constant.expect new file mode 100644 index 000000000..dda9e660d --- /dev/null +++ b/lib/tinycc/tests/tests2/72_long_long_constant.expect @@ -0,0 +1 @@ +long long constant test ok. diff --git a/lib/tinycc/tests/tests2/73_arm64.c b/lib/tinycc/tests/tests2/73_arm64.c new file mode 100644 index 000000000..855c47671 --- /dev/null +++ b/lib/tinycc/tests/tests2/73_arm64.c @@ -0,0 +1,538 @@ +// This program is designed to test some arm64-specific things, such as the +// calling convention, but should give the same results on any architecture. + +#include +#include +#include + +struct s1 { char x[1]; } s1 = { "0" }; +struct s2 { char x[2]; } s2 = { "12" }; +struct s3 { char x[3]; } s3 = { "345" }; +struct s4 { char x[4]; } s4 = { "6789" }; +struct s5 { char x[5]; } s5 = { "abcde" }; +struct s6 { char x[6]; } s6 = { "fghijk" }; +struct s7 { char x[7]; } s7 = { "lmnopqr" }; +struct s8 { char x[8]; } s8 = { "stuvwxyz" }; +struct s9 { char x[9]; } s9 = { "ABCDEFGHI" }; +struct s10 { char x[10]; } s10 = { "JKLMNOPQRS" }; +struct s11 { char x[11]; } s11 = { "TUVWXYZ0123" }; +struct s12 { char x[12]; } s12 = { "456789abcdef" }; +struct s13 { char x[13]; } s13 = { "ghijklmnopqrs" }; +struct s14 { char x[14]; } s14 = { "tuvwxyzABCDEFG" }; +struct s15 { char x[15]; } s15 = { "HIJKLMNOPQRSTUV" }; +struct s16 { char x[16]; } s16 = { "WXYZ0123456789ab" }; +struct s17 { char x[17]; } s17 = { "cdefghijklmnopqrs" }; + +struct hfa11 { float a; } hfa11 = { 11.1 }; +struct hfa12 { float a, b; } hfa12 = { 12.1, 12.2 }; +struct hfa13 { float a, b, c; } hfa13 = { 13.1, 13.2, 13.3 }; +struct hfa14 { float a, b, c, d; } hfa14 = { 14.1, 14.2, 14.3, 14.4 }; + +struct hfa21 { double a; } hfa21 = { 21.1 }; +struct hfa22 { double a, b; } hfa22 = { 22.1, 22.2 }; +struct hfa23 { double a, b, c; } hfa23 = { 23.1, 23.2, 23.3 }; +struct hfa24 { double a, b, c, d; } hfa24 = { 24.1, 24.2, 24.3, 24.4 }; + +struct hfa31 { long double a; } hfa31 = { 31.1 }; +struct hfa32 { long double a, b; } hfa32 = { 32.1, 32.2 }; +struct hfa33 { long double a, b, c; } hfa33 = { 33.1, 33.2, 33.3 }; +struct hfa34 { long double a, b, c, d; } hfa34 = { 34.1, 34.2, 34.3, 34.4 }; + +void fa_s1(struct s1 a) { printf("%.1s\n", a.x); } +void fa_s2(struct s2 a) { printf("%.2s\n", a.x); } +void fa_s3(struct s3 a) { printf("%.3s\n", a.x); } +void fa_s4(struct s4 a) { printf("%.4s\n", a.x); } +void fa_s5(struct s5 a) { printf("%.5s\n", a.x); } +void fa_s6(struct s6 a) { printf("%.6s\n", a.x); } +void fa_s7(struct s7 a) { printf("%.7s\n", a.x); } +void fa_s8(struct s8 a) { printf("%.8s\n", a.x); } +void fa_s9(struct s9 a) { printf("%.9s\n", a.x); } +void fa_s10(struct s10 a) { printf("%.10s\n", a.x); } +void fa_s11(struct s11 a) { printf("%.11s\n", a.x); } +void fa_s12(struct s12 a) { printf("%.12s\n", a.x); } +void fa_s13(struct s13 a) { printf("%.13s\n", a.x); } +void fa_s14(struct s14 a) { printf("%.14s\n", a.x); } +void fa_s15(struct s15 a) { printf("%.15s\n", a.x); } +void fa_s16(struct s16 a) { printf("%.16s\n", a.x); } +void fa_s17(struct s17 a) { printf("%.17s\n", a.x); } + +void fa_hfa11(struct hfa11 a) +{ printf("%.1f\n", a.a); } +void fa_hfa12(struct hfa12 a) +{ printf("%.1f %.1f\n", a.a, a.a); } +void fa_hfa13(struct hfa13 a) +{ printf("%.1f %.1f %.1f\n", a.a, a.b, a.c); } +void fa_hfa14(struct hfa14 a) +{ printf("%.1f %.1f %.1f %.1f\n", a.a, a.b, a.c, a.d); } + +void fa_hfa21(struct hfa21 a) +{ printf("%.1f\n", a.a); } +void fa_hfa22(struct hfa22 a) +{ printf("%.1f %.1f\n", a.a, a.a); } +void fa_hfa23(struct hfa23 a) +{ printf("%.1f %.1f %.1f\n", a.a, a.b, a.c); } +void fa_hfa24(struct hfa24 a) +{ printf("%.1f %.1f %.1f %.1f\n", a.a, a.b, a.c, a.d); } + +void fa_hfa31(struct hfa31 a) +{ printf("%.1Lf\n", a.a); } +void fa_hfa32(struct hfa32 a) +{ printf("%.1Lf %.1Lf\n", a.a, a.a); } +void fa_hfa33(struct hfa33 a) +{ printf("%.1Lf %.1Lf %.1Lf\n", a.a, a.b, a.c); } +void fa_hfa34(struct hfa34 a) +{ printf("%.1Lf %.1Lf %.1Lf %.1Lf\n", a.a, a.b, a.c, a.d); } + +void fa1(struct s8 a, struct s9 b, struct s10 c, struct s11 d, + struct s12 e, struct s13 f) +{ + printf("%.3s %.3s %.3s %.3s %.3s %.3s\n", a.x, b.x, c.x, d.x, e.x, f.x); +} + +void fa2(struct s9 a, struct s10 b, struct s11 c, struct s12 d, + struct s13 e, struct s14 f) +{ + printf("%.3s %.3s %.3s %.3s %.3s %.3s\n", a.x, b.x, c.x, d.x, e.x, f.x); +} + +void fa3(struct hfa14 a, struct hfa23 b, struct hfa32 c) +{ + printf("%.1f %.1f %.1f %.1f %.1Lf %.1Lf\n", + a.a, a.d, b.a, b.c, c.a, c.b); +} + +void fa4(struct s1 a, struct hfa14 b, struct s2 c, struct hfa24 d, + struct s3 e, struct hfa34 f) +{ + printf("%.1s %.1f %.1f %.2s %.1f %.1f %.3s %.1Lf %.1Lf\n", + a.x, b.a, b.d, c.x, d.a, d.d, e.x, f.a, f.d); +} + +void arg(void) +{ + printf("Arguments:\n"); + fa_s1(s1); + fa_s2(s2); + fa_s3(s3); + fa_s4(s4); + fa_s5(s5); + fa_s6(s6); + fa_s7(s7); + fa_s8(s8); + fa_s9(s9); + fa_s10(s10); + fa_s11(s11); + fa_s12(s12); + fa_s13(s13); + fa_s14(s14); + fa_s15(s15); + fa_s16(s16); + fa_s17(s17); + fa_hfa11(hfa11); + fa_hfa12(hfa12); + fa_hfa13(hfa13); + fa_hfa14(hfa14); + fa_hfa21(hfa21); + fa_hfa22(hfa22); + fa_hfa23(hfa23); + fa_hfa24(hfa24); + fa_hfa31(hfa31); + fa_hfa32(hfa32); + fa_hfa33(hfa33); + fa_hfa34(hfa34); + fa1(s8, s9, s10, s11, s12, s13); + fa2(s9, s10, s11, s12, s13, s14); + fa3(hfa14, hfa23, hfa32); + fa4(s1, hfa14, s2, hfa24, s3, hfa34); +} + +struct s1 fr_s1(void) { return s1; } +struct s2 fr_s2(void) { return s2; } +struct s3 fr_s3(void) { return s3; } +struct s4 fr_s4(void) { return s4; } +struct s5 fr_s5(void) { return s5; } +struct s6 fr_s6(void) { return s6; } +struct s7 fr_s7(void) { return s7; } +struct s8 fr_s8(void) { return s8; } +struct s9 fr_s9(void) { return s9; } +struct s10 fr_s10(void) { return s10; } +struct s11 fr_s11(void) { return s11; } +struct s12 fr_s12(void) { return s12; } +struct s13 fr_s13(void) { return s13; } +struct s14 fr_s14(void) { return s14; } +struct s15 fr_s15(void) { return s15; } +struct s16 fr_s16(void) { return s16; } +struct s17 fr_s17(void) { return s17; } + +struct hfa11 fr_hfa11(void) { return hfa11; } +struct hfa12 fr_hfa12(void) { return hfa12; } +struct hfa13 fr_hfa13(void) { return hfa13; } +struct hfa14 fr_hfa14(void) { return hfa14; } + +struct hfa21 fr_hfa21(void) { return hfa21; } +struct hfa22 fr_hfa22(void) { return hfa22; } +struct hfa23 fr_hfa23(void) { return hfa23; } +struct hfa24 fr_hfa24(void) { return hfa24; } + +struct hfa31 fr_hfa31(void) { return hfa31; } +struct hfa32 fr_hfa32(void) { return hfa32; } +struct hfa33 fr_hfa33(void) { return hfa33; } +struct hfa34 fr_hfa34(void) { return hfa34; } + +void ret(void) +{ + struct s1 t1 = fr_s1(); + struct s2 t2 = fr_s2(); + struct s3 t3 = fr_s3(); + struct s4 t4 = fr_s4(); + struct s5 t5 = fr_s5(); + struct s6 t6 = fr_s6(); + struct s7 t7 = fr_s7(); + struct s8 t8 = fr_s8(); + struct s9 t9 = fr_s9(); + struct s10 t10 = fr_s10(); + struct s11 t11 = fr_s11(); + struct s12 t12 = fr_s12(); + struct s13 t13 = fr_s13(); + struct s14 t14 = fr_s14(); + struct s15 t15 = fr_s15(); + struct s16 t16 = fr_s16(); + struct s17 t17 = fr_s17(); + printf("Return values:\n"); + printf("%.1s\n", t1.x); + printf("%.2s\n", t2.x); + printf("%.3s\n", t3.x); + printf("%.4s\n", t4.x); + printf("%.5s\n", t5.x); + printf("%.6s\n", t6.x); + printf("%.7s\n", t7.x); + printf("%.8s\n", t8.x); + printf("%.9s\n", t9.x); + printf("%.10s\n", t10.x); + printf("%.11s\n", t11.x); + printf("%.12s\n", t12.x); + printf("%.13s\n", t13.x); + printf("%.14s\n", t14.x); + printf("%.15s\n", t15.x); + printf("%.16s\n", t16.x); + printf("%.17s\n", t17.x); + printf("%.1f\n", fr_hfa11().a); + printf("%.1f %.1f\n", fr_hfa12().a, fr_hfa12().b); + printf("%.1f %.1f\n", fr_hfa13().a, fr_hfa13().c); + printf("%.1f %.1f\n", fr_hfa14().a, fr_hfa14().d); + printf("%.1f\n", fr_hfa21().a); + printf("%.1f %.1f\n", fr_hfa22().a, fr_hfa22().b); + printf("%.1f %.1f\n", fr_hfa23().a, fr_hfa23().c); + printf("%.1f %.1f\n", fr_hfa24().a, fr_hfa24().d); + printf("%.1Lf\n", fr_hfa31().a); + printf("%.1Lf %.1Lf\n", fr_hfa32().a, fr_hfa32().b); + printf("%.1Lf %.1Lf\n", fr_hfa33().a, fr_hfa33().c); + printf("%.1Lf %.1Lf\n", fr_hfa34().a, fr_hfa34().d); +} + +void* +va_arg_with_struct_ptr(va_list ap) { + /* + * This was a BUG identified with FFTW-3.3.8 on arm64. + * The test case only checks it compiles. + */ + struct X { int _x; }; + struct X *x = va_arg(ap, struct X *); + return x; +} + +int match(const char **s, const char *f) +{ + const char *p = *s; + for (p = *s; *f && *f == *p; f++, p++) + ; + if (!*f) { + *s = p - 1; + return 1; + } + return 0; +} + +void myprintf(const char *format, ...) +{ + const char *s; + va_list ap; + va_start(ap, format); + for (s = format; *s; s++) { + if (match(&s, "%7s")) { + struct s7 t7 = va_arg(ap, struct s7); + printf("%.7s", t7.x); + } + else if (match(&s, "%9s")) { + struct s9 t9 = va_arg(ap, struct s9); + printf("%.9s", t9.x); + } + else if (match(&s, "%hfa11")) { + struct hfa11 x = va_arg(ap, struct hfa11); + printf("%.1f,%.1f", x.a, x.a); + } + else if (match(&s, "%hfa12")) { + struct hfa12 x = va_arg(ap, struct hfa12); + printf("%.1f,%.1f", x.a, x.b); + } + else if (match(&s, "%hfa13")) { + struct hfa13 x = va_arg(ap, struct hfa13); + printf("%.1f,%.1f", x.a, x.c); + } + else if (match(&s, "%hfa14")) { + struct hfa14 x = va_arg(ap, struct hfa14); + printf("%.1f,%.1f", x.a, x.d); + } + else if (match(&s, "%hfa21")) { + struct hfa21 x = va_arg(ap, struct hfa21); + printf("%.1f,%.1f", x.a, x.a); + } + else if (match(&s, "%hfa22")) { + struct hfa22 x = va_arg(ap, struct hfa22); + printf("%.1f,%.1f", x.a, x.b); + } + else if (match(&s, "%hfa23")) { + struct hfa23 x = va_arg(ap, struct hfa23); + printf("%.1f,%.1f", x.a, x.c); + } + else if (match(&s, "%hfa24")) { + struct hfa24 x = va_arg(ap, struct hfa24); + printf("%.1f,%.1f", x.a, x.d); + } + else if (match(&s, "%hfa31")) { + struct hfa31 x = va_arg(ap, struct hfa31); + printf("%.1Lf,%.1Lf", x.a, x.a); + } + else if (match(&s, "%hfa32")) { + struct hfa32 x = va_arg(ap, struct hfa32); + printf("%.1Lf,%.1Lf", x.a, x.b); + } + else if (match(&s, "%hfa33")) { + struct hfa33 x = va_arg(ap, struct hfa33); + printf("%.1Lf,%.1Lf", x.a, x.c); + } + else if (match(&s, "%hfa34")) { + struct hfa34 x = va_arg(ap, struct hfa34); + printf("%.1Lf,%.1Lf", x.a, x.d); + } + else + putchar(*s); + } + putchar('\n'); +} + +void stdarg(void) +{ + printf("stdarg:\n"); + myprintf("%9s %9s %9s %9s %9s %9s", s9, s9, s9, s9, s9, s9); + myprintf("%7s %9s %9s %9s %9s %9s", s7, s9, s9, s9, s9, s9); + + myprintf("HFA long double:"); + myprintf("%hfa34 %hfa34 %hfa34 %hfa34", hfa34, hfa34, hfa34, hfa34); + myprintf("%hfa33 %hfa34 %hfa34 %hfa34", hfa33, hfa34, hfa34, hfa34); + myprintf("%hfa32 %hfa34 %hfa34 %hfa34", hfa32, hfa34, hfa34, hfa34); + myprintf("%hfa31 %hfa34 %hfa34 %hfa34", hfa31, hfa34, hfa34, hfa34); + + myprintf("%hfa32 %hfa33 %hfa33 %hfa33 %hfa33", + hfa32, hfa33, hfa33, hfa33, hfa33); + myprintf("%hfa31 %hfa33 %hfa33 %hfa33 %hfa33", + hfa31, hfa33, hfa33, hfa33, hfa33); + myprintf("%hfa33 %hfa33 %hfa33 %hfa33", + hfa33, hfa33, hfa33, hfa33); + + myprintf("%hfa34 %hfa32 %hfa32 %hfa32 %hfa32", + hfa34, hfa32, hfa32, hfa32, hfa32); + myprintf("%hfa33 %hfa32 %hfa32 %hfa32 %hfa32", + hfa33, hfa32, hfa32, hfa32, hfa32); + + myprintf("%hfa34 %hfa32 %hfa31 %hfa31 %hfa31 %hfa31", + hfa34, hfa32, hfa31, hfa31, hfa31, hfa31); + + myprintf("HFA double:"); + myprintf("%hfa24 %hfa24 %hfa24 %hfa24", hfa24, hfa24, hfa24, hfa24); + myprintf("%hfa23 %hfa24 %hfa24 %hfa24", hfa23, hfa24, hfa24, hfa24); + myprintf("%hfa22 %hfa24 %hfa24 %hfa24", hfa22, hfa24, hfa24, hfa24); + myprintf("%hfa21 %hfa24 %hfa24 %hfa24", hfa21, hfa24, hfa24, hfa24); + + myprintf("%hfa22 %hfa23 %hfa23 %hfa23 %hfa23", + hfa22, hfa23, hfa23, hfa23, hfa23); + myprintf("%hfa21 %hfa23 %hfa23 %hfa23 %hfa23", + hfa21, hfa23, hfa23, hfa23, hfa23); + myprintf("%hfa23 %hfa23 %hfa23 %hfa23", + hfa23, hfa23, hfa23, hfa23); + + myprintf("%hfa24 %hfa22 %hfa22 %hfa22 %hfa22", + hfa24, hfa22, hfa22, hfa22, hfa22); + myprintf("%hfa23 %hfa22 %hfa22 %hfa22 %hfa22", + hfa23, hfa22, hfa22, hfa22, hfa22); + + myprintf("%hfa24 %hfa22 %hfa21 %hfa21 %hfa21 %hfa21", + hfa24, hfa22, hfa21, hfa21, hfa21, hfa21); + + myprintf("HFA float:"); + myprintf("%hfa14 %hfa14 %hfa14 %hfa14", hfa14, hfa14, hfa14, hfa14); + myprintf("%hfa13 %hfa14 %hfa14 %hfa14", hfa13, hfa14, hfa14, hfa14); + myprintf("%hfa12 %hfa14 %hfa14 %hfa14", hfa12, hfa14, hfa14, hfa14); + myprintf("%hfa11 %hfa14 %hfa14 %hfa14", hfa11, hfa14, hfa14, hfa14); + + myprintf("%hfa12 %hfa13 %hfa13 %hfa13 %hfa13", + hfa12, hfa13, hfa13, hfa13, hfa13); + myprintf("%hfa11 %hfa13 %hfa13 %hfa13 %hfa13", + hfa11, hfa13, hfa13, hfa13, hfa13); + myprintf("%hfa13 %hfa13 %hfa13 %hfa13", + hfa13, hfa13, hfa13, hfa13); + + myprintf("%hfa14 %hfa12 %hfa12 %hfa12 %hfa12", + hfa14, hfa12, hfa12, hfa12, hfa12); + myprintf("%hfa13 %hfa12 %hfa12 %hfa12 %hfa12", + hfa13, hfa12, hfa12, hfa12, hfa12); + + myprintf("%hfa14 %hfa12 %hfa11 %hfa11 %hfa11 %hfa11", + hfa14, hfa12, hfa11, hfa11, hfa11, hfa11); +} + +void pll(unsigned long long x) +{ + printf("%llx\n", x); +} + +void movi(void) +{ + printf("MOVI:\n"); + pll(0); + pll(0xabcd); + pll(0xabcd0000); + pll(0xabcd00000000); + pll(0xabcd000000000000); + pll(0xffffabcd); + pll(0xabcdffff); + pll(0xffffffffffffabcd); + pll(0xffffffffabcdffff); + pll(0xffffabcdffffffff); + pll(0xabcdffffffffffff); + pll(0xaaaaaaaa); + pll(0x5555555555555555); + pll(0x77777777); + pll(0x3333333333333333); + pll(0xf8f8f8f8); + pll(0x1e1e1e1e1e1e1e1e); + pll(0x3f803f80); + pll(0x01ff01ff01ff01ff); + pll(0x007fffc0); + pll(0x03fff80003fff800); + pll(0x0007fffffffffe00); + + pll(0xabcd1234); + pll(0xabcd00001234); + pll(0xabcd000000001234); + pll(0xabcd12340000); + pll(0xabcd000012340000); + pll(0xabcd123400000000); + pll(0xffffffffabcd1234); + pll(0xffffabcdffff1234); + pll(0xabcdffffffff1234); + pll(0xffffabcd1234ffff); + pll(0xabcdffff1234ffff); + pll(0xabcd1234ffffffff); + + pll(0xffffef0123456789); + pll(0xabcdef012345ffff); + + pll(0xabcdef0123456789); +} + +static uint32_t addip0(uint32_t x) { return x + 0; } +static uint64_t sublp0(uint64_t x) { return x - 0; } +static uint32_t addip123(uint32_t x) { return x + 123; } +static uint64_t addlm123(uint64_t x) { return x + -123; } +static uint64_t sublp4095(uint64_t x) { return x - 4095; } +static uint32_t subim503808(uint32_t x) { return x - -503808; } +static uint64_t addp12345(uint64_t x) { return x + 12345; } +static uint32_t subp12345(uint32_t x) { return x - 12345; } + +static uint32_t mvni(uint32_t x) { return 0xffffffff - x; } +static uint64_t negl(uint64_t x) { return 0 - x; } +static uint32_t rsbi123(uint32_t x) { return 123 - x; } +static uint64_t rsbl123(uint64_t x) { return 123 - x; } + +static uint32_t andi0(uint32_t x) { return x & 0; } +static uint64_t andlm1(uint64_t x) { return x & -1; } +static uint64_t orrl0(uint64_t x) { return x | 0; } +static uint32_t orrim1(uint32_t x) { return x | -1; } +static uint32_t eori0(uint32_t x) { return x ^ 0; } +static uint64_t eorlm1(uint64_t x) { return x ^ -1; } +static uint32_t and0xf0(uint32_t x) { return x & 0xf0; } +static uint64_t orr0xf0(uint64_t x) { return x | 0xf0; } +static uint64_t eor0xf0(uint64_t x) { return x ^ 0xf0; } + +static uint32_t lsli0(uint32_t x) { return x << 0; } +static uint32_t lsri0(uint32_t x) { return x >> 0; } +static int64_t asrl0(int64_t x) { return x >> 0; } +static uint32_t lsli1(uint32_t x) { return x << 1; } +static uint32_t lsli31(uint32_t x) { return x << 31; } +static uint64_t lsll1(uint64_t x) { return x << 1; } +static uint64_t lsll63(uint64_t x) { return x << 63; } +static uint32_t lsri1(uint32_t x) { return x >> 1; } +static uint32_t lsri31(uint32_t x) { return x >> 31; } +static uint64_t lsrl1(uint64_t x) { return x >> 1; } +static uint64_t lsrl63(uint64_t x) { return x >> 63; } +static int32_t asri1(int32_t x) { return x >> 1; } +static int32_t asri31(int32_t x) { return x >> 31; } +static int64_t asrl1(int64_t x) { return x >> 1; } +static int64_t asrl63(int64_t x) { return x >> 63; } + +void opi(void) +{ + int x = 1000; + pll(addip0(x)); + pll(sublp0(x)); + pll(addip123(x)); + pll(addlm123(x)); + pll(sublp4095(x)); + pll(subim503808(x)); + pll(addp12345(x)); + pll(subp12345(x)); + pll(mvni(x)); + pll(negl(x)); + pll(rsbi123(x)); + pll(rsbl123(x)); + pll(andi0(x)); + pll(andlm1(x)); + pll(orrl0(x)); + pll(orrim1(x)); + pll(eori0(x)); + pll(eorlm1(x)); + pll(and0xf0(x)); + pll(orr0xf0(x)); + pll(eor0xf0(x)); + pll(lsli0(x)); + pll(lsri0(x)); + pll(asrl0(x)); + pll(lsli1(x)); + pll(lsli31(x)); + pll(lsll1(x)); + pll(lsll63(x)); + pll(lsri1(x)); + pll(lsri31(x)); + pll(lsrl1(x)); + pll(lsrl63(x)); + pll(asri1(x)); + pll(asri31(x)); + pll(asrl1(x)); + pll(asrl63(x)); +} + +void pcs(void) +{ + arg(); + ret(); + stdarg(); + movi(); + opi(); +} + +int main() +{ + pcs(); + return 0; +} diff --git a/lib/tinycc/tests/tests2/73_arm64.expect b/lib/tinycc/tests/tests2/73_arm64.expect new file mode 100644 index 000000000..7bdebd307 --- /dev/null +++ b/lib/tinycc/tests/tests2/73_arm64.expect @@ -0,0 +1,174 @@ +Arguments: +0 +12 +345 +6789 +abcde +fghijk +lmnopqr +stuvwxyz +ABCDEFGHI +JKLMNOPQRS +TUVWXYZ0123 +456789abcdef +ghijklmnopqrs +tuvwxyzABCDEFG +HIJKLMNOPQRSTUV +WXYZ0123456789ab +cdefghijklmnopqrs +11.1 +12.1 12.1 +13.1 13.2 13.3 +14.1 14.2 14.3 14.4 +21.1 +22.1 22.1 +23.1 23.2 23.3 +24.1 24.2 24.3 24.4 +31.1 +32.1 32.1 +33.1 33.2 33.3 +34.1 34.2 34.3 34.4 +stu ABC JKL TUV 456 ghi +ABC JKL TUV 456 ghi tuv +14.1 14.4 23.1 23.3 32.1 32.2 +0 14.1 14.4 12 24.1 24.4 345 34.1 34.4 +Return values: +0 +12 +345 +6789 +abcde +fghijk +lmnopqr +stuvwxyz +ABCDEFGHI +JKLMNOPQRS +TUVWXYZ0123 +456789abcdef +ghijklmnopqrs +tuvwxyzABCDEFG +HIJKLMNOPQRSTUV +WXYZ0123456789ab +cdefghijklmnopqrs +11.1 +12.1 12.2 +13.1 13.3 +14.1 14.4 +21.1 +22.1 22.2 +23.1 23.3 +24.1 24.4 +31.1 +32.1 32.2 +33.1 33.3 +34.1 34.4 +stdarg: +ABCDEFGHI ABCDEFGHI ABCDEFGHI ABCDEFGHI ABCDEFGHI ABCDEFGHI +lmnopqr ABCDEFGHI ABCDEFGHI ABCDEFGHI ABCDEFGHI ABCDEFGHI +HFA long double: +34.1,34.4 34.1,34.4 34.1,34.4 34.1,34.4 +33.1,33.3 34.1,34.4 34.1,34.4 34.1,34.4 +32.1,32.2 34.1,34.4 34.1,34.4 34.1,34.4 +31.1,31.1 34.1,34.4 34.1,34.4 34.1,34.4 +32.1,32.2 33.1,33.3 33.1,33.3 33.1,33.3 33.1,33.3 +31.1,31.1 33.1,33.3 33.1,33.3 33.1,33.3 33.1,33.3 +33.1,33.3 33.1,33.3 33.1,33.3 33.1,33.3 +34.1,34.4 32.1,32.2 32.1,32.2 32.1,32.2 32.1,32.2 +33.1,33.3 32.1,32.2 32.1,32.2 32.1,32.2 32.1,32.2 +34.1,34.4 32.1,32.2 31.1,31.1 31.1,31.1 31.1,31.1 31.1,31.1 +HFA double: +24.1,24.4 24.1,24.4 24.1,24.4 24.1,24.4 +23.1,23.3 24.1,24.4 24.1,24.4 24.1,24.4 +22.1,22.2 24.1,24.4 24.1,24.4 24.1,24.4 +21.1,21.1 24.1,24.4 24.1,24.4 24.1,24.4 +22.1,22.2 23.1,23.3 23.1,23.3 23.1,23.3 23.1,23.3 +21.1,21.1 23.1,23.3 23.1,23.3 23.1,23.3 23.1,23.3 +23.1,23.3 23.1,23.3 23.1,23.3 23.1,23.3 +24.1,24.4 22.1,22.2 22.1,22.2 22.1,22.2 22.1,22.2 +23.1,23.3 22.1,22.2 22.1,22.2 22.1,22.2 22.1,22.2 +24.1,24.4 22.1,22.2 21.1,21.1 21.1,21.1 21.1,21.1 21.1,21.1 +HFA float: +14.1,14.4 14.1,14.4 14.1,14.4 14.1,14.4 +13.1,13.3 14.1,14.4 14.1,14.4 14.1,14.4 +12.1,12.2 14.1,14.4 14.1,14.4 14.1,14.4 +11.1,11.1 14.1,14.4 14.1,14.4 14.1,14.4 +12.1,12.2 13.1,13.3 13.1,13.3 13.1,13.3 13.1,13.3 +11.1,11.1 13.1,13.3 13.1,13.3 13.1,13.3 13.1,13.3 +13.1,13.3 13.1,13.3 13.1,13.3 13.1,13.3 +14.1,14.4 12.1,12.2 12.1,12.2 12.1,12.2 12.1,12.2 +13.1,13.3 12.1,12.2 12.1,12.2 12.1,12.2 12.1,12.2 +14.1,14.4 12.1,12.2 11.1,11.1 11.1,11.1 11.1,11.1 11.1,11.1 +MOVI: +0 +abcd +abcd0000 +abcd00000000 +abcd000000000000 +ffffabcd +abcdffff +ffffffffffffabcd +ffffffffabcdffff +ffffabcdffffffff +abcdffffffffffff +aaaaaaaa +5555555555555555 +77777777 +3333333333333333 +f8f8f8f8 +1e1e1e1e1e1e1e1e +3f803f80 +1ff01ff01ff01ff +7fffc0 +3fff80003fff800 +7fffffffffe00 +abcd1234 +abcd00001234 +abcd000000001234 +abcd12340000 +abcd000012340000 +abcd123400000000 +ffffffffabcd1234 +ffffabcdffff1234 +abcdffffffff1234 +ffffabcd1234ffff +abcdffff1234ffff +abcd1234ffffffff +ffffef0123456789 +abcdef012345ffff +abcdef0123456789 +3e8 +3e8 +463 +36d +fffffffffffff3e9 +7b3e8 +3421 +ffffd3af +fffffc17 +fffffffffffffc18 +fffffc93 +fffffffffffffc93 +0 +3e8 +3e8 +ffffffff +3e8 +fffffffffffffc17 +e0 +3f8 +318 +3e8 +3e8 +3e8 +7d0 +0 +7d0 +0 +1f4 +0 +1f4 +0 +1f4 +0 +1f4 +0 diff --git a/lib/tinycc/tests/tests2/75_array_in_struct_init.c b/lib/tinycc/tests/tests2/75_array_in_struct_init.c new file mode 100644 index 000000000..234e3c4fa --- /dev/null +++ b/lib/tinycc/tests/tests2/75_array_in_struct_init.c @@ -0,0 +1,33 @@ +#include + +/* This test is a snippet from the J interpreter */ + +typedef long I; +typedef struct{I c[4];I b,e,k;} PT; + +PT cases[] = { + ((I)4194304L +(I)2097152L +(I)67108864L), (I)262144L, (((I)1L +(I)256L +(I)4L +(I)8L +(I)16L +(I)64L +(I)128L +(I)268435456L +(I)536870912L +(I)1024L +(I)4096L +(I)8192L +(I)16384L)+((I)2L +(I)131072L +(I)2048L)+(I)32L +(I)32768L +(I)65536L), -1L, 1,2,1, + ((I)+4194304L +(I)2097152L +(I)67108864L)+( (I)524288L +(I)262144L +(((I)1L +(I)256L +(I)4L +(I)8L +(I)16L +(I)64L +(I)128L +(I)268435456L +(I)536870912L +(I)1024L +(I)4096L +(I)8192L +(I)16384L)+((I)2L +(I)131072L +(I)2048L)+(I)32L +(I)32768L +(I)65536L)), (I)262144L, (I)262144L, (((I)1L +(I)256L +(I)4L +(I)8L +(I)16L +(I)64L +(I)128L +(I)268435456L +(I)536870912L +(I)1024L +(I)4096L +(I)8192L +(I)16384L)+((I)2L +(I)131072L +(I)2048L)+(I)32L +(I)32768L +(I)65536L), 2,3,2, + ((I)4194304L +(I)2097152L +(I)67108864L)+( (I)524288L +(I)262144L +(((I)1L +(I)256L +(I)4L +(I)8L +(I)16L +(I)64L +(I)128L +(I)268435456L +(I)536870912L +(I)1024L +(I)4096L +(I)8192L +(I)16384L)+((I)2L +(I)131072L +(I)2048L)+(I)32L +(I)32768L +(I)65536L)), (((I)1L +(I)256L +(I)4L +(I)8L +(I)16L +(I)64L +(I)128L +(I)268435456L +(I)536870912L +(I)1024L +(I)4096L +(I)8192L +(I)16384L)+((I)2L +(I)131072L +(I)2048L)+(I)32L +(I)32768L +(I)65536L), (I)262144L, (((I)1L +(I)256L +(I)4L +(I)8L +(I)16L +(I)64L +(I)128L +(I)268435456L +(I)536870912L +(I)1024L +(I)4096L +(I)8192L +(I)16384L)+((I)2L +(I)131072L +(I)2048L)+(I)32L +(I)32768L +(I)65536L), 1,3,2, + ((I)4194304L +(I)2097152L +(I)67108864L)+( (I)524288L +(I)262144L +(((I)1L +(I)256L +(I)4L +(I)8L +(I)16L +(I)64L +(I)128L +(I)268435456L +(I)536870912L +(I)1024L +(I)4096L +(I)8192L +(I)16384L)+((I)2L +(I)131072L +(I)2048L)+(I)32L +(I)32768L +(I)65536L)), (I)262144L +(((I)1L +(I)256L +(I)4L +(I)8L +(I)16L +(I)64L +(I)128L +(I)268435456L +(I)536870912L +(I)1024L +(I)4096L +(I)8192L +(I)16384L)+((I)2L +(I)131072L +(I)2048L)+(I)32L +(I)32768L +(I)65536L), (I)524288L, -1L, 1,2,1, + ((I)4194304L +(I)2097152L +(I)67108864L)+( (I)524288L +(I)262144L +(((I)1L +(I)256L +(I)4L +(I)8L +(I)16L +(I)64L +(I)128L +(I)268435456L +(I)536870912L +(I)1024L +(I)4096L +(I)8192L +(I)16384L)+((I)2L +(I)131072L +(I)2048L)+(I)32L +(I)32768L +(I)65536L)), (I)262144L +(((I)1L +(I)256L +(I)4L +(I)8L +(I)16L +(I)64L +(I)128L +(I)268435456L +(I)536870912L +(I)1024L +(I)4096L +(I)8192L +(I)16384L)+((I)2L +(I)131072L +(I)2048L)+(I)32L +(I)32768L +(I)65536L), (I)1048576L, (I)262144L +(((I)1L +(I)256L +(I)4L +(I)8L +(I)16L +(I)64L +(I)128L +(I)268435456L +(I)536870912L +(I)1024L +(I)4096L +(I)8192L +(I)16384L)+((I)2L +(I)131072L +(I)2048L)+(I)32L +(I)32768L +(I)65536L), 1,3,1, + ((I)4194304L +(I)2097152L +(I)67108864L)+( (I)524288L +(I)262144L +(((I)1L +(I)256L +(I)4L +(I)8L +(I)16L +(I)64L +(I)128L +(I)268435456L +(I)536870912L +(I)1024L +(I)4096L +(I)8192L +(I)16384L)+((I)2L +(I)131072L +(I)2048L)+(I)32L +(I)32768L +(I)65536L)), (I)262144L +(((I)1L +(I)256L +(I)4L +(I)8L +(I)16L +(I)64L +(I)128L +(I)268435456L +(I)536870912L +(I)1024L +(I)4096L +(I)8192L +(I)16384L)+((I)2L +(I)131072L +(I)2048L)+(I)32L +(I)32768L +(I)65536L), (I)262144L, (I)262144L, 1,3,1, + ((I)4194304L +(I)2097152L +(I)67108864L), ((I)1048576L +(I)524288L +(I)262144L +(((I)1L +(I)256L +(I)4L +(I)8L +(I)16L +(I)64L +(I)128L +(I)268435456L +(I)536870912L +(I)1024L +(I)4096L +(I)8192L +(I)16384L)+((I)2L +(I)131072L +(I)2048L)+(I)32L +(I)32768L +(I)65536L)), ((I)1048576L +(I)524288L +(I)262144L +(((I)1L +(I)256L +(I)4L +(I)8L +(I)16L +(I)64L +(I)128L +(I)268435456L +(I)536870912L +(I)1024L +(I)4096L +(I)8192L +(I)16384L)+((I)2L +(I)131072L +(I)2048L)+(I)32L +(I)32768L +(I)65536L)), -1L, 1,2,1, + (I)33554432L +(((I)1L +(I)256L +(I)4L +(I)8L +(I)16L +(I)64L +(I)128L +(I)268435456L +(I)536870912L +(I)1024L +(I)4096L +(I)8192L +(I)16384L)+((I)2L +(I)131072L +(I)2048L)+(I)32L +(I)32768L +(I)65536L), (I)2097152L, ((I)1048576L +(I)524288L +(I)262144L +(((I)1L +(I)256L +(I)4L +(I)8L +(I)16L +(I)64L +(I)128L +(I)268435456L +(I)536870912L +(I)1024L +(I)4096L +(I)8192L +(I)16384L)+((I)2L +(I)131072L +(I)2048L)+(I)32L +(I)32768L +(I)65536L)), -1L, 0,2,1, + (I)67108864L, ((I)1048576L +(I)524288L +(I)262144L +(((I)1L +(I)256L +(I)4L +(I)8L +(I)16L +(I)64L +(I)128L +(I)268435456L +(I)536870912L +(I)1024L +(I)4096L +(I)8192L +(I)16384L)+((I)2L +(I)131072L +(I)2048L)+(I)32L +(I)32768L +(I)65536L)), (I)134217728L, -1L, 0,2,0, +}; + +int main() { + int i, j; + + for(j=0; j < sizeof(cases)/sizeof(cases[0]); j++) { + for(i=0; i < sizeof(cases->c)/sizeof(cases->c[0]); i++) + printf("cases[%d].c[%d]=%ld\n", j, i, cases[j].c[i]); + + printf("cases[%d].b=%ld\n", j, cases[j].b); + printf("cases[%d].e=%ld\n", j, cases[j].e); + printf("cases[%d].k=%ld\n", j, cases[j].k); + printf("\n"); + } + return 0; +} diff --git a/lib/tinycc/tests/tests2/75_array_in_struct_init.expect b/lib/tinycc/tests/tests2/75_array_in_struct_init.expect new file mode 100644 index 000000000..2b75aa59d --- /dev/null +++ b/lib/tinycc/tests/tests2/75_array_in_struct_init.expect @@ -0,0 +1,72 @@ +cases[0].c[0]=73400320 +cases[0].c[1]=262144 +cases[0].c[2]=805567999 +cases[0].c[3]=-1 +cases[0].b=1 +cases[0].e=2 +cases[0].k=1 + +cases[1].c[0]=879754751 +cases[1].c[1]=262144 +cases[1].c[2]=262144 +cases[1].c[3]=805567999 +cases[1].b=2 +cases[1].e=3 +cases[1].k=2 + +cases[2].c[0]=879754751 +cases[2].c[1]=805567999 +cases[2].c[2]=262144 +cases[2].c[3]=805567999 +cases[2].b=1 +cases[2].e=3 +cases[2].k=2 + +cases[3].c[0]=879754751 +cases[3].c[1]=805830143 +cases[3].c[2]=524288 +cases[3].c[3]=-1 +cases[3].b=1 +cases[3].e=2 +cases[3].k=1 + +cases[4].c[0]=879754751 +cases[4].c[1]=805830143 +cases[4].c[2]=1048576 +cases[4].c[3]=805830143 +cases[4].b=1 +cases[4].e=3 +cases[4].k=1 + +cases[5].c[0]=879754751 +cases[5].c[1]=805830143 +cases[5].c[2]=262144 +cases[5].c[3]=262144 +cases[5].b=1 +cases[5].e=3 +cases[5].k=1 + +cases[6].c[0]=73400320 +cases[6].c[1]=807403007 +cases[6].c[2]=807403007 +cases[6].c[3]=-1 +cases[6].b=1 +cases[6].e=2 +cases[6].k=1 + +cases[7].c[0]=839122431 +cases[7].c[1]=2097152 +cases[7].c[2]=807403007 +cases[7].c[3]=-1 +cases[7].b=0 +cases[7].e=2 +cases[7].k=1 + +cases[8].c[0]=67108864 +cases[8].c[1]=807403007 +cases[8].c[2]=134217728 +cases[8].c[3]=-1 +cases[8].b=0 +cases[8].e=2 +cases[8].k=0 + diff --git a/lib/tinycc/tests/tests2/76_dollars_in_identifiers.c b/lib/tinycc/tests/tests2/76_dollars_in_identifiers.c new file mode 100644 index 000000000..c5fcf99e0 --- /dev/null +++ b/lib/tinycc/tests/tests2/76_dollars_in_identifiers.c @@ -0,0 +1,41 @@ +#include + +#define $(x) x +#define $fred 10 +#define joe$ 20 +#define hen$y 30 + +#define $10(x) x*10 +#define _$10(x) x/10 + +int main() +{ + printf("fred=%d\n", $fred); + printf("joe=%d\n", joe$); + printf("henry=%d\n", hen$y); + + printf("fred2=%d\n", $($fred)); + printf("joe2=%d\n", $(joe$)); + printf("henry2=%d\n", $(hen$y)); + + printf("fred10=%d\n", $10($fred)); + printf("joe_10=%d\n", _$10(joe$)); + + int $ = 10; + int a100$ = 100; + int a$$ = 1000; + int a$c$b = 2121; + int $100 = 10000; + const char *$$$ = "money"; + + printf("local=%d\n", $); + printf("a100$=%d\n", a100$); + printf("a$$=%d\n", a$$); + printf("a$c$b=%d\n", a$c$b); + printf("$100=%d\n", $100); + printf("$$$=%s", $$$); + + return 0; +} + +/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/ diff --git a/lib/tinycc/tests/tests2/76_dollars_in_identifiers.expect b/lib/tinycc/tests/tests2/76_dollars_in_identifiers.expect new file mode 100644 index 000000000..4a20a52e6 --- /dev/null +++ b/lib/tinycc/tests/tests2/76_dollars_in_identifiers.expect @@ -0,0 +1,14 @@ +fred=10 +joe=20 +henry=30 +fred2=10 +joe2=20 +henry2=30 +fred10=100 +joe_10=2 +local=10 +a100$=100 +a$$=1000 +a$c$b=2121 +$100=10000 +$$$=money diff --git a/lib/tinycc/tests/tests2/77_push_pop_macro.c b/lib/tinycc/tests/tests2/77_push_pop_macro.c new file mode 100644 index 000000000..d38e0bfe3 --- /dev/null +++ b/lib/tinycc/tests/tests2/77_push_pop_macro.c @@ -0,0 +1,30 @@ +#include + +int main() +{ + /* must not affect how #pragma ppop_macro works */ + #define pop_macro foobar1 + + /* must not affect how #pragma push_macro works */ + #define push_macro foobar2 + + #undef abort + #define abort "111" + printf("abort = %s\n", abort); + + #pragma push_macro("abort") + #undef abort + #define abort "222" + printf("abort = %s\n", abort); + + #pragma push_macro("abort") + #undef abort + #define abort "333" + printf("abort = %s\n", abort); + + #pragma pop_macro("abort") + printf("abort = %s\n", abort); + + #pragma pop_macro("abort") + printf("abort = %s\n", abort); +} diff --git a/lib/tinycc/tests/tests2/77_push_pop_macro.expect b/lib/tinycc/tests/tests2/77_push_pop_macro.expect new file mode 100644 index 000000000..d8a55305a --- /dev/null +++ b/lib/tinycc/tests/tests2/77_push_pop_macro.expect @@ -0,0 +1,5 @@ +abort = 111 +abort = 222 +abort = 333 +abort = 222 +abort = 111 diff --git a/lib/tinycc/tests/tests2/78_vla_label.c b/lib/tinycc/tests/tests2/78_vla_label.c new file mode 100644 index 000000000..4096495d9 --- /dev/null +++ b/lib/tinycc/tests/tests2/78_vla_label.c @@ -0,0 +1,45 @@ +#include + +/* This test segfaults as of April 27, 2015. */ +void f1(int argc) +{ + char test[argc]; + if(0) + label: + printf("boom!\n"); + if(argc-- == 0) + return; + goto label; +} + +/* This segfaulted on 2015-11-19. */ +void f2(void) +{ + goto start; + { + int a[1 && 1]; /* not a variable-length array */ + int b[1 || 1]; /* not a variable-length array */ + int c[1 ? 1 : 1]; /* not a variable-length array */ + start: + a[0] = 0; + b[0] = 0; + c[0] = 0; + } +} + +void f3(void) +{ + printf("%d\n", 0 ? printf("x1\n") : 11); + printf("%d\n", 1 ? 12 : printf("x2\n")); + printf("%d\n", 0 && printf("x3\n")); + printf("%d\n", 1 || printf("x4\n")); +} + +int main() +{ + f1(2); + f2(); + f3(); + + return 0; +} diff --git a/lib/tinycc/tests/tests2/78_vla_label.expect b/lib/tinycc/tests/tests2/78_vla_label.expect new file mode 100644 index 000000000..3f4063bec --- /dev/null +++ b/lib/tinycc/tests/tests2/78_vla_label.expect @@ -0,0 +1,6 @@ +boom! +boom! +11 +12 +0 +1 diff --git a/lib/tinycc/tests/tests2/79_vla_continue.c b/lib/tinycc/tests/tests2/79_vla_continue.c new file mode 100644 index 000000000..dd6379014 --- /dev/null +++ b/lib/tinycc/tests/tests2/79_vla_continue.c @@ -0,0 +1,119 @@ +#include + +int f(void) +{ + return 5; +} + +void test1() +{ + int count = 10; + void *addr[10]; + for(;count--;) { + int a[f()]; + + addr[count] = a; + + continue; + } + + if(addr[9] == addr[0]) { + printf("OK\n"); + } else { + printf("NOT OK\n"); + } +} + +void test2() +{ + int count = 10; + void *addr[count]; + for(;count--;) { + int a[f()]; + + addr[count] = a; + + continue; + } + + if(addr[9] == addr[0]) { + printf("OK\n"); + } else { + printf("NOT OK\n"); + } +} + +void test3() +{ + int count = 10; + void *addr[count]; + while(count--) { + int b[f()]; + if (count >= 0) { + int a[f()]; + + addr[count] = a; + + continue; + } + } + + if(addr[9] == addr[0]) { + printf("OK\n"); + } else { + printf("NOT OK\n"); + } +} + +void test4() +{ + int count = 10; + void *addr[count]; + do { + int a[f()]; + + addr[--count] = a; + + continue; + } while (count); + + if(addr[9] == addr[0]) { + printf("OK\n"); + } else { + printf("NOT OK\n"); + } +} + +void test5() +{ + int count = 10; + int a[f()]; + int c[f()]; + + c[0] = 42; + + for(;count--;) { + int b[f()]; + int i; + for (i=0; i +struct wchar { + char *data; char mem[]; +}; +struct wint { + char *data; int mem[]; +}; +int f1char (void) { + char s[9]="nonono"; + struct wchar q = {"bugs"}; + return !s[0]; +} +int f1int (void) { + char s[9]="nonono"; + struct wint q = {"bugs"}; + return !s[0]; +} +int empty[] = {}; // GNU extension +int main (void) { + char s[9]="nonono"; + static struct wchar q = {"bugs", {'c'}}; + //printf ("tcc has %s %s\n", s, q.data); + if (f1char() || f1int()) + printf ("bla\n"); + return !s[0]; +} diff --git a/lib/tinycc/tests/tests2/80_flexarray.expect b/lib/tinycc/tests/tests2/80_flexarray.expect new file mode 100644 index 000000000..e69de29bb diff --git a/lib/tinycc/tests/tests2/81_types.c b/lib/tinycc/tests/tests2/81_types.c new file mode 100644 index 000000000..0bc3bae42 --- /dev/null +++ b/lib/tinycc/tests/tests2/81_types.c @@ -0,0 +1,55 @@ +/* The following are all valid decls, even though some subtypes + are incomplete. */ +enum E *e; +const enum E *e1; +enum E const *e2; +struct S *s; +const struct S *s1; +struct S const *s2; + +/* Various strangely looking declarators, which are all valid + and have to map to the same numbered typedefs. */ +typedef int (*fptr1)(); +int f1 (int (), int); +typedef int (*fptr2)(int x); +int f2 (int (int x), int); +typedef int (*fptr3)(int); +int f3 (int (int), int); +typedef int (*fptr4[4])(int); +int f4 (int (*[4])(int), int); +typedef int (*fptr5)(fptr1); +int f5 (int (int()), fptr1); +int f1 (fptr1 fp, int i) +{ + return (*fp)(i); +} +int f2 (fptr2 fp, int i) +{ + return (*fp)(i); +} +int f3 (fptr3 fp, int i) +{ + return (*fp)(i); +} +int f4 (fptr4 fp, int i) +{ + return (*fp[i])(i); +} +int f5 (fptr5 fp, fptr1 i) +{ + return fp(i); +} +typedef int intx4[4]; +int f8 (intx4, int); +int f8 (int ([4]), int); +int f8 (int y[4], int i) +{ + return y[i]; +} +int f9 (int (*)(int), int); +int f9 (int ((int)), int); +int f9 (int f(int), int i) +{ + return f(i); +} +int main () { return 0; } diff --git a/lib/tinycc/tests/tests2/81_types.expect b/lib/tinycc/tests/tests2/81_types.expect new file mode 100644 index 000000000..e69de29bb diff --git a/lib/tinycc/tests/tests2/82_attribs_position.c b/lib/tinycc/tests/tests2/82_attribs_position.c new file mode 100644 index 000000000..d8c9fe5f1 --- /dev/null +++ b/lib/tinycc/tests/tests2/82_attribs_position.c @@ -0,0 +1,71 @@ +typedef unsigned short uint16_t; +typedef unsigned char uint8_t; + +typedef union Unaligned16a { + uint16_t u; + uint8_t b[2]; +} __attribute__((packed)) Unaligned16a; + +typedef union __attribute__((packed)) Unaligned16b { + uint16_t u; + uint8_t b[2]; +} Unaligned16b; + +extern void foo (void) __attribute__((stdcall)); +void __attribute__((stdcall)) foo (void) +{ +} + +#define __stdcall __attribute__((stdcall)) +extern int some_stdcall_func (int, int, int) __stdcall; +__stdcall int __stdcall some_stdcall_func(int foo, int bar, int baz) { + //printf("Hello from stdcall: %i %i %i\n", foo, bar, baz); + return 43; +} + +/* The actual attribute isn't important, must just be + parsable. */ +#define ATTR __attribute__((__noinline__)) +int ATTR actual_function() { + return 42; +} + +int label_attribute (void) +{ +lab1: __attribute__((__unused__)); + return 0; +} + +extern int printf (const char *, ...); +static int globalvar; +int main() +{ + void *function_pointer = &actual_function; + int localvar = 42, i; + + 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); + + /* All these should work and leave the stack pointer in its original + position. */ + some_stdcall_func(1, 10, 100); + ((int __stdcall (*)(int, int, int))some_stdcall_func) (2, 20, 200); + ((int(*__stdcall)(int, int, int))some_stdcall_func) (3, 30, 300); + for (i = 0; i < 1024; i++) { + globalvar = i; + /* This was once misparsed at <= gitrev 325241c0, forgetting + the stdcall attribute on the function pointer leading to + stack increment being done twice (in callee and caller). + This will clobber 'i' and 'localvar' which is how we detect + this. */ + ((int(__stdcall*)(int, int, int))some_stdcall_func) (4, 40, 400); + if (localvar != 42 || globalvar != i) + printf("error, localvar=%d i=%d globalvar=%d\n", localvar, i, globalvar); + } + return 0; +} diff --git a/lib/tinycc/tests/tests2/82_attribs_position.expect b/lib/tinycc/tests/tests2/82_attribs_position.expect new file mode 100644 index 000000000..daaac9e30 --- /dev/null +++ b/lib/tinycc/tests/tests2/82_attribs_position.expect @@ -0,0 +1,2 @@ +42 +42 diff --git a/lib/tinycc/tests/tests2/83_utf8_in_identifiers.c b/lib/tinycc/tests/tests2/83_utf8_in_identifiers.c new file mode 100644 index 000000000..1f8609525 --- /dev/null +++ b/lib/tinycc/tests/tests2/83_utf8_in_identifiers.c @@ -0,0 +1,9 @@ +#include +double привет=0.1; +int Lefèvre=2; +int main(){ + printf("привет=%g\n",привет); + printf("Lefèvre=%d\n",Lefèvre); + return 0; +} +// pcc & tcc only diff --git a/lib/tinycc/tests/tests2/83_utf8_in_identifiers.expect b/lib/tinycc/tests/tests2/83_utf8_in_identifiers.expect new file mode 100644 index 000000000..1553f5f6f --- /dev/null +++ b/lib/tinycc/tests/tests2/83_utf8_in_identifiers.expect @@ -0,0 +1,2 @@ +привет=0.1 +Lefèvre=2 diff --git a/lib/tinycc/tests/tests2/84_hex-float.c b/lib/tinycc/tests/tests2/84_hex-float.c new file mode 100644 index 000000000..0ef09bfc2 --- /dev/null +++ b/lib/tinycc/tests/tests2/84_hex-float.c @@ -0,0 +1,12 @@ +extern int printf(const char *format, ...); + +#define ACPI_TYPE_INVALID 0x1E +#define NUM_NS_TYPES ACPI_TYPE_INVALID+1 +int array[NUM_NS_TYPES]; + +#define n 0xe +int main() +{ + printf("n+1 = %d\n", n+1); +// printf("n+1 = %d\n", 0xe+1); +} diff --git a/lib/tinycc/tests/tests2/84_hex-float.expect b/lib/tinycc/tests/tests2/84_hex-float.expect new file mode 100644 index 000000000..2175385aa --- /dev/null +++ b/lib/tinycc/tests/tests2/84_hex-float.expect @@ -0,0 +1 @@ +n+1 = 15 diff --git a/lib/tinycc/tests/tests2/85_asm-outside-function.c b/lib/tinycc/tests/tests2/85_asm-outside-function.c new file mode 100644 index 000000000..3d7434dd9 --- /dev/null +++ b/lib/tinycc/tests/tests2/85_asm-outside-function.c @@ -0,0 +1,15 @@ +#ifdef __leading_underscore +# define _ "_" +#else +# define _ +#endif + +extern int printf (const char *, ...); +extern void vide(void); +__asm__(_"vide: ret"); + +int main() { + vide(); + printf ("okay\n"); + return 0; +} diff --git a/lib/tinycc/tests/tests2/85_asm-outside-function.expect b/lib/tinycc/tests/tests2/85_asm-outside-function.expect new file mode 100644 index 000000000..dcf02b2fb --- /dev/null +++ b/lib/tinycc/tests/tests2/85_asm-outside-function.expect @@ -0,0 +1 @@ +okay diff --git a/lib/tinycc/tests/tests2/86_memory-model.c b/lib/tinycc/tests/tests2/86_memory-model.c new file mode 100644 index 000000000..744c3e207 --- /dev/null +++ b/lib/tinycc/tests/tests2/86_memory-model.c @@ -0,0 +1,38 @@ +#include + +int +main() +{ +#if defined(__LLP64__) + if (sizeof(short) == 2 + && sizeof(int) == 4 + && sizeof(long int) == 4 + && sizeof(long long int) == 8 + && sizeof(void*) == 8) { + (void)printf("Ok\n"); + } else { + (void)printf("KO __LLP64__\n"); + } +#elif defined(__LP64__) + if (sizeof(short) == 2 + && sizeof(int) == 4 + && sizeof(long int) == 8 + && sizeof(long long int) == 8 + && sizeof(void*) == 8) { + (void)printf("Ok\n"); + } else { + (void)printf("KO __LP64__\n"); + } +#elif defined(__ILP32__) + if (sizeof(short) == 2 + && sizeof(int) == 4 + && sizeof(long int) == 4 + && sizeof(void*) == 4) { + (void)printf("Ok\n"); + } else { + (void)printf("KO __ILP32__\n"); + } +#else + (void)printf("KO no __*LP*__ defined.\n"); +#endif +} diff --git a/lib/tinycc/tests/tests2/86_memory-model.expect b/lib/tinycc/tests/tests2/86_memory-model.expect new file mode 100644 index 000000000..7326d9603 --- /dev/null +++ b/lib/tinycc/tests/tests2/86_memory-model.expect @@ -0,0 +1 @@ +Ok diff --git a/lib/tinycc/tests/tests2/87_dead_code.c b/lib/tinycc/tests/tests2/87_dead_code.c new file mode 100644 index 000000000..369f4bab6 --- /dev/null +++ b/lib/tinycc/tests/tests2/87_dead_code.c @@ -0,0 +1,165 @@ +/* This checks various ways of dead code inside if statements + where there are non-obvious ways of how the code is actually + not dead due to reachable by labels. */ +extern int printf (const char *, ...); +static void kb_wait_1(void) +{ + unsigned long timeout = 2; + do { + /* Here the else arm is a statement expression that's supposed + to be suppressed. The label inside the while would unsuppress + code generation again if not handled correctly. And that + would wreak havoc to the cond-expression because there's no + jump-around emitted, the whole statement expression really + needs to not generate code (perhaps except useless forward jumps). */ + (1 ? + printf("timeout=%ld\n", timeout) : + ({ + int i = 1; + while (1) + while (i--) + some_label: + printf("error\n"); + goto some_label; + }) + ); + 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()); +} + +static void nondead_after_dead_return(void) +{ + /* This statement expr is not entered, and hence that fact that it + doesn't fall-through should not influence the surrounding code. */ + 0 && ({ return; 0;}); + printf ("nondead works\n"); + return; +} + +int main (void) +{ + int i = 1; + kb_wait_1(); + + /* Simple test of dead code at first sight which isn't actually dead. */ + if (0) { +yeah: + printf ("yeah\n"); + } else { + printf ("boo\n"); + } + if (i--) + goto yeah; + + /* Some more non-obvious uses where the problems are loops, so that even + the first loop statements aren't actually dead. */ + i = 1; + if (0) { + while (i--) { + printf ("once\n"); +enterloop: + printf ("twice\n"); + } + } + if (i >= 0) + goto enterloop; + + /* The same with statement expressions. One might be tempted to + handle them specially by counting if inside statement exprs and + not unsuppressing code at loops at all then. + See kb_wait_1 for the other side of the medal where that wouldn't work. */ + i = ({ + int j = 1; + if (0) { + while (j--) { + printf ("SEonce\n"); + enterexprloop: + printf ("SEtwice\n"); + } + } + if (j >= 0) + goto enterexprloop; + j; }); + + /* The other two loop forms: */ + i = 1; + if (0) { + for (i = 1; i--;) { + printf ("once2\n"); +enterloop2: + printf ("twice2\n"); + } + } + if (i > 0) + goto enterloop2; + + i = 1; + if (0) { + do { + printf ("once3\n"); +enterloop3: + printf ("twice3\n"); + } while (i--); + } + if (i > 0) + goto enterloop3; + + /* And check that case and default labels have the same effect + of disabling code suppression. */ + i = 41; + switch (i) { + if (0) { + printf ("error\n"); + case 42: + printf ("error2\n"); + case 41: + printf ("caseok\n"); + } + } + + i = 41; + switch (i) { + if (0) { + printf ("error3\n"); + default: + printf ("caseok2\n"); + break; + case 42: + printf ("error4\n"); + } + } + + dowhile(); + nondead_after_dead_return(); + + return 0; +} diff --git a/lib/tinycc/tests/tests2/87_dead_code.expect b/lib/tinycc/tests/tests2/87_dead_code.expect new file mode 100644 index 000000000..781ff518e --- /dev/null +++ b/lib/tinycc/tests/tests2/87_dead_code.expect @@ -0,0 +1,24 @@ +timeout=2 +timeout=1 +boo +yeah +twice +once +twice +SEtwice +SEonce +SEtwice +twice2 +once2 +twice2 +twice3 +once3 +twice3 +caseok +caseok2 +g=1 +check 1 +g=2 +check 2 +g=3 +nondead works diff --git a/lib/tinycc/tests/tests2/88_codeopt.c b/lib/tinycc/tests/tests2/88_codeopt.c new file mode 100644 index 000000000..3faa5fac6 --- /dev/null +++ b/lib/tinycc/tests/tests2/88_codeopt.c @@ -0,0 +1,80 @@ +/* Check some way in where code suppression caused various + miscompilations. */ +extern int printf (const char *, ...); +typedef __SIZE_TYPE__ size_t; + +size_t _brk_start, _brk_end; +void * extend_brk(size_t size, size_t align) +{ + size_t mask = align - 1; + void *ret = 0; + + do { + if (__builtin_expect(!!(_brk_start == 0), 0)) + do { + printf("wrong1\n"); + } while (0); + } while (0); + _brk_end = (_brk_end + mask) & ~mask; + ret = (void *)_brk_end; + _brk_end += size; + + return ret; +} + +static void get_args (int a, int b) +{ + if (a != 1) + printf("wrong2\n"); + else + printf("okay\n"); +} + +void bla(void) +{ + int __ret = 42; + ({ + if (__builtin_expect(!!(0), 0)) { + if (__builtin_expect(!!__ret, 0)) + printf("wrong3\n"); + int x = !!(__ret); + } + __ret; + }); + get_args(!!__ret, sizeof(__ret)); +} + +int ext; + +void broken_jumpopt (int xxx) +{ + /* This was broken in 8227db3a2 by code suppression during suppressed + code :) */ + ext = (xxx || 1) || ((xxx && 1) || 1); + printf("okay: %d %d\n", xxx, ext); +} + +_Bool chk(unsigned long addr, unsigned long limit, unsigned long size) +{ + _Bool ret; + /* This just needs to compile, no runtime test. (And it doesn't compile + only with certain internal checking added that's not committed). */ + if (0) + ret = 0 != (!!(addr > limit - size)); + return 0; +} + +int main() +{ + void *r; + _brk_start = 1024; + _brk_end = 1024; + r = extend_brk (4096, 16); + if (!r) + printf("wrong4\n"); + else + printf("okay\n"); + bla(); + broken_jumpopt(42); + return 0; +} diff --git a/lib/tinycc/tests/tests2/88_codeopt.expect b/lib/tinycc/tests/tests2/88_codeopt.expect new file mode 100644 index 000000000..76b582b39 --- /dev/null +++ b/lib/tinycc/tests/tests2/88_codeopt.expect @@ -0,0 +1,3 @@ +okay +okay +okay: 42 1 diff --git a/lib/tinycc/tests/tests2/89_nocode_wanted.c b/lib/tinycc/tests/tests2/89_nocode_wanted.c new file mode 100644 index 000000000..73e0a4bc8 --- /dev/null +++ b/lib/tinycc/tests/tests2/89_nocode_wanted.c @@ -0,0 +1,112 @@ +extern int printf(const char *format, ...); +static void kb_wait_1(void) +{ + unsigned long timeout = 2; + do { + (1 ? + printf("timeout=%ld\n", timeout) : + ({ + while (1) + printf("error\n"); + }) + ); + timeout--; + } while (timeout); +} +static void kb_wait_2(void) +{ + unsigned long timeout = 2; + do { + (1 ? + printf("timeout=%ld\n", timeout) : + ({ + for (;;) + printf("error\n"); + }) + ); + timeout--; + } while (timeout); +} +static void kb_wait_2_1(void) +{ + unsigned long timeout = 2; + do { + (1 ? + printf("timeout=%ld\n", timeout) : + ({ + do { + printf("error\n"); + } while (1); + }) + ); + timeout--; + } while (timeout); +} +static void kb_wait_2_2(void) +{ + unsigned long timeout = 2; + do { + (1 ? + printf("timeout=%ld\n", timeout) : + ({ + label: + printf("error\n"); + goto label; + }) + ); + timeout--; + } while (timeout); +} +static void kb_wait_3(void) +{ + unsigned long timeout = 2; + do { + (1 ? + printf("timeout=%ld\n", timeout) : + ({ + int i = 1; + goto label; + i = i + 2; + label: + i = i + 3; + }) + ); + timeout--; + } while (timeout); +} +static void kb_wait_4(void) +{ + unsigned long timeout = 2; + do { + (1 ? + printf("timeout=%ld\n", timeout) : + ({ + switch(timeout) { + case 2: + printf("timeout is 2"); + break; + case 1: + printf("timeout is 1"); + break; + default: + printf("timeout is 0?"); + break; + }; + // return; + }) + ); + timeout--; + } while (timeout); +} +int main() +{ + printf("begin\n"); + kb_wait_1(); + kb_wait_2(); + kb_wait_2_1(); + kb_wait_2_2(); + kb_wait_3(); + kb_wait_4(); + printf("end\n"); + return 0; +} diff --git a/lib/tinycc/tests/tests2/89_nocode_wanted.expect b/lib/tinycc/tests/tests2/89_nocode_wanted.expect new file mode 100644 index 000000000..c44d4ea6c --- /dev/null +++ b/lib/tinycc/tests/tests2/89_nocode_wanted.expect @@ -0,0 +1,14 @@ +begin +timeout=2 +timeout=1 +timeout=2 +timeout=1 +timeout=2 +timeout=1 +timeout=2 +timeout=1 +timeout=2 +timeout=1 +timeout=2 +timeout=1 +end diff --git a/lib/tinycc/tests/tests2/90_struct-init.c b/lib/tinycc/tests/tests2/90_struct-init.c new file mode 100644 index 000000000..4a71a93dc --- /dev/null +++ b/lib/tinycc/tests/tests2/90_struct-init.c @@ -0,0 +1,424 @@ +typedef unsigned char u8; +typedef struct {} empty_s; +struct contains_empty { + u8 a; + empty_s empty; + u8 b; +}; +struct contains_empty ce = { { (1) }, (empty_s){}, 022, }; +/* The following decl of 'q' would demonstrate the TCC bug in init_putv when + handling copying compound literals. (Compound literals + aren't acceptable constant initializers in isoc99, but + we accept them like gcc, except for this case) +//char *q = (char *){ "trara" }; */ +struct SS {u8 a[3], b; }; +struct SS sinit16[] = { { 1 }, 2 }; +struct S +{ + u8 a,b; + u8 c[2]; +}; + +struct T +{ + u8 s[16]; + u8 a; +}; + +struct U +{ + u8 a; + struct S s; + u8 b; + struct T t; +}; + +struct V +{ + struct S s; + struct T t; + u8 a; +}; + +struct W +{ + struct V t; + struct S s[]; +}; + +struct S gs = ((struct S){1, 2, 3, 4}); +struct S gs2 = {1, 2, {3, 4}}; +struct T gt = {"hello", 42}; +struct U gu = {3, 5,6,7,8, 4, "huhu", 43}; +struct U gu2 = {3, {5,6,7,8}, 4, {"huhu", 43}}; +/* Optional braces around scalar initializers. Accepted, but with + a warning. */ +struct U gu3 = { {3}, {5,6,7,8,}, 4, {"huhu", 43}}; +/* Many superfluous braces and leaving out one initializer for U.s.c[1] */ +struct U gu4 = { 3, {5,6,7,}, 5, { "bla", {44}} }; +/* Superfluous braces and useless parens around values */ +struct S gs3 = { (1), {(2)}, {(((3))), {4}}}; +/* Superfluous braces, and leaving out braces for V.t, plus cast */ +struct V gv = {{{3},4,{5,6}}, "haha", (u8)45, 46}; +/* Compound literal */ +struct V gv2 = {(struct S){7,8,{9,10}}, {"hihi", 47}, 48}; +/* Parens around compound literal */ +struct V gv3 = {((struct S){7,8,{9,10}}), {"hoho", 49}, 50}; +/* Initialization of a flex array member (warns in GCC) */ +struct W gw = {{1,2,3,4}, {1,2,3,4,5}}; + +union UU { + u8 a; + u8 b; +}; +struct SU { + union UU u; + u8 c; +}; +struct SU gsu = {5,6}; + +/* Unnamed struct/union members aren't ISO C, but it's a widely accepted + extension. See below for further extensions to that under -fms-extension.*/ +union UV { + struct {u8 a,b;}; + struct S s; +}; +union UV guv = {{6,5}}; +union UV guv2 = {{.b = 7, .a = 8}}; +union UV guv3 = {.b = 8, .a = 7}; + +struct SSU { + int y; + struct { int x; }; +}; +struct SSU gssu1 = { .y = 5, .x = 3 }; +struct SSU gssu2 = { 5, 3 }; + +/* Under -fms-extensions also the following is valid: +union UV2 { + struct Anon {u8 a,b;}; // unnamed member, but tagged struct, ... + struct S s; +}; +struct Anon gan = { 10, 11 }; // ... which makes it available here. +union UV2 guv4 = {{4,3}}; // and the other inits from above as well +*/ + +struct in6_addr { + union { + u8 u6_addr8[16]; + unsigned short u6_addr16[8]; + } u; +}; +struct flowi6 { + struct in6_addr saddr, daddr; +}; +struct pkthdr { + struct in6_addr daddr, saddr; +}; +struct pkthdr phdr = { { { 6,5,4,3 } }, { { 9,8,7,6 } } }; + +struct Wrap { + void *func; +}; +int global; +void inc_global (void) +{ + global++; +} + +struct Wrap global_wrap[] = { + ((struct Wrap) {inc_global}), + inc_global, +}; + +#include +void print_ (const char *name, const u8 *p, long size) +{ + printf ("%s:", name); + while (size--) { + printf (" %x", *p++); + } + printf ("\n"); +} +#define print(x) print_(#x, (u8*)&x, sizeof (x)) +#if 1 +void foo (struct W *w, struct pkthdr *phdr_) +{ + struct S ls = {1, 2, 3, 4}; + struct S ls2 = {1, 2, {3, 4}}; + struct T lt = {"hello", 42}; + struct U lu = {3, 5,6,7,8, 4, "huhu", 43}; + struct U lu1 = {3, ls, 4, {"huhu", 43}}; + struct U lu2 = {3, (ls), 4, {"huhu", 43}}; + const struct S *pls = &ls; + struct S ls21 = *pls; + struct U lu22 = {3, *pls, 4, {"huhu", 43}}; + /* Incomplete bracing. */ + struct U lu21 = {3, ls, 4, "huhu", 43}; + /* Optional braces around scalar initializers. Accepted, but with + a warning. */ + struct U lu3 = { 3, {5,6,7,8,}, 4, {"huhu", 43}}; + /* Many superfluous braces and leaving out one initializer for U.s.c[1] */ + struct U lu4 = { 3, {5,6,7,}, 5, { "bla", 44} }; + /* Superfluous braces and useless parens around values */ + struct S ls3 = { (1), (2), {(((3))), 4}}; + /* Superfluous braces, and leaving out braces for V.t, plus cast */ + struct V lv = {{3,4,{5,6}}, "haha", (u8)45, 46}; + /* Compound literal */ + struct V lv2 = {(struct S)w->t.s, {"hihi", 47}, 48}; + /* Parens around compound literal */ + struct V lv3 = {((struct S){7,8,{9,10}}), ((const struct W *)w)->t.t, 50}; + const struct pkthdr *phdr = phdr_; + struct flowi6 flow = { .daddr = phdr->daddr, .saddr = phdr->saddr }; + int elt = 0x42; + /* Range init, overlapping */ + struct T lt2 = { { [1 ... 5] = 9, [6 ... 10] = elt, [4 ... 7] = elt+1 }, 1 }; + struct SSU lssu1 = { 5, 3 }; + struct SSU lssu2 = { .y = 5, .x = 3 }; + /* designated initializers in GNU form */ +#if defined(__GNUC__) || defined(__TINYC__) + struct S ls4 = {a: 1, b: 2, c: {3, 4}}; +#else + struct S ls4 = {.a = 1, .b = 2, .c = {3, 4}}; +#endif + print(ls); + print(ls2); + print(lt); + print(lu); + print(lu1); + print(lu2); + print(ls21); + print(lu21); + print(lu22); + print(lu3); + print(lu4); + print(ls3); + print(lv); + print(lv2); + print(lv3); + print(lt2); + print(lssu1); + print(lssu2); + print(flow); + print(ls4); +} +#endif + +void test_compound_with_relocs (void) +{ + struct Wrap local_wrap[] = { + ((struct Wrap) {inc_global}), + inc_global, + }; + void (*p)(void); + p = global_wrap[0].func; p(); + p = global_wrap[1].func; p(); + p = local_wrap[0].func; p(); + p = local_wrap[1].func; p(); +} + +void sys_ni(void) { printf("ni\n"); } +void sys_one(void) { printf("one\n"); } +void sys_two(void) { printf("two\n"); } +void sys_three(void) { printf("three\n"); } +void sys_four(void) { printf("four\n"); } +typedef void (*fptr)(void); + +#define array_size(a) (sizeof a / sizeof a[0]) + +void test_multi_relocs(void) +{ + int i; + + static const fptr tabl1[4] = { + [0 ... 3] = &sys_ni, + [0] = sys_one, + [1] = sys_two, + [2] = sys_three, + sys_four, + [1 ... 2] = &sys_ni, + [1] = 0, + }; + for (i = 0; i < array_size(tabl1); i++) + if (tabl1[i]) + tabl1[i](); + else + printf("(0)\n"); + + const fptr tabl2[4] = { + [0 ... 3] = &sys_ni, + [0] = sys_one, + [1] = sys_two, + [2] = sys_three, + sys_four, + [1 ... 2] = &sys_ni, + [1] = 0, + }; + for (i = 0; i < array_size(tabl2); i++) + if (tabl2[i]) + tabl2[i](); + else + printf("(0)\n"); + + int c = 0; + int dd[] = { + [0 ... 1] = ++c, + [2 ... 3] = ++c + }; + for (i = 0; i < array_size(dd); i++) + printf(" %d", dd[i]); + printf("\n"); + + /* multi-dimensional flex array with range initializers */ + static char m1[][2][3] = {[0 ... 2]={{3,4,5},{6,7,8}},{{9},10},"abc"}; + char m2[][2][3] = {[0 ... 2]={{3,4,5},{6,7,8}},{{9},10},"abc"}; + int g, j, k; + for (g = 2; g-- > 0;) { + printf("mdfa %s: %d -", "locl\0glob" + g * 5, sizeof m1); + for (i = 0; i < array_size(m1); i++) + for (j = 0; j < array_size(m1[0]); j++) + for (k = 0; k < array_size(m1[0][0]); k++) + printf(" %d", (g ? m1:m2)[i][j][k]); + printf("\n"); + } +} + +void test_init_ranges(void) { + int i,c=0; + static void *gostring[] = { + [0 ... 31] = &&l_bad, [127] = &&l_bad, + [32 ... 126] = &&l_loop, + ['\\'] = &&l_esc, ['"'] = &&l_qdown, + [128 ... 191] = &&l_bad, + [192 ... 223] = &&l_utf8_2, + [224 ... 239] = &&l_utf8_3, + [240 ... 247] = &&l_utf8_4, + [248 ... 255] = &&l_bad + }; + + for (i = 0; i < 256; i++) { + goto *gostring[i]; + l_bad: c++; + l_loop: c++; + l_esc: c++; + l_qdown: c++; + l_utf8_2: c++; + l_utf8_3: c++; + l_utf8_4: c++; + } + printf ("%d\n", c); +} + + +/* Following is from GCC gcc.c-torture/execute/20050613-1.c. */ + +struct SEA { int i; int j; int k; int l; }; +struct SEB { struct SEA a; int r[1]; }; +struct SEC { struct SEA a; int r[0]; }; +struct SED { struct SEA a; int r[]; }; + +static void +test_correct_filling (struct SEA *x) +{ + static int i; + if (x->i != 0 || x->j != 5 || x->k != 0 || x->l != 0) + printf("sea_fill%d: wrong\n", i); + else + printf("sea_fill%d: okay\n", i); + i++; +} + +int +test_zero_init (void) +{ + /* The peculiarity here is that only a.j is initialized. That + means that all other members must be zero initialized. TCC + once didn't do that for sub-level designators. */ + struct SEB b = { .a.j = 5 }; + struct SEC c = { .a.j = 5 }; + struct SED d = { .a.j = 5 }; + test_correct_filling (&b.a); + test_correct_filling (&c.a); + test_correct_filling (&d.a); + return 0; +} + +void test_init_struct_from_struct(void) +{ + int i = 0; + struct S {int x,y;} + a = {1,2}, + b = {3,4}, + c[] = {a,b}, + d[] = {++i, ++i, ++i, ++i}, + e[] = {b, (struct S){5,6}} + ; + + printf("%s: %d %d %d %d - %d %d %d %d - %d %d %d %d\n", + __FUNCTION__, + c[0].x, + c[0].y, + c[1].x, + c[1].y, + d[0].x, + d[0].y, + d[1].x, + d[1].y, + e[0].x, + e[0].y, + e[1].x, + e[1].y + ); +} + +typedef struct { + unsigned int a; + unsigned int : 32; + unsigned int b; + unsigned long long : 64; + unsigned int c; +} tst_bf; + +tst_bf arr[] = { { 1, 2, 3 } }; + +void +test_init_bf(void) +{ + printf ("%s: %d %d %d\n", __FUNCTION__, arr[0].a, arr[0].b, arr[0].c); +} + + +int main() +{ + print(ce); + print(gs); + print(gs2); + print(gt); + print(gu); + print(gu2); + print(gu3); + print(gu4); + print(gs3); + print(gv); + print(gv2); + print(gv3); + print(sinit16); + print(gw); + print(gsu); + print(guv); + print(guv.b); + print(guv2); + print(guv3); + print(gssu1); + print(gssu2); + print(phdr); + foo(&gw, &phdr); + //printf("q: %s\n", q); + test_compound_with_relocs(); + test_multi_relocs(); + test_zero_init(); + test_init_ranges(); + test_init_struct_from_struct(); + test_init_bf(); + return 0; +} diff --git a/lib/tinycc/tests/tests2/90_struct-init.expect b/lib/tinycc/tests/tests2/90_struct-init.expect new file mode 100644 index 000000000..5014f8216 --- /dev/null +++ b/lib/tinycc/tests/tests2/90_struct-init.expect @@ -0,0 +1,59 @@ +ce: 1 12 +gs: 1 2 3 4 +gs2: 1 2 3 4 +gt: 68 65 6c 6c 6f 0 0 0 0 0 0 0 0 0 0 0 2a +gu: 3 5 6 7 8 4 68 75 68 75 0 0 0 0 0 0 0 0 0 0 0 0 2b +gu2: 3 5 6 7 8 4 68 75 68 75 0 0 0 0 0 0 0 0 0 0 0 0 2b +gu3: 3 5 6 7 8 4 68 75 68 75 0 0 0 0 0 0 0 0 0 0 0 0 2b +gu4: 3 5 6 7 0 5 62 6c 61 0 0 0 0 0 0 0 0 0 0 0 0 0 2c +gs3: 1 2 3 4 +gv: 3 4 5 6 68 61 68 61 0 0 0 0 0 0 0 0 0 0 0 0 2d 2e +gv2: 7 8 9 a 68 69 68 69 0 0 0 0 0 0 0 0 0 0 0 0 2f 30 +gv3: 7 8 9 a 68 6f 68 6f 0 0 0 0 0 0 0 0 0 0 0 0 31 32 +sinit16: 1 0 0 0 2 0 0 0 +gw: 1 2 3 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +gsu: 5 6 +guv: 6 5 0 0 +guv.b: 5 +guv2: 8 7 0 0 +guv3: 7 8 0 0 +gssu1: 5 0 0 0 3 0 0 0 +gssu2: 5 0 0 0 3 0 0 0 +phdr: 6 5 4 3 0 0 0 0 0 0 0 0 0 0 0 0 9 8 7 6 0 0 0 0 0 0 0 0 0 0 0 0 +ls: 1 2 3 4 +ls2: 1 2 3 4 +lt: 68 65 6c 6c 6f 0 0 0 0 0 0 0 0 0 0 0 2a +lu: 3 5 6 7 8 4 68 75 68 75 0 0 0 0 0 0 0 0 0 0 0 0 2b +lu1: 3 1 2 3 4 4 68 75 68 75 0 0 0 0 0 0 0 0 0 0 0 0 2b +lu2: 3 1 2 3 4 4 68 75 68 75 0 0 0 0 0 0 0 0 0 0 0 0 2b +ls21: 1 2 3 4 +lu21: 3 1 2 3 4 4 68 75 68 75 0 0 0 0 0 0 0 0 0 0 0 0 2b +lu22: 3 1 2 3 4 4 68 75 68 75 0 0 0 0 0 0 0 0 0 0 0 0 2b +lu3: 3 5 6 7 8 4 68 75 68 75 0 0 0 0 0 0 0 0 0 0 0 0 2b +lu4: 3 5 6 7 0 5 62 6c 61 0 0 0 0 0 0 0 0 0 0 0 0 0 2c +ls3: 1 2 3 4 +lv: 3 4 5 6 68 61 68 61 0 0 0 0 0 0 0 0 0 0 0 0 2d 2e +lv2: 1 2 3 4 68 69 68 69 0 0 0 0 0 0 0 0 0 0 0 0 2f 30 +lv3: 7 8 9 a 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 32 +lt2: 0 9 9 9 43 43 43 43 42 42 42 0 0 0 0 0 1 +lssu1: 5 0 0 0 3 0 0 0 +lssu2: 5 0 0 0 3 0 0 0 +flow: 9 8 7 6 0 0 0 0 0 0 0 0 0 0 0 0 6 5 4 3 0 0 0 0 0 0 0 0 0 0 0 0 +ls4: 1 2 3 4 +one +(0) +ni +four +one +(0) +ni +four + 1 1 2 2 +mdfa glob: 30 - 3 4 5 6 7 8 3 4 5 6 7 8 3 4 5 6 7 8 9 0 0 10 0 0 97 98 99 0 0 0 +mdfa locl: 30 - 3 4 5 6 7 8 3 4 5 6 7 8 3 4 5 6 7 8 9 0 0 10 0 0 97 98 99 0 0 0 +sea_fill0: okay +sea_fill1: okay +sea_fill2: okay +1438 +test_init_struct_from_struct: 1 2 3 4 - 1 2 3 4 - 3 4 5 6 +test_init_bf: 1 2 3 diff --git a/lib/tinycc/tests/tests2/91_ptr_longlong_arith32.c b/lib/tinycc/tests/tests2/91_ptr_longlong_arith32.c new file mode 100644 index 000000000..bf07915ab --- /dev/null +++ b/lib/tinycc/tests/tests2/91_ptr_longlong_arith32.c @@ -0,0 +1,15 @@ +int printf(const char *, ...); +char t[] = "012345678"; + +int main(void) +{ + char *data = t; + unsigned long long r = 4; + unsigned a = 5; + unsigned long long b = 12; + + *(unsigned*)(data + r) += a - b; + + printf("data = \"%s\"\n", data); + return 0; +} diff --git a/lib/tinycc/tests/tests2/91_ptr_longlong_arith32.expect b/lib/tinycc/tests/tests2/91_ptr_longlong_arith32.expect new file mode 100644 index 000000000..f91e4b420 --- /dev/null +++ b/lib/tinycc/tests/tests2/91_ptr_longlong_arith32.expect @@ -0,0 +1 @@ +data = "0123-5678" diff --git a/lib/tinycc/tests/tests2/92_enum_bitfield.c b/lib/tinycc/tests/tests2/92_enum_bitfield.c new file mode 100644 index 000000000..fb8f7a372 --- /dev/null +++ b/lib/tinycc/tests/tests2/92_enum_bitfield.c @@ -0,0 +1,58 @@ +/* This checks if enums needing 8 bit but only having positive + values are correctly zero extended (instead of sign extended) + when stored into/loaded from a 8 bit bit-field of enum type (which + itself is implementation defined, so isn't necessarily supported by all + other compilers). */ +enum tree_code { + SOME_CODE = 148, /* has bit 7 set, and hence all further enum values as well */ + LAST_AND_UNUSED_TREE_CODE +}; +typedef union tree_node *tree; +struct tree_common +{ + union tree_node *chain; + union tree_node *type; + enum tree_code code : 8; + unsigned side_effects_flag : 1; +}; +union tree_node +{ + struct tree_common common; + }; +enum c_tree_code { + C_DUMMY_TREE_CODE = LAST_AND_UNUSED_TREE_CODE, + STMT_EXPR, + LAST_C_TREE_CODE +}; +enum cplus_tree_code { + CP_DUMMY_TREE_CODE = LAST_C_TREE_CODE, + AMBIG_CONV, + LAST_CPLUS_TREE_CODE +}; + +extern int printf(const char *, ...); +int blah(){return 0;} + +int convert_like_real (tree convs) +{ + switch (((enum tree_code) (convs)->common.code)) + { + case AMBIG_CONV: /* This has bit 7 set, which must not be the sign + bit in tree_common.code, i.e. the bitfield must + be somehow marked unsigned. */ + return blah(); + default: + break; + }; + printf("unsigned enum bit-fields broken\n"); + return 0; +} + +int main() +{ + union tree_node convs; + + convs.common.code = AMBIG_CONV; + convert_like_real (&convs); + return 0; +} diff --git a/lib/tinycc/tests/tests2/92_enum_bitfield.expect b/lib/tinycc/tests/tests2/92_enum_bitfield.expect new file mode 100644 index 000000000..e69de29bb diff --git a/lib/tinycc/tests/tests2/93_integer_promotion.c b/lib/tinycc/tests/tests2/93_integer_promotion.c new file mode 100644 index 000000000..a1176fc6b --- /dev/null +++ b/lib/tinycc/tests/tests2/93_integer_promotion.c @@ -0,0 +1,71 @@ +/* integer promotion */ + +int printf(const char*, ...); +#define promote(s) printf(" %ssigned : %s\n", (s) - 100 < 0 ? " " : "un", #s); + +int main (void) +{ + struct { + unsigned ub:3; + unsigned u:32; + unsigned long long ullb:35; + unsigned long long ull:64; + unsigned char c; + } s = { 1, 1, 1 }; + + promote(s.ub); + promote(s.u); + promote(s.ullb); + promote(s.ull); + promote(s.c); + printf("\n"); + + promote((1 ? s.ub : 1)); + promote((1 ? s.u : 1)); + promote((1 ? s.ullb : 1)); + promote((1 ? s.ull : 1)); + promote((1 ? s.c : 1)); + printf("\n"); + + promote(s.ub << 1); + promote(s.u << 1); + promote(s.ullb << 1); + promote(s.ull << 1); + promote(s.c << 1); + printf("\n"); + + promote(+s.ub); + promote(+s.u); + promote(+s.ullb); + promote(+s.ull); + promote(+s.c); + printf("\n"); + + promote(-s.ub); + promote(-s.u); + promote(-s.ullb); + promote(-s.ull); + promote(-s.c); + printf("\n"); + + promote(~s.ub); + promote(~s.u); + promote(~s.ullb); + promote(~s.ull); + promote(~s.c); + printf("\n"); + + promote(!s.ub); + promote(!s.u); + promote(!s.ullb); + promote(!s.ull); + promote(!s.c); + printf("\n"); + + promote(+(unsigned)s.ub); + promote(-(unsigned)s.ub); + promote(~(unsigned)s.ub); + promote(!(unsigned)s.ub); + + return 0; +} diff --git a/lib/tinycc/tests/tests2/93_integer_promotion.expect b/lib/tinycc/tests/tests2/93_integer_promotion.expect new file mode 100644 index 000000000..34b9c145c --- /dev/null +++ b/lib/tinycc/tests/tests2/93_integer_promotion.expect @@ -0,0 +1,46 @@ + signed : s.ub + unsigned : s.u + signed : s.ullb + unsigned : s.ull + signed : s.c + + signed : (1 ? s.ub : 1) + unsigned : (1 ? s.u : 1) + signed : (1 ? s.ullb : 1) + unsigned : (1 ? s.ull : 1) + signed : (1 ? s.c : 1) + + signed : s.ub << 1 + unsigned : s.u << 1 + signed : s.ullb << 1 + unsigned : s.ull << 1 + signed : s.c << 1 + + signed : +s.ub + unsigned : +s.u + signed : +s.ullb + unsigned : +s.ull + signed : +s.c + + signed : -s.ub + unsigned : -s.u + signed : -s.ullb + unsigned : -s.ull + signed : -s.c + + signed : ~s.ub + unsigned : ~s.u + signed : ~s.ullb + unsigned : ~s.ull + signed : ~s.c + + signed : !s.ub + signed : !s.u + signed : !s.ullb + signed : !s.ull + signed : !s.c + + unsigned : +(unsigned)s.ub + unsigned : -(unsigned)s.ub + unsigned : ~(unsigned)s.ub + signed : !(unsigned)s.ub diff --git a/lib/tinycc/tests/tests2/94_generic.c b/lib/tinycc/tests/tests2/94_generic.c new file mode 100644 index 000000000..7ad9dd067 --- /dev/null +++ b/lib/tinycc/tests/tests2/94_generic.c @@ -0,0 +1,131 @@ +#include + +const int a = 0; + +struct a { + int a; +}; + +struct b { + int a; +}; + +int a_f() +{ + return 20; +} + +int b_f() +{ + return 10; +} + +typedef int (*fptr)(int); +typedef void (*vfptr)(int); +int foo(int i) +{ + return i; +} +void void_foo(int i) {} + +typedef int int_type1; + +typedef int T[4]; +int f(T t) +{ + return _Generic(t, __typeof__( ((void)0, (T){0}) ) : 1 ); +} + +#define gen_sw(a) _Generic(a, const char *: 1, default: 8, int: 123); + +int main() +{ + int i = 0; + signed long int l = 2; + struct b titi; + const int * const ptr; + const char *ti; + int_type1 i2; + T t; + + i = _Generic(a, int: a_f, const int: b_f)(); + printf("%d\n", i); + i = _Generic(a, int: a_f() / 2, const int: b_f() / 2); + printf("%d\n", i); + i = _Generic(ptr, int *:1, int * const:2, default:20); + printf("%d\n", i); + i = gen_sw(a); + printf("%d\n", i); + i = _Generic(titi, struct a:1, struct b:2, default:20); + printf("%d\n", i); + i = _Generic(i2, char: 1, int : 0); + printf("%d\n", i); + i = _Generic(a, char:1, int[4]:2, default:5); + printf("%d\n", i); + i = _Generic(17, int :1, int **:2); + printf("%d\n", i); + i = _Generic(17L, int :1, long :2, long long : 3); + printf("%d\n", i); + i = _Generic("17, io", char *: 3, const char *: 1); + printf("%d\n", i); + i = _Generic(ti, const unsigned char *:1, const char *:4, char *:3, + const signed char *:2); + printf("%d\n", i); + printf("%s\n", _Generic(i + 2L, long: "long", int: "int", + long long: "long long")); + i = _Generic(l, long: 1, int: 2); + printf("%d\n", i); + i = _Generic(foo, fptr: 3, int: 4, vfptr: 5); + printf("%d\n", i); + i = _Generic(void_foo, fptr: 3, int: 4, vfptr: 5); + 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); + //but this is no null-ptr constant, so fallback to void-choice + i = 0; + _Generic( 1?(void*)(i*0LL):&i, 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); })); + } + + printf ("%d\n", f(t)); + + return 0; +} diff --git a/lib/tinycc/tests/tests2/94_generic.expect b/lib/tinycc/tests/tests2/94_generic.expect new file mode 100644 index 000000000..79be7ab0f --- /dev/null +++ b/lib/tinycc/tests/tests2/94_generic.expect @@ -0,0 +1,16 @@ +20 +10 +20 +123 +2 +0 +5 +1 +2 +3 +4 +long +1 +3 +5 +1 diff --git a/lib/tinycc/tests/tests2/95_bitfields.c b/lib/tinycc/tests/tests2/95_bitfields.c new file mode 100644 index 000000000..4ac38da66 --- /dev/null +++ b/lib/tinycc/tests/tests2/95_bitfields.c @@ -0,0 +1,241 @@ +/* ----------------------------------------------------------------------- */ +#if TEST == 1 +{ + struct M P A __s + { + unsigned x : 12; + unsigned char y : 7; + unsigned z : 28; + unsigned a: 4; + unsigned b: 5; + }; + TEST_STRUCT(0x333,0x44,0x555555,6,7); +} + +/* ----------------------------------------------------------------------- */ +#elif TEST == 2 +{ + struct M P __s + { + int x: 12; + char y: 6; + long long z:63; + A char a:4; + long long b:2; + + }; + TEST_STRUCT(3,30,0x123456789abcdef0LL,5,2); +} + +/* ----------------------------------------------------------------------- */ +#elif TEST == 3 +{ + struct M P __s + { + unsigned x:5, y:5, :0, z:5; char a:5; A short b:5; + }; + TEST_STRUCT(21,23,25,6,14); +} + +/* ----------------------------------------------------------------------- */ +#elif TEST == 4 +{ + struct M P __s { + int x : 3; + int : 2; + int y : 1; + int : 0; + int z : 5; + int a : 7; + unsigned int b : 7; + }; + TEST_STRUCT(3,1,15,120,120); +} + +/* ----------------------------------------------------------------------- */ +#elif TEST == 5 +{ + struct M P __s { + long long x : 45; + long long : 2; + long long y : 30; + unsigned long long z : 38; + char a; short b; + }; + TEST_STRUCT(0x123456789ULL, 120<<25, 120, 0x44, 0x77); +} + +/* ----------------------------------------------------------------------- */ +#elif TEST == 6 +{ + struct M P __s { + int a; + signed char b; + int x : 12, y : 4, : 0, : 4, z : 3; + char d; + }; + TEST_STRUCT(1,2,3,4,-3); +} + +/* ----------------------------------------------------------------------- */ +#elif TEST == 7 +{ +#ifdef _WIN32 + typedef long long int ll; +#else + typedef long int ll; +#endif + struct M P __s { + ll d : 16; + ll b : 16; + ll x : 16; + ll y : 1; + ll z : 2; + ll a : 11; + ll e : 1; + ll f : 1; + }; + TEST_STRUCT(1,2,3,4,5); +} + +/* ----------------------------------------------------------------------- */ +#elif defined PACK + +#if PACK +# pragma pack(push,1) +# define P //_P +#else +# define P +#endif + +printf("\n\n" + 2*top); +#define TEST 1 +#include SELF +top = 0; +#define TEST 2 +#include SELF +#define TEST 3 +#include SELF +#define TEST 4 +#include SELF +#define TEST 5 +#include SELF +#define TEST 6 +#include SELF +#define TEST 7 +#include SELF + +#if PACK +# pragma pack(pop) +#endif + +#undef P +#undef PACK + +/* ----------------------------------------------------------------------- */ +#elif defined ALIGN + +#if ALIGN +# define A _A(16) +#else +# define A +#endif + +#define PACK 0 +#include SELF +#define PACK 1 +#include SELF + +#undef A +#undef ALIGN + +/* ----------------------------------------------------------------------- */ +#elif defined MS_BF + +#if MS_BF +# ifdef __TINYC__ +# pragma comment(option, "-mms-bitfields") +# elif defined __GNUC__ +# define M __attribute__((ms_struct)) +# endif +#else +# ifdef __TINYC__ +# pragma comment(option, "-mno-ms-bitfields") +# elif defined __GNUC__ +# define M __attribute__((gcc_struct)) +# endif +#endif +#ifndef M +# define M +#endif + +#define ALIGN 0 +#include SELF +#define ALIGN 1 +#include SELF + +#undef M +#undef MS_BF + +/* ----------------------------------------------------------------------- */ +#else + +#include +#include +/* some gcc headers #define __attribute__ to empty if it's not gcc */ +#undef __attribute__ + +void dump(void *p, int s) +{ + int i; + for (i = s; --i >= 0;) + printf("%02X", ((unsigned char*)p)[i]); + printf("\n"); +} + +#define pv(m) \ + printf(sizeof (s->m + 0) == 8 ? " %016llx" : " %02x", s->m) + +#define TEST_STRUCT(v1,v2,v3,v4,v5) { \ + struct __s _s, *s = & _s; \ + printf("\n---- TEST %d%s%s%s ----\n" + top, \ + TEST, MS_BF?" - MS-BITFIELDS":"", \ + PACK?" - PACKED":"", \ + ALIGN?" - WITH ALIGN":""); \ + memset(s, 0, sizeof *s); \ + s->x = -1, s->y = -1, s->z = -1, s->a = -1, s->b = -1; \ + printf("bits in use : "), dump(s, sizeof *s); \ + s->x = v1, s->y = v2, s->z = v3, s->a += v4, ++s->a, s->b = v5; \ + printf("bits as set : "), dump(s, sizeof *s); \ + printf("values :"), pv(x), pv(y), pv(z), pv(a), pv(b), printf("\n"); \ + printf("align/size : %d %d\n", alignof(struct __s),sizeof(struct __s)); \ + } + +#ifdef _MSC_VER +# define _A(n) __declspec(align(n)) +# define _P +# define alignof(x) __alignof(x) +#else +# define _A(n) __attribute__((aligned(n))) +# define _P __attribute__((packed)) +# define alignof(x) __alignof__(x) +#endif + +#ifndef MS_BITFIELDS +# define MS_BITFIELDS 0 +#endif + +#define SELF "95_bitfields.c" + +int top = 1; + +int main() +{ +#define MS_BF MS_BITFIELDS +#include SELF + return 0; +} + +/* ----------------------------------------------------------------------- */ +#endif +#undef TEST diff --git a/lib/tinycc/tests/tests2/95_bitfields.expect b/lib/tinycc/tests/tests2/95_bitfields.expect new file mode 100644 index 000000000..215055d35 --- /dev/null +++ b/lib/tinycc/tests/tests2/95_bitfields.expect @@ -0,0 +1,173 @@ +---- TEST 1 ---- +bits in use : 0000001FFFFFFFFF007F0FFF +bits as set : 000000076055555500440333 +values : 333 44 555555 06 07 +align/size : 4 12 + +---- TEST 2 ---- +bits in use : 000000000000003F7FFFFFFFFFFFFFFF00000000003F0FFF +bits as set : 0000000000000025123456789ABCDEF000000000001E0003 +values : 03 1e 123456789abcdef0 05 fffffffe +align/size : 8 24 + +---- TEST 3 ---- +bits in use : 001F1F1F000003FF +bits as set : 000E0619000002F5 +values : 15 17 19 06 0e +align/size : 4 8 + +---- TEST 4 ---- +bits in use : 0007FFFF00000027 +bits as set : 00078F0F00000023 +values : 03 ffffffff 0f fffffff8 78 +align/size : 4 8 + +---- TEST 5 ---- +bits in use : FFFFFF3FFFFFFFFF000000003FFFFFFF00001FFFFFFFFFFF +bits as set : 007744000000007800000000300000000000000123456789 +values : 0000000123456789 f0000000 0000000000000078 44 77 +align/size : 8 24 + +---- TEST 6 ---- +bits in use : 0000007000FFFFFFFFFFFFFF +bits as set : 00000030002001FD00000004 +values : 01 02 03 04 fffffffd +align/size : 4 12 + +---- TEST 7 ---- +bits in use : 3FFFFFFFFFFF0000 +bits as set : 0026000100050000 +values : 01 00 ffffffff 04 05 +align/size : 8 8 + + + +---- TEST 1 - PACKED ---- +bits in use : FFFFFFFFFFFFFF +bits as set : 3B02AAAAAC4333 +values : 333 44 555555 06 07 +align/size : 1 7 + +---- TEST 2 - PACKED ---- +bits in use : 7FFFFFFFFFFFFFFFFFFFFF +bits as set : 4A48D159E26AF37BC1E003 +values : 03 1e 123456789abcdef0 05 fffffffe +align/size : 1 11 + +---- TEST 3 - PACKED ---- +bits in use : 7FFF000003FF +bits as set : 38D9000002F5 +values : 15 17 19 06 0e +align/size : 1 6 + +---- TEST 4 - PACKED ---- +bits in use : 07FFFF00000027 +bits as set : 078F0F00000023 +values : 03 ffffffff 0f fffffff8 78 +align/size : 1 7 + +---- TEST 5 - PACKED ---- +bits in use : FFFFFF07FFFFFFFFFFFFFFFF9FFFFFFFFFFF +bits as set : 007744000000000F18000000000123456789 +values : 0000000123456789 f0000000 0000000000000078 44 77 +align/size : 1 18 + +---- TEST 6 - PACKED ---- +bits in use : 007000FFFFFFFFFFFFFF +bits as set : 0030002001FD00000004 +values : 01 02 03 04 fffffffd +align/size : 1 10 + +---- TEST 7 - PACKED ---- +bits in use : 3FFFFFFFFFFF0000 +bits as set : 0026000100050000 +values : 01 00 ffffffff 04 05 +align/size : 1 8 + + + +---- TEST 1 - WITH ALIGN ---- +bits in use : 000000000000001FFFFFFFFF007F0FFF +bits as set : 00000000000000076055555500440333 +values : 333 44 555555 06 07 +align/size : 16 16 + +---- TEST 2 - WITH ALIGN ---- +bits in use : 0000000000000000000000000000003F7FFFFFFFFFFFFFFF00000000003F0FFF +bits as set : 00000000000000000000000000000025123456789ABCDEF000000000001E0003 +values : 03 1e 123456789abcdef0 05 fffffffe +align/size : 16 32 + +---- TEST 3 - WITH ALIGN ---- +bits in use : 0000000000000000000000000000001F000000000000000000001F1F000003FF +bits as set : 0000000000000000000000000000000E000000000000000000000619000002F5 +values : 15 17 19 06 0e +align/size : 16 32 + +---- TEST 4 - WITH ALIGN ---- +bits in use : 0007FFFF00000027 +bits as set : 00078F0F00000023 +values : 03 ffffffff 0f fffffff8 78 +align/size : 4 8 + +---- TEST 5 - WITH ALIGN ---- +bits in use : FFFFFF3FFFFFFFFF000000003FFFFFFF00001FFFFFFFFFFF +bits as set : 007744000000007800000000300000000000000123456789 +values : 0000000123456789 f0000000 0000000000000078 44 77 +align/size : 8 24 + +---- TEST 6 - WITH ALIGN ---- +bits in use : 0000007000FFFFFFFFFFFFFF +bits as set : 00000030002001FD00000004 +values : 01 02 03 04 fffffffd +align/size : 4 12 + +---- TEST 7 - WITH ALIGN ---- +bits in use : 3FFFFFFFFFFF0000 +bits as set : 0026000100050000 +values : 01 00 ffffffff 04 05 +align/size : 8 8 + + + +---- TEST 1 - PACKED - WITH ALIGN ---- +bits in use : 000000000000000000FFFFFFFFFFFFFF +bits as set : 0000000000000000003B02AAAAAC4333 +values : 333 44 555555 06 07 +align/size : 16 16 + +---- TEST 2 - PACKED - WITH ALIGN ---- +bits in use : 3F01FFFFFFFFFFFFFFFFFFFF +bits as set : 250048D159E26AF37BC1E003 +values : 03 1e 123456789abcdef0 05 fffffffe +align/size : 1 12 + +---- TEST 3 - PACKED - WITH ALIGN ---- +bits in use : 1F03FF000003FF +bits as set : 0E00D9000002F5 +values : 15 17 19 06 0e +align/size : 1 7 + +---- TEST 4 - PACKED - WITH ALIGN ---- +bits in use : 07FFFF00000027 +bits as set : 078F0F00000023 +values : 03 ffffffff 0f fffffff8 78 +align/size : 1 7 + +---- TEST 5 - PACKED - WITH ALIGN ---- +bits in use : FFFFFF07FFFFFFFFFFFFFFFF9FFFFFFFFFFF +bits as set : 007744000000000F18000000000123456789 +values : 0000000123456789 f0000000 0000000000000078 44 77 +align/size : 1 18 + +---- TEST 6 - PACKED - WITH ALIGN ---- +bits in use : 007000FFFFFFFFFFFFFF +bits as set : 0030002001FD00000004 +values : 01 02 03 04 fffffffd +align/size : 1 10 + +---- TEST 7 - PACKED - WITH ALIGN ---- +bits in use : 3FFFFFFFFFFF0000 +bits as set : 0026000100050000 +values : 01 00 ffffffff 04 05 +align/size : 1 8 diff --git a/lib/tinycc/tests/tests2/95_bitfields_ms.c b/lib/tinycc/tests/tests2/95_bitfields_ms.c new file mode 100644 index 000000000..b196fbd66 --- /dev/null +++ b/lib/tinycc/tests/tests2/95_bitfields_ms.c @@ -0,0 +1,2 @@ +#define MS_BITFIELDS 1 +#include "95_bitfields.c" diff --git a/lib/tinycc/tests/tests2/95_bitfields_ms.expect b/lib/tinycc/tests/tests2/95_bitfields_ms.expect new file mode 100644 index 000000000..97c46be56 --- /dev/null +++ b/lib/tinycc/tests/tests2/95_bitfields_ms.expect @@ -0,0 +1,173 @@ +---- TEST 1 - MS-BITFIELDS ---- +bits in use : 0000001FFFFFFFFF0000007F00000FFF +bits as set : 00000007605555550000004400000333 +values : 333 44 555555 06 07 +align/size : 4 16 + +---- TEST 2 - MS-BITFIELDS ---- +bits in use : 0000000000000003000000000000000F7FFFFFFFFFFFFFFF0000003F00000FFF +bits as set : 00000000000000020000000000000005123456789ABCDEF00000001E00000003 +values : 03 1e 123456789abcdef0 05 fffffffffffffffe +align/size : 8 32 + +---- TEST 3 - MS-BITFIELDS ---- +bits in use : 001F001F0000001F000003FF +bits as set : 000E000600000019000002F5 +values : 15 17 19 06 0e +align/size : 4 12 + +---- TEST 4 - MS-BITFIELDS ---- +bits in use : 0007FFFF00000027 +bits as set : 00078F0F00000023 +values : 03 ffffffff 0f fffffff8 78 +align/size : 4 8 + +---- TEST 5 - MS-BITFIELDS ---- +bits in use : 00000000FFFF00FF0000003FFFFFFFFF000000003FFFFFFF00001FFFFFFFFFFF +bits as set : 0000000000770044000000000000007800000000300000000000000123456789 +values : 0000000123456789 fffffffff0000000 0000000000000078 44 77 +align/size : 8 32 + +---- TEST 6 - MS-BITFIELDS ---- +bits in use : 00000000000000700000FFFF000000FFFFFFFFFF +bits as set : 000000000000003000002001000000FD00000004 +values : 01 02 03 04 fffffffd +align/size : 4 20 + +---- TEST 7 - MS-BITFIELDS ---- +bits in use : 3FFFFFFFFFFF0000 +bits as set : 0026000100050000 +values : 0000000000000001 0000000000000000 ffffffffffffffff 0000000000000004 0000000000000005 +align/size : 8 8 + + + +---- TEST 1 - MS-BITFIELDS - PACKED ---- +bits in use : 0000001FFFFFFFFF7F00000FFF +bits as set : 00000007605555554400000333 +values : 333 44 555555 06 07 +align/size : 1 13 + +---- TEST 2 - MS-BITFIELDS - PACKED ---- +bits in use : 00000000000000030F7FFFFFFFFFFFFFFF3F00000FFF +bits as set : 000000000000000205123456789ABCDEF01E00000003 +values : 03 1e 123456789abcdef0 05 fffffffffffffffe +align/size : 1 22 + +---- TEST 3 - MS-BITFIELDS - PACKED ---- +bits in use : 001F1F0000001F000003FF +bits as set : 000E0600000019000002F5 +values : 15 17 19 06 0e +align/size : 1 11 + +---- TEST 4 - MS-BITFIELDS - PACKED ---- +bits in use : 0007FFFF00000027 +bits as set : 00078F0F00000023 +values : 03 ffffffff 0f fffffff8 78 +align/size : 1 8 + +---- TEST 5 - MS-BITFIELDS - PACKED ---- +bits in use : FFFFFF0000003FFFFFFFFF000000003FFFFFFF00001FFFFFFFFFFF +bits as set : 007744000000000000007800000000300000000000000123456789 +values : 0000000123456789 fffffffff0000000 0000000000000078 44 77 +align/size : 1 27 + +---- TEST 6 - MS-BITFIELDS - PACKED ---- +bits in use : 00000000700000FFFFFFFFFFFFFF +bits as set : 000000003000002001FD00000004 +values : 01 02 03 04 fffffffd +align/size : 1 14 + +---- TEST 7 - MS-BITFIELDS - PACKED ---- +bits in use : 3FFFFFFFFFFF0000 +bits as set : 0026000100050000 +values : 0000000000000001 0000000000000000 ffffffffffffffff 0000000000000004 0000000000000005 +align/size : 1 8 + + + +---- TEST 1 - MS-BITFIELDS - WITH ALIGN ---- +bits in use : 0000001FFFFFFFFF0000007F00000FFF +bits as set : 00000007605555550000004400000333 +values : 333 44 555555 06 07 +align/size : 16 16 + +---- TEST 2 - MS-BITFIELDS - WITH ALIGN ---- +bits in use : 0000000000000003000000000000000F7FFFFFFFFFFFFFFF0000003F00000FFF +bits as set : 00000000000000020000000000000005123456789ABCDEF00000001E00000003 +values : 03 1e 123456789abcdef0 05 fffffffffffffffe +align/size : 16 32 + +---- TEST 3 - MS-BITFIELDS - WITH ALIGN ---- +bits in use : 0000000000000000000000000000001F000000000000001F0000001F000003FF +bits as set : 0000000000000000000000000000000E000000000000000600000019000002F5 +values : 15 17 19 06 0e +align/size : 16 32 + +---- TEST 4 - MS-BITFIELDS - WITH ALIGN ---- +bits in use : 0007FFFF00000027 +bits as set : 00078F0F00000023 +values : 03 ffffffff 0f fffffff8 78 +align/size : 4 8 + +---- TEST 5 - MS-BITFIELDS - WITH ALIGN ---- +bits in use : 00000000FFFF00FF0000003FFFFFFFFF000000003FFFFFFF00001FFFFFFFFFFF +bits as set : 0000000000770044000000000000007800000000300000000000000123456789 +values : 0000000123456789 fffffffff0000000 0000000000000078 44 77 +align/size : 8 32 + +---- TEST 6 - MS-BITFIELDS - WITH ALIGN ---- +bits in use : 00000000000000700000FFFF000000FFFFFFFFFF +bits as set : 000000000000003000002001000000FD00000004 +values : 01 02 03 04 fffffffd +align/size : 4 20 + +---- TEST 7 - MS-BITFIELDS - WITH ALIGN ---- +bits in use : 3FFFFFFFFFFF0000 +bits as set : 0026000100050000 +values : 0000000000000001 0000000000000000 ffffffffffffffff 0000000000000004 0000000000000005 +align/size : 8 8 + + + +---- TEST 1 - MS-BITFIELDS - PACKED - WITH ALIGN ---- +bits in use : 0000000000001FFFFFFFFF7F00000FFF +bits as set : 00000000000007605555554400000333 +values : 333 44 555555 06 07 +align/size : 16 16 + +---- TEST 2 - MS-BITFIELDS - PACKED - WITH ALIGN ---- +bits in use : 00000000000000030F0000007FFFFFFFFFFFFFFF3F00000FFF +bits as set : 000000000000000205000000123456789ABCDEF01E00000003 +values : 03 1e 123456789abcdef0 05 fffffffffffffffe +align/size : 16 25 + +---- TEST 3 - MS-BITFIELDS - PACKED - WITH ALIGN ---- +bits in use : 001F000000000000001F0000001F000003FF +bits as set : 000E000000000000000600000019000002F5 +values : 15 17 19 06 0e +align/size : 16 18 + +---- TEST 4 - MS-BITFIELDS - PACKED - WITH ALIGN ---- +bits in use : 0007FFFF00000027 +bits as set : 00078F0F00000023 +values : 03 ffffffff 0f fffffff8 78 +align/size : 1 8 + +---- TEST 5 - MS-BITFIELDS - PACKED - WITH ALIGN ---- +bits in use : FFFFFF0000003FFFFFFFFF000000003FFFFFFF00001FFFFFFFFFFF +bits as set : 007744000000000000007800000000300000000000000123456789 +values : 0000000123456789 fffffffff0000000 0000000000000078 44 77 +align/size : 1 27 + +---- TEST 6 - MS-BITFIELDS - PACKED - WITH ALIGN ---- +bits in use : 00000000700000FFFFFFFFFFFFFF +bits as set : 000000003000002001FD00000004 +values : 01 02 03 04 fffffffd +align/size : 1 14 + +---- TEST 7 - MS-BITFIELDS - PACKED - WITH ALIGN ---- +bits in use : 3FFFFFFFFFFF0000 +bits as set : 0026000100050000 +values : 0000000000000001 0000000000000000 ffffffffffffffff 0000000000000004 0000000000000005 +align/size : 1 8 diff --git a/lib/tinycc/tests/tests2/96_nodata_wanted.c b/lib/tinycc/tests/tests2/96_nodata_wanted.c new file mode 100644 index 000000000..95938b545 --- /dev/null +++ b/lib/tinycc/tests/tests2/96_nodata_wanted.c @@ -0,0 +1,102 @@ +/*****************************************************************************/ +/* test 'nodata_wanted' data output suppression */ + +#if defined test_static_data_error +void foo() { + if (1) { + static short w = (int)&foo; /* initializer not computable */ + } +} + +#elif defined test_static_nodata_error +void foo() { + if (0) { + static short w = (int)&foo; /* initializer not computable */ + } +} + +#elif defined test_global_data_error +void foo(); +static short w = (int)&foo; /* initializer not computable */ + + +#elif defined test_local_data_noerror +void foo() { + short w = &foo; /* 2 cast warnings */ +} + +#elif defined test_data_suppression_off || defined test_data_suppression_on + +#if defined test_data_suppression_on +# define SKIP 1 +#else +# define SKIP 0 +#endif + +#include +/* some gcc headers #define __attribute__ to empty if it's not gcc */ +#undef __attribute__ + +int main() +{ + __label__ ts0, te0, ts1, te1; + int tl, dl; + + static const char ds0 = 0; + static const char de0 = 0; + /* get reference size of empty jmp */ +ts0:; + if (!SKIP) {} +te0:; + dl = -(&de0 - &ds0); + tl = -(&&te0 - &&ts0); + + /* test data and code suppression */ + static const char ds1 = 0; +ts1:; + if (!SKIP) { + void *p = (void*)&main; + char cc[] = "static string"; + double d = 8.0; + struct +#ifndef __arm__ + __attribute__((packed)) +#endif + { + unsigned x : 12; + unsigned char y : 7; + unsigned z : 28, a: 4, b: 5; + } s = { 0x333,0x44,0x555555,6,7 }; + + printf("data:\n"); + printf(" %d - %.1f - %.1f - %s - %s\n", + sizeof 8.0, 8.0, d, __FUNCTION__, cc); + printf(" %x %x %x %x %x\n", + s.x, s.y, s.z, s.a, s.b); + } +te1:; + static const char de1 = 0; + + dl += &de1 - &ds1; + tl += &&te1 - &&ts1; + printf("size of data/text:\n %s/%s\n", + dl ? "non-zero":"zero", tl ? "non-zero":"zero"); + /*printf("# %d/%d\n", dl, tl);*/ +} + +#elif defined test_static_data + +#include +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 diff --git a/lib/tinycc/tests/tests2/96_nodata_wanted.expect b/lib/tinycc/tests/tests2/96_nodata_wanted.expect new file mode 100644 index 000000000..92dc9c4cc --- /dev/null +++ b/lib/tinycc/tests/tests2/96_nodata_wanted.expect @@ -0,0 +1,26 @@ +[test_static_data_error] +96_nodata_wanted.c:7: error: initializer element is not computable at load time + +[test_static_nodata_error] +96_nodata_wanted.c:14: error: initializer element is not computable at load time + +[test_global_data_error] +96_nodata_wanted.c:20: error: initializer element is not computable at load time + +[test_local_data_noerror] +96_nodata_wanted.c:25: warning: assignment makes integer from pointer without a cast +96_nodata_wanted.c:25: warning: cast between pointer and integer of different size + +[test_data_suppression_off] +data: + 8 - 8.0 - 8.0 - main - static string + 333 44 555555 6 7 +size of data/text: + non-zero/non-zero + +[test_data_suppression_on] +size of data/text: + zero/zero + +[test_static_data] +a = 1 diff --git a/lib/tinycc/tests/tests2/97_utf8_string_literal.c b/lib/tinycc/tests/tests2/97_utf8_string_literal.c new file mode 100644 index 000000000..5bfb6c88e --- /dev/null +++ b/lib/tinycc/tests/tests2/97_utf8_string_literal.c @@ -0,0 +1,20 @@ +// this file contains BMP chars encoded in UTF-8 +#include +#include +#include +#include + +int main() +{ + char hello_world_in_czech[] = "čau, světe"; + char hello_world_in_czech_ucn[] = "\u010dau, sv\u011bte"; + if (sizeof(hello_world_in_czech) != sizeof(hello_world_in_czech_ucn) + || strcmp(hello_world_in_czech, hello_world_in_czech_ucn)) + abort(); + + wchar_t s[] = L"hello$$你好¢¢世界€€world"; + wchar_t *p; + for (p = s; *p; p++) printf("%04X ", (unsigned) *p); + printf("\n"); + return 0; +} diff --git a/lib/tinycc/tests/tests2/97_utf8_string_literal.expect b/lib/tinycc/tests/tests2/97_utf8_string_literal.expect new file mode 100644 index 000000000..9a1593cdd --- /dev/null +++ b/lib/tinycc/tests/tests2/97_utf8_string_literal.expect @@ -0,0 +1 @@ +0068 0065 006C 006C 006F 0024 0024 4F60 597D 00A2 00A2 4E16 754C 20AC 20AC 0077 006F 0072 006C 0064 diff --git a/lib/tinycc/tests/tests2/98_al_ax_extend.c b/lib/tinycc/tests/tests2/98_al_ax_extend.c new file mode 100644 index 000000000..1cd65857e --- /dev/null +++ b/lib/tinycc/tests/tests2/98_al_ax_extend.c @@ -0,0 +1,41 @@ +#include +#include +asm ( + ".text;" + ".globl _us;.globl _ss;.globl _uc;.globl _sc;" + "_us:;_ss:;_uc:;_sc:;" + "movl $0x1234ABCD, %eax;" + "ret;" +); + +#ifndef __leading_underscore +#define us _us +#define ss _ss +#define uc _uc +#define sc _sc +#endif + +int main() +{ + unsigned short us(void); + short ss(void); + unsigned char uc(void); + signed char sc(void); + + unsigned short (*fpus)(void) = us; + short (*fpss)(void) = ss; + unsigned char (*fpuc)(void) = uc; + signed char (*fpsc)(void) = sc; + + printf("%08X %08X\n", us() + 1, fpus() + 1); + printf("%08X %08X\n", ss() + 1, fpss() + 1); + printf("%08X %08X\n", uc() + 1, fpuc() + 1); + printf("%08X %08X\n", sc() + 1, fpsc() + 1); + printf("\n"); + printf("%08X %08X\n", fpus() + 1, us() + 1); + printf("%08X %08X\n", fpss() + 1, ss() + 1); + printf("%08X %08X\n", fpuc() + 1, uc() + 1); + printf("%08X %08X\n", fpsc() + 1, sc() + 1); + + return 0; +} diff --git a/lib/tinycc/tests/tests2/98_al_ax_extend.expect b/lib/tinycc/tests/tests2/98_al_ax_extend.expect new file mode 100644 index 000000000..c5752e843 --- /dev/null +++ b/lib/tinycc/tests/tests2/98_al_ax_extend.expect @@ -0,0 +1,9 @@ +0000ABCE 0000ABCE +FFFFABCE FFFFABCE +000000CE 000000CE +FFFFFFCE FFFFFFCE + +0000ABCE 0000ABCE +FFFFABCE FFFFABCE +000000CE 000000CE +FFFFFFCE FFFFFFCE diff --git a/lib/tinycc/tests/tests2/99_fastcall.c b/lib/tinycc/tests/tests2/99_fastcall.c new file mode 100644 index 000000000..db97acb7f --- /dev/null +++ b/lib/tinycc/tests/tests2/99_fastcall.c @@ -0,0 +1,276 @@ +#include +#include + +#if !(defined( _WIN32) || (defined(__FreeBSD__) && defined(__i386__))) +#define __fastcall __attribute((fastcall)) +#endif + +#ifndef __leading_underscore +#define SYMBOL(x) _##x +#else +#define SYMBOL(x) x +#endif + +///////////////////////////////////////////////////////////////////////// +////////// TRAP FRAMEWORK +///////////////////////////////////////////////////////////////////////// +// if you cast 'TRAP' to a function pointer and call it, +// it will save all 8 registers, +// and jump into C-code (previously set using 'SET_TRAP_HANDLER(x)'), +// in C-code you can pop DWORDs from stack and modify registers +// + +void *SYMBOL(trap_handler); + +extern unsigned char SYMBOL(trap)[]; +asm ( + ".text;" + "_trap:;" + "pushl %esp;" + "pusha;" + "addl $0x4, 0xc(%esp);" + "pushl %esp;" + "call *_trap_handler;" + "addl $0x4, %esp;" + "movl 0xc(%esp), %eax;" + "movl %eax, 0x20(%esp);" + "popa;" + "popl %esp;" + "ret;" +); + +struct trapframe { + unsigned edi, esi, ebp, esp, ebx, edx, ecx, eax; +}; + + +#define M_FLOAT(addr) (*(float *)(addr)) +#define M_DWORD(addr) (*(unsigned *)(addr)) +#define M_WORD(addr) (*(unsigned short *)(addr)) +#define M_BYTE(addr) (*(unsigned char *)(addr)) +#define R_EAX ((tf)->eax) +#define R_ECX ((tf)->ecx) +#define R_EDX ((tf)->edx) +#define R_EBX ((tf)->ebx) +#define R_ESP ((tf)->esp) +#define R_EBP ((tf)->ebp) +#define R_ESI ((tf)->esi) +#define R_EDI ((tf)->edi) + +#define ARG(x) (M_DWORD(R_ESP + (x) * 4)) + +#define RETN(x) do { \ + M_DWORD(R_ESP + (x)) = M_DWORD(R_ESP); \ + R_ESP += (x); \ +} while (0) + +#define DUMP() do { \ + unsigned i; \ + printf("EAX: %08X\n", R_EAX); \ + printf("ECX: %08X\n", R_ECX); \ + printf("EDX: %08X\n", R_EDX); \ + printf("EBX: %08X\n", R_EBX); \ + printf("ESP: %08X\n", R_ESP); \ + printf("EBP: %08X\n", R_EBP); \ + printf("ESI: %08X\n", R_ESI); \ + printf("EDI: %08X\n", R_EDI); \ + printf("\n"); \ + printf("[RETADDR]: %08X\n", M_DWORD(R_ESP)); \ + for (i = 1; i <= 8; i++) { \ + printf("[ARG%4d]: %08X\n", i, ARG(i)); \ + } \ +} while (0) + +#define SET_TRAP_HANDLER(x) ((SYMBOL(trap_handler)) = (x)) +#define TRAP ((void *) &SYMBOL(trap)) + + + +///////////////////////////////////////////////////////////////////////// +////////// SAFECALL FRAMEWORK +///////////////////////////////////////////////////////////////////////// +// this framework will convert any calling convention to cdecl +// usage: first set call target with 'SET_SAFECALL_TARGET(x)' +// then cast 'SAFECALL' to target function pointer type and invoke it +// after calling, 'ESPDIFF' is the difference of old and new esp + +void *SYMBOL(sc_call_target); +unsigned SYMBOL(sc_retn_addr); +unsigned SYMBOL(sc_old_esp); +unsigned SYMBOL(sc_new_esp); + +extern unsigned char SYMBOL(safecall)[]; +asm ( + ".text;" + "_safecall:;" + "popl _sc_retn_addr;" + "movl %esp, _sc_old_esp;" + "call *_sc_call_target;" + "movl %esp, _sc_new_esp;" + "movl _sc_old_esp, %esp;" + "jmp *_sc_retn_addr;" +); + +#define SET_SAFECALL_TARGET(x) ((SYMBOL(sc_call_target)) = (x)) +#define SAFECALL ((void *) &SYMBOL(safecall)) +#define ESPDIFF (SYMBOL(sc_new_esp) - SYMBOL(sc_old_esp)) + + +///////////////////////////////////////////////////////////////////////// +////////// TEST FASTCALL INVOKE +///////////////////////////////////////////////////////////////////////// + +void check_fastcall_invoke_0(struct trapframe *tf) +{ + //DUMP(); + RETN(0); +} + +void check_fastcall_invoke_1(struct trapframe *tf) +{ + //DUMP(); + assert(R_ECX == 0x11111111); + RETN(0); +} +void check_fastcall_invoke_2(struct trapframe *tf) +{ + //DUMP(); + assert(R_ECX == 0x11111111); + assert(R_EDX == 0x22222222); + RETN(0); +} +void check_fastcall_invoke_3(struct trapframe *tf) +{ + //DUMP(); + assert(R_ECX == 0x11111111); + assert(R_EDX == 0x22222222); + assert(ARG(1) == 0x33333333); + RETN(1*4); +} +void check_fastcall_invoke_4(struct trapframe *tf) +{ + //DUMP(); + assert(R_ECX == 0x11111111); + assert(R_EDX == 0x22222222); + assert(ARG(1) == 0x33333333); + assert(ARG(2) == 0x44444444); + RETN(2*4); +} + +void check_fastcall_invoke_5(struct trapframe *tf) +{ + //DUMP(); + assert(R_ECX == 0x11111111); + assert(R_EDX == 0x22222222); + assert(ARG(1) == 0x33333333); + assert(ARG(2) == 0x44444444); + assert(ARG(3) == 0x55555555); + RETN(3*4); +} + +void test_fastcall_invoke() +{ + SET_TRAP_HANDLER(check_fastcall_invoke_0); + ((void __fastcall (*)(void)) TRAP)(); + + SET_TRAP_HANDLER(check_fastcall_invoke_1); + ((void __fastcall (*)(unsigned)) TRAP)(0x11111111); + + SET_TRAP_HANDLER(check_fastcall_invoke_2); + ((void __fastcall (*)(unsigned, unsigned)) TRAP)(0x11111111, 0x22222222); + + SET_TRAP_HANDLER(check_fastcall_invoke_3); + ((void __fastcall (*)(unsigned, unsigned, unsigned)) TRAP)(0x11111111, 0x22222222, 0x33333333); + + SET_TRAP_HANDLER(check_fastcall_invoke_4); + ((void __fastcall (*)(unsigned, unsigned, unsigned, unsigned)) TRAP)(0x11111111, 0x22222222, 0x33333333, 0x44444444); + + SET_TRAP_HANDLER(check_fastcall_invoke_5); + ((void __fastcall (*)(unsigned, unsigned, unsigned, unsigned, unsigned)) TRAP)(0x11111111, 0x22222222, 0x33333333, 0x44444444, 0x55555555); +} + + +///////////////////////////////////////////////////////////////////////// +////////// TEST FUNCTION CODE GENERATION +///////////////////////////////////////////////////////////////////////// + +int __fastcall check_fastcall_espdiff_0(void) +{ + return 0; +} + +int __fastcall check_fastcall_espdiff_1(int a) +{ + return a; +} + +int __fastcall check_fastcall_espdiff_2(int a, int b) +{ + return a + b; +} + +int __fastcall check_fastcall_espdiff_3(int a, int b, int c) +{ + return a + b + c; +} + +int __fastcall check_fastcall_espdiff_4(int a, int b, int c, int d) +{ + return a + b + c + d; +} + +int __fastcall check_fastcall_espdiff_5(int a, int b, int c, int d, int e) +{ + return a + b + c + d + e; +} + +void test_fastcall_espdiff() +{ + int x; + SET_SAFECALL_TARGET(check_fastcall_espdiff_0); + x = ((typeof(&check_fastcall_espdiff_0))SAFECALL)(); + assert(x == 0); + assert(ESPDIFF == 0); + + SET_SAFECALL_TARGET(check_fastcall_espdiff_1); + x = ((typeof(&check_fastcall_espdiff_1))SAFECALL)(1); + assert(x == 1); + assert(ESPDIFF == 0); + + SET_SAFECALL_TARGET(check_fastcall_espdiff_2); + x = ((typeof(&check_fastcall_espdiff_2))SAFECALL)(1, 2); + assert(x == 1 + 2); + assert(ESPDIFF == 0); + + SET_SAFECALL_TARGET(check_fastcall_espdiff_3); + x = ((typeof(&check_fastcall_espdiff_3))SAFECALL)(1, 2, 3); + assert(x == 1 + 2 + 3); + assert(ESPDIFF == 1*4); + + SET_SAFECALL_TARGET(check_fastcall_espdiff_4); + x = ((typeof(&check_fastcall_espdiff_4))SAFECALL)(1, 2, 3, 4); + assert(x == 1 + 2 + 3 + 4); + assert(ESPDIFF == 2*4); + + SET_SAFECALL_TARGET(check_fastcall_espdiff_5); + x = ((typeof(&check_fastcall_espdiff_5))SAFECALL)(1, 2, 3, 4, 5); + assert(x == 1 + 2 + 3 + 4 + 5); + assert(ESPDIFF == 3*4); +} + +int main() +{ +#define N 10000 + int i; + + for (i = 1; i <= N; i++) { + test_fastcall_espdiff(); + } + + for (i = 1; i <= N; i++) { + test_fastcall_invoke(); + } + + puts("TEST OK"); + return 0; +} diff --git a/lib/tinycc/tests/tests2/99_fastcall.expect b/lib/tinycc/tests/tests2/99_fastcall.expect new file mode 100644 index 000000000..3835d63df --- /dev/null +++ b/lib/tinycc/tests/tests2/99_fastcall.expect @@ -0,0 +1 @@ +TEST OK diff --git a/lib/tinycc/tests/tests2/LICENSE b/lib/tinycc/tests/tests2/LICENSE new file mode 100644 index 000000000..b08a652f6 --- /dev/null +++ b/lib/tinycc/tests/tests2/LICENSE @@ -0,0 +1,37 @@ +The tests in this directory are either directly copied from the picoc project or +are subsequently modified and added to for the purpose of TinyCC project. All +these modifications are licensed under the same terms as TinyCC as specified in +the file COPYING. + +=== picoc license === + +Copyright (c) 2009-2011, Zik Saleeba +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + * Neither the name of the Zik Saleeba nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/lib/tinycc/tests/tests2/Makefile b/lib/tinycc/tests/tests2/Makefile new file mode 100644 index 000000000..f485b2540 --- /dev/null +++ b/lib/tinycc/tests/tests2/Makefile @@ -0,0 +1,180 @@ +TOP = ../.. +include $(TOP)/Makefile +SRC = $(TOPSRC)/tests/tests2 +VPATH = $(SRC) + +TESTS = $(patsubst %.c,%.test,\ + $(sort $(notdir $(wildcard $(SRC)/??_*.c)))\ + $(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 +ifeq (-$(CONFIG_arm_eabi)-$(CONFIG_arm_vfp)-,-yes--) + SKIP += 22_floating_point.test +endif +ifeq (,$(filter i386,$(ARCH))) + SKIP += 98_al_ax_extend.test 99_fastcall.test +endif +ifeq (,$(filter i386 x86_64,$(ARCH))) + SKIP += 85_asm-outside-function.test # x86 asm + SKIP += 127_asm_goto.test # hardcodes x86 asm +endif +ifeq ($(CONFIG_backtrace),no) + SKIP += 113_btdll.test + CONFIG_bcheck = no +# no bcheck without backtrace +endif +ifeq ($(CONFIG_bcheck),no) + SKIP += 112_backtrace.test + SKIP += 114_bound_signal.test + SKIP += 115_bound_setjmp.test + SKIP += 116_bound_setjmp2.test + SKIP += 117_builtins.test + SKIP += 126_bound_global.test +endif +ifeq ($(CONFIG_dll),no) + SKIP += 113_btdll.test # no shared lib support yet +endif +ifeq (-$(findstring gcc,$(CC))-,--) + SKIP += $(patsubst %.expect,%.test,$(GEN-ALWAYS)) +endif +ifeq (-$(CONFIG_WIN32)-$(CONFIG_i386)$(CONFIG_arm)-,--yes-) + SKIP += 95_bitfields%.test # type_align is different on 32bit-non-windows +endif +ifeq (-$(CONFIG_WIN32)-,-yes-) + SKIP += 106_versym.test # No pthread support + SKIP += 114_bound_signal.test # No pthread support + SKIP += 117_builtins.test # win32 port doesn't define __builtins + SKIP += 124_atomic_counter.test # No pthread support +endif +ifneq (,$(filter OpenBSD FreeBSD NetBSD,$(TARGETOS))) + SKIP += 106_versym.test # no pthread_condattr_setpshared + SKIP += 114_bound_signal.test # libc problem signal/fork + SKIP += 116_bound_setjmp2.test # No TLS_FUNC/TLS_VAR in bcheck.c +endif + +# Some tests might need arguments +ARGS = +31_args.test : ARGS = arg1 arg2 arg3 arg4 arg5 +46_grep.test : ARGS = '[^* ]*[:a:d: ]+\:\*-/: $$' $(SRC)/46_grep.c + +# And some tests don't test the right thing with -run +NORUN = +42_function_pointer.test : NORUN = true + +# Some tests might need different flags +FLAGS = +76_dollars_in_identifiers.test : FLAGS += -fdollars-in-identifiers +ifneq (-$(CONFIG_WIN32)-,-yes-) +22_floating_point.test: FLAGS += -lm +24_math_library.test: FLAGS += -lm +endif + +# These tests run several snippets from the same file one by one +60_errors_and_warnings.test : FLAGS += -dt +96_nodata_wanted.test : FLAGS += -dt + +# Always generate certain .expects (don't put these in the GIT), +GEN-ALWAYS = +# GEN-ALWAYS += 95_bitfields.expect # does not work + +# using the ms compiler for the really ms-compatible bitfields +95_bitfields_ms.test : GEN = $(GEN-MSC) + +# this test compiles/links two files: +104_inline.test : FLAGS += $(subst 104,104+,$1) +104_inline.test : GEN = $(GEN-TCC) + +# this test needs two files, and we want to invoke the linker +120_alias.test : FLAGS += $(subst 120,120+,$1) +120_alias.test : GEN = $(GEN-TCC) +120_alias.test : NORUN = true + +# this test needs pthread +106_versym.test: FLAGS += -pthread +106_versym.test: NORUN = true + +# constructor/destructor +108_constructor.test: NORUN = true + +112_backtrace.test: FLAGS += -dt -b +112_backtrace.test 113_btdll.test 126_bound_global.test: FILTER += \ + -e 's;[0-9A-Fa-fx]\{5,\};........;g' \ + -e 's;0x[0-9A-Fa-f]\{1,\};0x?;g' + +# this test creates two DLLs and an EXE +113_btdll.test: T1 = \ + $(TCC) -bt $1 -shared -D DLL=1 -o a1$(DLLSUF) && \ + $(TCC) -bt $1 -shared -D DLL=2 -o a2$(DLLSUF) && \ + $(TCC) -bt $1 a1$(DLLSUF) a2$(DLLSUF) -Wl,-rpath=. -o $(basename $@).exe && \ + ./$(basename $@).exe + +114_bound_signal.test: FLAGS += -b +114_bound_signal.test: NORUN = true # tcc -run does not support fork and -b and SELINUX +115_bound_setjmp.test: FLAGS += -b +116_bound_setjmp2.test: FLAGS += -b +117_builtins.test: T1 = ( $(TCC) -run $1 && $(TCC) -b -run $1 ) +ifneq ($(CONFIG_bcheck),no) +121_struct_return.test: FLAGS += -b +122_vla_reuse.test: FLAGS += -b +endif +125_atomic_misc.test: FLAGS += -dt +124_atomic_counter.test: FLAGS += -pthread +126_bound_global.test: FLAGS += -b +126_bound_global.test: NORUN = true +128_run_atexit.test: FLAGS += -dt +132_bound_test.test: FLAGS += -b + +# Filter source directory in warnings/errors (out-of-tree builds) +FILTER = 2>&1 | sed -e 's,$(SRC)/,,g' + +all test tests2.all: $(filter-out $(SKIP),$(TESTS)) + @$(MAKE) clean --no-print-directory -s + +%.test: %.c %.expect + @echo Test: $*... + @$(call T1,$<) $(T3) + +T1 = $(TCC) $(FLAGS) $(T2) $(ARGS) +T2 = $(if $(NORUN),$1 -o $(basename $@).exe && ./$(basename $@).exe,-run $1) +T3 = $(FILTER) >$*.output 2>&1 || true \ + && diff -Nbu $(filter %.expect,$^) $*.output \ + && rm -f $*.output $(filter $*.expect,$(GEN-ALWAYS)) + +# run single test and update .expect file, e.g. "make tests2.37+" +tests2.%+: + @$(MAKE) $(call F2,$(call F1,$*)) --no-print-directory + +# just run tcc to see the output, e.g. "make tests2.37-" +tests2.%-: + @$(MAKE) $(call F1,$*) T3= --no-print-directory + +# run single test, e.g. "make tests2.37" +tests2.%: + @$(MAKE) $(call F1,$*) --no-print-directory + +F1 = $(or $(filter $1_%,$(TESTS)),$1_???.test) +F2 = $1 UPDATE="$(patsubst %.test,%.expect,$1)" + +# automatically generate .expect files with gcc: +%.expect : + @echo Generating: $@ + @$(call GEN,$(SRC)/$*.c) $(FILTER) >$@ 2>&1 + @rm -f *.exe *.obj *.pdb + +# using TCC for .expect if -dt in FLAGS +GEN = $(if $(filter -dt -bt -b,$(FLAGS)),$(GEN-TCC),$(GEN-CC)) +GEN-CC = $(CC) -w -std=gnu99 $(FLAGS) $1 -o $(basename $@).exe && ./$(basename $@).exe $(ARGS) +GEN-TCC = $(T1) +GEN-MSC = $(MS-CC) $1 && ./$(basename $@).exe +MS-CC = cl + +# tell make not to delete +.PRECIOUS: %.expect + +# force .expect generation for these files +$(sort $(GEN-ALWAYS) $(UPDATE)) : force +force: + +clean : + rm -f fred.txt *.output *.exe *.dll *.so *.def $(GEN-ALWAYS) diff --git a/lib/tinycc/tests/vla_test.c b/lib/tinycc/tests/vla_test.c new file mode 100644 index 000000000..3616c46d4 --- /dev/null +++ b/lib/tinycc/tests/vla_test.c @@ -0,0 +1,84 @@ +/* + * Test that allocating a variable length array in a loop + * does not use up a linear amount of memory + */ + +#include +#include +#include + +#define LOOP_COUNT 1000 +#define ARRAY_SIZE 100 + +/* Overwrite a VLA. This will overwrite the return address if SP is incorrect */ +void smash(char *p, int n) { + memset(p, 0, n); +} + +int test1(int n) { + int i; + char *array_ptrs[LOOP_COUNT]; + + for (i = 0; i < LOOP_COUNT; ++i) { + char test[n]; + smash(test, n); + array_ptrs[i] = test; + } + + return (array_ptrs[0]-array_ptrs[LOOP_COUNT-1] < n) ? 0 : 1; +} + +/* ensure goto does not circumvent array free */ +int test2(int n) { + char *array_ptrs[LOOP_COUNT]; + + int i = 0; +loop:; + char test[n]; + smash(test, n); + if (i >= LOOP_COUNT) + goto end; + array_ptrs[i] = test; + ++i; + goto loop; + +end: + smash(test, n); + char test2[n]; + smash(test2, n); + return (array_ptrs[0] - array_ptrs[LOOP_COUNT-1] < n) ? 0 : 1; +} + +int test3(int n) { + char test[n]; + smash(test, n); + goto label; +label: + smash(test, n); + char test2[n]; + smash(test2, n); + return (test-test2 >= n) ? 0 : 1; +} + +#define RUN_TEST(t) \ + if (!testname || (strcmp(#t, testname) == 0)) { \ + fputs(#t "... ", stdout); \ + fflush(stdout); \ + if (t(ARRAY_SIZE) == 0) { \ + fputs("success\n", stdout); \ + } else { \ + fputs("failure\n", stdout); \ + retval = EXIT_FAILURE; \ + } \ + } + +int main(int argc, char **argv) { + const char *testname = NULL; + int retval = EXIT_SUCCESS; + if (argc > 1) + testname = argv[1]; + RUN_TEST(test1) + RUN_TEST(test2) + RUN_TEST(test3) + return retval; +}