aboutsummaryrefslogtreecommitdiff
path: root/tinycc/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tinycc/tests')
-rw-r--r--tinycc/tests/42test.h13
-rw-r--r--tinycc/tests/Makefile335
-rw-r--r--tinycc/tests/abitest.c691
-rw-r--r--tinycc/tests/arm-asm-testsuite.sh243
-rw-r--r--tinycc/tests/asm-c-connect-1.c69
-rw-r--r--tinycc/tests/asm-c-connect-2.c48
-rw-r--r--tinycc/tests/asmtest.S1025
-rw-r--r--tinycc/tests/boundtest.c309
-rw-r--r--tinycc/tests/bug.c35
-rw-r--r--tinycc/tests/gcctestsuite.sh151
-rw-r--r--tinycc/tests/libtcc_test.c110
-rw-r--r--tinycc/tests/libtcc_test_mt.c305
-rw-r--r--tinycc/tests/pp/01.c6
-rw-r--r--tinycc/tests/pp/01.expect1
-rw-r--r--tinycc/tests/pp/02.c28
-rw-r--r--tinycc/tests/pp/02.expect5
-rw-r--r--tinycc/tests/pp/03.c15
-rw-r--r--tinycc/tests/pp/03.expect5
-rw-r--r--tinycc/tests/pp/04.c4
-rw-r--r--tinycc/tests/pp/04.expect1
-rw-r--r--tinycc/tests/pp/05.c7
-rw-r--r--tinycc/tests/pp/05.expect3
-rw-r--r--tinycc/tests/pp/06.c5
-rw-r--r--tinycc/tests/pp/06.expect1
-rw-r--r--tinycc/tests/pp/07.c4
-rw-r--r--tinycc/tests/pp/07.expect2
-rw-r--r--tinycc/tests/pp/08.c4
-rw-r--r--tinycc/tests/pp/08.expect1
-rw-r--r--tinycc/tests/pp/09.c4
-rw-r--r--tinycc/tests/pp/09.expect1
-rw-r--r--tinycc/tests/pp/10.c10
-rw-r--r--tinycc/tests/pp/10.expect5
-rw-r--r--tinycc/tests/pp/11.c36
-rw-r--r--tinycc/tests/pp/11.expect16
-rw-r--r--tinycc/tests/pp/12.S8
-rw-r--r--tinycc/tests/pp/12.expect2
-rw-r--r--tinycc/tests/pp/13.S6
-rw-r--r--tinycc/tests/pp/13.expect2
-rw-r--r--tinycc/tests/pp/14.c13
-rw-r--r--tinycc/tests/pp/14.expect3
-rw-r--r--tinycc/tests/pp/15.c18
-rw-r--r--tinycc/tests/pp/15.expect5
-rw-r--r--tinycc/tests/pp/16.c3
-rw-r--r--tinycc/tests/pp/16.expect2
-rw-r--r--tinycc/tests/pp/17.c14
-rw-r--r--tinycc/tests/pp/17.expect6
-rw-r--r--tinycc/tests/pp/18.c15
-rw-r--r--tinycc/tests/pp/18.expect3
-rw-r--r--tinycc/tests/pp/19.c101
-rw-r--r--tinycc/tests/pp/19.expect14
-rw-r--r--tinycc/tests/pp/20.c13
-rw-r--r--tinycc/tests/pp/20.expect6
-rw-r--r--tinycc/tests/pp/21.c36
-rw-r--r--tinycc/tests/pp/21.expect8
-rw-r--r--tinycc/tests/pp/22.c12
-rw-r--r--tinycc/tests/pp/22.expect2
-rw-r--r--tinycc/tests/pp/Makefile51
-rw-r--r--tinycc/tests/pp/pp-counter.c27
-rw-r--r--tinycc/tests/pp/pp-counter.expect15
-rw-r--r--tinycc/tests/tcctest.c4473
-rw-r--r--tinycc/tests/tcctest.h9
-rw-r--r--tinycc/tests/testfp.c510
-rw-r--r--tinycc/tests/tests2/00_assignment.c18
-rw-r--r--tinycc/tests/tests2/00_assignment.expect3
-rw-r--r--tinycc/tests/tests2/01_comment.c14
-rw-r--r--tinycc/tests/tests2/01_comment.expect5
-rw-r--r--tinycc/tests/tests2/02_printf.c18
-rw-r--r--tinycc/tests/tests2/02_printf.expect15
-rw-r--r--tinycc/tests/tests2/03_struct.c38
-rw-r--r--tinycc/tests/tests2/03_struct.expect8
-rw-r--r--tinycc/tests/tests2/04_for.c15
-rw-r--r--tinycc/tests/tests2/04_for.expect10
-rw-r--r--tinycc/tests/tests2/05_array.c21
-rw-r--r--tinycc/tests/tests2/05_array.expect10
-rw-r--r--tinycc/tests/tests2/06_case.c29
-rw-r--r--tinycc/tests/tests2/06_case.expect8
-rw-r--r--tinycc/tests/tests2/07_function.c35
-rw-r--r--tinycc/tests/tests2/07_function.expect4
-rw-r--r--tinycc/tests/tests2/08_while.c24
-rw-r--r--tinycc/tests/tests2/08_while.expect11
-rw-r--r--tinycc/tests/tests2/09_do_while.c24
-rw-r--r--tinycc/tests/tests2/09_do_while.expect11
-rw-r--r--tinycc/tests/tests2/100_c99array-decls.c34
-rw-r--r--tinycc/tests/tests2/100_c99array-decls.expect0
-rw-r--r--tinycc/tests/tests2/101_cleanup.c227
-rw-r--r--tinycc/tests/tests2/101_cleanup.expect59
-rw-r--r--tinycc/tests/tests2/102_alignas.c29
-rw-r--r--tinycc/tests/tests2/102_alignas.expect2
-rw-r--r--tinycc/tests/tests2/103_implicit_memmove.c20
-rw-r--r--tinycc/tests/tests2/103_implicit_memmove.expect0
-rw-r--r--tinycc/tests/tests2/104+_inline.c54
-rw-r--r--tinycc/tests/tests2/104_inline.c132
-rw-r--r--tinycc/tests/tests2/104_inline.expect39
-rw-r--r--tinycc/tests/tests2/105_local_extern.c12
-rw-r--r--tinycc/tests/tests2/105_local_extern.expect2
-rw-r--r--tinycc/tests/tests2/106_versym.c18
-rw-r--r--tinycc/tests/tests2/106_versym.expect1
-rw-r--r--tinycc/tests/tests2/107_stack_safe.c13
-rw-r--r--tinycc/tests/tests2/107_stack_safe.expect1
-rw-r--r--tinycc/tests/tests2/108_constructor.c20
-rw-r--r--tinycc/tests/tests2/108_constructor.expect3
-rw-r--r--tinycc/tests/tests2/109_float_struct_calling.c24
-rw-r--r--tinycc/tests/tests2/109_float_struct_calling.expect1
-rw-r--r--tinycc/tests/tests2/10_pointer.c40
-rw-r--r--tinycc/tests/tests2/10_pointer.expect8
-rw-r--r--tinycc/tests/tests2/110_average.c27
-rw-r--r--tinycc/tests/tests2/110_average.expect1
-rw-r--r--tinycc/tests/tests2/111_conversion.c22
-rw-r--r--tinycc/tests/tests2/111_conversion.expect1
-rw-r--r--tinycc/tests/tests2/112_backtrace.c175
-rw-r--r--tinycc/tests/tests2/112_backtrace.expect162
-rw-r--r--tinycc/tests/tests2/113_btdll.c43
-rw-r--r--tinycc/tests/tests2/113_btdll.expect6
-rw-r--r--tinycc/tests/tests2/114_bound_signal.c143
-rw-r--r--tinycc/tests/tests2/114_bound_signal.expect2
-rw-r--r--tinycc/tests/tests2/115_bound_setjmp.c172
-rw-r--r--tinycc/tests/tests2/115_bound_setjmp.expect0
-rw-r--r--tinycc/tests/tests2/116_bound_setjmp2.c84
-rw-r--r--tinycc/tests/tests2/116_bound_setjmp2.expect0
-rw-r--r--tinycc/tests/tests2/117_builtins.c94
-rw-r--r--tinycc/tests/tests2/117_builtins.expect4
-rw-r--r--tinycc/tests/tests2/118_switch.c75
-rw-r--r--tinycc/tests/tests2/118_switch.expect40
-rw-r--r--tinycc/tests/tests2/119_random_stuff.c120
-rw-r--r--tinycc/tests/tests2/119_random_stuff.expect6
-rw-r--r--tinycc/tests/tests2/11_precedence.c41
-rw-r--r--tinycc/tests/tests2/11_precedence.expect15
-rw-r--r--tinycc/tests/tests2/120+_alias.c15
-rw-r--r--tinycc/tests/tests2/120_alias.c29
-rw-r--r--tinycc/tests/tests2/120_alias.expect5
-rw-r--r--tinycc/tests/tests2/121_struct_return.c35
-rw-r--r--tinycc/tests/tests2/121_struct_return.expect1
-rw-r--r--tinycc/tests/tests2/122_vla_reuse.c31
-rw-r--r--tinycc/tests/tests2/122_vla_reuse.expect1
-rw-r--r--tinycc/tests/tests2/123_vla_bug.c40
-rw-r--r--tinycc/tests/tests2/123_vla_bug.expect5
-rw-r--r--tinycc/tests/tests2/124_atomic_counter.c152
-rw-r--r--tinycc/tests/tests2/124_atomic_counter.expect3
-rw-r--r--tinycc/tests/tests2/125_atomic_misc.c227
-rw-r--r--tinycc/tests/tests2/125_atomic_misc.expect59
-rw-r--r--tinycc/tests/tests2/126_bound_global.c13
-rw-r--r--tinycc/tests/tests2/126_bound_global.expect2
-rw-r--r--tinycc/tests/tests2/127_asm_goto.c62
-rw-r--r--tinycc/tests/tests2/127_asm_goto.expect5
-rw-r--r--tinycc/tests/tests2/128_run_atexit.c54
-rw-r--r--tinycc/tests/tests2/128_run_atexit.expect15
-rw-r--r--tinycc/tests/tests2/129_scopes.c43
-rw-r--r--tinycc/tests/tests2/129_scopes.expect0
-rw-r--r--tinycc/tests/tests2/12_hashdefine.c14
-rw-r--r--tinycc/tests/tests2/12_hashdefine.expect2
-rw-r--r--tinycc/tests/tests2/130_large_argument.c41
-rw-r--r--tinycc/tests/tests2/130_large_argument.expect3
-rw-r--r--tinycc/tests/tests2/13_integer_literals.c20
-rw-r--r--tinycc/tests/tests2/13_integer_literals.expect5
-rw-r--r--tinycc/tests/tests2/14_if.c21
-rw-r--r--tinycc/tests/tests2/14_if.expect2
-rw-r--r--tinycc/tests/tests2/15_recursion.c21
-rw-r--r--tinycc/tests/tests2/15_recursion.expect10
-rw-r--r--tinycc/tests/tests2/16_nesting.c21
-rw-r--r--tinycc/tests/tests2/16_nesting.expect18
-rw-r--r--tinycc/tests/tests2/17_enum.c72
-rw-r--r--tinycc/tests/tests2/17_enum.expect4
-rw-r--r--tinycc/tests/tests2/18_include.c47
-rw-r--r--tinycc/tests/tests2/18_include.expect8
-rw-r--r--tinycc/tests/tests2/18_include.h5
-rw-r--r--tinycc/tests/tests2/18_include2.h2
-rw-r--r--tinycc/tests/tests2/19_pointer_arithmetic.c28
-rw-r--r--tinycc/tests/tests2/19_pointer_arithmetic.expect3
-rw-r--r--tinycc/tests/tests2/20_pointer_comparison.c24
-rw-r--r--tinycc/tests/tests2/20_pointer_comparison.expect6
-rw-r--r--tinycc/tests/tests2/21_char_array.c33
-rw-r--r--tinycc/tests/tests2/21_char_array.expect7
-rw-r--r--tinycc/tests/tests2/22_floating_point.c70
-rw-r--r--tinycc/tests/tests2/22_floating_point.expect17
-rw-r--r--tinycc/tests/tests2/23_type_coercion.c54
-rw-r--r--tinycc/tests/tests2/23_type_coercion.expect12
-rw-r--r--tinycc/tests/tests2/24_math_library.c30
-rw-r--r--tinycc/tests/tests2/24_math_library.expect18
-rw-r--r--tinycc/tests/tests2/25_quicksort.c83
-rw-r--r--tinycc/tests/tests2/25_quicksort.expect2
-rw-r--r--tinycc/tests/tests2/26_character_constants.c17
-rw-r--r--tinycc/tests/tests2/26_character_constants.expect8
-rw-r--r--tinycc/tests/tests2/27_sizeof.c18
-rw-r--r--tinycc/tests/tests2/27_sizeof.expect4
-rw-r--r--tinycc/tests/tests2/28_strings.c45
-rw-r--r--tinycc/tests/tests2/28_strings.expect19
-rw-r--r--tinycc/tests/tests2/29_array_address.c13
-rw-r--r--tinycc/tests/tests2/29_array_address.expect1
-rw-r--r--tinycc/tests/tests2/30_hanoi.c122
-rw-r--r--tinycc/tests/tests2/30_hanoi.expect71
-rw-r--r--tinycc/tests/tests2/31_args.c14
-rw-r--r--tinycc/tests/tests2/31_args.expect6
-rw-r--r--tinycc/tests/tests2/32_led.c266
-rw-r--r--tinycc/tests/tests2/32_led.expect4
-rw-r--r--tinycc/tests/tests2/33_ternary_op.c119
-rw-r--r--tinycc/tests/tests2/33_ternary_op.expect14
-rw-r--r--tinycc/tests/tests2/34_array_assignment.c23
-rw-r--r--tinycc/tests/tests2/34_array_assignment.expect2
-rw-r--r--tinycc/tests/tests2/35_sizeof.c14
-rw-r--r--tinycc/tests/tests2/35_sizeof.expect2
-rw-r--r--tinycc/tests/tests2/36_array_initialisers.c25
-rw-r--r--tinycc/tests/tests2/36_array_initialisers.expect30
-rw-r--r--tinycc/tests/tests2/37_sprintf.c17
-rw-r--r--tinycc/tests/tests2/37_sprintf.expect20
-rw-r--r--tinycc/tests/tests2/38_multiple_array_index.c32
-rw-r--r--tinycc/tests/tests2/38_multiple_array_index.expect4
-rw-r--r--tinycc/tests/tests2/39_typedef.c65
-rw-r--r--tinycc/tests/tests2/39_typedef.expect3
-rw-r--r--tinycc/tests/tests2/40_stdio.c52
-rw-r--r--tinycc/tests/tests2/40_stdio.expect27
-rw-r--r--tinycc/tests/tests2/41_hashif.c85
-rw-r--r--tinycc/tests/tests2/41_hashif.expect6
-rw-r--r--tinycc/tests/tests2/42_function_pointer.c22
-rw-r--r--tinycc/tests/tests2/42_function_pointer.expect2
-rw-r--r--tinycc/tests/tests2/43_void_param.c15
-rw-r--r--tinycc/tests/tests2/43_void_param.expect1
-rw-r--r--tinycc/tests/tests2/44_scoped_declarations.c17
-rw-r--r--tinycc/tests/tests2/44_scoped_declarations.expect1
-rw-r--r--tinycc/tests/tests2/45_empty_for.c18
-rw-r--r--tinycc/tests/tests2/45_empty_for.expect10
-rw-r--r--tinycc/tests/tests2/46_grep.c570
-rw-r--r--tinycc/tests/tests2/46_grep.expect3
-rw-r--r--tinycc/tests/tests2/47_switch_return.c24
-rw-r--r--tinycc/tests/tests2/47_switch_return.expect4
-rw-r--r--tinycc/tests/tests2/48_nested_break.c26
-rw-r--r--tinycc/tests/tests2/48_nested_break.expect1
-rw-r--r--tinycc/tests/tests2/49_bracket_evaluation.c23
-rw-r--r--tinycc/tests/tests2/49_bracket_evaluation.expect1
-rw-r--r--tinycc/tests/tests2/50_logical_second_arg.c29
-rw-r--r--tinycc/tests/tests2/50_logical_second_arg.expect20
-rw-r--r--tinycc/tests/tests2/51_static.c30
-rw-r--r--tinycc/tests/tests2/51_static.expect8
-rw-r--r--tinycc/tests/tests2/52_unnamed_enum.c27
-rw-r--r--tinycc/tests/tests2/52_unnamed_enum.expect9
-rw-r--r--tinycc/tests/tests2/54_goto.c56
-rw-r--r--tinycc/tests/tests2/54_goto.expect8
-rw-r--r--tinycc/tests/tests2/55_lshift_type.c52
-rw-r--r--tinycc/tests/tests2/55_lshift_type.expect1
-rw-r--r--tinycc/tests/tests2/60_errors_and_warnings.c466
-rw-r--r--tinycc/tests/tests2/60_errors_and_warnings.expect230
-rw-r--r--tinycc/tests/tests2/61_integers.c70
-rw-r--r--tinycc/tests/tests2/61_integers.expect56
-rw-r--r--tinycc/tests/tests2/64_macro_nesting.c12
-rw-r--r--tinycc/tests/tests2/64_macro_nesting.expect1
-rw-r--r--tinycc/tests/tests2/67_macro_concat.c14
-rw-r--r--tinycc/tests/tests2/67_macro_concat.expect2
-rw-r--r--tinycc/tests/tests2/70_floating_point_literals.c77
-rw-r--r--tinycc/tests/tests2/70_floating_point_literals.expect53
-rw-r--r--tinycc/tests/tests2/71_macro_empty_arg.c9
-rw-r--r--tinycc/tests/tests2/71_macro_empty_arg.expect1
-rw-r--r--tinycc/tests/tests2/72_long_long_constant.c19
-rw-r--r--tinycc/tests/tests2/72_long_long_constant.expect1
-rw-r--r--tinycc/tests/tests2/73_arm64.c538
-rw-r--r--tinycc/tests/tests2/73_arm64.expect174
-rw-r--r--tinycc/tests/tests2/75_array_in_struct_init.c33
-rw-r--r--tinycc/tests/tests2/75_array_in_struct_init.expect72
-rw-r--r--tinycc/tests/tests2/76_dollars_in_identifiers.c41
-rw-r--r--tinycc/tests/tests2/76_dollars_in_identifiers.expect14
-rw-r--r--tinycc/tests/tests2/77_push_pop_macro.c30
-rw-r--r--tinycc/tests/tests2/77_push_pop_macro.expect5
-rw-r--r--tinycc/tests/tests2/78_vla_label.c45
-rw-r--r--tinycc/tests/tests2/78_vla_label.expect6
-rw-r--r--tinycc/tests/tests2/79_vla_continue.c119
-rw-r--r--tinycc/tests/tests2/79_vla_continue.expect5
-rw-r--r--tinycc/tests/tests2/80_flexarray.c26
-rw-r--r--tinycc/tests/tests2/80_flexarray.expect0
-rw-r--r--tinycc/tests/tests2/81_types.c55
-rw-r--r--tinycc/tests/tests2/81_types.expect0
-rw-r--r--tinycc/tests/tests2/82_attribs_position.c71
-rw-r--r--tinycc/tests/tests2/82_attribs_position.expect2
-rw-r--r--tinycc/tests/tests2/83_utf8_in_identifiers.c9
-rw-r--r--tinycc/tests/tests2/83_utf8_in_identifiers.expect2
-rw-r--r--tinycc/tests/tests2/84_hex-float.c12
-rw-r--r--tinycc/tests/tests2/84_hex-float.expect1
-rw-r--r--tinycc/tests/tests2/85_asm-outside-function.c15
-rw-r--r--tinycc/tests/tests2/85_asm-outside-function.expect1
-rw-r--r--tinycc/tests/tests2/86_memory-model.c38
-rw-r--r--tinycc/tests/tests2/86_memory-model.expect1
-rw-r--r--tinycc/tests/tests2/87_dead_code.c165
-rw-r--r--tinycc/tests/tests2/87_dead_code.expect24
-rw-r--r--tinycc/tests/tests2/88_codeopt.c80
-rw-r--r--tinycc/tests/tests2/88_codeopt.expect3
-rw-r--r--tinycc/tests/tests2/89_nocode_wanted.c112
-rw-r--r--tinycc/tests/tests2/89_nocode_wanted.expect14
-rw-r--r--tinycc/tests/tests2/90_struct-init.c424
-rw-r--r--tinycc/tests/tests2/90_struct-init.expect59
-rw-r--r--tinycc/tests/tests2/91_ptr_longlong_arith32.c15
-rw-r--r--tinycc/tests/tests2/91_ptr_longlong_arith32.expect1
-rw-r--r--tinycc/tests/tests2/92_enum_bitfield.c58
-rw-r--r--tinycc/tests/tests2/92_enum_bitfield.expect0
-rw-r--r--tinycc/tests/tests2/93_integer_promotion.c71
-rw-r--r--tinycc/tests/tests2/93_integer_promotion.expect46
-rw-r--r--tinycc/tests/tests2/94_generic.c122
-rw-r--r--tinycc/tests/tests2/94_generic.expect15
-rw-r--r--tinycc/tests/tests2/95_bitfields.c241
-rw-r--r--tinycc/tests/tests2/95_bitfields.expect173
-rw-r--r--tinycc/tests/tests2/95_bitfields_ms.c2
-rw-r--r--tinycc/tests/tests2/95_bitfields_ms.expect173
-rw-r--r--tinycc/tests/tests2/96_nodata_wanted.c102
-rw-r--r--tinycc/tests/tests2/96_nodata_wanted.expect26
-rw-r--r--tinycc/tests/tests2/97_utf8_string_literal.c20
-rw-r--r--tinycc/tests/tests2/97_utf8_string_literal.expect1
-rw-r--r--tinycc/tests/tests2/98_al_ax_extend.c41
-rw-r--r--tinycc/tests/tests2/98_al_ax_extend.expect9
-rw-r--r--tinycc/tests/tests2/99_fastcall.c276
-rw-r--r--tinycc/tests/tests2/99_fastcall.expect1
-rw-r--r--tinycc/tests/tests2/LICENSE37
-rw-r--r--tinycc/tests/tests2/Makefile175
-rw-r--r--tinycc/tests/vla_test.c84
309 files changed, 19690 insertions, 0 deletions
diff --git a/tinycc/tests/42test.h b/tinycc/tests/42test.h
new file mode 100644
index 0000000..5db7d1c
--- /dev/null
+++ b/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/tinycc/tests/Makefile b/tinycc/tests/Makefile
new file mode 100644
index 0000000..a46c852
--- /dev/null
+++ b/tinycc/tests/Makefile
@@ -0,0 +1,335 @@
+#
+# 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 \
+ memtest \
+ dlltest \
+ abitest \
+ asm-c-connect-test \
+ vla_test-run \
+ cross-test \
+ tests2-dir \
+ pp-dir
+
+# test4_static -- Not all relocation types are implemented yet.
+# asmtest / asmtest2 -- minor differences with gcc
+
+ifneq ($(CONFIG_bcheck),no)
+ TESTS += btest test1b
+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 :
+ @$(MAKE) --no-print-directory -s clean
+ @$(MAKE) --no-print-directory -s -r $(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
+
+# 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
+
+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$(EXESUF) asm-c-connect-sep$(EXESUF)
+ rm -f ex? tcc_g weaktest.*.txt *.def *.pdb *.obj libtcc_test_mt
+ @$(MAKE) -C tests2 $@
+ @$(MAKE) -C pp $@
+
diff --git a/tinycc/tests/abitest.c b/tinycc/tests/abitest.c
new file mode 100644
index 0000000..4a192bd
--- /dev/null
+++ b/tinycc/tests/abitest.c
@@ -0,0 +1,691 @@
+#include <libtcc.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+
+// 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, TCC_RELOCATE_AUTO) == -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 <stdarg.h>\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 <stdarg.h>\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 <stdarg.h>\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/tinycc/tests/arm-asm-testsuite.sh b/tinycc/tests/arm-asm-testsuite.sh
new file mode 100644
index 0000000..61c5dad
--- /dev/null
+++ b/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/tinycc/tests/asm-c-connect-1.c b/tinycc/tests/asm-c-connect-1.c
new file mode 100644
index 0000000..90f59c8
--- /dev/null
+++ b/tinycc/tests/asm-c-connect-1.c
@@ -0,0 +1,69 @@
+#include <stdio.h>
+
+#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/tinycc/tests/asm-c-connect-2.c b/tinycc/tests/asm-c-connect-2.c
new file mode 100644
index 0000000..654db0e
--- /dev/null
+++ b/tinycc/tests/asm-c-connect-2.c
@@ -0,0 +1,48 @@
+#include <stdio.h>
+
+#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/tinycc/tests/asmtest.S b/tinycc/tests/asmtest.S
new file mode 100644
index 0000000..7f31ce5
--- /dev/null
+++ b/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/tinycc/tests/boundtest.c b/tinycc/tests/boundtest.c
new file mode 100644
index 0000000..e4b2ab1
--- /dev/null
+++ b/tinycc/tests/boundtest.c
@@ -0,0 +1,309 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#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<TAB_SIZE;i++) {
+ sum += tab[i];
+ }
+ return sum;
+}
+
+/* error */
+int test2(void)
+{
+ int i, sum = 0;
+ for(i=0;i<TAB_SIZE + 1;i++) {
+ sum += tab[i];
+ }
+ return sum;
+}
+
+/* actually, profiling test */
+int test3(void)
+{
+ int sum;
+ int i, it;
+
+ sum = 0;
+ for(it=0;it<NB_ITS;it++) {
+ for(i=0;i<TAB_SIZE;i++) {
+ sum += tab[i];
+ }
+ }
+ return sum;
+}
+
+/* ok */
+int test4(void)
+{
+ int i, sum = 0;
+ int *tab4;
+
+ tab4 = malloc(20 * sizeof(int));
+ for(i=0;i<20;i++) {
+ sum += tab4[i];
+ }
+ free(tab4);
+
+ return sum;
+}
+
+/* error */
+int test5(void)
+{
+ int i, sum = 0;
+ int *tab4;
+
+ tab4 = malloc(20 * sizeof(int));
+ for(i=0;i<21;i++) {
+ sum += tab4[i];
+ }
+ free(tab4);
+
+ return sum;
+}
+
+/* error */
+int test6(void)
+{
+ int i, sum = 0;
+ int *tab4;
+
+ tab4 = malloc(20 * sizeof(int));
+ free(tab4);
+ for(i=0;i<21;i++) {
+ sum += tab4[i];
+ }
+
+ return sum;
+}
+
+/* error */
+int test7(void)
+{
+ int i, sum = 0;
+ int *p;
+
+ for(i=0;i<TAB_SIZE + 1;i++) {
+ p = &tab[i];
+ if (i == TAB_SIZE)
+ printf("i=%d %x\n", i, p);
+ sum += *p;
+ }
+ return sum;
+}
+
+/* ok */
+int test8(void)
+{
+ int i, sum = 0;
+ int tab[10];
+
+ for(i=0;i<10;i++) {
+ sum += tab[i];
+ }
+ return sum;
+}
+
+/* error */
+int test9(void)
+{
+ int i, sum = 0;
+ char tab[10];
+
+ for(i=0;i<11;i++) {
+ sum += tab[i];
+ }
+ return sum;
+}
+
+/* ok */
+int test10(void)
+{
+ char tab[10];
+ char tab1[10];
+
+ memset(tab, 0, 10);
+ memcpy(tab, tab1, 10);
+ memmove(tab, tab1, 10);
+ return 0;
+}
+
+/* error */
+int test11(void)
+{
+ char tab[10];
+
+ memset(tab, 0, 11);
+ return 0;
+}
+
+/* error */
+int test12(void)
+{
+ void *ptr;
+ ptr = malloc(10);
+ free(ptr);
+ free(ptr);
+ return 0;
+}
+
+/* error */
+int test13(void)
+{
+ char pad1 = 0;
+ char tab[10];
+ char pad2 = 0;
+ memset(tab, 'a', sizeof(tab));
+ return strlen(tab);
+}
+
+#if defined __i386__ || defined __x86_64__
+#define allocf(x)
+#else
+#undef alloca
+#define alloca(x) malloc(x)
+#define allocf(x) free(x)
+#endif
+
+int test14(void)
+{
+ char *p = alloca(TAB_SIZE);
+ size_t ret;
+ memset(p, 'a', TAB_SIZE);
+ p[TAB_SIZE-1] = 0;
+ ret = strlen(p);
+ allocf(p);
+ return ret;
+}
+
+/* error */
+int test15(void)
+{
+ char *p = alloca(TAB_SIZE-1);
+ size_t ret;
+ memset(p, 'a', TAB_SIZE);
+ p[TAB_SIZE-1] = 0;
+ ret = strlen(p);
+ allocf(p);
+ return ret;
+}
+
+/* ok */
+int test16()
+{
+ char *demo = "This is only a test.";
+ char *p;
+
+ p = alloca(16);
+ strcpy(p,"12345678901234");
+
+ /* Test alloca embedded in a larger expression */
+ printf("alloca : %s : %s\n", p, strcpy(alloca(strlen(demo)+1),demo) );
+ allocf(p);
+
+ return 0;
+}
+
+/* error */
+int test17()
+{
+ char *demo = "This is only a test.";
+ char *p;
+
+ p = alloca(16);
+ strcpy(p,"12345678901234");
+
+ /* Test alloca embedded in a larger expression */
+ printf("alloca : %s : %s\n", p, strcpy(alloca(strlen(demo)),demo) );
+ allocf(p);
+
+ return 0;
+}
+
+int test18(void)
+{
+ int i, sum = 0, n = TAB_SIZE;
+ int tab[n];
+ for(i=0;i<TAB_SIZE+1;i++) {
+ sum += tab[i];
+ }
+ return sum;
+}
+
+int (*table_test[])(void) = {
+ test1,
+ test2,
+ test3,
+ test4,
+ test5,
+ test6,
+ test7,
+ test8,
+ test9,
+ test10,
+ test11,
+ test12,
+ test13,
+ test14,
+ test15,
+ test16,
+ test17,
+ test18
+};
+
+int main(int argc, char **argv)
+{
+ int i;
+ char *cp;
+ int index;
+ int (*ftest)(void);
+ int index_max = sizeof(table_test)/sizeof(table_test[0]);
+
+ /* check bounds checking main arg */
+ for (i = 0; i < argc; i++) {
+ cp = argv[i];
+ while (*cp) {
+ cp++;
+ }
+ }
+
+ if (argc < 2) {
+ printf(
+ "test TCC bound checking system\n"
+ "usage: boundtest N\n"
+ " 1 <= N <= %d\n", index_max);
+ exit(1);
+ }
+
+ index = 0;
+ if (argc >= 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/tinycc/tests/bug.c b/tinycc/tests/bug.c
new file mode 100644
index 0000000..b0bc2d5
--- /dev/null
+++ b/tinycc/tests/bug.c
@@ -0,0 +1,35 @@
+#include <stdio.h>
+#include <stdarg.h>
+
+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/tinycc/tests/gcctestsuite.sh b/tinycc/tests/gcctestsuite.sh
new file mode 100644
index 0000000..b6f9ec2
--- /dev/null
+++ b/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/tinycc/tests/libtcc_test.c b/tinycc/tests/libtcc_test.c
new file mode 100644
index 0000000..d21c7fe
--- /dev/null
+++ b/tinycc/tests/libtcc_test.c
@@ -0,0 +1,110 @@
+/*
+ * Simple Test program for libtcc
+ *
+ * libtcc can be useful to use tcc as a "backend" for a code generator.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#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 <tcclib.h>\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);
+ }
+
+ assert(tcc_get_error_func(s) == NULL);
+ assert(tcc_get_error_opaque(s) == NULL);
+
+ tcc_set_error_func(s, stderr, handle_error);
+
+ assert(tcc_get_error_func(s) == handle_error);
+ assert(tcc_get_error_opaque(s) == stderr);
+
+ /* 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, TCC_RELOCATE_AUTO) < 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/tinycc/tests/libtcc_test_mt.c b/tinycc/tests/libtcc_test_mt.c
new file mode 100644
index 0000000..1e5a386
--- /dev/null
+++ b/tinycc/tests/libtcc_test_mt.c
@@ -0,0 +1,305 @@
+/*
+ * Multi-thread Test for libtcc
+ */
+
+#ifndef FIB
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "libtcc.h"
+
+#define M 20 /* number of states */
+#define F(n) (n % 20 + 2) /* fib argument */
+
+#ifdef _WIN32
+#include <windows.h>
+#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 <sys/time.h>
+#include <unistd.h>
+#include <pthread.h>
+#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 <tcclib.h>\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"
+"int foo(int n)\n"
+"{\n"
+" printf(\" %d\", fib(n));\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);
+ }
+ }
+}
+
+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 (!w) tcc_set_options(s, "-w");
+ 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, TCC_RELOCATE_AUTO) < 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(void)
+{
+ TCCState *s[M];
+ int (*func[M])(int);
+ int n;
+
+ 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(0);
+ if (b < M)
+ if (tcc_compile_string(s[b], my_program) == -1)
+ break;
+ if (c < M)
+ func[c] = reloc_state(s[c], "foo");
+ if (d < M && func[d])
+ func[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;
+
+ s = new_state(0);
+ sleep_ms(1);
+ ret = tcc_compile_string(s, my_program);
+ sleep_ms(1);
+ if (ret >= 0) {
+ func = reloc_state(s, "foo");
+ if (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)
+ exit(1);
+ 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 <options>\n");
+ return 1;
+ }
+
+#if 1
+ printf("running fib with mixed calls\n "), fflush(stdout);
+ t = getclock_ms();
+ state_test();
+ printf("\n (%u ms)\n", getclock_ms() - t);
+#endif
+#if 1
+ 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 <tcclib.h>
+
+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/tinycc/tests/pp/01.c b/tinycc/tests/pp/01.c
new file mode 100644
index 0000000..2fc3d79
--- /dev/null
+++ b/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/tinycc/tests/pp/01.expect b/tinycc/tests/pp/01.expect
new file mode 100644
index 0000000..cf5b153
--- /dev/null
+++ b/tinycc/tests/pp/01.expect
@@ -0,0 +1 @@
+char p[] = "x ## y";
diff --git a/tinycc/tests/pp/02.c b/tinycc/tests/pp/02.c
new file mode 100644
index 0000000..feb1254
--- /dev/null
+++ b/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/tinycc/tests/pp/02.expect b/tinycc/tests/pp/02.expect
new file mode 100644
index 0000000..8ae2eb9
--- /dev/null
+++ b/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/tinycc/tests/pp/03.c b/tinycc/tests/pp/03.c
new file mode 100644
index 0000000..a659245
--- /dev/null
+++ b/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/tinycc/tests/pp/03.expect b/tinycc/tests/pp/03.expect
new file mode 100644
index 0000000..44aad0a
--- /dev/null
+++ b/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/tinycc/tests/pp/04.c b/tinycc/tests/pp/04.c
new file mode 100644
index 0000000..0068f37
--- /dev/null
+++ b/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/tinycc/tests/pp/04.expect b/tinycc/tests/pp/04.expect
new file mode 100644
index 0000000..7c67b01
--- /dev/null
+++ b/tinycc/tests/pp/04.expect
@@ -0,0 +1 @@
+(1)
diff --git a/tinycc/tests/pp/05.c b/tinycc/tests/pp/05.c
new file mode 100644
index 0000000..7274941
--- /dev/null
+++ b/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/tinycc/tests/pp/05.expect b/tinycc/tests/pp/05.expect
new file mode 100644
index 0000000..9f9be37
--- /dev/null
+++ b/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/tinycc/tests/pp/06.c b/tinycc/tests/pp/06.c
new file mode 100644
index 0000000..28cfdde
--- /dev/null
+++ b/tinycc/tests/pp/06.c
@@ -0,0 +1,5 @@
+#define X(a,b, \
+ c,d) \
+ foo
+
+X(1,2,3,4)
diff --git a/tinycc/tests/pp/06.expect b/tinycc/tests/pp/06.expect
new file mode 100644
index 0000000..257cc56
--- /dev/null
+++ b/tinycc/tests/pp/06.expect
@@ -0,0 +1 @@
+foo
diff --git a/tinycc/tests/pp/07.c b/tinycc/tests/pp/07.c
new file mode 100644
index 0000000..b22b22b
--- /dev/null
+++ b/tinycc/tests/pp/07.c
@@ -0,0 +1,4 @@
+#define a() YES
+#define b() a
+b()
+b()()
diff --git a/tinycc/tests/pp/07.expect b/tinycc/tests/pp/07.expect
new file mode 100644
index 0000000..ad0e20a
--- /dev/null
+++ b/tinycc/tests/pp/07.expect
@@ -0,0 +1,2 @@
+a
+YES
diff --git a/tinycc/tests/pp/08.c b/tinycc/tests/pp/08.c
new file mode 100644
index 0000000..93018e1
--- /dev/null
+++ b/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/tinycc/tests/pp/08.expect b/tinycc/tests/pp/08.expect
new file mode 100644
index 0000000..2b2e3ee
--- /dev/null
+++ b/tinycc/tests/pp/08.expect
@@ -0,0 +1 @@
+(hej.s_s.s_pos)
diff --git a/tinycc/tests/pp/09.c b/tinycc/tests/pp/09.c
new file mode 100644
index 0000000..315b297
--- /dev/null
+++ b/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/tinycc/tests/pp/09.expect b/tinycc/tests/pp/09.expect
new file mode 100644
index 0000000..adce0f9
--- /dev/null
+++ b/tinycc/tests/pp/09.expect
@@ -0,0 +1 @@
+aaaaoooo
diff --git a/tinycc/tests/pp/10.c b/tinycc/tests/pp/10.c
new file mode 100644
index 0000000..f180eff
--- /dev/null
+++ b/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/tinycc/tests/pp/10.expect b/tinycc/tests/pp/10.expect
new file mode 100644
index 0000000..bd18e18
--- /dev/null
+++ b/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/tinycc/tests/pp/11.c b/tinycc/tests/pp/11.c
new file mode 100644
index 0000000..5ce868b
--- /dev/null
+++ b/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/tinycc/tests/pp/11.expect b/tinycc/tests/pp/11.expect
new file mode 100644
index 0000000..bb5d6b7
--- /dev/null
+++ b/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/tinycc/tests/pp/12.S b/tinycc/tests/pp/12.S
new file mode 100644
index 0000000..597ccb4
--- /dev/null
+++ b/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/tinycc/tests/pp/12.expect b/tinycc/tests/pp/12.expect
new file mode 100644
index 0000000..17a861c
--- /dev/null
+++ b/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/tinycc/tests/pp/13.S b/tinycc/tests/pp/13.S
new file mode 100644
index 0000000..bf0b525
--- /dev/null
+++ b/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/tinycc/tests/pp/13.expect b/tinycc/tests/pp/13.expect
new file mode 100644
index 0000000..c7a3230
--- /dev/null
+++ b/tinycc/tests/pp/13.expect
@@ -0,0 +1,2 @@
+.text
+endtext:
diff --git a/tinycc/tests/pp/14.c b/tinycc/tests/pp/14.c
new file mode 100644
index 0000000..e15468c
--- /dev/null
+++ b/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/tinycc/tests/pp/14.expect b/tinycc/tests/pp/14.expect
new file mode 100644
index 0000000..3786044
--- /dev/null
+++ b/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/tinycc/tests/pp/15.c b/tinycc/tests/pp/15.c
new file mode 100644
index 0000000..cf13f9a
--- /dev/null
+++ b/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/tinycc/tests/pp/15.expect b/tinycc/tests/pp/15.expect
new file mode 100644
index 0000000..b4f885e
--- /dev/null
+++ b/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/tinycc/tests/pp/16.c b/tinycc/tests/pp/16.c
new file mode 100644
index 0000000..8b5b642
--- /dev/null
+++ b/tinycc/tests/pp/16.c
@@ -0,0 +1,3 @@
+/* The following should warn */
+#define A ...
+#define A <<=
diff --git a/tinycc/tests/pp/16.expect b/tinycc/tests/pp/16.expect
new file mode 100644
index 0000000..695d6d4
--- /dev/null
+++ b/tinycc/tests/pp/16.expect
@@ -0,0 +1,2 @@
+
+16.c:3: warning: A redefined
diff --git a/tinycc/tests/pp/17.c b/tinycc/tests/pp/17.c
new file mode 100644
index 0000000..f12196f
--- /dev/null
+++ b/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/tinycc/tests/pp/17.expect b/tinycc/tests/pp/17.expect
new file mode 100644
index 0000000..e95aafe
--- /dev/null
+++ b/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/tinycc/tests/pp/18.c b/tinycc/tests/pp/18.c
new file mode 100644
index 0000000..0961426
--- /dev/null
+++ b/tinycc/tests/pp/18.c
@@ -0,0 +1,15 @@
+#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()
diff --git a/tinycc/tests/pp/18.expect b/tinycc/tests/pp/18.expect
new file mode 100644
index 0000000..447a9b2
--- /dev/null
+++ b/tinycc/tests/pp/18.expect
@@ -0,0 +1,3 @@
+X181 1
+X182 0
+X183 yeah
diff --git a/tinycc/tests/pp/19.c b/tinycc/tests/pp/19.c
new file mode 100644
index 0000000..aa91abe
--- /dev/null
+++ b/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/tinycc/tests/pp/19.expect b/tinycc/tests/pp/19.expect
new file mode 100644
index 0000000..08c0858
--- /dev/null
+++ b/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/tinycc/tests/pp/20.c b/tinycc/tests/pp/20.c
new file mode 100644
index 0000000..7944d62
--- /dev/null
+++ b/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/tinycc/tests/pp/20.expect b/tinycc/tests/pp/20.expect
new file mode 100644
index 0000000..d19405d
--- /dev/null
+++ b/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/tinycc/tests/pp/21.c b/tinycc/tests/pp/21.c
new file mode 100644
index 0000000..1316226
--- /dev/null
+++ b/tinycc/tests/pp/21.c
@@ -0,0 +1,36 @@
+/* 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
diff --git a/tinycc/tests/pp/21.expect b/tinycc/tests/pp/21.expect
new file mode 100644
index 0000000..5a1376b
--- /dev/null
+++ b/tinycc/tests/pp/21.expect
@@ -0,0 +1,8 @@
+----- 1 ------
+OK
+----- 2 ------
+OK
+----- 3 ------
+OK
+----- 4 ------
+OK
diff --git a/tinycc/tests/pp/22.c b/tinycc/tests/pp/22.c
new file mode 100644
index 0000000..76e2315
--- /dev/null
+++ b/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/tinycc/tests/pp/22.expect b/tinycc/tests/pp/22.expect
new file mode 100644
index 0000000..ceaea03
--- /dev/null
+++ b/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/tinycc/tests/pp/Makefile b/tinycc/tests/pp/Makefile
new file mode 100644
index 0000000..224c866
--- /dev/null
+++ b/tinycc/tests/pp/Makefile
@@ -0,0 +1,51 @@
+#
+# 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 ;
+
+# 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 <RE> ignore lines matching RE
diff --git a/tinycc/tests/pp/pp-counter.c b/tinycc/tests/pp/pp-counter.c
new file mode 100644
index 0000000..3978e1a
--- /dev/null
+++ b/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/tinycc/tests/pp/pp-counter.expect b/tinycc/tests/pp/pp-counter.expect
new file mode 100644
index 0000000..02fc535
--- /dev/null
+++ b/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/tinycc/tests/tcctest.c b/tinycc/tests/tcctest.c
new file mode 100644
index 0000000..a982aba
--- /dev/null
+++ b/tinycc/tests/tcctest.c
@@ -0,0 +1,4473 @@
+/*
+ * 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 <tcclib.h>
+#define TCCLIB_INC1 <tcclib
+#define TCCLIB_INC2 h>
+#define TCCLIB_INC3 "tcclib.h"
+
+#include TCCLIB_INC
+
+#include TCCLIB_INC1.TCCLIB_INC2
+
+#include TCCLIB_INC1.h>
+
+#include TCCLIB_INC3
+
+#include <tcclib.h>
+
+#include "tcclib.h"
+
+#include "tcctest.h"
+
+/* Test two more ways to include a file named like a pp-number */
+#define INC(name) <tests/name.h>
+#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 <tests/42test.h>
+#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
+
+#ifdef __TINYC__
+/* We try to handle this syntax. Make at least sure it doesn't segfault. */
+char invalid_function_def()[] {return 0;}
+#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))));
+}
+
+int op(a,b)
+{
+ return a / b;
+}
+
+int ret(a)
+{
+ if (a == 2)
+ return 1;
+ if (a == 3)
+ return 2;
+ return 0;
+}
+
+#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(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 *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
+}
+
+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
+}
+
+/* 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;
+}
+
+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)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 = &num;
+ (*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<d; z++) {
+ for (y=0; y<h; y++) {
+ for (x=0; x<w; x++) {
+ arr[z][y][x] = c++;
+ }
+ }
+ }
+ for (z=0; z<d; z++) {
+ for (y=0; y<h; y++) {
+ for (x=0; x<w; x++) {
+ printf(" %2d", arr[z][y][x]);
+ }
+ puts("");
+ }
+ puts("");
+ }
+ starr = &arr[1];
+ printf(" sizes : %d %d %d\n"
+ " pdiff : %d %d\n"
+ " tests : %d %d %d\n",
+ sizeof (*arr), sizeof (*arr)[0], sizeof (*arr)[0][0],
+ arr + 2 - arr, *arr + 3 - *arr,
+ 0 == sizeof (*arr + 1) - sizeof arr,
+ 0 == sizeof sizeof *arr - sizeof arr,
+ starr[0][2][3] == arr[1][2][3]
+ );
+ free (arr);
+}
+
+void c99_vla_test_3a (int arr[2][3][4])
+{
+ printf ("%d\n", arr[1][2][3]);
+}
+
+void c99_vla_test_3b(int s, int arr[s][3][4])
+{
+ printf ("%d\n", arr[1][2][3]);
+}
+
+void c99_vla_test_3c(int s, int arr[2][s][4])
+{
+ printf ("%d\n", arr[1][2][3]);
+}
+
+void c99_vla_test_3d(int s, int arr[2][3][s])
+{
+ printf ("%d\n", arr[1][2][3]);
+}
+
+void c99_vla_test_3e(int s, int arr[][3][--s])
+{
+ printf ("%d %d\n", s, arr[1][2][3]);
+}
+
+void c99_vla_test_3(void)
+{
+ int a[2][3][4];
+
+ memset (a, 0, sizeof(a));
+ a[1][2][3] = 123;
+ c99_vla_test_3a(a);
+ c99_vla_test_3b(2, a);
+ c99_vla_test_3c(3, a);
+ c99_vla_test_3d(4, a);
+ c99_vla_test_3e(5, a);
+}
+
+void c99_vla_test(void)
+{
+ c99_vla_test_1(5, 2);
+ c99_vla_test_2(3, 4, 5);
+ c99_vla_test_3();
+}
+
+
+void sizeof_test(void)
+{
+ int a;
+ int **ptr;
+
+ printf("sizeof(int) = %d\n", sizeof(int));
+ printf("sizeof(unsigned int) = %d\n", sizeof(unsigned int));
+ printf("sizeof(long) = %d\n", sizeof(long));
+ printf("sizeof(unsigned long) = %d\n", sizeof(unsigned long));
+ printf("sizeof(short) = %d\n", sizeof(short));
+ printf("sizeof(unsigned short) = %d\n", sizeof(unsigned short));
+ printf("sizeof(char) = %d\n", sizeof(char));
+ printf("sizeof(unsigned char) = %d\n", sizeof(unsigned char));
+ printf("sizeof(func) = %d\n", sizeof sizeof_test());
+ a = 1;
+ printf("sizeof(a++) = %d\n", sizeof a++);
+ printf("a=%d\n", a);
+ ptr = NULL;
+ printf("sizeof(**ptr) = %d\n", sizeof (**ptr));
+
+ /* The type of sizeof should be as large as a pointer, actually
+ it should be size_t. */
+ printf("sizeof(sizeof(int) = %d\n", sizeof(sizeof(int)));
+ uintptr_t t = 1;
+ uintptr_t t2;
+ /* Effectively <<32, but defined also on 32bit machines. */
+ t <<= 16;
+ t <<= 16;
+ t++;
+ /* This checks that sizeof really can be used to manipulate
+ uintptr_t objects, without truncation. */
+ t2 = t & -sizeof(uintptr_t);
+ printf ("%lu %lu\n", t, t2);
+
+ /* some alignof tests */
+ printf("__alignof__(int) = %d\n", __alignof__(int));
+ printf("__alignof__(unsigned int) = %d\n", __alignof__(unsigned int));
+ printf("__alignof__(short) = %d\n", __alignof__(short));
+ printf("__alignof__(unsigned short) = %d\n", __alignof__(unsigned short));
+ printf("__alignof__(char) = %d\n", __alignof__(char));
+ printf("__alignof__(unsigned char) = %d\n", __alignof__(unsigned char));
+ printf("__alignof__(func) = %d\n", __alignof__ sizeof_test());
+
+ /* sizes of VLAs need to be evaluated even inside sizeof: */
+ a = 2;
+ printf("sizeof(char[1+2*a]) = %d\n", sizeof(char[1+2*a]));
+ /* And checking if sizeof compound literal works. Parenthesized: */
+ printf("sizeof( (struct {int i; int j;}){4,5} ) = %d\n",
+ sizeof( (struct {int i; int j;}){4,5} ));
+ /* And as direct sizeof argument (as unary expression): */
+ printf("sizeof (struct {short i; short j;}){4,5} = %d\n",
+ sizeof (struct {short i; short j;}){4,5} );
+
+ /* sizeof(x && y) should be sizeof(int), even if constant
+ evaluating is possible. */
+ printf("sizeof(t && 0) = %d\n", sizeof(t && 0));
+ printf("sizeof(1 && 1) = %d\n", sizeof(1 && 1));
+ printf("sizeof(t || 1) = %d\n", sizeof(t || 1));
+ printf("sizeof(0 || 0) = %d\n", sizeof(0 || 0));
+}
+
+void typeof_test(void)
+{
+ double a;
+ typeof(a) b;
+ typeof(float) c;
+
+ a = 1.5;
+ b = 2.5;
+ c = 3.5;
+ printf("a=%f b=%f c=%f\n", a, b, c);
+}
+
+
+struct hlist_node;
+struct hlist_head {
+ struct hlist_node *first, *last;
+};
+
+void consume_ulong (unsigned long i)
+{
+ i = 0;
+}
+
+void statement_expr_test(void)
+{
+ int a, i;
+
+ /* Basic stmt expr test */
+ a = 0;
+ for(i=0;i<10;i++) {
+ a += 1 +
+ ( { int b, j;
+ b = 0;
+ for(j=0;j<5;j++)
+ b += j; b;
+ } );
+ }
+ printf("a=%d\n", a);
+
+ /* Test that symbols aren't freed prematurely.
+ With SYM_DEBUG valgrind will show a read from a freed
+ symbol, and tcc will show an (invalid) warning on the initialization
+ of 'ptr' below, if symbols are popped after the stmt expr. */
+ void *v = (void*)39;
+ typeof(({
+ (struct hlist_node *)v;
+ })) x;
+ typeof (x)
+ ptr = (struct hlist_node *)v;
+
+ /* This part used to segfault when symbols were popped prematurely.
+ The symbols for the static local would be overwritten with
+ helper symbols from the pre-processor expansions in between. */
+#define some_attr __attribute__((aligned(1)))
+#define tps(str) ({ \
+ static const char *t some_attr = str; \
+ t; \
+ })
+ printf ("stmtexpr: %s %s\n",
+ tps("somerandomlongstring"),
+ tps("anotherlongstring"));
+
+ /* Test that the three decls of 't' don't interact. */
+ int t = 40;
+ int b = ({ int t = 41; t; });
+ int c = ({ int t = 42; t; });
+
+ /* Test that aggregate return values work. */
+ struct hlist_head h
+ = ({
+ typedef struct hlist_head T;
+ long pre = 48;
+ T t = { (void*)43, (void*)44 };
+ long post = 49;
+ t;
+ });
+ printf ("stmtexpr: %d %d %d\n", t, b, c);
+ printf ("stmtexpr: %ld %ld\n", (long)h.first, (long)h.last);
+
+ /* Test that we can give out addresses of local labels. */
+ consume_ulong(({ __label__ __here; __here: (unsigned long)&&__here; }));
+
+ /* Test interaction between local and global label stacks and the
+ need to defer popping symbol from them when within statement
+ expressions. Note how the labels are both named LBL. */
+ i = 0;
+ ({
+ {
+ __label__ LBL;
+ LBL: if (i++ == 0) goto LBL;
+ }
+ /* jump to a classical label out of an expr-stmt that had previously
+ overshadowed that classical label */
+ goto LBL;
+ });
+ LBL:
+ printf("stmtexpr: %d should be 2\n", i);
+}
+
+void local_label_test(void)
+{
+ int a;
+ goto l1;
+ l2:
+ a = 1 + ({
+ __label__ l1, l2, l3, l4;
+ goto l1;
+ l4:
+ printf("aa1\n");
+ goto l3;
+ l2:
+ printf("aa3\n");
+ goto l4;
+ l1:
+ printf("aa2\n");
+ goto l2;
+ l3:;
+ 1;
+ });
+ printf("a=%d\n", a);
+ return;
+ l4:
+ printf("bb1\n");
+ goto l2;
+ l1:
+ printf("bb2\n");
+ goto l4;
+}
+
+/* inline assembler test */
+#if defined(__i386__) || defined(__x86_64__)
+
+typedef __SIZE_TYPE__ word;
+
+/* from linux kernel */
+static char * strncat1(char * dest,const char * src,size_t count)
+{
+word d0, d1, d2, d3;
+__asm__ __volatile__(
+ "repne\n\t"
+ "scasb\n\t"
+ "dec %1\n\t"
+ "mov %8,%3\n"
+ "1:\tdec %3\n\t"
+ "js 2f\n\t"
+ "lodsb\n\t"
+ "stosb\n\t"
+ "testb %%al,%%al\n\t"
+ "jne 1b\n"
+ "2:\txor %2,%2\n\t"
+ "stosb"
+ : "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3)
+ : "0" (src),"1" (dest),"2" (0),"3" (0xffffffff), "g" (count)
+ : "memory");
+return dest;
+}
+
+static char * strncat2(char * dest,const char * src,size_t count)
+{
+word d0, d1, d2, d3;
+__asm__ __volatile__(
+ "repne scasb\n\t" /* one-line repne prefix + string op */
+ "dec %1\n\t"
+ "mov %8,%3\n"
+ "1:\tdec %3\n\t"
+ "js 2f\n\t"
+ "lodsb\n\t"
+ "stosb\n\t"
+ "testb %%al,%%al\n\t"
+ "jne 1b\n"
+ "2:\txor %2,%2\n\t"
+ "stosb"
+ : "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3)
+ : "0" (src),"1" (dest),"2" (0),"3" (0xffffffff), "g" (count)
+ : "memory");
+return dest;
+}
+
+static inline void * memcpy1(void * to, const void * from, size_t n)
+{
+word d0, d1, d2;
+__asm__ __volatile__(
+ "rep ; movsl\n\t"
+ "testb $2,%b4\n\t"
+ "je 1f\n\t"
+ "movsw\n"
+ "1:\ttestb $1,%b4\n\t"
+ "je 2f\n\t"
+ "movsb\n"
+ "2:"
+ : "=&c" (d0), "=&D" (d1), "=&S" (d2)
+ :"0" (n/4), "q" (n),"1" ((word) to),"2" ((word) from)
+ : "memory");
+return (to);
+}
+
+static inline void * memcpy2(void * to, const void * from, size_t n)
+{
+word d0, d1, d2;
+__asm__ __volatile__(
+ "rep movsl\n\t" /* one-line rep prefix + string op */
+ "testb $2,%b4\n\t"
+ "je 1f\n\t"
+ "movsw\n"
+ "1:\ttestb $1,%b4\n\t"
+ "je 2f\n\t"
+ "movsb\n"
+ "2:"
+ : "=&c" (d0), "=&D" (d1), "=&S" (d2)
+ :"0" (n/4), "q" (n),"1" ((word) to),"2" ((word) from)
+ : "memory");
+return (to);
+}
+
+static __inline__ void sigaddset1(unsigned int *set, int _sig)
+{
+ __asm__("btsl %1,%0" : "=m"(*set) : "Ir"(_sig - 1) : "cc");
+}
+
+static __inline__ void sigdelset1(unsigned int *set, int _sig)
+{
+ asm("btrl %1,%0" : "=m"(*set) : "Ir"(_sig - 1) : "cc", "flags");
+}
+
+#ifdef __clang__
+/* clang's inline asm is uncapable of 'xchgb %b0,%h0' */
+static __inline__ __const__ unsigned int swab32(unsigned int x)
+{
+ return ((x >> 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_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();
+ 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 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 *);
+/* space is needed because tcc preprocessor introduces a space between each token */
+ 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));
+#ifdef __clang__
+ /* clang doesn't regard this as constant expression */
+ printf("res6 = 1\n");
+#else
+ printf("res6 = %d\n", __builtin_constant_p(i && 0));
+#endif
+ printf("res7 = %d\n", __builtin_constant_p(i && 1));
+#ifdef __clang__
+ /* clang doesn't regard this as constant expression */
+ printf("res8 = 1\n");
+#else
+ printf("res8 = %d\n", __builtin_constant_p(i && 0 ? i : 34));
+#endif
+ printf("res9 = %d\n", __builtin_constant_p("hi"));
+ printf("res10 = %d\n", __builtin_constant_p(func()));
+ printf("res11 = %d\n", __builtin_constant_p((i++, 7)));
+ 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/tinycc/tests/tcctest.h b/tinycc/tests/tcctest.h
new file mode 100644
index 0000000..b301c7c
--- /dev/null
+++ b/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/tinycc/tests/testfp.c b/tinycc/tests/testfp.c
new file mode 100644
index 0000000..63342b4
--- /dev/null
+++ b/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 <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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/tinycc/tests/tests2/00_assignment.c b/tinycc/tests/tests2/00_assignment.c
new file mode 100644
index 0000000..c96109f
--- /dev/null
+++ b/tinycc/tests/tests2/00_assignment.c
@@ -0,0 +1,18 @@
+#include <stdio.h>
+
+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/tinycc/tests/tests2/00_assignment.expect b/tinycc/tests/tests2/00_assignment.expect
new file mode 100644
index 0000000..d4407f3
--- /dev/null
+++ b/tinycc/tests/tests2/00_assignment.expect
@@ -0,0 +1,3 @@
+42
+64
+12, 34
diff --git a/tinycc/tests/tests2/01_comment.c b/tinycc/tests/tests2/01_comment.c
new file mode 100644
index 0000000..a2e6bc6
--- /dev/null
+++ b/tinycc/tests/tests2/01_comment.c
@@ -0,0 +1,14 @@
+#include <stdio.h>
+
+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/tinycc/tests/tests2/01_comment.expect b/tinycc/tests/tests2/01_comment.expect
new file mode 100644
index 0000000..b1387ad
--- /dev/null
+++ b/tinycc/tests/tests2/01_comment.expect
@@ -0,0 +1,5 @@
+Hello
+Hello
+Hello
+Hello
+Hello
diff --git a/tinycc/tests/tests2/02_printf.c b/tinycc/tests/tests2/02_printf.c
new file mode 100644
index 0000000..4c34dd8
--- /dev/null
+++ b/tinycc/tests/tests2/02_printf.c
@@ -0,0 +1,18 @@
+#include <stdio.h>
+
+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/tinycc/tests/tests2/02_printf.expect b/tinycc/tests/tests2/02_printf.expect
new file mode 100644
index 0000000..f67a0f6
--- /dev/null
+++ b/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/tinycc/tests/tests2/03_struct.c b/tinycc/tests/tests2/03_struct.c
new file mode 100644
index 0000000..fd73133
--- /dev/null
+++ b/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/tinycc/tests/tests2/03_struct.expect b/tinycc/tests/tests2/03_struct.expect
new file mode 100644
index 0000000..be8df37
--- /dev/null
+++ b/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/tinycc/tests/tests2/04_for.c b/tinycc/tests/tests2/04_for.c
new file mode 100644
index 0000000..312fed8
--- /dev/null
+++ b/tinycc/tests/tests2/04_for.c
@@ -0,0 +1,15 @@
+#include <stdio.h>
+
+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/tinycc/tests/tests2/04_for.expect b/tinycc/tests/tests2/04_for.expect
new file mode 100644
index 0000000..f00c965
--- /dev/null
+++ b/tinycc/tests/tests2/04_for.expect
@@ -0,0 +1,10 @@
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
diff --git a/tinycc/tests/tests2/05_array.c b/tinycc/tests/tests2/05_array.c
new file mode 100644
index 0000000..c218f31
--- /dev/null
+++ b/tinycc/tests/tests2/05_array.c
@@ -0,0 +1,21 @@
+#include <stdio.h>
+
+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/tinycc/tests/tests2/05_array.expect b/tinycc/tests/tests2/05_array.expect
new file mode 100644
index 0000000..bc7257c
--- /dev/null
+++ b/tinycc/tests/tests2/05_array.expect
@@ -0,0 +1,10 @@
+1
+4
+9
+16
+25
+36
+49
+64
+81
+100
diff --git a/tinycc/tests/tests2/06_case.c b/tinycc/tests/tests2/06_case.c
new file mode 100644
index 0000000..c0191e2
--- /dev/null
+++ b/tinycc/tests/tests2/06_case.c
@@ -0,0 +1,29 @@
+#include <stdio.h>
+
+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/tinycc/tests/tests2/06_case.expect b/tinycc/tests/tests2/06_case.expect
new file mode 100644
index 0000000..fab2c20
--- /dev/null
+++ b/tinycc/tests/tests2/06_case.expect
@@ -0,0 +1,8 @@
+0
+0
+1
+1
+2
+2
+3
+0
diff --git a/tinycc/tests/tests2/07_function.c b/tinycc/tests/tests2/07_function.c
new file mode 100644
index 0000000..006e0a7
--- /dev/null
+++ b/tinycc/tests/tests2/07_function.c
@@ -0,0 +1,35 @@
+#include <stdio.h>
+
+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/tinycc/tests/tests2/07_function.expect b/tinycc/tests/tests2/07_function.expect
new file mode 100644
index 0000000..8ffb0a7
--- /dev/null
+++ b/tinycc/tests/tests2/07_function.expect
@@ -0,0 +1,4 @@
+9
+16
+a=1234
+qfunc()
diff --git a/tinycc/tests/tests2/08_while.c b/tinycc/tests/tests2/08_while.c
new file mode 100644
index 0000000..602ffc7
--- /dev/null
+++ b/tinycc/tests/tests2/08_while.c
@@ -0,0 +1,24 @@
+#include <stdio.h>
+
+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/tinycc/tests/tests2/08_while.expect b/tinycc/tests/tests2/08_while.expect
new file mode 100644
index 0000000..702d4c0
--- /dev/null
+++ b/tinycc/tests/tests2/08_while.expect
@@ -0,0 +1,11 @@
+1
+1
+2
+3
+5
+8
+13
+21
+34
+55
+89
diff --git a/tinycc/tests/tests2/09_do_while.c b/tinycc/tests/tests2/09_do_while.c
new file mode 100644
index 0000000..1d3315d
--- /dev/null
+++ b/tinycc/tests/tests2/09_do_while.c
@@ -0,0 +1,24 @@
+#include <stdio.h>
+
+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/tinycc/tests/tests2/09_do_while.expect b/tinycc/tests/tests2/09_do_while.expect
new file mode 100644
index 0000000..702d4c0
--- /dev/null
+++ b/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/tinycc/tests/tests2/100_c99array-decls.c b/tinycc/tests/tests2/100_c99array-decls.c
new file mode 100644
index 0000000..46950aa
--- /dev/null
+++ b/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/tinycc/tests/tests2/100_c99array-decls.expect b/tinycc/tests/tests2/100_c99array-decls.expect
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tinycc/tests/tests2/100_c99array-decls.expect
diff --git a/tinycc/tests/tests2/101_cleanup.c b/tinycc/tests/tests2/101_cleanup.c
new file mode 100644
index 0000000..de5dca2
--- /dev/null
+++ b/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/tinycc/tests/tests2/101_cleanup.expect b/tinycc/tests/tests2/101_cleanup.expect
new file mode 100644
index 0000000..84960cd
--- /dev/null
+++ b/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/tinycc/tests/tests2/102_alignas.c b/tinycc/tests/tests2/102_alignas.c
new file mode 100644
index 0000000..62d3ed2
--- /dev/null
+++ b/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/tinycc/tests/tests2/102_alignas.expect b/tinycc/tests/tests2/102_alignas.expect
new file mode 100644
index 0000000..b458e07
--- /dev/null
+++ b/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/tinycc/tests/tests2/103_implicit_memmove.c b/tinycc/tests/tests2/103_implicit_memmove.c
new file mode 100644
index 0000000..1592fb2
--- /dev/null
+++ b/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/tinycc/tests/tests2/103_implicit_memmove.expect b/tinycc/tests/tests2/103_implicit_memmove.expect
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tinycc/tests/tests2/103_implicit_memmove.expect
diff --git a/tinycc/tests/tests2/104+_inline.c b/tinycc/tests/tests2/104+_inline.c
new file mode 100644
index 0000000..3c48eb8
--- /dev/null
+++ b/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/tinycc/tests/tests2/104_inline.c b/tinycc/tests/tests2/104_inline.c
new file mode 100644
index 0000000..766f94a
--- /dev/null
+++ b/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/tinycc/tests/tests2/104_inline.expect b/tinycc/tests/tests2/104_inline.expect
new file mode 100644
index 0000000..bdb0994
--- /dev/null
+++ b/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/tinycc/tests/tests2/105_local_extern.c b/tinycc/tests/tests2/105_local_extern.c
new file mode 100644
index 0000000..a248bb4
--- /dev/null
+++ b/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/tinycc/tests/tests2/105_local_extern.expect b/tinycc/tests/tests2/105_local_extern.expect
new file mode 100644
index 0000000..445ae74
--- /dev/null
+++ b/tinycc/tests/tests2/105_local_extern.expect
@@ -0,0 +1,2 @@
+f
+f
diff --git a/tinycc/tests/tests2/106_versym.c b/tinycc/tests/tests2/106_versym.c
new file mode 100644
index 0000000..dcce508
--- /dev/null
+++ b/tinycc/tests/tests2/106_versym.c
@@ -0,0 +1,18 @@
+#include <stdio.h>
+#include <pthread.h>
+#include <errno.h>
+
+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/tinycc/tests/tests2/106_versym.expect b/tinycc/tests/tests2/106_versym.expect
new file mode 100644
index 0000000..9766475
--- /dev/null
+++ b/tinycc/tests/tests2/106_versym.expect
@@ -0,0 +1 @@
+ok
diff --git a/tinycc/tests/tests2/107_stack_safe.c b/tinycc/tests/tests2/107_stack_safe.c
new file mode 100644
index 0000000..479c84d
--- /dev/null
+++ b/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/tinycc/tests/tests2/107_stack_safe.expect b/tinycc/tests/tests2/107_stack_safe.expect
new file mode 100644
index 0000000..e9e9cd7
--- /dev/null
+++ b/tinycc/tests/tests2/107_stack_safe.expect
@@ -0,0 +1 @@
+1 2 3 4 \ No newline at end of file
diff --git a/tinycc/tests/tests2/108_constructor.c b/tinycc/tests/tests2/108_constructor.c
new file mode 100644
index 0000000..145d0da
--- /dev/null
+++ b/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/tinycc/tests/tests2/108_constructor.expect b/tinycc/tests/tests2/108_constructor.expect
new file mode 100644
index 0000000..167ca51
--- /dev/null
+++ b/tinycc/tests/tests2/108_constructor.expect
@@ -0,0 +1,3 @@
+constructor
+main
+destructor
diff --git a/tinycc/tests/tests2/109_float_struct_calling.c b/tinycc/tests/tests2/109_float_struct_calling.c
new file mode 100644
index 0000000..90fc045
--- /dev/null
+++ b/tinycc/tests/tests2/109_float_struct_calling.c
@@ -0,0 +1,24 @@
+#include <stdio.h>
+
+/* 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/tinycc/tests/tests2/109_float_struct_calling.expect b/tinycc/tests/tests2/109_float_struct_calling.expect
new file mode 100644
index 0000000..eaa6787
--- /dev/null
+++ b/tinycc/tests/tests2/109_float_struct_calling.expect
@@ -0,0 +1 @@
+5.000000
diff --git a/tinycc/tests/tests2/10_pointer.c b/tinycc/tests/tests2/10_pointer.c
new file mode 100644
index 0000000..0177f4d
--- /dev/null
+++ b/tinycc/tests/tests2/10_pointer.c
@@ -0,0 +1,40 @@
+#include <stdio.h>
+
+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/tinycc/tests/tests2/10_pointer.expect b/tinycc/tests/tests2/10_pointer.expect
new file mode 100644
index 0000000..1e3c473
--- /dev/null
+++ b/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/tinycc/tests/tests2/110_average.c b/tinycc/tests/tests2/110_average.c
new file mode 100644
index 0000000..273b511
--- /dev/null
+++ b/tinycc/tests/tests2/110_average.c
@@ -0,0 +1,27 @@
+#include <stdio.h>
+
+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/tinycc/tests/tests2/110_average.expect b/tinycc/tests/tests2/110_average.expect
new file mode 100644
index 0000000..4955335
--- /dev/null
+++ b/tinycc/tests/tests2/110_average.expect
@@ -0,0 +1 @@
+15 2
diff --git a/tinycc/tests/tests2/111_conversion.c b/tinycc/tests/tests2/111_conversion.c
new file mode 100644
index 0000000..c0815e1
--- /dev/null
+++ b/tinycc/tests/tests2/111_conversion.c
@@ -0,0 +1,22 @@
+#include <stdio.h>
+
+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/tinycc/tests/tests2/111_conversion.expect b/tinycc/tests/tests2/111_conversion.expect
new file mode 100644
index 0000000..d81cc07
--- /dev/null
+++ b/tinycc/tests/tests2/111_conversion.expect
@@ -0,0 +1 @@
+42
diff --git a/tinycc/tests/tests2/112_backtrace.c b/tinycc/tests/tests2/112_backtrace.c
new file mode 100644
index 0000000..0b596d0
--- /dev/null
+++ b/tinycc/tests/tests2/112_backtrace.c
@@ -0,0 +1,175 @@
+#include <stdio.h>
+
+/* ------------------------------------------------------- */
+#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 <stdlib.h>
+#include <string.h>
+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/tinycc/tests/tests2/112_backtrace.expect b/tinycc/tests/tests2/112_backtrace.expect
new file mode 100644
index 0000000..ec2c6b8
--- /dev/null
+++ b/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/tinycc/tests/tests2/113_btdll.c b/tinycc/tests/tests2/113_btdll.c
new file mode 100644
index 0000000..8ae8981
--- /dev/null
+++ b/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/tinycc/tests/tests2/113_btdll.expect b/tinycc/tests/tests2/113_btdll.expect
new file mode 100644
index 0000000..34de481
--- /dev/null
+++ b/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/tinycc/tests/tests2/114_bound_signal.c b/tinycc/tests/tests2/114_bound_signal.c
new file mode 100644
index 0000000..d11b146
--- /dev/null
+++ b/tinycc/tests/tests2/114_bound_signal.c
@@ -0,0 +1,143 @@
+#include <stdio.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <signal.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <setjmp.h>
+
+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/tinycc/tests/tests2/114_bound_signal.expect b/tinycc/tests/tests2/114_bound_signal.expect
new file mode 100644
index 0000000..5d0fb3b
--- /dev/null
+++ b/tinycc/tests/tests2/114_bound_signal.expect
@@ -0,0 +1,2 @@
+start
+end
diff --git a/tinycc/tests/tests2/115_bound_setjmp.c b/tinycc/tests/tests2/115_bound_setjmp.c
new file mode 100644
index 0000000..793db58
--- /dev/null
+++ b/tinycc/tests/tests2/115_bound_setjmp.c
@@ -0,0 +1,172 @@
+#include <stdio.h>
+#include <string.h>
+#include <setjmp.h>
+
+#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/tinycc/tests/tests2/115_bound_setjmp.expect b/tinycc/tests/tests2/115_bound_setjmp.expect
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tinycc/tests/tests2/115_bound_setjmp.expect
diff --git a/tinycc/tests/tests2/116_bound_setjmp2.c b/tinycc/tests/tests2/116_bound_setjmp2.c
new file mode 100644
index 0000000..151114d
--- /dev/null
+++ b/tinycc/tests/tests2/116_bound_setjmp2.c
@@ -0,0 +1,84 @@
+#include <stdio.h>
+#include <string.h>
+#include <setjmp.h>
+#if !defined(_WIN32)
+#include <pthread.h>
+#else
+#include <windows.h>
+#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/tinycc/tests/tests2/116_bound_setjmp2.expect b/tinycc/tests/tests2/116_bound_setjmp2.expect
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tinycc/tests/tests2/116_bound_setjmp2.expect
diff --git a/tinycc/tests/tests2/117_builtins.c b/tinycc/tests/tests2/117_builtins.c
new file mode 100644
index 0000000..b57a73e
--- /dev/null
+++ b/tinycc/tests/tests2/117_builtins.c
@@ -0,0 +1,94 @@
+#include <stdio.h>
+
+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/tinycc/tests/tests2/117_builtins.expect b/tinycc/tests/tests2/117_builtins.expect
new file mode 100644
index 0000000..f2c78ba
--- /dev/null
+++ b/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/tinycc/tests/tests2/118_switch.c b/tinycc/tests/tests2/118_switch.c
new file mode 100644
index 0000000..789dd06
--- /dev/null
+++ b/tinycc/tests/tests2/118_switch.c
@@ -0,0 +1,75 @@
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+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/tinycc/tests/tests2/118_switch.expect b/tinycc/tests/tests2/118_switch.expect
new file mode 100644
index 0000000..4155eb4
--- /dev/null
+++ b/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/tinycc/tests/tests2/119_random_stuff.c b/tinycc/tests/tests2/119_random_stuff.c
new file mode 100644
index 0000000..0b7a4e5
--- /dev/null
+++ b/tinycc/tests/tests2/119_random_stuff.c
@@ -0,0 +1,120 @@
+#include <stdio.h>
+
+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 <sys/mman.h>
+
+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);
+}
+
+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();
+}
diff --git a/tinycc/tests/tests2/119_random_stuff.expect b/tinycc/tests/tests2/119_random_stuff.expect
new file mode 100644
index 0000000..3bd4a87
--- /dev/null
+++ b/tinycc/tests/tests2/119_random_stuff.expect
@@ -0,0 +1,6 @@
+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
diff --git a/tinycc/tests/tests2/11_precedence.c b/tinycc/tests/tests2/11_precedence.c
new file mode 100644
index 0000000..845b6bf
--- /dev/null
+++ b/tinycc/tests/tests2/11_precedence.c
@@ -0,0 +1,41 @@
+//#include <stdio.h>
+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/tinycc/tests/tests2/11_precedence.expect b/tinycc/tests/tests2/11_precedence.expect
new file mode 100644
index 0000000..b692396
--- /dev/null
+++ b/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/tinycc/tests/tests2/120+_alias.c b/tinycc/tests/tests2/120+_alias.c
new file mode 100644
index 0000000..8f29d8d
--- /dev/null
+++ b/tinycc/tests/tests2/120+_alias.c
@@ -0,0 +1,15 @@
+extern int printf (const char *, ...);
+extern void target(void);
+extern void alias_for_target(void);
+extern void asm_for_target(void);
+
+void inunit2(void);
+
+void inunit2(void)
+{
+ target();
+ alias_for_target();
+ /* This symbol is not supposed to be available in this unit:
+ asm_for_target();
+ */
+}
diff --git a/tinycc/tests/tests2/120_alias.c b/tinycc/tests/tests2/120_alias.c
new file mode 100644
index 0000000..5bead0f
--- /dev/null
+++ b/tinycc/tests/tests2/120_alias.c
@@ -0,0 +1,29 @@
+/* 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")));
+#ifdef __leading_underscore
+void asm_for_target(void) __asm__("_target");
+#else
+void asm_for_target(void) __asm__("target");
+#endif
+
+/* 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();
+ inunit2();
+ return 0;
+}
diff --git a/tinycc/tests/tests2/120_alias.expect b/tinycc/tests/tests2/120_alias.expect
new file mode 100644
index 0000000..021e3f0
--- /dev/null
+++ b/tinycc/tests/tests2/120_alias.expect
@@ -0,0 +1,5 @@
+in target function
+in target function
+in target function
+in target function
+in target function
diff --git a/tinycc/tests/tests2/121_struct_return.c b/tinycc/tests/tests2/121_struct_return.c
new file mode 100644
index 0000000..147761b
--- /dev/null
+++ b/tinycc/tests/tests2/121_struct_return.c
@@ -0,0 +1,35 @@
+#include <stdio.h>
+
+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/tinycc/tests/tests2/121_struct_return.expect b/tinycc/tests/tests2/121_struct_return.expect
new file mode 100644
index 0000000..fa68b11
--- /dev/null
+++ b/tinycc/tests/tests2/121_struct_return.expect
@@ -0,0 +1 @@
+0 1 2 3 1234 2345
diff --git a/tinycc/tests/tests2/122_vla_reuse.c b/tinycc/tests/tests2/122_vla_reuse.c
new file mode 100644
index 0000000..feb47de
--- /dev/null
+++ b/tinycc/tests/tests2/122_vla_reuse.c
@@ -0,0 +1,31 @@
+#include <stdio.h>
+
+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/tinycc/tests/tests2/122_vla_reuse.expect b/tinycc/tests/tests2/122_vla_reuse.expect
new file mode 100644
index 0000000..d86bac9
--- /dev/null
+++ b/tinycc/tests/tests2/122_vla_reuse.expect
@@ -0,0 +1 @@
+OK
diff --git a/tinycc/tests/tests2/123_vla_bug.c b/tinycc/tests/tests2/123_vla_bug.c
new file mode 100644
index 0000000..6d92c27
--- /dev/null
+++ b/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/tinycc/tests/tests2/123_vla_bug.expect b/tinycc/tests/tests2/123_vla_bug.expect
new file mode 100644
index 0000000..2468f80
--- /dev/null
+++ b/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/tinycc/tests/tests2/124_atomic_counter.c b/tinycc/tests/tests2/124_atomic_counter.c
new file mode 100644
index 0000000..67a500a
--- /dev/null
+++ b/tinycc/tests/tests2/124_atomic_counter.c
@@ -0,0 +1,152 @@
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <pthread.h>
+#include <stdatomic.h>
+
+#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/tinycc/tests/tests2/124_atomic_counter.expect b/tinycc/tests/tests2/124_atomic_counter.expect
new file mode 100644
index 0000000..21667a7
--- /dev/null
+++ b/tinycc/tests/tests2/124_atomic_counter.expect
@@ -0,0 +1,3 @@
+SUCCESS
+SUCCESS
+SUCCESS
diff --git a/tinycc/tests/tests2/125_atomic_misc.c b/tinycc/tests/tests2/125_atomic_misc.c
new file mode 100644
index 0000000..2d10631
--- /dev/null
+++ b/tinycc/tests/tests2/125_atomic_misc.c
@@ -0,0 +1,227 @@
+#include <stdatomic.h>
+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/tinycc/tests/tests2/125_atomic_misc.expect b/tinycc/tests/tests2/125_atomic_misc.expect
new file mode 100644
index 0000000..61bd29f
--- /dev/null
+++ b/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/tinycc/tests/tests2/126_bound_global.c b/tinycc/tests/tests2/126_bound_global.c
new file mode 100644
index 0000000..d3a5c3b
--- /dev/null
+++ b/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/tinycc/tests/tests2/126_bound_global.expect b/tinycc/tests/tests2/126_bound_global.expect
new file mode 100644
index 0000000..fcdea90
--- /dev/null
+++ b/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/tinycc/tests/tests2/127_asm_goto.c b/tinycc/tests/tests2/127_asm_goto.c
new file mode 100644
index 0000000..de631aa
--- /dev/null
+++ b/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/tinycc/tests/tests2/127_asm_goto.expect b/tinycc/tests/tests2/127_asm_goto.expect
new file mode 100644
index 0000000..e1b7169
--- /dev/null
+++ b/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/tinycc/tests/tests2/128_run_atexit.c b/tinycc/tests/tests2/128_run_atexit.c
new file mode 100644
index 0000000..0748c86
--- /dev/null
+++ b/tinycc/tests/tests2/128_run_atexit.c
@@ -0,0 +1,54 @@
+#include <stdio.h>
+
+int atexit(void (*function)(void));
+int on_exit(void (*function)(int, void *), void *arg);
+void exit(int status);
+
+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/tinycc/tests/tests2/128_run_atexit.expect b/tinycc/tests/tests2/128_run_atexit.expect
new file mode 100644
index 0000000..3305785
--- /dev/null
+++ b/tinycc/tests/tests2/128_run_atexit.expect
@@ -0,0 +1,15 @@
+[test_128_return]
+cleanup5
+1 cleanup4
+1 cleanup3
+cleanup2
+cleanup1
+[returns 1]
+
+[test_128_exit]
+cleanup5
+2 cleanup4
+2 cleanup3
+cleanup2
+cleanup1
+[returns 2]
diff --git a/tinycc/tests/tests2/129_scopes.c b/tinycc/tests/tests2/129_scopes.c
new file mode 100644
index 0000000..b63b682
--- /dev/null
+++ b/tinycc/tests/tests2/129_scopes.c
@@ -0,0 +1,43 @@
+#include <stdio.h>
+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/tinycc/tests/tests2/129_scopes.expect b/tinycc/tests/tests2/129_scopes.expect
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tinycc/tests/tests2/129_scopes.expect
diff --git a/tinycc/tests/tests2/12_hashdefine.c b/tinycc/tests/tests2/12_hashdefine.c
new file mode 100644
index 0000000..5c521e0
--- /dev/null
+++ b/tinycc/tests/tests2/12_hashdefine.c
@@ -0,0 +1,14 @@
+#include <stdio.h>
+
+#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/tinycc/tests/tests2/12_hashdefine.expect b/tinycc/tests/tests2/12_hashdefine.expect
new file mode 100644
index 0000000..99f2ed5
--- /dev/null
+++ b/tinycc/tests/tests2/12_hashdefine.expect
@@ -0,0 +1,2 @@
+12
+12, 24, 36
diff --git a/tinycc/tests/tests2/130_large_argument.c b/tinycc/tests/tests2/130_large_argument.c
new file mode 100644
index 0000000..8415c85
--- /dev/null
+++ b/tinycc/tests/tests2/130_large_argument.c
@@ -0,0 +1,41 @@
+#include<stdio.h>
+
+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/tinycc/tests/tests2/130_large_argument.expect b/tinycc/tests/tests2/130_large_argument.expect
new file mode 100644
index 0000000..8c5d9cd
--- /dev/null
+++ b/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/tinycc/tests/tests2/13_integer_literals.c b/tinycc/tests/tests2/13_integer_literals.c
new file mode 100644
index 0000000..7cee98b
--- /dev/null
+++ b/tinycc/tests/tests2/13_integer_literals.c
@@ -0,0 +1,20 @@
+#include <stdio.h>
+
+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/tinycc/tests/tests2/13_integer_literals.expect b/tinycc/tests/tests2/13_integer_literals.expect
new file mode 100644
index 0000000..f5aca06
--- /dev/null
+++ b/tinycc/tests/tests2/13_integer_literals.expect
@@ -0,0 +1,5 @@
+24680
+342391
+2386092
+2386092
+1365
diff --git a/tinycc/tests/tests2/14_if.c b/tinycc/tests/tests2/14_if.c
new file mode 100644
index 0000000..2bd2550
--- /dev/null
+++ b/tinycc/tests/tests2/14_if.c
@@ -0,0 +1,21 @@
+#include <stdio.h>
+
+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/tinycc/tests/tests2/14_if.expect b/tinycc/tests/tests2/14_if.expect
new file mode 100644
index 0000000..c32c415
--- /dev/null
+++ b/tinycc/tests/tests2/14_if.expect
@@ -0,0 +1,2 @@
+a is true
+b is false
diff --git a/tinycc/tests/tests2/15_recursion.c b/tinycc/tests/tests2/15_recursion.c
new file mode 100644
index 0000000..f79a00d
--- /dev/null
+++ b/tinycc/tests/tests2/15_recursion.c
@@ -0,0 +1,21 @@
+#include <stdio.h>
+
+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/tinycc/tests/tests2/15_recursion.expect b/tinycc/tests/tests2/15_recursion.expect
new file mode 100644
index 0000000..db47b28
--- /dev/null
+++ b/tinycc/tests/tests2/15_recursion.expect
@@ -0,0 +1,10 @@
+1
+2
+6
+24
+120
+720
+5040
+40320
+362880
+3628800
diff --git a/tinycc/tests/tests2/16_nesting.c b/tinycc/tests/tests2/16_nesting.c
new file mode 100644
index 0000000..2b72cc0
--- /dev/null
+++ b/tinycc/tests/tests2/16_nesting.c
@@ -0,0 +1,21 @@
+#include <stdio.h>
+
+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/tinycc/tests/tests2/16_nesting.expect b/tinycc/tests/tests2/16_nesting.expect
new file mode 100644
index 0000000..5a3431e
--- /dev/null
+++ b/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/tinycc/tests/tests2/17_enum.c b/tinycc/tests/tests2/17_enum.c
new file mode 100644
index 0000000..e2bc736
--- /dev/null
+++ b/tinycc/tests/tests2/17_enum.c
@@ -0,0 +1,72 @@
+#include <stdio.h>
+
+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/tinycc/tests/tests2/17_enum.expect b/tinycc/tests/tests2/17_enum.expect
new file mode 100644
index 0000000..d453a61
--- /dev/null
+++ b/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/tinycc/tests/tests2/18_include.c b/tinycc/tests/tests2/18_include.c
new file mode 100644
index 0000000..9ff60c9
--- /dev/null
+++ b/tinycc/tests/tests2/18_include.c
@@ -0,0 +1,47 @@
+#include <stdio.h>
+
+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/tinycc/tests/tests2/18_include.expect b/tinycc/tests/tests2/18_include.expect
new file mode 100644
index 0000000..fbc6d13
--- /dev/null
+++ b/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/tinycc/tests/tests2/18_include.h b/tinycc/tests/tests2/18_include.h
new file mode 100644
index 0000000..cad2433
--- /dev/null
+++ b/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/tinycc/tests/tests2/18_include2.h b/tinycc/tests/tests2/18_include2.h
new file mode 100644
index 0000000..2a89c3d
--- /dev/null
+++ b/tinycc/tests/tests2/18_include2.h
@@ -0,0 +1,2 @@
+#pragma once
+printf ("counter %d\n", __COUNTER__);
diff --git a/tinycc/tests/tests2/19_pointer_arithmetic.c b/tinycc/tests/tests2/19_pointer_arithmetic.c
new file mode 100644
index 0000000..aff65e5
--- /dev/null
+++ b/tinycc/tests/tests2/19_pointer_arithmetic.c
@@ -0,0 +1,28 @@
+#include <stdio.h>
+
+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/tinycc/tests/tests2/19_pointer_arithmetic.expect b/tinycc/tests/tests2/19_pointer_arithmetic.expect
new file mode 100644
index 0000000..0cf781b
--- /dev/null
+++ b/tinycc/tests/tests2/19_pointer_arithmetic.expect
@@ -0,0 +1,3 @@
+42
+b is not NULL
+c is NULL
diff --git a/tinycc/tests/tests2/20_pointer_comparison.c b/tinycc/tests/tests2/20_pointer_comparison.c
new file mode 100644
index 0000000..825f778
--- /dev/null
+++ b/tinycc/tests/tests2/20_pointer_comparison.c
@@ -0,0 +1,24 @@
+#include <stdio.h>
+
+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/tinycc/tests/tests2/20_pointer_comparison.expect b/tinycc/tests/tests2/20_pointer_comparison.expect
new file mode 100644
index 0000000..5d1e5f5
--- /dev/null
+++ b/tinycc/tests/tests2/20_pointer_comparison.expect
@@ -0,0 +1,6 @@
+12
+34
+0
+1
+1
+0
diff --git a/tinycc/tests/tests2/21_char_array.c b/tinycc/tests/tests2/21_char_array.c
new file mode 100644
index 0000000..f22f527
--- /dev/null
+++ b/tinycc/tests/tests2/21_char_array.c
@@ -0,0 +1,33 @@
+#include <stdio.h>
+
+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/tinycc/tests/tests2/21_char_array.expect b/tinycc/tests/tests2/21_char_array.expect
new file mode 100644
index 0000000..dbc6068
--- /dev/null
+++ b/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/tinycc/tests/tests2/22_floating_point.c b/tinycc/tests/tests2/22_floating_point.c
new file mode 100644
index 0000000..5dc7b74
--- /dev/null
+++ b/tinycc/tests/tests2/22_floating_point.c
@@ -0,0 +1,70 @@
+#include <stdio.h>
+#include <math.h>
+
+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;
+ }
+}
+
+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 a = 12.34 + 56.78;
+ printf("%f\n", a);
+
+ // infix operators
+ printf("%f\n", 12.34 + 56.78);
+ printf("%f\n", 12.34 - 56.78);
+ printf("%f\n", 12.34 * 56.78);
+ printf("%f\n", 12.34 / 56.78);
+
+ // comparison operators
+ 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", e1, e2, e3, e4, e5, e6);
+
+ // assignment operators
+ a = 12.34;
+ a += 56.78;
+ printf("%f\n", a);
+
+ a = 12.34;
+ a -= 56.78;
+ printf("%f\n", a);
+
+ a = 12.34;
+ a *= 56.78;
+ printf("%f\n", a);
+
+ a = 12.34;
+ a /= 56.78;
+ printf("%f\n", a);
+
+ // prefix operators
+ printf("%f\n", +12.34);
+ printf("%f\n", -12.34);
+
+ // type coercion
+ a = 2;
+ printf("%f\n", a);
+ printf("%f\n", sin(2));
+
+ return 0;
+}
+
+/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/
diff --git a/tinycc/tests/tests2/22_floating_point.expect b/tinycc/tests/tests2/22_floating_point.expect
new file mode 100644
index 0000000..a989eca
--- /dev/null
+++ b/tinycc/tests/tests2/22_floating_point.expect
@@ -0,0 +1,17 @@
+69.120003
+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
+0 1 1 0 1 0
+69.120003
+-44.439999
+700.665222
+0.217330
+12.340000
+-12.340000
+2.000000
+0.909297
diff --git a/tinycc/tests/tests2/23_type_coercion.c b/tinycc/tests/tests2/23_type_coercion.c
new file mode 100644
index 0000000..1fcc335
--- /dev/null
+++ b/tinycc/tests/tests2/23_type_coercion.c
@@ -0,0 +1,54 @@
+#include <stdio.h>
+
+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/tinycc/tests/tests2/23_type_coercion.expect b/tinycc/tests/tests2/23_type_coercion.expect
new file mode 100644
index 0000000..d9076f0
--- /dev/null
+++ b/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/tinycc/tests/tests2/24_math_library.c b/tinycc/tests/tests2/24_math_library.c
new file mode 100644
index 0000000..514a25f
--- /dev/null
+++ b/tinycc/tests/tests2/24_math_library.c
@@ -0,0 +1,30 @@
+#define _ISOC99_SOURCE 1
+
+#include <stdio.h>
+#include <math.h>
+
+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/tinycc/tests/tests2/24_math_library.expect b/tinycc/tests/tests2/24_math_library.expect
new file mode 100644
index 0000000..99f7299
--- /dev/null
+++ b/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/tinycc/tests/tests2/25_quicksort.c b/tinycc/tests/tests2/25_quicksort.c
new file mode 100644
index 0000000..5cc08bd
--- /dev/null
+++ b/tinycc/tests/tests2/25_quicksort.c
@@ -0,0 +1,83 @@
+#include <stdio.h>
+
+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/tinycc/tests/tests2/25_quicksort.expect b/tinycc/tests/tests2/25_quicksort.expect
new file mode 100644
index 0000000..2d39cd3
--- /dev/null
+++ b/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/tinycc/tests/tests2/26_character_constants.c b/tinycc/tests/tests2/26_character_constants.c
new file mode 100644
index 0000000..95c4423
--- /dev/null
+++ b/tinycc/tests/tests2/26_character_constants.c
@@ -0,0 +1,17 @@
+#include <stdio.h>
+
+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/tinycc/tests/tests2/26_character_constants.expect b/tinycc/tests/tests2/26_character_constants.expect
new file mode 100644
index 0000000..8f8bfa4
--- /dev/null
+++ b/tinycc/tests/tests2/26_character_constants.expect
@@ -0,0 +1,8 @@
+1
+8
+64
+1
+14
+16
+64
+test @
diff --git a/tinycc/tests/tests2/27_sizeof.c b/tinycc/tests/tests2/27_sizeof.c
new file mode 100644
index 0000000..5ae0ede
--- /dev/null
+++ b/tinycc/tests/tests2/27_sizeof.c
@@ -0,0 +1,18 @@
+#include <stdio.h>
+
+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/tinycc/tests/tests2/27_sizeof.expect b/tinycc/tests/tests2/27_sizeof.expect
new file mode 100644
index 0000000..a47ea3a
--- /dev/null
+++ b/tinycc/tests/tests2/27_sizeof.expect
@@ -0,0 +1,4 @@
+1
+4
+8
+4
diff --git a/tinycc/tests/tests2/28_strings.c b/tinycc/tests/tests2/28_strings.c
new file mode 100644
index 0000000..2db2298
--- /dev/null
+++ b/tinycc/tests/tests2/28_strings.c
@@ -0,0 +1,45 @@
+#include <stdio.h>
+#include <string.h>
+
+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/tinycc/tests/tests2/28_strings.expect b/tinycc/tests/tests2/28_strings.expect
new file mode 100644
index 0000000..fd9217a
--- /dev/null
+++ b/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/tinycc/tests/tests2/29_array_address.c b/tinycc/tests/tests2/29_array_address.c
new file mode 100644
index 0000000..bda5ddd
--- /dev/null
+++ b/tinycc/tests/tests2/29_array_address.c
@@ -0,0 +1,13 @@
+#include <stdio.h>
+#include <string.h>
+
+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/tinycc/tests/tests2/29_array_address.expect b/tinycc/tests/tests2/29_array_address.expect
new file mode 100644
index 0000000..9bc8683
--- /dev/null
+++ b/tinycc/tests/tests2/29_array_address.expect
@@ -0,0 +1 @@
+bcdef
diff --git a/tinycc/tests/tests2/30_hanoi.c b/tinycc/tests/tests2/30_hanoi.c
new file mode 100644
index 0000000..7c0893b
--- /dev/null
+++ b/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 <stdio.h>
+#include <stdlib.h>
+
+#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<N;i++)printf(" %d ",A[i]);
+ printf("\n");
+
+ printf("B: ");
+ for(i=0;i<N;i++)printf(" %d ",B[i]);
+ printf("\n");
+
+ printf("C: ");
+ for(i=0;i<N;i++)printf(" %d ",C[i]);
+ printf("\n");
+ printf("------------------------------------------\n");
+ return;
+}
+
+/* Move the leftmost nonzero element of source to dest, leave behind 0. */
+/* Returns the value moved (not used.) */
+int Move(int *source, int *dest)
+{
+ int i = 0, j = 0;
+
+ while (i<N && (source[i])==0) i++;
+ while (j<N && (dest[j])==0) j++;
+
+ dest[j-1] = source[i];
+ source[i] = 0;
+ PrintAll(); /* Print configuration after each move. */
+ return dest[j-1];
+}
+
+
+/* Moves first n nonzero numbers from source to dest using the rules of Hanoi.
+ Calls itself recursively.
+ */
+void Hanoi(int n,int *source, int *dest, int *spare)
+{
+ int i;
+ if(n==1){
+ Move(source,dest);
+ return;
+ }
+
+ Hanoi(n-1,source,spare,dest);
+ Move(source,dest);
+ Hanoi(n-1,spare,dest,source);
+ return;
+}
+
+int main()
+{
+ int i;
+
+ /* initialize the towers */
+ for(i=0;i<N;i++)A[i]=i+1;
+ for(i=0;i<N;i++)B[i]=0;
+ for(i=0;i<N;i++)C[i]=0;
+
+ printf("Solution of Tower of Hanoi Problem with %d Disks\n\n",N);
+
+ /* Print the starting state */
+ printf("Starting state:\n");
+ PrintAll();
+ printf("\n\nSubsequent states:\n\n");
+
+ /* Do it! Use A = Source, B = Destination, C = Spare */
+ Hanoi(N,A,B,C);
+
+ return 0;
+}
+
+/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/
diff --git a/tinycc/tests/tests2/30_hanoi.expect b/tinycc/tests/tests2/30_hanoi.expect
new file mode 100644
index 0000000..7798ee0
--- /dev/null
+++ b/tinycc/tests/tests2/30_hanoi.expect
@@ -0,0 +1,71 @@
+Solution of Tower of Hanoi Problem with 4 Disks
+
+Starting state:
+A: 1 2 3 4
+B: 0 0 0 0
+C: 0 0 0 0
+------------------------------------------
+
+
+Subsequent states:
+
+A: 0 2 3 4
+B: 0 0 0 0
+C: 0 0 0 1
+------------------------------------------
+A: 0 0 3 4
+B: 0 0 0 2
+C: 0 0 0 1
+------------------------------------------
+A: 0 0 3 4
+B: 0 0 1 2
+C: 0 0 0 0
+------------------------------------------
+A: 0 0 0 4
+B: 0 0 1 2
+C: 0 0 0 3
+------------------------------------------
+A: 0 0 1 4
+B: 0 0 0 2
+C: 0 0 0 3
+------------------------------------------
+A: 0 0 1 4
+B: 0 0 0 0
+C: 0 0 2 3
+------------------------------------------
+A: 0 0 0 4
+B: 0 0 0 0
+C: 0 1 2 3
+------------------------------------------
+A: 0 0 0 0
+B: 0 0 0 4
+C: 0 1 2 3
+------------------------------------------
+A: 0 0 0 0
+B: 0 0 1 4
+C: 0 0 2 3
+------------------------------------------
+A: 0 0 0 2
+B: 0 0 1 4
+C: 0 0 0 3
+------------------------------------------
+A: 0 0 1 2
+B: 0 0 0 4
+C: 0 0 0 3
+------------------------------------------
+A: 0 0 1 2
+B: 0 0 3 4
+C: 0 0 0 0
+------------------------------------------
+A: 0 0 0 2
+B: 0 0 3 4
+C: 0 0 0 1
+------------------------------------------
+A: 0 0 0 0
+B: 0 2 3 4
+C: 0 0 0 1
+------------------------------------------
+A: 0 0 0 0
+B: 1 2 3 4
+C: 0 0 0 0
+------------------------------------------
diff --git a/tinycc/tests/tests2/31_args.c b/tinycc/tests/tests2/31_args.c
new file mode 100644
index 0000000..dcafed5
--- /dev/null
+++ b/tinycc/tests/tests2/31_args.c
@@ -0,0 +1,14 @@
+#include <stdio.h>
+
+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/tinycc/tests/tests2/31_args.expect b/tinycc/tests/tests2/31_args.expect
new file mode 100644
index 0000000..8c60bfc
--- /dev/null
+++ b/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/tinycc/tests/tests2/32_led.c b/tinycc/tests/tests2/32_led.c
new file mode 100644
index 0000000..5596cbf
--- /dev/null
+++ b/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 <stdlib.h>
+#include <stdio.h>
+
+#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/tinycc/tests/tests2/32_led.expect b/tinycc/tests/tests2/32_led.expect
new file mode 100644
index 0000000..c53b58a
--- /dev/null
+++ b/tinycc/tests/tests2/32_led.expect
@@ -0,0 +1,4 @@
+ _ _ _ _
+ | _| _| |_| |_ |_ |
+ | |_ _| | _| |_| |
+
diff --git a/tinycc/tests/tests2/33_ternary_op.c b/tinycc/tests/tests2/33_ternary_op.c
new file mode 100644
index 0000000..8305438
--- /dev/null
+++ b/tinycc/tests/tests2/33_ternary_op.c
@@ -0,0 +1,119 @@
+#include <assert.h>
+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/tinycc/tests/tests2/33_ternary_op.expect b/tinycc/tests/tests2/33_ternary_op.expect
new file mode 100644
index 0000000..c21f5fb
--- /dev/null
+++ b/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/tinycc/tests/tests2/34_array_assignment.c b/tinycc/tests/tests2/34_array_assignment.c
new file mode 100644
index 0000000..5885c97
--- /dev/null
+++ b/tinycc/tests/tests2/34_array_assignment.c
@@ -0,0 +1,23 @@
+#include <stdio.h>
+
+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/tinycc/tests/tests2/34_array_assignment.expect b/tinycc/tests/tests2/34_array_assignment.expect
new file mode 100644
index 0000000..9736bf5
--- /dev/null
+++ b/tinycc/tests/tests2/34_array_assignment.expect
@@ -0,0 +1,2 @@
+12 23 34 45
+12 23 34 45
diff --git a/tinycc/tests/tests2/35_sizeof.c b/tinycc/tests/tests2/35_sizeof.c
new file mode 100644
index 0000000..672e87e
--- /dev/null
+++ b/tinycc/tests/tests2/35_sizeof.c
@@ -0,0 +1,14 @@
+#include <stdio.h>
+
+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/tinycc/tests/tests2/35_sizeof.expect b/tinycc/tests/tests2/35_sizeof.expect
new file mode 100644
index 0000000..534fb83
--- /dev/null
+++ b/tinycc/tests/tests2/35_sizeof.expect
@@ -0,0 +1,2 @@
+1 1
+2 2
diff --git a/tinycc/tests/tests2/36_array_initialisers.c b/tinycc/tests/tests2/36_array_initialisers.c
new file mode 100644
index 0000000..ac56f5a
--- /dev/null
+++ b/tinycc/tests/tests2/36_array_initialisers.c
@@ -0,0 +1,25 @@
+#include <stdio.h>
+
+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/tinycc/tests/tests2/36_array_initialisers.expect b/tinycc/tests/tests2/36_array_initialisers.expect
new file mode 100644
index 0000000..4bb5ab7
--- /dev/null
+++ b/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/tinycc/tests/tests2/37_sprintf.c b/tinycc/tests/tests2/37_sprintf.c
new file mode 100644
index 0000000..1dd1dce
--- /dev/null
+++ b/tinycc/tests/tests2/37_sprintf.c
@@ -0,0 +1,17 @@
+#include <stdio.h>
+
+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/tinycc/tests/tests2/37_sprintf.expect b/tinycc/tests/tests2/37_sprintf.expect
new file mode 100644
index 0000000..a643da8
--- /dev/null
+++ b/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/tinycc/tests/tests2/38_multiple_array_index.c b/tinycc/tests/tests2/38_multiple_array_index.c
new file mode 100644
index 0000000..4e1868e
--- /dev/null
+++ b/tinycc/tests/tests2/38_multiple_array_index.c
@@ -0,0 +1,32 @@
+#include <stdio.h>
+
+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/tinycc/tests/tests2/38_multiple_array_index.expect b/tinycc/tests/tests2/38_multiple_array_index.expect
new file mode 100644
index 0000000..747ad75
--- /dev/null
+++ b/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/tinycc/tests/tests2/39_typedef.c b/tinycc/tests/tests2/39_typedef.c
new file mode 100644
index 0000000..da73f71
--- /dev/null
+++ b/tinycc/tests/tests2/39_typedef.c
@@ -0,0 +1,65 @@
+#include <stdio.h>
+
+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/tinycc/tests/tests2/39_typedef.expect b/tinycc/tests/tests2/39_typedef.expect
new file mode 100644
index 0000000..b9050a9
--- /dev/null
+++ b/tinycc/tests/tests2/39_typedef.expect
@@ -0,0 +1,3 @@
+1
+12,34
+12,34
diff --git a/tinycc/tests/tests2/40_stdio.c b/tinycc/tests/tests2/40_stdio.c
new file mode 100644
index 0000000..b986093
--- /dev/null
+++ b/tinycc/tests/tests2/40_stdio.c
@@ -0,0 +1,52 @@
+#include <stdio.h>
+
+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/tinycc/tests/tests2/40_stdio.expect b/tinycc/tests/tests2/40_stdio.expect
new file mode 100644
index 0000000..e08167a
--- /dev/null
+++ b/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/tinycc/tests/tests2/41_hashif.c b/tinycc/tests/tests2/41_hashif.c
new file mode 100644
index 0000000..cb37b9e
--- /dev/null
+++ b/tinycc/tests/tests2/41_hashif.c
@@ -0,0 +1,85 @@
+#include <stdio.h>
+
+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/tinycc/tests/tests2/41_hashif.expect b/tinycc/tests/tests2/41_hashif.expect
new file mode 100644
index 0000000..5fd414b
--- /dev/null
+++ b/tinycc/tests/tests2/41_hashif.expect
@@ -0,0 +1,6 @@
+#include test
+b
+g
+i
+p
+r
diff --git a/tinycc/tests/tests2/42_function_pointer.c b/tinycc/tests/tests2/42_function_pointer.c
new file mode 100644
index 0000000..697bd79
--- /dev/null
+++ b/tinycc/tests/tests2/42_function_pointer.c
@@ -0,0 +1,22 @@
+#include <stdio.h>
+
+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/tinycc/tests/tests2/42_function_pointer.expect b/tinycc/tests/tests2/42_function_pointer.expect
new file mode 100644
index 0000000..6c8b6ce
--- /dev/null
+++ b/tinycc/tests/tests2/42_function_pointer.expect
@@ -0,0 +1,2 @@
+yo 24
+42
diff --git a/tinycc/tests/tests2/43_void_param.c b/tinycc/tests/tests2/43_void_param.c
new file mode 100644
index 0000000..de17098
--- /dev/null
+++ b/tinycc/tests/tests2/43_void_param.c
@@ -0,0 +1,15 @@
+#include <stdio.h>
+
+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/tinycc/tests/tests2/43_void_param.expect b/tinycc/tests/tests2/43_void_param.expect
new file mode 100644
index 0000000..092bfb9
--- /dev/null
+++ b/tinycc/tests/tests2/43_void_param.expect
@@ -0,0 +1 @@
+yo
diff --git a/tinycc/tests/tests2/44_scoped_declarations.c b/tinycc/tests/tests2/44_scoped_declarations.c
new file mode 100644
index 0000000..f38664f
--- /dev/null
+++ b/tinycc/tests/tests2/44_scoped_declarations.c
@@ -0,0 +1,17 @@
+#include <stdio.h>
+
+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/tinycc/tests/tests2/44_scoped_declarations.expect b/tinycc/tests/tests2/44_scoped_declarations.expect
new file mode 100644
index 0000000..231ccc0
--- /dev/null
+++ b/tinycc/tests/tests2/44_scoped_declarations.expect
@@ -0,0 +1 @@
+it's all good
diff --git a/tinycc/tests/tests2/45_empty_for.c b/tinycc/tests/tests2/45_empty_for.c
new file mode 100644
index 0000000..7cef513
--- /dev/null
+++ b/tinycc/tests/tests2/45_empty_for.c
@@ -0,0 +1,18 @@
+#include <stdio.h>
+
+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/tinycc/tests/tests2/45_empty_for.expect b/tinycc/tests/tests2/45_empty_for.expect
new file mode 100644
index 0000000..f00c965
--- /dev/null
+++ b/tinycc/tests/tests2/45_empty_for.expect
@@ -0,0 +1,10 @@
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
diff --git a/tinycc/tests/tests2/46_grep.c b/tinycc/tests/tests2/46_grep.c
new file mode 100644
index 0000000..acda793
--- /dev/null
+++ b/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 <stdio.h>
+#include <stdlib.h>
+#include <ctype.h> // tolower()
+
+/*
+ * grep
+ *
+ * Runs on the Decus compiler or on vms, On vms, define as:
+ * grep :== "$disk:[account]grep" (native)
+ * grep :== "$disk:[account]grep grep" (Decus)
+ * See below for more information.
+ */
+
+char *documentation[] = {
+ "grep searches a file for a given pattern. Execute by",
+ " grep [flags] regular_expression file_list\n",
+ "Flags are single characters preceded by '-':",
+ " -c Only a count of matching lines is printed",
+ " -f Print file name for matching lines switch, see below",
+ " -n Each line is preceded by its line number",
+ " -v Only print non-matching lines\n",
+ "The file_list is a list of files (wildcards are acceptable on RSX modes).",
+ "\nThe file name is normally printed if there is a file given.",
+ "The -f flag reverses this action (print name no file, not if more).\n",
+ 0 };
+
+char *patdoc[] = {
+ "The regular_expression defines the pattern to search for. Upper- and",
+ "lower-case are always ignored. Blank lines never match. The expression",
+ "should be quoted to prevent file-name translation.",
+ "x An ordinary character (not mentioned below) matches that character.",
+ "'\\' The backslash quotes any character. \"\\$\" matches a dollar-sign.",
+ "'^' A circumflex at the beginning of an expression matches the",
+ " beginning of a line.",
+ "'$' A dollar-sign at the end of an expression matches the end of a line.",
+ "'.' A period matches any character except \"new-line\".",
+ "':a' A colon matches a class of characters described by the following",
+ "':d' character. \":a\" matches any alphabetic, \":d\" matches digits,",
+ "':n' \":n\" matches alphanumerics, \": \" matches spaces, tabs, and",
+ "': ' other control characters, such as new-line.",
+ "'*' An expression followed by an asterisk matches zero or more",
+ " occurrences of that expression: \"fo*\" matches \"f\", \"fo\"",
+ " \"foo\", etc.",
+ "'+' An expression followed by a plus sign matches one or more",
+ " occurrences of that expression: \"fo+\" matches \"fo\", etc.",
+ "'-' An expression followed by a minus sign optionally matches",
+ " the expression.",
+ "'[]' A string enclosed in square brackets matches any character in",
+ " that string, but no others. If the first character in the",
+ " string is a circumflex, the expression matches any character",
+ " except \"new-line\" and the characters in the string. For",
+ " example, \"[xyz]\" matches \"xx\" and \"zyx\", while \"[^xyz]\"",
+ " matches \"abc\" but not \"axb\". A range of characters may be",
+ " specified by two characters separated by \"-\". Note that,",
+ " [a-z] matches alphabetics, while [z-a] never matches.",
+ "The concatenation of regular expressions is a regular expression.",
+ 0};
+
+#define LMAX 512
+#define PMAX 256
+
+#define CHAR 1
+#define BOL 2
+#define EOL 3
+#define ANY 4
+#define CLASS 5
+#define NCLASS 6
+#define STAR 7
+#define PLUS 8
+#define MINUS 9
+#define ALPHA 10
+#define DIGIT 11
+#define NALPHA 12
+#define PUNCT 13
+#define RANGE 14
+#define ENDPAT 15
+
+int cflag=0, fflag=0, nflag=0, vflag=0, nfile=0, debug=0;
+
+char *pp, lbuf[LMAX], pbuf[PMAX];
+
+char *cclass();
+char *pmatch();
+void store(int);
+void error(char *);
+void badpat(char *, char *, char *);
+int match(void);
+
+
+/*** Display a file name *******************************/
+void file(char *s)
+{
+ printf("File %s:\n", s);
+}
+
+/*** Report unopenable file ****************************/
+void cant(char *s)
+{
+ fprintf(stderr, "%s: cannot open\n", s);
+}
+
+/*** Give good help ************************************/
+void help(char **hp)
+{
+ char **dp;
+
+ for (dp = hp; *dp; ++dp)
+ printf("%s\n", *dp);
+}
+
+/*** Display usage summary *****************************/
+void usage(char *s)
+{
+ fprintf(stderr, "?GREP-E-%s\n", s);
+ fprintf(stderr,
+ "Usage: grep [-cfnv] pattern [file ...]. grep ? for help\n");
+ exit(1);
+}
+
+/*** Compile the pattern into global pbuf[] ************/
+void compile(char *source)
+{
+ char *s; /* Source string pointer */
+ char *lp; /* Last pattern pointer */
+ int c; /* Current character */
+ int o; /* Temp */
+ char *spp; /* Save beginning of pattern */
+
+ s = source;
+ if (debug)
+ printf("Pattern = \"%s\"\n", s);
+ pp = pbuf;
+ while (c = *s++) {
+ /*
+ * STAR, PLUS and MINUS are special.
+ */
+ if (c == '*' || c == '+' || c == '-') {
+ if (pp == pbuf ||
+ (o=pp[-1]) == BOL ||
+ o == EOL ||
+ o == STAR ||
+ o == PLUS ||
+ o == MINUS)
+ badpat("Illegal occurrence op.", source, s);
+ store(ENDPAT);
+ store(ENDPAT);
+ spp = pp; /* Save pattern end */
+ while (--pp > lp) /* Move pattern down */
+ *pp = pp[-1]; /* one byte */
+ *pp = (c == '*') ? STAR :
+ (c == '-') ? MINUS : PLUS;
+ pp = spp; /* Restore pattern end */
+ continue;
+ }
+ /*
+ * All the rest.
+ */
+ lp = pp; /* Remember start */
+ switch(c) {
+
+ case '^':
+ store(BOL);
+ break;
+
+ case '$':
+ store(EOL);
+ break;
+
+ case '.':
+ store(ANY);
+ break;
+
+ case '[':
+ s = cclass(source, s);
+ break;
+
+ case ':':
+ if (*s) {
+ switch(tolower(c = *s++)) {
+
+ case 'a':
+ case 'A':
+ store(ALPHA);
+ break;
+
+ case 'd':
+ case 'D':
+ store(DIGIT);
+ break;
+
+ case 'n':
+ case 'N':
+ store(NALPHA);
+ break;
+
+ case ' ':
+ store(PUNCT);
+ break;
+
+ default:
+ badpat("Unknown : type", source, s);
+
+ }
+ break;
+ }
+ else badpat("No : type", source, s);
+
+ case '\\':
+ if (*s)
+ c = *s++;
+
+ default:
+ store(CHAR);
+ store(tolower(c));
+ }
+ }
+ store(ENDPAT);
+ store(0); /* Terminate string */
+ if (debug) {
+ for (lp = pbuf; lp < pp;) {
+ if ((c = (*lp++ & 0377)) < ' ')
+ printf("\\%o ", c);
+ else printf("%c ", c);
+ }
+ printf("\n");
+ }
+}
+
+/*** Compile a class (within []) ***********************/
+char *cclass(char *source, char *src)
+ /* char *source; // Pattern start -- for error msg. */
+ /* char *src; // Class start */
+{
+ char *s; /* Source pointer */
+ char *cp; /* Pattern start */
+ int c; /* Current character */
+ int o; /* Temp */
+
+ s = src;
+ o = CLASS;
+ if (*s == '^') {
+ ++s;
+ o = NCLASS;
+ }
+ store(o);
+ cp = pp;
+ store(0); /* Byte count */
+ while ((c = *s++) && c!=']') {
+ if (c == '\\') { /* Store quoted char */
+ if ((c = *s++) == '\0') /* Gotta get something */
+ badpat("Class terminates badly", source, s);
+ else store(tolower(c));
+ }
+ else if (c == '-' &&
+ (pp - cp) > 1 && *s != ']' && *s != '\0') {
+ c = pp[-1]; /* Range start */
+ pp[-1] = RANGE; /* Range signal */
+ store(c); /* Re-store start */
+ c = *s++; /* Get end char and*/
+ store(tolower(c)); /* Store it */
+ }
+ else {
+ store(tolower(c)); /* Store normal char */
+ }
+ }
+ if (c != ']')
+ badpat("Unterminated class", source, s);
+ if ((c = (pp - cp)) >= 256)
+ badpat("Class too large", source, s);
+ if (c == 0)
+ badpat("Empty class", source, s);
+ *cp = c;
+ return(s);
+}
+
+/*** Store an entry in the pattern buffer **************/
+void store(int op)
+{
+ if (pp >= &pbuf[PMAX])
+ error("Pattern too complex\n");
+ *pp++ = op;
+}
+
+/*** Report a bad pattern specification ****************/
+void badpat(char *message, char *source, char *stop)
+ /* char *message; // Error message */
+ /* char *source; // Pattern start */
+ /* char *stop; // Pattern end */
+{
+ fprintf(stderr, "-GREP-E-%s, pattern is\"%s\"\n", message, source);
+ fprintf(stderr, "-GREP-E-Stopped at byte %ld, '%c'\n",
+ stop-source, stop[-1]);
+ error("?GREP-E-Bad pattern\n");
+}
+
+/*** Scan the file for the pattern in pbuf[] ***********/
+void grep(FILE *fp, char *fn)
+ /* FILE *fp; // File to process */
+ /* char *fn; // File name (for -f option) */
+{
+ int lno, count, m;
+
+ lno = 0;
+ count = 0;
+ while (fgets(lbuf, LMAX, fp)) {
+ ++lno;
+ m = match();
+ if ((m && !vflag) || (!m && vflag)) {
+ ++count;
+ if (!cflag) {
+ if (fflag && fn) {
+ file(fn);
+ fn = 0;
+ }
+ if (nflag)
+ printf("%d\t", lno);
+ printf("%s\n", lbuf);
+ }
+ }
+ }
+ if (cflag) {
+ if (fflag && fn)
+ file(fn);
+ printf("%d\n", count);
+ }
+}
+
+/*** Match line (lbuf) with pattern (pbuf) return 1 if match ***/
+int match()
+{
+ char *l; /* Line pointer */
+
+ for (l = lbuf; *l; ++l) {
+ if (pmatch(l, pbuf))
+ return(1);
+ }
+ return(0);
+}
+
+/*** Match partial line with pattern *******************/
+char *pmatch(char *line, char *pattern)
+ /* char *line; // (partial) line to match */
+ /* char *pattern; // (partial) pattern to match */
+{
+ char *l; /* Current line pointer */
+ char *p; /* Current pattern pointer */
+ char c; /* Current character */
+ char *e; /* End for STAR and PLUS match */
+ int op; /* Pattern operation */
+ int n; /* Class counter */
+ char *are; /* Start of STAR match */
+
+ l = line;
+ if (debug > 1)
+ printf("pmatch(\"%s\")\n", line);
+ p = pattern;
+ while ((op = *p++) != ENDPAT) {
+ if (debug > 1)
+ printf("byte[%ld] = 0%o, '%c', op = 0%o\n",
+ l-line, *l, *l, op);
+ switch(op) {
+
+ case CHAR:
+ if (tolower(*l++) != *p++)
+ return(0);
+ break;
+
+ case BOL:
+ if (l != lbuf)
+ return(0);
+ break;
+
+ case EOL:
+ if (*l != '\0')
+ return(0);
+ break;
+
+ case ANY:
+ if (*l++ == '\0')
+ return(0);
+ break;
+
+ case DIGIT:
+ if ((c = *l++) < '0' || (c > '9'))
+ return(0);
+ break;
+
+ case ALPHA:
+ c = tolower(*l++);
+ if (c < 'a' || c > 'z')
+ return(0);
+ break;
+
+ case NALPHA:
+ c = tolower(*l++);
+ if (c >= 'a' && c <= 'z')
+ break;
+ else if (c < '0' || c > '9')
+ return(0);
+ break;
+
+ case PUNCT:
+ c = *l++;
+ if (c == 0 || c > ' ')
+ return(0);
+ break;
+
+ case CLASS:
+ case NCLASS:
+ c = tolower(*l++);
+ n = *p++ & 0377;
+ do {
+ if (*p == RANGE) {
+ p += 3;
+ n -= 2;
+ if (c >= p[-2] && c <= p[-1])
+ break;
+ }
+ else if (c == *p++)
+ break;
+ } while (--n > 1);
+ if ((op == CLASS) == (n <= 1))
+ return(0);
+ if (op == CLASS)
+ p += n - 2;
+ break;
+
+ case MINUS:
+ e = pmatch(l, p); /* Look for a match */
+ while (*p++ != ENDPAT); /* Skip over pattern */
+ if (e) /* Got a match? */
+ l = e; /* Yes, update string */
+ break; /* Always succeeds */
+
+ case PLUS: /* One or more ... */
+ if ((l = pmatch(l, p)) == 0)
+ return(0); /* Gotta have a match */
+ case STAR: /* Zero or more ... */
+ are = l; /* Remember line start */
+ while (*l && (e = pmatch(l, p)))
+ l = e; /* Get longest match */
+ while (*p++ != ENDPAT); /* Skip over pattern */
+ while (l > are) { /* Try to match rest */
+ if (e = pmatch(l, p))
+ return(e);
+ --l; /* Nope, try earlier */
+ }
+ 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/tinycc/tests/tests2/46_grep.expect b/tinycc/tests/tests2/46_grep.expect
new file mode 100644
index 0000000..e8a6791
--- /dev/null
+++ b/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/tinycc/tests/tests2/47_switch_return.c b/tinycc/tests/tests2/47_switch_return.c
new file mode 100644
index 0000000..1ec7924
--- /dev/null
+++ b/tinycc/tests/tests2/47_switch_return.c
@@ -0,0 +1,24 @@
+#include <stdio.h>
+
+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/tinycc/tests/tests2/47_switch_return.expect b/tinycc/tests/tests2/47_switch_return.expect
new file mode 100644
index 0000000..b6deb7e
--- /dev/null
+++ b/tinycc/tests/tests2/47_switch_return.expect
@@ -0,0 +1,4 @@
+1
+2
+out
+3
diff --git a/tinycc/tests/tests2/48_nested_break.c b/tinycc/tests/tests2/48_nested_break.c
new file mode 100644
index 0000000..5bc5ba4
--- /dev/null
+++ b/tinycc/tests/tests2/48_nested_break.c
@@ -0,0 +1,26 @@
+#include <stdio.h>
+
+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/tinycc/tests/tests2/48_nested_break.expect b/tinycc/tests/tests2/48_nested_break.expect
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/tinycc/tests/tests2/48_nested_break.expect
@@ -0,0 +1 @@
+0
diff --git a/tinycc/tests/tests2/49_bracket_evaluation.c b/tinycc/tests/tests2/49_bracket_evaluation.c
new file mode 100644
index 0000000..0cbe57d
--- /dev/null
+++ b/tinycc/tests/tests2/49_bracket_evaluation.c
@@ -0,0 +1,23 @@
+#include <stdio.h>
+
+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/tinycc/tests/tests2/49_bracket_evaluation.expect b/tinycc/tests/tests2/49_bracket_evaluation.expect
new file mode 100644
index 0000000..1da66db
--- /dev/null
+++ b/tinycc/tests/tests2/49_bracket_evaluation.expect
@@ -0,0 +1 @@
+12.340000, 56.780000
diff --git a/tinycc/tests/tests2/50_logical_second_arg.c b/tinycc/tests/tests2/50_logical_second_arg.c
new file mode 100644
index 0000000..ddec08c
--- /dev/null
+++ b/tinycc/tests/tests2/50_logical_second_arg.c
@@ -0,0 +1,29 @@
+#include <stdio.h>
+
+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/tinycc/tests/tests2/50_logical_second_arg.expect b/tinycc/tests/tests2/50_logical_second_arg.expect
new file mode 100644
index 0000000..d6174ae
--- /dev/null
+++ b/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/tinycc/tests/tests2/51_static.c b/tinycc/tests/tests2/51_static.c
new file mode 100644
index 0000000..d6c0917
--- /dev/null
+++ b/tinycc/tests/tests2/51_static.c
@@ -0,0 +1,30 @@
+#include <stdio.h>
+
+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/tinycc/tests/tests2/51_static.expect b/tinycc/tests/tests2/51_static.expect
new file mode 100644
index 0000000..18224fa
--- /dev/null
+++ b/tinycc/tests/tests2/51_static.expect
@@ -0,0 +1,8 @@
+1234
+4567
+4568
+4569
+4570
+1234
+8901
+2345
diff --git a/tinycc/tests/tests2/52_unnamed_enum.c b/tinycc/tests/tests2/52_unnamed_enum.c
new file mode 100644
index 0000000..d0395b2
--- /dev/null
+++ b/tinycc/tests/tests2/52_unnamed_enum.c
@@ -0,0 +1,27 @@
+#include <stdio.h>
+
+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/tinycc/tests/tests2/52_unnamed_enum.expect b/tinycc/tests/tests2/52_unnamed_enum.expect
new file mode 100644
index 0000000..84f2ac8
--- /dev/null
+++ b/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/tinycc/tests/tests2/54_goto.c b/tinycc/tests/tests2/54_goto.c
new file mode 100644
index 0000000..2e151bb
--- /dev/null
+++ b/tinycc/tests/tests2/54_goto.c
@@ -0,0 +1,56 @@
+#include <stdio.h>
+
+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/tinycc/tests/tests2/54_goto.expect b/tinycc/tests/tests2/54_goto.expect
new file mode 100644
index 0000000..8e553fa
--- /dev/null
+++ b/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/tinycc/tests/tests2/55_lshift_type.c b/tinycc/tests/tests2/55_lshift_type.c
new file mode 100644
index 0000000..aa3e51a
--- /dev/null
+++ b/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 <vincent@vinc17.net>.
+
+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 <stdio.h>
+
+#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/tinycc/tests/tests2/55_lshift_type.expect b/tinycc/tests/tests2/55_lshift_type.expect
new file mode 100644
index 0000000..8523767
--- /dev/null
+++ b/tinycc/tests/tests2/55_lshift_type.expect
@@ -0,0 +1 @@
+0 test(s) failed
diff --git a/tinycc/tests/tests2/60_errors_and_warnings.c b/tinycc/tests/tests2/60_errors_and_warnings.c
new file mode 100644
index 0000000..960c64f
--- /dev/null
+++ b/tinycc/tests/tests2/60_errors_and_warnings.c
@@ -0,0 +1,466 @@
+#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
+
+#endif
diff --git a/tinycc/tests/tests2/60_errors_and_warnings.expect b/tinycc/tests/tests2/60_errors_and_warnings.expect
new file mode 100644
index 0000000..9a95e93
--- /dev/null
+++ b/tinycc/tests/tests2/60_errors_and_warnings.expect
@@ -0,0 +1,230 @@
+[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: unknown type size
+
+[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: identifier expected
+
+[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
diff --git a/tinycc/tests/tests2/61_integers.c b/tinycc/tests/tests2/61_integers.c
new file mode 100644
index 0000000..de29b3c
--- /dev/null
+++ b/tinycc/tests/tests2/61_integers.c
@@ -0,0 +1,70 @@
+#include <stdio.h>
+
+/* 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/tinycc/tests/tests2/61_integers.expect b/tinycc/tests/tests2/61_integers.expect
new file mode 100644
index 0000000..22c8d1b
--- /dev/null
+++ b/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/tinycc/tests/tests2/64_macro_nesting.c b/tinycc/tests/tests2/64_macro_nesting.c
new file mode 100644
index 0000000..676e5d3
--- /dev/null
+++ b/tinycc/tests/tests2/64_macro_nesting.c
@@ -0,0 +1,12 @@
+#include <stdio.h> // 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/tinycc/tests/tests2/64_macro_nesting.expect b/tinycc/tests/tests2/64_macro_nesting.expect
new file mode 100644
index 0000000..d81cc07
--- /dev/null
+++ b/tinycc/tests/tests2/64_macro_nesting.expect
@@ -0,0 +1 @@
+42
diff --git a/tinycc/tests/tests2/67_macro_concat.c b/tinycc/tests/tests2/67_macro_concat.c
new file mode 100644
index 0000000..c580d3a
--- /dev/null
+++ b/tinycc/tests/tests2/67_macro_concat.c
@@ -0,0 +1,14 @@
+#include <stdio.h>
+
+#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/tinycc/tests/tests2/67_macro_concat.expect b/tinycc/tests/tests2/67_macro_concat.expect
new file mode 100644
index 0000000..8386c2d
--- /dev/null
+++ b/tinycc/tests/tests2/67_macro_concat.expect
@@ -0,0 +1,2 @@
+jim: 21, bob: 42
+jim: 63
diff --git a/tinycc/tests/tests2/70_floating_point_literals.c b/tinycc/tests/tests2/70_floating_point_literals.c
new file mode 100644
index 0000000..012fb4f
--- /dev/null
+++ b/tinycc/tests/tests2/70_floating_point_literals.c
@@ -0,0 +1,77 @@
+#include <stdio.h>
+
+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/tinycc/tests/tests2/70_floating_point_literals.expect b/tinycc/tests/tests2/70_floating_point_literals.expect
new file mode 100644
index 0000000..7eb1efb
--- /dev/null
+++ b/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/tinycc/tests/tests2/71_macro_empty_arg.c b/tinycc/tests/tests2/71_macro_empty_arg.c
new file mode 100644
index 0000000..f0d3511
--- /dev/null
+++ b/tinycc/tests/tests2/71_macro_empty_arg.c
@@ -0,0 +1,9 @@
+#include <stdio.h>
+
+#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/tinycc/tests/tests2/71_macro_empty_arg.expect b/tinycc/tests/tests2/71_macro_empty_arg.expect
new file mode 100644
index 0000000..98d9bcb
--- /dev/null
+++ b/tinycc/tests/tests2/71_macro_empty_arg.expect
@@ -0,0 +1 @@
+17
diff --git a/tinycc/tests/tests2/72_long_long_constant.c b/tinycc/tests/tests2/72_long_long_constant.c
new file mode 100644
index 0000000..6608213
--- /dev/null
+++ b/tinycc/tests/tests2/72_long_long_constant.c
@@ -0,0 +1,19 @@
+#include <stdio.h>
+
+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/tinycc/tests/tests2/72_long_long_constant.expect b/tinycc/tests/tests2/72_long_long_constant.expect
new file mode 100644
index 0000000..dda9e66
--- /dev/null
+++ b/tinycc/tests/tests2/72_long_long_constant.expect
@@ -0,0 +1 @@
+long long constant test ok.
diff --git a/tinycc/tests/tests2/73_arm64.c b/tinycc/tests/tests2/73_arm64.c
new file mode 100644
index 0000000..855c476
--- /dev/null
+++ b/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 <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+
+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/tinycc/tests/tests2/73_arm64.expect b/tinycc/tests/tests2/73_arm64.expect
new file mode 100644
index 0000000..7bdebd3
--- /dev/null
+++ b/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/tinycc/tests/tests2/75_array_in_struct_init.c b/tinycc/tests/tests2/75_array_in_struct_init.c
new file mode 100644
index 0000000..234e3c4
--- /dev/null
+++ b/tinycc/tests/tests2/75_array_in_struct_init.c
@@ -0,0 +1,33 @@
+#include <stdio.h>
+
+/* 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/tinycc/tests/tests2/75_array_in_struct_init.expect b/tinycc/tests/tests2/75_array_in_struct_init.expect
new file mode 100644
index 0000000..2b75aa5
--- /dev/null
+++ b/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/tinycc/tests/tests2/76_dollars_in_identifiers.c b/tinycc/tests/tests2/76_dollars_in_identifiers.c
new file mode 100644
index 0000000..c5fcf99
--- /dev/null
+++ b/tinycc/tests/tests2/76_dollars_in_identifiers.c
@@ -0,0 +1,41 @@
+#include <stdio.h>
+
+#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/tinycc/tests/tests2/76_dollars_in_identifiers.expect b/tinycc/tests/tests2/76_dollars_in_identifiers.expect
new file mode 100644
index 0000000..4a20a52
--- /dev/null
+++ b/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/tinycc/tests/tests2/77_push_pop_macro.c b/tinycc/tests/tests2/77_push_pop_macro.c
new file mode 100644
index 0000000..d38e0bf
--- /dev/null
+++ b/tinycc/tests/tests2/77_push_pop_macro.c
@@ -0,0 +1,30 @@
+#include <stdio.h>
+
+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/tinycc/tests/tests2/77_push_pop_macro.expect b/tinycc/tests/tests2/77_push_pop_macro.expect
new file mode 100644
index 0000000..d8a5530
--- /dev/null
+++ b/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/tinycc/tests/tests2/78_vla_label.c b/tinycc/tests/tests2/78_vla_label.c
new file mode 100644
index 0000000..4096495
--- /dev/null
+++ b/tinycc/tests/tests2/78_vla_label.c
@@ -0,0 +1,45 @@
+#include <stdio.h>
+
+/* 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/tinycc/tests/tests2/78_vla_label.expect b/tinycc/tests/tests2/78_vla_label.expect
new file mode 100644
index 0000000..3f4063b
--- /dev/null
+++ b/tinycc/tests/tests2/78_vla_label.expect
@@ -0,0 +1,6 @@
+boom!
+boom!
+11
+12
+0
+1
diff --git a/tinycc/tests/tests2/79_vla_continue.c b/tinycc/tests/tests2/79_vla_continue.c
new file mode 100644
index 0000000..dd63790
--- /dev/null
+++ b/tinycc/tests/tests2/79_vla_continue.c
@@ -0,0 +1,119 @@
+#include <stdio.h>
+
+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<f(); i++) {
+ b[i] = count;
+ }
+ }
+
+ if (c[0] == 42) {
+ printf("OK\n");
+ } else {
+ printf("NOT OK\n");
+ }
+}
+
+int main(void)
+{
+ test1();
+ test2();
+ test3();
+ test4();
+ test5();
+
+ return 0;
+}
diff --git a/tinycc/tests/tests2/79_vla_continue.expect b/tinycc/tests/tests2/79_vla_continue.expect
new file mode 100644
index 0000000..21da4d2
--- /dev/null
+++ b/tinycc/tests/tests2/79_vla_continue.expect
@@ -0,0 +1,5 @@
+OK
+OK
+OK
+OK
+OK
diff --git a/tinycc/tests/tests2/80_flexarray.c b/tinycc/tests/tests2/80_flexarray.c
new file mode 100644
index 0000000..864d429
--- /dev/null
+++ b/tinycc/tests/tests2/80_flexarray.c
@@ -0,0 +1,26 @@
+#include <stdio.h>
+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/tinycc/tests/tests2/80_flexarray.expect b/tinycc/tests/tests2/80_flexarray.expect
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tinycc/tests/tests2/80_flexarray.expect
diff --git a/tinycc/tests/tests2/81_types.c b/tinycc/tests/tests2/81_types.c
new file mode 100644
index 0000000..0bc3bae
--- /dev/null
+++ b/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/tinycc/tests/tests2/81_types.expect b/tinycc/tests/tests2/81_types.expect
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tinycc/tests/tests2/81_types.expect
diff --git a/tinycc/tests/tests2/82_attribs_position.c b/tinycc/tests/tests2/82_attribs_position.c
new file mode 100644
index 0000000..d8c9fe5
--- /dev/null
+++ b/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/tinycc/tests/tests2/82_attribs_position.expect b/tinycc/tests/tests2/82_attribs_position.expect
new file mode 100644
index 0000000..daaac9e
--- /dev/null
+++ b/tinycc/tests/tests2/82_attribs_position.expect
@@ -0,0 +1,2 @@
+42
+42
diff --git a/tinycc/tests/tests2/83_utf8_in_identifiers.c b/tinycc/tests/tests2/83_utf8_in_identifiers.c
new file mode 100644
index 0000000..1f86095
--- /dev/null
+++ b/tinycc/tests/tests2/83_utf8_in_identifiers.c
@@ -0,0 +1,9 @@
+#include <stdio.h>
+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/tinycc/tests/tests2/83_utf8_in_identifiers.expect b/tinycc/tests/tests2/83_utf8_in_identifiers.expect
new file mode 100644
index 0000000..1553f5f
--- /dev/null
+++ b/tinycc/tests/tests2/83_utf8_in_identifiers.expect
@@ -0,0 +1,2 @@
+привет=0.1
+Lefèvre=2
diff --git a/tinycc/tests/tests2/84_hex-float.c b/tinycc/tests/tests2/84_hex-float.c
new file mode 100644
index 0000000..0ef09bf
--- /dev/null
+++ b/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/tinycc/tests/tests2/84_hex-float.expect b/tinycc/tests/tests2/84_hex-float.expect
new file mode 100644
index 0000000..2175385
--- /dev/null
+++ b/tinycc/tests/tests2/84_hex-float.expect
@@ -0,0 +1 @@
+n+1 = 15
diff --git a/tinycc/tests/tests2/85_asm-outside-function.c b/tinycc/tests/tests2/85_asm-outside-function.c
new file mode 100644
index 0000000..3d7434d
--- /dev/null
+++ b/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/tinycc/tests/tests2/85_asm-outside-function.expect b/tinycc/tests/tests2/85_asm-outside-function.expect
new file mode 100644
index 0000000..dcf02b2
--- /dev/null
+++ b/tinycc/tests/tests2/85_asm-outside-function.expect
@@ -0,0 +1 @@
+okay
diff --git a/tinycc/tests/tests2/86_memory-model.c b/tinycc/tests/tests2/86_memory-model.c
new file mode 100644
index 0000000..744c3e2
--- /dev/null
+++ b/tinycc/tests/tests2/86_memory-model.c
@@ -0,0 +1,38 @@
+#include <stdio.h>
+
+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/tinycc/tests/tests2/86_memory-model.expect b/tinycc/tests/tests2/86_memory-model.expect
new file mode 100644
index 0000000..7326d96
--- /dev/null
+++ b/tinycc/tests/tests2/86_memory-model.expect
@@ -0,0 +1 @@
+Ok
diff --git a/tinycc/tests/tests2/87_dead_code.c b/tinycc/tests/tests2/87_dead_code.c
new file mode 100644
index 0000000..369f4ba
--- /dev/null
+++ b/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/tinycc/tests/tests2/87_dead_code.expect b/tinycc/tests/tests2/87_dead_code.expect
new file mode 100644
index 0000000..781ff51
--- /dev/null
+++ b/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/tinycc/tests/tests2/88_codeopt.c b/tinycc/tests/tests2/88_codeopt.c
new file mode 100644
index 0000000..3faa5fa
--- /dev/null
+++ b/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/tinycc/tests/tests2/88_codeopt.expect b/tinycc/tests/tests2/88_codeopt.expect
new file mode 100644
index 0000000..76b582b
--- /dev/null
+++ b/tinycc/tests/tests2/88_codeopt.expect
@@ -0,0 +1,3 @@
+okay
+okay
+okay: 42 1
diff --git a/tinycc/tests/tests2/89_nocode_wanted.c b/tinycc/tests/tests2/89_nocode_wanted.c
new file mode 100644
index 0000000..73e0a4b
--- /dev/null
+++ b/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/tinycc/tests/tests2/89_nocode_wanted.expect b/tinycc/tests/tests2/89_nocode_wanted.expect
new file mode 100644
index 0000000..c44d4ea
--- /dev/null
+++ b/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/tinycc/tests/tests2/90_struct-init.c b/tinycc/tests/tests2/90_struct-init.c
new file mode 100644
index 0000000..4a71a93
--- /dev/null
+++ b/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 <stdio.h>
+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/tinycc/tests/tests2/90_struct-init.expect b/tinycc/tests/tests2/90_struct-init.expect
new file mode 100644
index 0000000..5014f82
--- /dev/null
+++ b/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/tinycc/tests/tests2/91_ptr_longlong_arith32.c b/tinycc/tests/tests2/91_ptr_longlong_arith32.c
new file mode 100644
index 0000000..bf07915
--- /dev/null
+++ b/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/tinycc/tests/tests2/91_ptr_longlong_arith32.expect b/tinycc/tests/tests2/91_ptr_longlong_arith32.expect
new file mode 100644
index 0000000..f91e4b4
--- /dev/null
+++ b/tinycc/tests/tests2/91_ptr_longlong_arith32.expect
@@ -0,0 +1 @@
+data = "0123-5678"
diff --git a/tinycc/tests/tests2/92_enum_bitfield.c b/tinycc/tests/tests2/92_enum_bitfield.c
new file mode 100644
index 0000000..fb8f7a3
--- /dev/null
+++ b/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/tinycc/tests/tests2/92_enum_bitfield.expect b/tinycc/tests/tests2/92_enum_bitfield.expect
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tinycc/tests/tests2/92_enum_bitfield.expect
diff --git a/tinycc/tests/tests2/93_integer_promotion.c b/tinycc/tests/tests2/93_integer_promotion.c
new file mode 100644
index 0000000..a1176fc
--- /dev/null
+++ b/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/tinycc/tests/tests2/93_integer_promotion.expect b/tinycc/tests/tests2/93_integer_promotion.expect
new file mode 100644
index 0000000..34b9c14
--- /dev/null
+++ b/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/tinycc/tests/tests2/94_generic.c b/tinycc/tests/tests2/94_generic.c
new file mode 100644
index 0000000..1cb0164
--- /dev/null
+++ b/tinycc/tests/tests2/94_generic.c
@@ -0,0 +1,122 @@
+#include <stdio.h>
+
+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;
+
+#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;
+
+ 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); }));
+ }
+
+ return 0;
+}
diff --git a/tinycc/tests/tests2/94_generic.expect b/tinycc/tests/tests2/94_generic.expect
new file mode 100644
index 0000000..80d4ed9
--- /dev/null
+++ b/tinycc/tests/tests2/94_generic.expect
@@ -0,0 +1,15 @@
+20
+10
+20
+123
+2
+0
+5
+1
+2
+3
+4
+long
+1
+3
+5
diff --git a/tinycc/tests/tests2/95_bitfields.c b/tinycc/tests/tests2/95_bitfields.c
new file mode 100644
index 0000000..4ac38da
--- /dev/null
+++ b/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 <stdio.h>
+#include <string.h>
+/* 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/tinycc/tests/tests2/95_bitfields.expect b/tinycc/tests/tests2/95_bitfields.expect
new file mode 100644
index 0000000..215055d
--- /dev/null
+++ b/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/tinycc/tests/tests2/95_bitfields_ms.c b/tinycc/tests/tests2/95_bitfields_ms.c
new file mode 100644
index 0000000..b196fbd
--- /dev/null
+++ b/tinycc/tests/tests2/95_bitfields_ms.c
@@ -0,0 +1,2 @@
+#define MS_BITFIELDS 1
+#include "95_bitfields.c"
diff --git a/tinycc/tests/tests2/95_bitfields_ms.expect b/tinycc/tests/tests2/95_bitfields_ms.expect
new file mode 100644
index 0000000..97c46be
--- /dev/null
+++ b/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/tinycc/tests/tests2/96_nodata_wanted.c b/tinycc/tests/tests2/96_nodata_wanted.c
new file mode 100644
index 0000000..95938b5
--- /dev/null
+++ b/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 <stdio.h>
+/* 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 <stdio.h>
+int main(int argc, char **argv)
+{
+ goto there;
+ if (0) {
+ static int a = 1;
+ printf("hello\n"); /* the "hello\n" string is still suppressed */
+there:
+ printf("a = %d\n", a);
+ }
+ return 0;
+}
+
+#endif
diff --git a/tinycc/tests/tests2/96_nodata_wanted.expect b/tinycc/tests/tests2/96_nodata_wanted.expect
new file mode 100644
index 0000000..92dc9c4
--- /dev/null
+++ b/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/tinycc/tests/tests2/97_utf8_string_literal.c b/tinycc/tests/tests2/97_utf8_string_literal.c
new file mode 100644
index 0000000..5bfb6c8
--- /dev/null
+++ b/tinycc/tests/tests2/97_utf8_string_literal.c
@@ -0,0 +1,20 @@
+// this file contains BMP chars encoded in UTF-8
+#include <stdio.h>
+#include <wchar.h>
+#include <stdlib.h>
+#include <string.h>
+
+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/tinycc/tests/tests2/97_utf8_string_literal.expect b/tinycc/tests/tests2/97_utf8_string_literal.expect
new file mode 100644
index 0000000..9a1593c
--- /dev/null
+++ b/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/tinycc/tests/tests2/98_al_ax_extend.c b/tinycc/tests/tests2/98_al_ax_extend.c
new file mode 100644
index 0000000..1cd6585
--- /dev/null
+++ b/tinycc/tests/tests2/98_al_ax_extend.c
@@ -0,0 +1,41 @@
+#include <stdio.h>
+#include <stdlib.h>
+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/tinycc/tests/tests2/98_al_ax_extend.expect b/tinycc/tests/tests2/98_al_ax_extend.expect
new file mode 100644
index 0000000..c5752e8
--- /dev/null
+++ b/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/tinycc/tests/tests2/99_fastcall.c b/tinycc/tests/tests2/99_fastcall.c
new file mode 100644
index 0000000..db97acb
--- /dev/null
+++ b/tinycc/tests/tests2/99_fastcall.c
@@ -0,0 +1,276 @@
+#include <stdio.h>
+#include <assert.h>
+
+#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/tinycc/tests/tests2/99_fastcall.expect b/tinycc/tests/tests2/99_fastcall.expect
new file mode 100644
index 0000000..3835d63
--- /dev/null
+++ b/tinycc/tests/tests2/99_fastcall.expect
@@ -0,0 +1 @@
+TEST OK
diff --git a/tinycc/tests/tests2/LICENSE b/tinycc/tests/tests2/LICENSE
new file mode 100644
index 0000000..b08a652
--- /dev/null
+++ b/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/tinycc/tests/tests2/Makefile b/tinycc/tests/tests2/Makefile
new file mode 100644
index 0000000..92da80e
--- /dev/null
+++ b/tinycc/tests/tests2/Makefile
@@ -0,0 +1,175 @@
+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
+
+# 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
+
+# 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/tinycc/tests/vla_test.c b/tinycc/tests/vla_test.c
new file mode 100644
index 0000000..3616c46
--- /dev/null
+++ b/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 <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#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;
+}