2002-01-05 20:03:02 +03:00
|
|
|
|
/*
|
|
|
|
|
* TCC auto test program
|
|
|
|
|
*/
|
2013-04-17 23:32:07 +04:00
|
|
|
|
#include "config.h"
|
2003-04-13 23:48:52 +04:00
|
|
|
|
|
|
|
|
|
#if GCC_MAJOR >= 3
|
2002-01-05 20:03:02 +03:00
|
|
|
|
|
|
|
|
|
/* Unfortunately, gcc version < 3 does not handle that! */
|
2003-04-13 23:48:52 +04:00
|
|
|
|
#define ALL_ISOC99
|
2002-01-05 20:03:02 +03:00
|
|
|
|
|
|
|
|
|
/* only gcc 3 handles _Bool correctly */
|
2003-04-13 23:48:52 +04:00
|
|
|
|
#define BOOL_ISOC99
|
2002-01-05 20:03:02 +03:00
|
|
|
|
|
2002-12-08 17:37:00 +03:00
|
|
|
|
/* gcc 2.95.3 does not handle correctly CR in strings or after strays */
|
2003-04-13 23:48:52 +04:00
|
|
|
|
#define CORRECT_CR_HANDLING
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
2013-04-26 04:27:04 +04:00
|
|
|
|
#if defined(_WIN32)
|
|
|
|
|
#define LONG_LONG_FORMAT "%lld"
|
|
|
|
|
#define ULONG_LONG_FORMAT "%llu"
|
|
|
|
|
#else
|
|
|
|
|
#define LONG_LONG_FORMAT "%Ld"
|
|
|
|
|
#define ULONG_LONG_FORMAT "%Lu"
|
|
|
|
|
#endif
|
|
|
|
|
|
2013-04-17 23:32:07 +04:00
|
|
|
|
// 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
|
|
|
|
|
|
2004-10-29 01:13:47 +04:00
|
|
|
|
/* deprecated and no longer supported in gcc 3.3 */
|
|
|
|
|
//#define ACCEPT_CR_IN_STRINGS
|
|
|
|
|
|
2003-04-13 23:48:52 +04:00
|
|
|
|
/* __VA_ARGS__ and __func__ support */
|
|
|
|
|
#define C99_MACROS
|
2002-12-08 17:37:00 +03:00
|
|
|
|
|
2002-08-18 17:18:20 +04:00
|
|
|
|
/* test various include syntaxes */
|
|
|
|
|
|
|
|
|
|
#define TCCLIB_INC <tcclib.h>
|
|
|
|
|
#define TCCLIB_INC1 <tcclib
|
|
|
|
|
#define TCCLIB_INC2 h>
|
2016-08-08 23:26:11 +03:00
|
|
|
|
#define TCCLIB_INC3 "tcclib.h"
|
2002-08-18 17:18:20 +04:00
|
|
|
|
|
|
|
|
|
#include TCCLIB_INC
|
|
|
|
|
|
|
|
|
|
#include TCCLIB_INC1.TCCLIB_INC2
|
|
|
|
|
|
|
|
|
|
#include TCCLIB_INC1.h>
|
|
|
|
|
|
2016-08-08 23:26:11 +03:00
|
|
|
|
#include TCCLIB_INC3
|
2002-08-18 17:18:20 +04:00
|
|
|
|
|
|
|
|
|
#include <tcclib.h>
|
|
|
|
|
|
|
|
|
|
#include "tcclib.h"
|
|
|
|
|
|
2016-07-13 16:37:36 +03:00
|
|
|
|
#include "tcctest.h"
|
|
|
|
|
|
2016-08-08 23:26:11 +03:00
|
|
|
|
/* 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/
|
|
|
|
|
#define incname < incdir funnyname >
|
|
|
|
|
#define __stringify(x) #x
|
|
|
|
|
#define stringify(x) __stringify(x)
|
|
|
|
|
#include INC(42test)
|
|
|
|
|
#include incname
|
|
|
|
|
#include stringify(funnyname)
|
|
|
|
|
|
Add ARM aeabi functions needed to run tcctest
Add implementation for float / integer conversion functions:
__aeabi_d2lz, __aeabi_d2ulz, __aeabi_f2lz, __aeabi_f2ulz, __aeabi_l2d,
__aeabi_l2f, __aeabi_ul2d, __aeabi_ul2f
Add implementation for long long helper functions:
__aeabi_ldivmod, __aeabi_uldivmod, __aeabi_llsl, __aeabi_llsr, __aeabi_lasr
Add implementation for integer division functions:
__aeabi_uidiv, __aeabi_uidivmod, __aeabi_idiv, __aeabi_idivmod,
2013-04-07 19:02:57 +04:00
|
|
|
|
void intdiv_test();
|
2002-01-05 20:03:02 +03:00
|
|
|
|
void string_test();
|
|
|
|
|
void expr_test();
|
|
|
|
|
void macro_test();
|
2011-02-02 00:23:40 +03:00
|
|
|
|
void recursive_macro_test();
|
2002-01-05 20:03:02 +03:00
|
|
|
|
void scope_test();
|
2019-03-18 07:53:03 +03:00
|
|
|
|
void scope_test2();
|
2002-01-05 20:03:02 +03:00
|
|
|
|
void forward_test();
|
|
|
|
|
void funcptr_test();
|
|
|
|
|
void loop_test();
|
|
|
|
|
void switch_test();
|
|
|
|
|
void goto_test();
|
|
|
|
|
void enum_test();
|
|
|
|
|
void typedef_test();
|
|
|
|
|
void struct_test();
|
|
|
|
|
void array_test();
|
|
|
|
|
void expr_ptr_test();
|
|
|
|
|
void bool_test();
|
2016-09-19 19:38:12 +03:00
|
|
|
|
void optimize_out();
|
2002-01-05 20:03:02 +03:00
|
|
|
|
void expr2_test();
|
|
|
|
|
void constant_expr_test();
|
|
|
|
|
void expr_cmp_test();
|
|
|
|
|
void char_short_test();
|
|
|
|
|
void init_test(void);
|
|
|
|
|
void compound_literal_test(void);
|
|
|
|
|
int kr_test();
|
2002-07-13 21:24:30 +04:00
|
|
|
|
void struct_assign_test(void);
|
2002-01-05 20:03:02 +03:00
|
|
|
|
void cast_test(void);
|
|
|
|
|
void bitfield_test(void);
|
|
|
|
|
void c99_bool_test(void);
|
|
|
|
|
void float_test(void);
|
|
|
|
|
void longlong_test(void);
|
2008-12-01 21:22:57 +03:00
|
|
|
|
void manyarg_test(void);
|
2002-08-31 16:45:26 +04:00
|
|
|
|
void stdarg_test(void);
|
|
|
|
|
void whitespace_test(void);
|
|
|
|
|
void relocation_test(void);
|
2002-11-02 23:46:36 +03:00
|
|
|
|
void old_style_function(void);
|
2009-05-17 00:30:13 +04:00
|
|
|
|
void alloca_test(void);
|
2011-04-06 20:17:03 +04:00
|
|
|
|
void c99_vla_test(int size1, int size2);
|
2002-11-02 23:46:36 +03:00
|
|
|
|
void sizeof_test(void);
|
|
|
|
|
void typeof_test(void);
|
2003-01-06 23:19:20 +03:00
|
|
|
|
void local_label_test(void);
|
|
|
|
|
void statement_expr_test(void);
|
|
|
|
|
void asm_test(void);
|
2003-04-27 15:45:54 +04:00
|
|
|
|
void builtin_test(void);
|
2011-02-01 11:37:53 +03:00
|
|
|
|
void weak_test(void);
|
2012-04-15 21:29:45 +04:00
|
|
|
|
void global_data_test(void);
|
2012-04-16 04:52:15 +04:00
|
|
|
|
void cmp_comparison_test(void);
|
2012-05-13 04:21:51 +04:00
|
|
|
|
void math_cmp_test(void);
|
2012-06-10 11:01:13 +04:00
|
|
|
|
void callsave_test(void);
|
Add support for __builtin_frame_address(level)
Continuing d6072d37 (Add __builtin_frame_address(0)) implement
__builtin_frame_address for levels greater than zero, in order for
tinycc to be able to compile its own lib/bcheck.c after
cffb7af9 (lib/bcheck: Prevent __bound_local_new / __bound_local_delete
from being miscompiled).
I'm new to the internals, and used the most simple way to do it.
Generated code is not very good for levels >= 2, compare
gcc tcc
level=0 mov %ebp,%eax lea 0x0(%ebp),%eax
level=1 mov 0x0(%ebp),%eax mov 0x0(%ebp),%eax
level=2 mov 0x0(%ebp),%eax mov 0x0(%ebp),%eax
mov (%eax),%eax mov %eax,-0x10(%ebp)
mov -0x10(%ebp),%eax
mov (%eax),%eax
level=3 mov 0x0(%ebp),%eax mov 0x0(%ebp),%eax
mov (%eax),%eax mov (%eax),%ecx
mov (%eax),%eax mov (%ecx),%eax
But this is still an improvement and for bcheck we need level=1 for
which the code is good.
For the tests I had to force gcc use -O0 to not inline the functions.
And -fno-omit-frame-pointer just in case.
If someone knows how to improve the generated code - help is
appreciated.
Thanks,
Kirill
Cc: Michael Matz <matz@suse.de>
Cc: Shinichiro Hamaji <shinichiro.hamaji@gmail.com>
2012-11-15 03:31:49 +04:00
|
|
|
|
void builtin_frame_address_test(void);
|
2016-07-11 19:38:00 +03:00
|
|
|
|
void attrib_test(void);
|
2019-12-10 10:07:25 +03:00
|
|
|
|
void bounds_check1_test(void);
|
2002-01-05 20:03:02 +03:00
|
|
|
|
|
|
|
|
|
int fib(int n);
|
|
|
|
|
void num(int n);
|
|
|
|
|
void forward_ref(void);
|
|
|
|
|
int isid(int c);
|
|
|
|
|
|
2016-03-24 17:58:32 +03:00
|
|
|
|
/* Line joining happens before tokenization, so the following
|
|
|
|
|
must be parsed as ellipsis. */
|
|
|
|
|
void funny_line_continuation (int, ..\
|
|
|
|
|
. );
|
|
|
|
|
|
2016-03-26 19:57:22 +03:00
|
|
|
|
char via_volatile (char);
|
|
|
|
|
|
2002-01-05 20:03:02 +03:00
|
|
|
|
#define A 2
|
|
|
|
|
#define N 1234 + A
|
|
|
|
|
#define pf printf
|
|
|
|
|
#define M1(a, b) (a) + (b)
|
|
|
|
|
|
2002-11-24 18:58:28 +03:00
|
|
|
|
#define str\
|
|
|
|
|
(s) # s
|
2002-01-05 20:03:02 +03:00
|
|
|
|
#define glue(a, b) a ## b
|
|
|
|
|
#define xglue(a, b) glue(a, b)
|
|
|
|
|
#define HIGHLOW "hello"
|
|
|
|
|
#define LOW LOW ", world"
|
|
|
|
|
|
2011-07-08 13:51:06 +04:00
|
|
|
|
static int onetwothree = 123;
|
|
|
|
|
#define onetwothree4 onetwothree
|
|
|
|
|
#define onetwothree xglue(onetwothree,4)
|
|
|
|
|
|
2002-01-05 20:03:02 +03:00
|
|
|
|
#define min(a, b) ((a) < (b) ? (a) : (b))
|
|
|
|
|
|
|
|
|
|
#ifdef C99_MACROS
|
|
|
|
|
#define dprintf(level,...) printf(__VA_ARGS__)
|
|
|
|
|
#endif
|
|
|
|
|
|
2002-07-13 21:24:30 +04:00
|
|
|
|
/* gcc vararg macros */
|
|
|
|
|
#define dprintf1(level, fmt, args...) printf(fmt, ## args)
|
|
|
|
|
|
|
|
|
|
#define MACRO_NOARGS()
|
|
|
|
|
|
2002-01-05 20:03:02 +03:00
|
|
|
|
#define AAA 3
|
|
|
|
|
#undef AAA
|
|
|
|
|
#define AAA 4
|
|
|
|
|
|
2002-01-26 20:24:07 +03:00
|
|
|
|
#if 1
|
|
|
|
|
#define B3 1
|
|
|
|
|
#elif 1
|
|
|
|
|
#define B3 2
|
|
|
|
|
#elif 0
|
|
|
|
|
#define B3 3
|
|
|
|
|
#else
|
|
|
|
|
#define B3 4
|
|
|
|
|
#endif
|
|
|
|
|
|
2017-05-05 23:01:02 +03:00
|
|
|
|
#ifdef __TINYC__
|
|
|
|
|
/* We try to handle this syntax. Make at least sure it doesn't segfault. */
|
2019-04-29 14:53:07 +03:00
|
|
|
|
char invalid_function_def()[] {return 0;}
|
2017-05-05 23:01:02 +03:00
|
|
|
|
#endif
|
|
|
|
|
|
2002-11-02 17:14:50 +03:00
|
|
|
|
#define __INT64_C(c) c ## LL
|
|
|
|
|
#define INT64_MIN (-__INT64_C(9223372036854775807)-1)
|
|
|
|
|
|
2003-05-18 21:08:55 +04:00
|
|
|
|
int qq(int x)
|
|
|
|
|
{
|
|
|
|
|
return x + 40;
|
|
|
|
|
}
|
|
|
|
|
#define qq(x) x
|
|
|
|
|
|
2005-06-18 02:06:18 +04:00
|
|
|
|
#define spin_lock(lock) do { } while (0)
|
|
|
|
|
#define wq_spin_lock spin_lock
|
|
|
|
|
#define TEST2() wq_spin_lock(a)
|
|
|
|
|
|
Add ARM aeabi functions needed to run tcctest
Add implementation for float / integer conversion functions:
__aeabi_d2lz, __aeabi_d2ulz, __aeabi_f2lz, __aeabi_f2ulz, __aeabi_l2d,
__aeabi_l2f, __aeabi_ul2d, __aeabi_ul2f
Add implementation for long long helper functions:
__aeabi_ldivmod, __aeabi_uldivmod, __aeabi_llsl, __aeabi_llsr, __aeabi_lasr
Add implementation for integer division functions:
__aeabi_uidiv, __aeabi_uidivmod, __aeabi_idiv, __aeabi_idivmod,
2013-04-07 19:02:57 +04:00
|
|
|
|
#define UINT_MAX ((unsigned) -1)
|
|
|
|
|
|
|
|
|
|
void intdiv_test(void)
|
|
|
|
|
{
|
|
|
|
|
printf("18/21=%u\n", 18/21);
|
2015-11-04 23:20:26 +03:00
|
|
|
|
printf("18%%21=%u\n", 18%21);
|
Add ARM aeabi functions needed to run tcctest
Add implementation for float / integer conversion functions:
__aeabi_d2lz, __aeabi_d2ulz, __aeabi_f2lz, __aeabi_f2ulz, __aeabi_l2d,
__aeabi_l2f, __aeabi_ul2d, __aeabi_ul2f
Add implementation for long long helper functions:
__aeabi_ldivmod, __aeabi_uldivmod, __aeabi_llsl, __aeabi_llsr, __aeabi_lasr
Add implementation for integer division functions:
__aeabi_uidiv, __aeabi_uidivmod, __aeabi_idiv, __aeabi_idivmod,
2013-04-07 19:02:57 +04:00
|
|
|
|
printf("41/21=%u\n", 41/21);
|
2015-11-04 23:20:26 +03:00
|
|
|
|
printf("41%%21=%u\n", 41%21);
|
Add ARM aeabi functions needed to run tcctest
Add implementation for float / integer conversion functions:
__aeabi_d2lz, __aeabi_d2ulz, __aeabi_f2lz, __aeabi_f2ulz, __aeabi_l2d,
__aeabi_l2f, __aeabi_ul2d, __aeabi_ul2f
Add implementation for long long helper functions:
__aeabi_ldivmod, __aeabi_uldivmod, __aeabi_llsl, __aeabi_llsr, __aeabi_lasr
Add implementation for integer division functions:
__aeabi_uidiv, __aeabi_uidivmod, __aeabi_idiv, __aeabi_idivmod,
2013-04-07 19:02:57 +04:00
|
|
|
|
printf("42/21=%u\n", 42/21);
|
2015-11-04 23:20:26 +03:00
|
|
|
|
printf("42%%21=%u\n", 42%21);
|
Add ARM aeabi functions needed to run tcctest
Add implementation for float / integer conversion functions:
__aeabi_d2lz, __aeabi_d2ulz, __aeabi_f2lz, __aeabi_f2ulz, __aeabi_l2d,
__aeabi_l2f, __aeabi_ul2d, __aeabi_ul2f
Add implementation for long long helper functions:
__aeabi_ldivmod, __aeabi_uldivmod, __aeabi_llsl, __aeabi_llsr, __aeabi_lasr
Add implementation for integer division functions:
__aeabi_uidiv, __aeabi_uidivmod, __aeabi_idiv, __aeabi_idivmod,
2013-04-07 19:02:57 +04:00
|
|
|
|
printf("43/21=%u\n", 43/21);
|
2015-11-04 23:20:26 +03:00
|
|
|
|
printf("43%%21=%u\n", 43%21);
|
Add ARM aeabi functions needed to run tcctest
Add implementation for float / integer conversion functions:
__aeabi_d2lz, __aeabi_d2ulz, __aeabi_f2lz, __aeabi_f2ulz, __aeabi_l2d,
__aeabi_l2f, __aeabi_ul2d, __aeabi_ul2f
Add implementation for long long helper functions:
__aeabi_ldivmod, __aeabi_uldivmod, __aeabi_llsl, __aeabi_llsr, __aeabi_lasr
Add implementation for integer division functions:
__aeabi_uidiv, __aeabi_uidivmod, __aeabi_idiv, __aeabi_idivmod,
2013-04-07 19:02:57 +04:00
|
|
|
|
printf("126/21=%u\n", 126/21);
|
2015-11-04 23:20:26 +03:00
|
|
|
|
printf("126%%21=%u\n", 126%21);
|
Add ARM aeabi functions needed to run tcctest
Add implementation for float / integer conversion functions:
__aeabi_d2lz, __aeabi_d2ulz, __aeabi_f2lz, __aeabi_f2ulz, __aeabi_l2d,
__aeabi_l2f, __aeabi_ul2d, __aeabi_ul2f
Add implementation for long long helper functions:
__aeabi_ldivmod, __aeabi_uldivmod, __aeabi_llsl, __aeabi_llsr, __aeabi_lasr
Add implementation for integer division functions:
__aeabi_uidiv, __aeabi_uidivmod, __aeabi_idiv, __aeabi_idivmod,
2013-04-07 19:02:57 +04:00
|
|
|
|
printf("131/21=%u\n", 131/21);
|
2015-11-04 23:20:26 +03:00
|
|
|
|
printf("131%%21=%u\n", 131%21);
|
Add ARM aeabi functions needed to run tcctest
Add implementation for float / integer conversion functions:
__aeabi_d2lz, __aeabi_d2ulz, __aeabi_f2lz, __aeabi_f2ulz, __aeabi_l2d,
__aeabi_l2f, __aeabi_ul2d, __aeabi_ul2f
Add implementation for long long helper functions:
__aeabi_ldivmod, __aeabi_uldivmod, __aeabi_llsl, __aeabi_llsr, __aeabi_lasr
Add implementation for integer division functions:
__aeabi_uidiv, __aeabi_uidivmod, __aeabi_idiv, __aeabi_idivmod,
2013-04-07 19:02:57 +04:00
|
|
|
|
printf("(UINT_MAX/2+3)/2=%u\n", (UINT_MAX/2+3)/2);
|
2015-11-04 23:20:26 +03:00
|
|
|
|
printf("(UINT_MAX/2+3)%%2=%u\n", (UINT_MAX/2+3)%2);
|
Add ARM aeabi functions needed to run tcctest
Add implementation for float / integer conversion functions:
__aeabi_d2lz, __aeabi_d2ulz, __aeabi_f2lz, __aeabi_f2ulz, __aeabi_l2d,
__aeabi_l2f, __aeabi_ul2d, __aeabi_ul2f
Add implementation for long long helper functions:
__aeabi_ldivmod, __aeabi_uldivmod, __aeabi_llsl, __aeabi_llsr, __aeabi_lasr
Add implementation for integer division functions:
__aeabi_uidiv, __aeabi_uidivmod, __aeabi_idiv, __aeabi_idivmod,
2013-04-07 19:02:57 +04:00
|
|
|
|
|
|
|
|
|
printf("18/-21=%u\n", 18/-21);
|
2015-11-04 23:20:26 +03:00
|
|
|
|
printf("18%%-21=%u\n", 18%-21);
|
Add ARM aeabi functions needed to run tcctest
Add implementation for float / integer conversion functions:
__aeabi_d2lz, __aeabi_d2ulz, __aeabi_f2lz, __aeabi_f2ulz, __aeabi_l2d,
__aeabi_l2f, __aeabi_ul2d, __aeabi_ul2f
Add implementation for long long helper functions:
__aeabi_ldivmod, __aeabi_uldivmod, __aeabi_llsl, __aeabi_llsr, __aeabi_lasr
Add implementation for integer division functions:
__aeabi_uidiv, __aeabi_uidivmod, __aeabi_idiv, __aeabi_idivmod,
2013-04-07 19:02:57 +04:00
|
|
|
|
printf("41/-21=%u\n", 41/-21);
|
2015-11-04 23:20:26 +03:00
|
|
|
|
printf("41%%-21=%u\n", 41%-21);
|
Add ARM aeabi functions needed to run tcctest
Add implementation for float / integer conversion functions:
__aeabi_d2lz, __aeabi_d2ulz, __aeabi_f2lz, __aeabi_f2ulz, __aeabi_l2d,
__aeabi_l2f, __aeabi_ul2d, __aeabi_ul2f
Add implementation for long long helper functions:
__aeabi_ldivmod, __aeabi_uldivmod, __aeabi_llsl, __aeabi_llsr, __aeabi_lasr
Add implementation for integer division functions:
__aeabi_uidiv, __aeabi_uidivmod, __aeabi_idiv, __aeabi_idivmod,
2013-04-07 19:02:57 +04:00
|
|
|
|
printf("42/-21=%u\n", 42/-21);
|
2015-11-04 23:20:26 +03:00
|
|
|
|
printf("42%%-21=%u\n", 42%-21);
|
Add ARM aeabi functions needed to run tcctest
Add implementation for float / integer conversion functions:
__aeabi_d2lz, __aeabi_d2ulz, __aeabi_f2lz, __aeabi_f2ulz, __aeabi_l2d,
__aeabi_l2f, __aeabi_ul2d, __aeabi_ul2f
Add implementation for long long helper functions:
__aeabi_ldivmod, __aeabi_uldivmod, __aeabi_llsl, __aeabi_llsr, __aeabi_lasr
Add implementation for integer division functions:
__aeabi_uidiv, __aeabi_uidivmod, __aeabi_idiv, __aeabi_idivmod,
2013-04-07 19:02:57 +04:00
|
|
|
|
printf("43/-21=%u\n", 43/-21);
|
2015-11-04 23:20:26 +03:00
|
|
|
|
printf("43%%-21=%u\n", 43%-21);
|
Add ARM aeabi functions needed to run tcctest
Add implementation for float / integer conversion functions:
__aeabi_d2lz, __aeabi_d2ulz, __aeabi_f2lz, __aeabi_f2ulz, __aeabi_l2d,
__aeabi_l2f, __aeabi_ul2d, __aeabi_ul2f
Add implementation for long long helper functions:
__aeabi_ldivmod, __aeabi_uldivmod, __aeabi_llsl, __aeabi_llsr, __aeabi_lasr
Add implementation for integer division functions:
__aeabi_uidiv, __aeabi_uidivmod, __aeabi_idiv, __aeabi_idivmod,
2013-04-07 19:02:57 +04:00
|
|
|
|
printf("126/-21=%u\n", 126/-21);
|
2015-11-04 23:20:26 +03:00
|
|
|
|
printf("126%%-21=%u\n", 126%-21);
|
Add ARM aeabi functions needed to run tcctest
Add implementation for float / integer conversion functions:
__aeabi_d2lz, __aeabi_d2ulz, __aeabi_f2lz, __aeabi_f2ulz, __aeabi_l2d,
__aeabi_l2f, __aeabi_ul2d, __aeabi_ul2f
Add implementation for long long helper functions:
__aeabi_ldivmod, __aeabi_uldivmod, __aeabi_llsl, __aeabi_llsr, __aeabi_lasr
Add implementation for integer division functions:
__aeabi_uidiv, __aeabi_uidivmod, __aeabi_idiv, __aeabi_idivmod,
2013-04-07 19:02:57 +04:00
|
|
|
|
printf("131/-21=%u\n", 131/-21);
|
2015-11-04 23:20:26 +03:00
|
|
|
|
printf("131%%-21=%u\n", 131%-21);
|
Add ARM aeabi functions needed to run tcctest
Add implementation for float / integer conversion functions:
__aeabi_d2lz, __aeabi_d2ulz, __aeabi_f2lz, __aeabi_f2ulz, __aeabi_l2d,
__aeabi_l2f, __aeabi_ul2d, __aeabi_ul2f
Add implementation for long long helper functions:
__aeabi_ldivmod, __aeabi_uldivmod, __aeabi_llsl, __aeabi_llsr, __aeabi_lasr
Add implementation for integer division functions:
__aeabi_uidiv, __aeabi_uidivmod, __aeabi_idiv, __aeabi_idivmod,
2013-04-07 19:02:57 +04:00
|
|
|
|
printf("(UINT_MAX/2+3)/-2=%u\n", (UINT_MAX/2+3)/-2);
|
2015-11-04 23:20:26 +03:00
|
|
|
|
printf("(UINT_MAX/2+3)%%-2=%u\n", (UINT_MAX/2+3)%-2);
|
Add ARM aeabi functions needed to run tcctest
Add implementation for float / integer conversion functions:
__aeabi_d2lz, __aeabi_d2ulz, __aeabi_f2lz, __aeabi_f2ulz, __aeabi_l2d,
__aeabi_l2f, __aeabi_ul2d, __aeabi_ul2f
Add implementation for long long helper functions:
__aeabi_ldivmod, __aeabi_uldivmod, __aeabi_llsl, __aeabi_llsr, __aeabi_lasr
Add implementation for integer division functions:
__aeabi_uidiv, __aeabi_uidivmod, __aeabi_idiv, __aeabi_idivmod,
2013-04-07 19:02:57 +04:00
|
|
|
|
|
|
|
|
|
printf("-18/21=%u\n", -18/21);
|
2015-11-04 23:20:26 +03:00
|
|
|
|
printf("-18%%21=%u\n", -18%21);
|
Add ARM aeabi functions needed to run tcctest
Add implementation for float / integer conversion functions:
__aeabi_d2lz, __aeabi_d2ulz, __aeabi_f2lz, __aeabi_f2ulz, __aeabi_l2d,
__aeabi_l2f, __aeabi_ul2d, __aeabi_ul2f
Add implementation for long long helper functions:
__aeabi_ldivmod, __aeabi_uldivmod, __aeabi_llsl, __aeabi_llsr, __aeabi_lasr
Add implementation for integer division functions:
__aeabi_uidiv, __aeabi_uidivmod, __aeabi_idiv, __aeabi_idivmod,
2013-04-07 19:02:57 +04:00
|
|
|
|
printf("-41/21=%u\n", -41/21);
|
2015-11-04 23:20:26 +03:00
|
|
|
|
printf("-41%%21=%u\n", -41%21);
|
Add ARM aeabi functions needed to run tcctest
Add implementation for float / integer conversion functions:
__aeabi_d2lz, __aeabi_d2ulz, __aeabi_f2lz, __aeabi_f2ulz, __aeabi_l2d,
__aeabi_l2f, __aeabi_ul2d, __aeabi_ul2f
Add implementation for long long helper functions:
__aeabi_ldivmod, __aeabi_uldivmod, __aeabi_llsl, __aeabi_llsr, __aeabi_lasr
Add implementation for integer division functions:
__aeabi_uidiv, __aeabi_uidivmod, __aeabi_idiv, __aeabi_idivmod,
2013-04-07 19:02:57 +04:00
|
|
|
|
printf("-42/21=%u\n", -42/21);
|
2015-11-04 23:20:26 +03:00
|
|
|
|
printf("-42%%21=%u\n", -42%21);
|
Add ARM aeabi functions needed to run tcctest
Add implementation for float / integer conversion functions:
__aeabi_d2lz, __aeabi_d2ulz, __aeabi_f2lz, __aeabi_f2ulz, __aeabi_l2d,
__aeabi_l2f, __aeabi_ul2d, __aeabi_ul2f
Add implementation for long long helper functions:
__aeabi_ldivmod, __aeabi_uldivmod, __aeabi_llsl, __aeabi_llsr, __aeabi_lasr
Add implementation for integer division functions:
__aeabi_uidiv, __aeabi_uidivmod, __aeabi_idiv, __aeabi_idivmod,
2013-04-07 19:02:57 +04:00
|
|
|
|
printf("-43/21=%u\n", -43/21);
|
2015-11-04 23:20:26 +03:00
|
|
|
|
printf("-43%%21=%u\n", -43%21);
|
Add ARM aeabi functions needed to run tcctest
Add implementation for float / integer conversion functions:
__aeabi_d2lz, __aeabi_d2ulz, __aeabi_f2lz, __aeabi_f2ulz, __aeabi_l2d,
__aeabi_l2f, __aeabi_ul2d, __aeabi_ul2f
Add implementation for long long helper functions:
__aeabi_ldivmod, __aeabi_uldivmod, __aeabi_llsl, __aeabi_llsr, __aeabi_lasr
Add implementation for integer division functions:
__aeabi_uidiv, __aeabi_uidivmod, __aeabi_idiv, __aeabi_idivmod,
2013-04-07 19:02:57 +04:00
|
|
|
|
printf("-126/21=%u\n", -126/21);
|
2015-11-04 23:20:26 +03:00
|
|
|
|
printf("-126%%21=%u\n", -126%21);
|
Add ARM aeabi functions needed to run tcctest
Add implementation for float / integer conversion functions:
__aeabi_d2lz, __aeabi_d2ulz, __aeabi_f2lz, __aeabi_f2ulz, __aeabi_l2d,
__aeabi_l2f, __aeabi_ul2d, __aeabi_ul2f
Add implementation for long long helper functions:
__aeabi_ldivmod, __aeabi_uldivmod, __aeabi_llsl, __aeabi_llsr, __aeabi_lasr
Add implementation for integer division functions:
__aeabi_uidiv, __aeabi_uidivmod, __aeabi_idiv, __aeabi_idivmod,
2013-04-07 19:02:57 +04:00
|
|
|
|
printf("-131/21=%u\n", -131/21);
|
2015-11-04 23:20:26 +03:00
|
|
|
|
printf("-131%%21=%u\n", -131%21);
|
Add ARM aeabi functions needed to run tcctest
Add implementation for float / integer conversion functions:
__aeabi_d2lz, __aeabi_d2ulz, __aeabi_f2lz, __aeabi_f2ulz, __aeabi_l2d,
__aeabi_l2f, __aeabi_ul2d, __aeabi_ul2f
Add implementation for long long helper functions:
__aeabi_ldivmod, __aeabi_uldivmod, __aeabi_llsl, __aeabi_llsr, __aeabi_lasr
Add implementation for integer division functions:
__aeabi_uidiv, __aeabi_uidivmod, __aeabi_idiv, __aeabi_idivmod,
2013-04-07 19:02:57 +04:00
|
|
|
|
printf("-(UINT_MAX/2+3)/2=%u\n", (0-(UINT_MAX/2+3))/2);
|
2015-11-04 23:20:26 +03:00
|
|
|
|
printf("-(UINT_MAX/2+3)%%2=%u\n", (0-(UINT_MAX/2+3))%2);
|
Add ARM aeabi functions needed to run tcctest
Add implementation for float / integer conversion functions:
__aeabi_d2lz, __aeabi_d2ulz, __aeabi_f2lz, __aeabi_f2ulz, __aeabi_l2d,
__aeabi_l2f, __aeabi_ul2d, __aeabi_ul2f
Add implementation for long long helper functions:
__aeabi_ldivmod, __aeabi_uldivmod, __aeabi_llsl, __aeabi_llsr, __aeabi_lasr
Add implementation for integer division functions:
__aeabi_uidiv, __aeabi_uidivmod, __aeabi_idiv, __aeabi_idivmod,
2013-04-07 19:02:57 +04:00
|
|
|
|
|
|
|
|
|
printf("-18/-21=%u\n", -18/-21);
|
2015-11-04 23:20:26 +03:00
|
|
|
|
printf("-18%%-21=%u\n", -18%-21);
|
Add ARM aeabi functions needed to run tcctest
Add implementation for float / integer conversion functions:
__aeabi_d2lz, __aeabi_d2ulz, __aeabi_f2lz, __aeabi_f2ulz, __aeabi_l2d,
__aeabi_l2f, __aeabi_ul2d, __aeabi_ul2f
Add implementation for long long helper functions:
__aeabi_ldivmod, __aeabi_uldivmod, __aeabi_llsl, __aeabi_llsr, __aeabi_lasr
Add implementation for integer division functions:
__aeabi_uidiv, __aeabi_uidivmod, __aeabi_idiv, __aeabi_idivmod,
2013-04-07 19:02:57 +04:00
|
|
|
|
printf("-41/-21=%u\n", -41/-21);
|
2015-11-04 23:20:26 +03:00
|
|
|
|
printf("-41%%-21=%u\n", -41%-21);
|
Add ARM aeabi functions needed to run tcctest
Add implementation for float / integer conversion functions:
__aeabi_d2lz, __aeabi_d2ulz, __aeabi_f2lz, __aeabi_f2ulz, __aeabi_l2d,
__aeabi_l2f, __aeabi_ul2d, __aeabi_ul2f
Add implementation for long long helper functions:
__aeabi_ldivmod, __aeabi_uldivmod, __aeabi_llsl, __aeabi_llsr, __aeabi_lasr
Add implementation for integer division functions:
__aeabi_uidiv, __aeabi_uidivmod, __aeabi_idiv, __aeabi_idivmod,
2013-04-07 19:02:57 +04:00
|
|
|
|
printf("-42/-21=%u\n", -42/-21);
|
2015-11-04 23:20:26 +03:00
|
|
|
|
printf("-42%%-21=%u\n", -42%-21);
|
Add ARM aeabi functions needed to run tcctest
Add implementation for float / integer conversion functions:
__aeabi_d2lz, __aeabi_d2ulz, __aeabi_f2lz, __aeabi_f2ulz, __aeabi_l2d,
__aeabi_l2f, __aeabi_ul2d, __aeabi_ul2f
Add implementation for long long helper functions:
__aeabi_ldivmod, __aeabi_uldivmod, __aeabi_llsl, __aeabi_llsr, __aeabi_lasr
Add implementation for integer division functions:
__aeabi_uidiv, __aeabi_uidivmod, __aeabi_idiv, __aeabi_idivmod,
2013-04-07 19:02:57 +04:00
|
|
|
|
printf("-43/-21=%u\n", -43/-21);
|
2015-11-04 23:20:26 +03:00
|
|
|
|
printf("-43%%-21=%u\n", -43%-21);
|
Add ARM aeabi functions needed to run tcctest
Add implementation for float / integer conversion functions:
__aeabi_d2lz, __aeabi_d2ulz, __aeabi_f2lz, __aeabi_f2ulz, __aeabi_l2d,
__aeabi_l2f, __aeabi_ul2d, __aeabi_ul2f
Add implementation for long long helper functions:
__aeabi_ldivmod, __aeabi_uldivmod, __aeabi_llsl, __aeabi_llsr, __aeabi_lasr
Add implementation for integer division functions:
__aeabi_uidiv, __aeabi_uidivmod, __aeabi_idiv, __aeabi_idivmod,
2013-04-07 19:02:57 +04:00
|
|
|
|
printf("-126/-21=%u\n", -126/-21);
|
2015-11-04 23:20:26 +03:00
|
|
|
|
printf("-126%%-21=%u\n", -126%-21);
|
Add ARM aeabi functions needed to run tcctest
Add implementation for float / integer conversion functions:
__aeabi_d2lz, __aeabi_d2ulz, __aeabi_f2lz, __aeabi_f2ulz, __aeabi_l2d,
__aeabi_l2f, __aeabi_ul2d, __aeabi_ul2f
Add implementation for long long helper functions:
__aeabi_ldivmod, __aeabi_uldivmod, __aeabi_llsl, __aeabi_llsr, __aeabi_lasr
Add implementation for integer division functions:
__aeabi_uidiv, __aeabi_uidivmod, __aeabi_idiv, __aeabi_idivmod,
2013-04-07 19:02:57 +04:00
|
|
|
|
printf("-131/-21=%u\n", -131/-21);
|
2015-11-04 23:20:26 +03:00
|
|
|
|
printf("-131%%-21=%u\n", -131%-21);
|
Add ARM aeabi functions needed to run tcctest
Add implementation for float / integer conversion functions:
__aeabi_d2lz, __aeabi_d2ulz, __aeabi_f2lz, __aeabi_f2ulz, __aeabi_l2d,
__aeabi_l2f, __aeabi_ul2d, __aeabi_ul2f
Add implementation for long long helper functions:
__aeabi_ldivmod, __aeabi_uldivmod, __aeabi_llsl, __aeabi_llsr, __aeabi_lasr
Add implementation for integer division functions:
__aeabi_uidiv, __aeabi_uidivmod, __aeabi_idiv, __aeabi_idivmod,
2013-04-07 19:02:57 +04:00
|
|
|
|
printf("-(UINT_MAX/2+3)/-2=%u\n", (0-(UINT_MAX/2+3))/-2);
|
2015-11-04 23:20:26 +03:00
|
|
|
|
printf("-(UINT_MAX/2+3)%%-2=%u\n", (0-(UINT_MAX/2+3))%-2);
|
Add ARM aeabi functions needed to run tcctest
Add implementation for float / integer conversion functions:
__aeabi_d2lz, __aeabi_d2ulz, __aeabi_f2lz, __aeabi_f2ulz, __aeabi_l2d,
__aeabi_l2f, __aeabi_ul2d, __aeabi_ul2f
Add implementation for long long helper functions:
__aeabi_ldivmod, __aeabi_uldivmod, __aeabi_llsl, __aeabi_llsr, __aeabi_lasr
Add implementation for integer division functions:
__aeabi_uidiv, __aeabi_uidivmod, __aeabi_idiv, __aeabi_idivmod,
2013-04-07 19:02:57 +04:00
|
|
|
|
}
|
|
|
|
|
|
2002-11-02 17:14:50 +03:00
|
|
|
|
void macro_test(void)
|
2002-01-05 20:03:02 +03:00
|
|
|
|
{
|
2002-08-31 16:45:26 +04:00
|
|
|
|
printf("macro:\n");
|
2002-01-05 20:03:02 +03:00
|
|
|
|
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));
|
2002-01-26 20:24:07 +03:00
|
|
|
|
printf("B3=%d\n", B3);
|
2002-01-05 20:03:02 +03:00
|
|
|
|
|
2011-07-08 13:51:06 +04:00
|
|
|
|
printf("onetwothree=%d\n", onetwothree);
|
|
|
|
|
|
2002-01-05 20:03:02 +03:00
|
|
|
|
#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
|
|
|
|
|
|
2002-07-13 21:24:30 +04:00
|
|
|
|
MACRO_NOARGS();
|
|
|
|
|
|
2002-08-31 16:45:26 +04:00
|
|
|
|
#ifdef __LINE__
|
|
|
|
|
printf("__LINE__ defined\n");
|
|
|
|
|
#endif
|
|
|
|
|
|
2002-01-05 20:03:02 +03:00
|
|
|
|
printf("__LINE__=%d __FILE__=%s\n",
|
|
|
|
|
__LINE__, __FILE__);
|
tccpp: fix issues, add tests
* fix some macro expansion issues
* add some pp tests in tests/pp
* improved tcc -E output for better diff'ability
* remove -dD feature (quirky code, exotic feature,
didn't work well)
Based partially on ideas / researches from PipCet
Some issues remain with VA_ARGS macros (if used in a
rather tricky way).
Also, to keep it simple, the pp doesn't automtically
add any extra spaces to separate tokens which otherwise
would form wrong tokens if re-read from tcc -E output
(such as '+' '=') GCC does that, other compilers don't.
* cleanups
- #line 01 "file" / # 01 "file" processing
- #pragma comment(lib,"foo")
- tcc -E: forward some pragmas to output (pack, comment(lib))
- fix macro parameter list parsing mess from
a3fc54345949535524d01319e1ca6378b7c2c201
a715d7143d9d17da17e67fec6af1c01409a71a31
(some coffee might help, next time ;)
- introduce TOK_PPSTR - to have character constants as
written in the file (similar to TOK_PPNUM)
- allow '\' appear in macros
- new functions begin/end_macro to:
- fix switching macro levels during expansion
- allow unget_tok to unget more than one tok
- slight speedup by using bitflags in isidnum_table
Also:
- x86_64.c : fix decl after statements
- i386-gen,c : fix a vstack leak with VLA on windows
- configure/Makefile : build on windows (MSYS) was broken
- tcc_warning: fflush stderr to keep output order (win32)
2015-05-09 15:29:39 +03:00
|
|
|
|
#if 0
|
2002-08-18 17:18:20 +04:00
|
|
|
|
#line 200
|
|
|
|
|
printf("__LINE__=%d __FILE__=%s\n",
|
|
|
|
|
__LINE__, __FILE__);
|
2015-07-29 23:53:57 +03:00
|
|
|
|
#line 203 "test"
|
2002-08-18 17:18:20 +04:00
|
|
|
|
printf("__LINE__=%d __FILE__=%s\n",
|
|
|
|
|
__LINE__, __FILE__);
|
2008-03-31 23:50:58 +04:00
|
|
|
|
#line 227 "tcctest.c"
|
tccpp: fix issues, add tests
* fix some macro expansion issues
* add some pp tests in tests/pp
* improved tcc -E output for better diff'ability
* remove -dD feature (quirky code, exotic feature,
didn't work well)
Based partially on ideas / researches from PipCet
Some issues remain with VA_ARGS macros (if used in a
rather tricky way).
Also, to keep it simple, the pp doesn't automtically
add any extra spaces to separate tokens which otherwise
would form wrong tokens if re-read from tcc -E output
(such as '+' '=') GCC does that, other compilers don't.
* cleanups
- #line 01 "file" / # 01 "file" processing
- #pragma comment(lib,"foo")
- tcc -E: forward some pragmas to output (pack, comment(lib))
- fix macro parameter list parsing mess from
a3fc54345949535524d01319e1ca6378b7c2c201
a715d7143d9d17da17e67fec6af1c01409a71a31
(some coffee might help, next time ;)
- introduce TOK_PPSTR - to have character constants as
written in the file (similar to TOK_PPNUM)
- allow '\' appear in macros
- new functions begin/end_macro to:
- fix switching macro levels during expansion
- allow unget_tok to unget more than one tok
- slight speedup by using bitflags in isidnum_table
Also:
- x86_64.c : fix decl after statements
- i386-gen,c : fix a vstack leak with VLA on windows
- configure/Makefile : build on windows (MSYS) was broken
- tcc_warning: fflush stderr to keep output order (win32)
2015-05-09 15:29:39 +03:00
|
|
|
|
#endif
|
2002-11-24 18:58:28 +03:00
|
|
|
|
|
2002-01-05 20:03:02 +03:00
|
|
|
|
/* not strictly preprocessor, but we test it there */
|
|
|
|
|
#ifdef C99_MACROS
|
|
|
|
|
printf("__func__ = %s\n", __func__);
|
|
|
|
|
dprintf(1, "vaarg=%d\n", 1);
|
|
|
|
|
#endif
|
2002-07-13 21:24:30 +04:00
|
|
|
|
dprintf1(1, "vaarg1\n");
|
|
|
|
|
dprintf1(1, "vaarg1=%d\n", 2);
|
|
|
|
|
dprintf1(1, "vaarg1=%d %d\n", 1, 2);
|
2002-08-31 16:45:26 +04:00
|
|
|
|
|
|
|
|
|
/* gcc extension */
|
|
|
|
|
printf("func='%s'\n", __FUNCTION__);
|
2002-11-02 17:14:50 +03:00
|
|
|
|
|
|
|
|
|
/* complicated macros in glibc */
|
2013-04-26 04:27:04 +04:00
|
|
|
|
printf("INT64_MIN=" LONG_LONG_FORMAT "\n", INT64_MIN);
|
2002-11-02 23:46:36 +03:00
|
|
|
|
{
|
|
|
|
|
int a;
|
|
|
|
|
a = 1;
|
|
|
|
|
glue(a+, +);
|
|
|
|
|
printf("a=%d\n", a);
|
|
|
|
|
glue(a <, <= 2);
|
|
|
|
|
printf("a=%d\n", a);
|
|
|
|
|
}
|
2015-07-29 23:53:57 +03:00
|
|
|
|
|
2003-04-13 23:48:52 +04:00
|
|
|
|
/* 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");
|
2015-07-29 23:53:57 +03:00
|
|
|
|
|
2017-09-25 04:03:26 +03:00
|
|
|
|
/* test macro substitution inside args (should not eat stream) */
|
2003-05-18 21:08:55 +04:00
|
|
|
|
printf("qq=%d\n", qq(qq)(2));
|
|
|
|
|
|
2003-05-18 22:48:33 +04:00
|
|
|
|
/* 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( ));
|
|
|
|
|
|
2002-11-24 18:58:28 +03:00
|
|
|
|
/* comment with stray handling *\
|
|
|
|
|
/
|
2003-04-13 23:48:52 +04:00
|
|
|
|
/* this is a valid *\/ comment */
|
|
|
|
|
/* this is a valid comment *\*/
|
|
|
|
|
// this is a valid\
|
|
|
|
|
comment
|
2005-06-18 02:06:18 +04:00
|
|
|
|
|
|
|
|
|
/* test function macro substitution when the function name is
|
|
|
|
|
substituted */
|
|
|
|
|
TEST2();
|
2012-04-16 02:21:40 +04:00
|
|
|
|
|
2017-09-25 04:03:26 +03:00
|
|
|
|
/* And again when the name and parentheses are separated by a
|
2012-04-16 02:21:40 +04:00
|
|
|
|
comment. */
|
|
|
|
|
TEST2 /* the comment */ ();
|
2016-07-13 16:37:36 +03:00
|
|
|
|
|
|
|
|
|
printf("%s\n", get_basefile_from_header());
|
|
|
|
|
printf("%s\n", __BASE_FILE__);
|
|
|
|
|
printf("%s\n", get_file_from_header());
|
|
|
|
|
printf("%s\n", __FILE__);
|
2016-08-08 23:26:11 +03:00
|
|
|
|
|
|
|
|
|
/* 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;
|
2002-01-05 20:03:02 +03:00
|
|
|
|
}
|
|
|
|
|
|
2011-02-02 00:23:40 +03:00
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
{
|
2011-07-08 11:55:34 +04:00
|
|
|
|
|
2011-02-02 00:23:40 +03:00
|
|
|
|
#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
|
2015-07-29 23:53:57 +03:00
|
|
|
|
|
2011-02-02 00:23:40 +03:00
|
|
|
|
#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))));
|
|
|
|
|
}
|
|
|
|
|
|
2002-01-05 20:03:02 +03:00
|
|
|
|
int op(a,b)
|
|
|
|
|
{
|
|
|
|
|
return a / b;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int ret(a)
|
|
|
|
|
{
|
|
|
|
|
if (a == 2)
|
|
|
|
|
return 1;
|
|
|
|
|
if (a == 3)
|
|
|
|
|
return 2;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2003-04-27 00:52:38 +04:00
|
|
|
|
void ps(const char *s)
|
2002-01-05 20:03:02 +03:00
|
|
|
|
{
|
|
|
|
|
int c;
|
|
|
|
|
while (1) {
|
|
|
|
|
c = *s;
|
|
|
|
|
if (c == 0)
|
|
|
|
|
break;
|
|
|
|
|
printf("%c", c);
|
|
|
|
|
s++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2003-04-13 23:48:52 +04:00
|
|
|
|
const char foo1_string[] = "\
|
|
|
|
|
bar\n\
|
|
|
|
|
test\14\
|
|
|
|
|
1";
|
|
|
|
|
|
2002-01-05 20:03:02 +03:00
|
|
|
|
void string_test()
|
|
|
|
|
{
|
2008-12-01 20:41:48 +03:00
|
|
|
|
unsigned int b;
|
2002-01-05 20:03:02 +03:00
|
|
|
|
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');
|
2003-04-13 23:48:52 +04:00
|
|
|
|
printf("foo1_string='%s'\n", foo1_string);
|
2002-11-24 18:58:28 +03:00
|
|
|
|
#if 0
|
2002-01-05 20:03:02 +03:00
|
|
|
|
printf("wstring=%S\n", L"abc");
|
|
|
|
|
printf("wstring=%S\n", L"abc" L"def" "ghi");
|
2002-09-09 01:56:11 +04:00
|
|
|
|
printf("'\\377'=%d '\\xff'=%d\n", '\377', '\xff');
|
|
|
|
|
printf("L'\\377'=%d L'\\xff'=%d\n", L'\377', L'\xff');
|
2002-11-24 18:58:28 +03:00
|
|
|
|
#endif
|
2002-07-14 18:39:27 +04:00
|
|
|
|
ps("test\n");
|
2002-01-05 20:03:02 +03:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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");
|
|
|
|
|
|
2011-03-09 02:19:54 +03:00
|
|
|
|
char count = 123;
|
2011-03-07 22:28:31 +03:00
|
|
|
|
/* c99 for loop init test */
|
|
|
|
|
for (size_t count = 1; count < 3; count++)
|
|
|
|
|
printf("count=%d\n", count);
|
2011-03-09 02:19:54 +03:00
|
|
|
|
printf("count = %d\n", count);
|
2011-03-07 22:28:31 +03:00
|
|
|
|
|
2002-01-05 20:03:02 +03:00
|
|
|
|
/* 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");
|
|
|
|
|
}
|
|
|
|
|
|
2012-04-16 00:17:51 +04:00
|
|
|
|
typedef int typedef_and_label;
|
2002-01-05 20:03:02 +03:00
|
|
|
|
|
|
|
|
|
void goto_test()
|
|
|
|
|
{
|
|
|
|
|
int i;
|
2002-11-03 03:44:07 +03:00
|
|
|
|
static void *label_table[3] = { &&label1, &&label2, &&label3 };
|
2002-01-05 20:03:02 +03:00
|
|
|
|
|
|
|
|
|
printf("goto:\n");
|
|
|
|
|
i = 0;
|
2012-04-16 00:17:51 +04:00
|
|
|
|
/* This needs to parse as label, not as start of decl. */
|
2019-04-29 14:53:07 +03:00
|
|
|
|
typedef_and_label x;
|
2012-04-16 00:17:51 +04:00
|
|
|
|
typedef_and_label:
|
2002-01-05 20:03:02 +03:00
|
|
|
|
s_loop:
|
2015-07-29 23:53:57 +03:00
|
|
|
|
if (i >= 10)
|
2002-01-05 20:03:02 +03:00
|
|
|
|
goto s_end;
|
|
|
|
|
printf("%d", i);
|
|
|
|
|
i++;
|
|
|
|
|
goto s_loop;
|
|
|
|
|
s_end:
|
|
|
|
|
printf("\n");
|
2002-11-03 03:44:07 +03:00
|
|
|
|
|
|
|
|
|
/* 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: ;
|
|
|
|
|
}
|
2002-01-05 20:03:02 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
enum {
|
|
|
|
|
E0,
|
|
|
|
|
E1 = 2,
|
|
|
|
|
E2 = 4,
|
|
|
|
|
E3,
|
|
|
|
|
E4,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
enum test {
|
|
|
|
|
E5 = 1000,
|
|
|
|
|
};
|
|
|
|
|
|
2016-08-15 19:54:11 +03:00
|
|
|
|
struct S_enum {
|
|
|
|
|
enum {E6 = 42, E7, E8} e:8;
|
|
|
|
|
};
|
2016-11-06 07:02:11 +03:00
|
|
|
|
|
|
|
|
|
enum ELong {
|
|
|
|
|
/* This is either 0 on L32 machines, or a large number
|
|
|
|
|
on L64 machines. We should be able to store this. */
|
2016-12-15 19:41:16 +03:00
|
|
|
|
EL_large = ((unsigned long)0xf000 << 31) << 1,
|
2016-11-06 07:02:11 +03:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
enum { BIASU = -1U<<31 };
|
|
|
|
|
enum { BIASS = -1 << 31 };
|
|
|
|
|
|
|
|
|
|
static int getint(int i)
|
|
|
|
|
{
|
|
|
|
|
if (i)
|
|
|
|
|
return 0;
|
|
|
|
|
else
|
|
|
|
|
return (int)(-1U << 31);
|
|
|
|
|
}
|
|
|
|
|
|
2002-01-05 20:03:02 +03:00
|
|
|
|
void enum_test()
|
|
|
|
|
{
|
|
|
|
|
enum test b1;
|
2016-08-07 01:09:10 +03:00
|
|
|
|
/* The following should give no warning */
|
2016-08-07 03:15:34 +03:00
|
|
|
|
unsigned *p = &b1;
|
2016-08-15 19:54:11 +03:00
|
|
|
|
struct S_enum s = {E7};
|
|
|
|
|
printf("enum: %d\n", s.e);
|
2002-01-05 20:03:02 +03:00
|
|
|
|
printf("enum:\n%d %d %d %d %d %d\n",
|
|
|
|
|
E0, E1, E2, E3, E4, E5);
|
|
|
|
|
b1 = 1;
|
|
|
|
|
printf("b1=%d\n", b1);
|
2016-11-06 07:02:11 +03:00
|
|
|
|
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");
|
2002-01-05 20:03:02 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
typedef int *my_ptr;
|
|
|
|
|
|
2006-10-28 18:28:33 +04:00
|
|
|
|
typedef int mytype1;
|
|
|
|
|
typedef int mytype2;
|
|
|
|
|
|
2002-01-05 20:03:02 +03:00
|
|
|
|
void typedef_test()
|
|
|
|
|
{
|
|
|
|
|
my_ptr a;
|
2006-10-28 18:28:33 +04:00
|
|
|
|
mytype1 mytype2;
|
2002-01-05 20:03:02 +03:00
|
|
|
|
int b;
|
2006-10-28 18:28:33 +04:00
|
|
|
|
|
2002-01-05 20:03:02 +03:00
|
|
|
|
a = &b;
|
|
|
|
|
*a = 1234;
|
|
|
|
|
printf("typedef:\n");
|
|
|
|
|
printf("a=%d\n", *a);
|
2006-10-28 18:28:33 +04:00
|
|
|
|
mytype2 = 2;
|
|
|
|
|
printf("mytype2=%d\n", mytype2);
|
2002-01-05 20:03:02 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void forward_test()
|
|
|
|
|
{
|
|
|
|
|
printf("forward:\n");
|
|
|
|
|
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;
|
|
|
|
|
|
2016-06-28 16:09:40 +03:00
|
|
|
|
struct empty_mem {
|
|
|
|
|
/* nothing */ ;
|
|
|
|
|
int x;
|
|
|
|
|
};
|
|
|
|
|
|
2002-01-05 20:03:02 +03:00
|
|
|
|
int main(int argc, char **argv)
|
|
|
|
|
{
|
|
|
|
|
string_test();
|
|
|
|
|
expr_test();
|
|
|
|
|
macro_test();
|
2011-02-02 00:23:40 +03:00
|
|
|
|
recursive_macro_test();
|
2002-01-05 20:03:02 +03:00
|
|
|
|
scope_test();
|
2019-03-18 07:53:03 +03:00
|
|
|
|
scope_test2();
|
2002-01-05 20:03:02 +03:00
|
|
|
|
forward_test();
|
|
|
|
|
funcptr_test();
|
|
|
|
|
loop_test();
|
|
|
|
|
switch_test();
|
|
|
|
|
goto_test();
|
|
|
|
|
enum_test();
|
|
|
|
|
typedef_test();
|
|
|
|
|
struct_test();
|
|
|
|
|
array_test();
|
|
|
|
|
expr_ptr_test();
|
|
|
|
|
bool_test();
|
2016-09-19 19:38:12 +03:00
|
|
|
|
optimize_out();
|
2002-01-05 20:03:02 +03:00
|
|
|
|
expr2_test();
|
|
|
|
|
constant_expr_test();
|
|
|
|
|
expr_cmp_test();
|
|
|
|
|
char_short_test();
|
|
|
|
|
init_test();
|
|
|
|
|
compound_literal_test();
|
|
|
|
|
kr_test();
|
|
|
|
|
struct_assign_test();
|
|
|
|
|
cast_test();
|
|
|
|
|
bitfield_test();
|
|
|
|
|
c99_bool_test();
|
|
|
|
|
float_test();
|
|
|
|
|
longlong_test();
|
2008-12-01 21:22:57 +03:00
|
|
|
|
manyarg_test();
|
2002-08-31 16:45:26 +04:00
|
|
|
|
stdarg_test();
|
|
|
|
|
whitespace_test();
|
|
|
|
|
relocation_test();
|
2002-11-02 23:46:36 +03:00
|
|
|
|
old_style_function();
|
2009-05-17 00:30:13 +04:00
|
|
|
|
alloca_test();
|
2011-04-06 20:17:03 +04:00
|
|
|
|
c99_vla_test(5, 2);
|
2002-11-02 23:46:36 +03:00
|
|
|
|
sizeof_test();
|
|
|
|
|
typeof_test();
|
2003-01-06 23:19:20 +03:00
|
|
|
|
statement_expr_test();
|
|
|
|
|
local_label_test();
|
|
|
|
|
asm_test();
|
2003-04-27 15:45:54 +04:00
|
|
|
|
builtin_test();
|
2013-02-05 17:27:38 +04:00
|
|
|
|
#ifndef _WIN32
|
2011-02-01 11:37:53 +03:00
|
|
|
|
weak_test();
|
2013-02-05 17:27:38 +04:00
|
|
|
|
#endif
|
2012-04-15 21:29:45 +04:00
|
|
|
|
global_data_test();
|
2012-04-16 04:52:15 +04:00
|
|
|
|
cmp_comparison_test();
|
2012-05-13 04:21:51 +04:00
|
|
|
|
math_cmp_test();
|
2012-06-10 11:01:13 +04:00
|
|
|
|
callsave_test();
|
Add support for __builtin_frame_address(level)
Continuing d6072d37 (Add __builtin_frame_address(0)) implement
__builtin_frame_address for levels greater than zero, in order for
tinycc to be able to compile its own lib/bcheck.c after
cffb7af9 (lib/bcheck: Prevent __bound_local_new / __bound_local_delete
from being miscompiled).
I'm new to the internals, and used the most simple way to do it.
Generated code is not very good for levels >= 2, compare
gcc tcc
level=0 mov %ebp,%eax lea 0x0(%ebp),%eax
level=1 mov 0x0(%ebp),%eax mov 0x0(%ebp),%eax
level=2 mov 0x0(%ebp),%eax mov 0x0(%ebp),%eax
mov (%eax),%eax mov %eax,-0x10(%ebp)
mov -0x10(%ebp),%eax
mov (%eax),%eax
level=3 mov 0x0(%ebp),%eax mov 0x0(%ebp),%eax
mov (%eax),%eax mov (%eax),%ecx
mov (%eax),%eax mov (%ecx),%eax
But this is still an improvement and for bcheck we need level=1 for
which the code is good.
For the tests I had to force gcc use -O0 to not inline the functions.
And -fno-omit-frame-pointer just in case.
If someone knows how to improve the generated code - help is
appreciated.
Thanks,
Kirill
Cc: Michael Matz <matz@suse.de>
Cc: Shinichiro Hamaji <shinichiro.hamaji@gmail.com>
2012-11-15 03:31:49 +04:00
|
|
|
|
builtin_frame_address_test();
|
Add ARM aeabi functions needed to run tcctest
Add implementation for float / integer conversion functions:
__aeabi_d2lz, __aeabi_d2ulz, __aeabi_f2lz, __aeabi_f2ulz, __aeabi_l2d,
__aeabi_l2f, __aeabi_ul2d, __aeabi_ul2f
Add implementation for long long helper functions:
__aeabi_ldivmod, __aeabi_uldivmod, __aeabi_llsl, __aeabi_llsr, __aeabi_lasr
Add implementation for integer division functions:
__aeabi_uidiv, __aeabi_uidivmod, __aeabi_idiv, __aeabi_idivmod,
2013-04-07 19:02:57 +04:00
|
|
|
|
intdiv_test();
|
2016-03-26 19:57:22 +03:00
|
|
|
|
if (via_volatile (42) != 42)
|
|
|
|
|
printf ("via_volatile broken\n");
|
2016-07-11 19:38:00 +03:00
|
|
|
|
attrib_test();
|
2019-12-10 10:07:25 +03:00
|
|
|
|
bounds_check1_test();
|
2015-07-29 23:53:57 +03:00
|
|
|
|
return 0;
|
2002-01-05 20:03:02 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int tab[3];
|
|
|
|
|
int tab2[3][2];
|
|
|
|
|
|
|
|
|
|
int g;
|
|
|
|
|
|
|
|
|
|
void f1(g)
|
|
|
|
|
{
|
|
|
|
|
printf("g1=%d\n", g);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void scope_test()
|
|
|
|
|
{
|
|
|
|
|
printf("scope:\n");
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-18 07:53:03 +03:00
|
|
|
|
int st2_i;
|
|
|
|
|
int *st2_p = &st2_i;
|
|
|
|
|
void scope_test2()
|
|
|
|
|
{
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-17 19:52:49 +03:00
|
|
|
|
/* 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;
|
|
|
|
|
|
2011-07-12 17:10:59 +04:00
|
|
|
|
void array_test()
|
2002-01-05 20:03:02 +03:00
|
|
|
|
{
|
2011-07-12 17:10:59 +04:00
|
|
|
|
int i, j, a[4];
|
2002-01-05 20:03:02 +03:00
|
|
|
|
|
|
|
|
|
printf("array:\n");
|
|
|
|
|
printf("sizeof(a) = %d\n", sizeof(a));
|
2002-07-27 18:06:23 +04:00
|
|
|
|
printf("sizeof(\"a\") = %d\n", sizeof("a"));
|
2002-08-18 17:18:20 +04:00
|
|
|
|
#ifdef C99_MACROS
|
2002-07-27 18:06:23 +04:00
|
|
|
|
printf("sizeof(__func__) = %d\n", sizeof(__func__));
|
2002-08-18 17:18:20 +04:00
|
|
|
|
#endif
|
2002-01-05 20:03:02 +03:00
|
|
|
|
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");
|
2009-07-18 23:26:19 +04:00
|
|
|
|
printf("sizeof(size_t)=%d\n", sizeof(size_t));
|
|
|
|
|
printf("sizeof(ptrdiff_t)=%d\n", sizeof(ptrdiff_t));
|
2002-01-05 20:03:02 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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);
|
2015-07-29 23:53:57 +03:00
|
|
|
|
printf("%d %d %d %d\n",
|
|
|
|
|
isid('a'),
|
|
|
|
|
isid('g'),
|
|
|
|
|
isid('T'),
|
2002-01-05 20:03:02 +03:00
|
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
printf("expr2:\n");
|
|
|
|
|
vstack_ptr = vstack;
|
|
|
|
|
vpush(1432432, 2);
|
|
|
|
|
vstack_ptr[-2] &= ~0xffffff80;
|
|
|
|
|
vpop(&a, &b);
|
|
|
|
|
printf("res= %d %d\n", a, b);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void constant_expr_test()
|
|
|
|
|
{
|
|
|
|
|
int a;
|
|
|
|
|
printf("constant_expr:\n");
|
|
|
|
|
a = 3;
|
|
|
|
|
printf("%d\n", a * 16);
|
|
|
|
|
printf("%d\n", a * 1);
|
|
|
|
|
printf("%d\n", a + 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int tab4[10];
|
|
|
|
|
|
|
|
|
|
void expr_ptr_test()
|
|
|
|
|
{
|
|
|
|
|
int *p, *q;
|
2008-12-01 21:22:57 +03:00
|
|
|
|
int i = -1;
|
2002-01-05 20:03:02 +03:00
|
|
|
|
|
|
|
|
|
printf("expr_ptr:\n");
|
|
|
|
|
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);
|
2008-12-01 21:22:57 +03:00
|
|
|
|
|
|
|
|
|
/* 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);
|
|
|
|
|
}
|
2016-10-04 02:20:33 +03:00
|
|
|
|
#ifdef __LP64__
|
|
|
|
|
i = 1;
|
|
|
|
|
p = (int*)0x100000000UL + i;
|
|
|
|
|
i = ((long)p) >> 32;
|
|
|
|
|
printf("largeptr: %p %d\n", p, i);
|
|
|
|
|
#endif
|
2002-01-05 20:03:02 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void expr_cmp_test()
|
|
|
|
|
{
|
|
|
|
|
int a, b;
|
|
|
|
|
printf("constant_expr:\n");
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
2002-11-24 18:58:28 +03:00
|
|
|
|
struct empty {
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct aligntest1 {
|
|
|
|
|
char a[10];
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct aligntest2 {
|
|
|
|
|
int a;
|
|
|
|
|
char b[10];
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct aligntest3 {
|
|
|
|
|
double a, b;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct aligntest4 {
|
|
|
|
|
double a[0];
|
|
|
|
|
};
|
|
|
|
|
|
2016-10-09 01:52:57 +03:00
|
|
|
|
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
|
2017-07-09 13:38:59 +03:00
|
|
|
|
a copy of it). -- FIXED */
|
|
|
|
|
struct aligntest7 altest7[2] __attribute__((aligned(16)));
|
2016-10-09 01:52:57 +03:00
|
|
|
|
|
2016-10-09 03:41:34 +03:00
|
|
|
|
struct aligntest8
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
} __attribute__((aligned(4096)));
|
|
|
|
|
|
2016-10-09 01:52:57 +03:00
|
|
|
|
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))));
|
|
|
|
|
|
2016-10-17 21:27:23 +03:00
|
|
|
|
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;
|
|
|
|
|
};
|
|
|
|
|
|
2002-01-05 20:03:02 +03:00
|
|
|
|
void struct_test()
|
|
|
|
|
{
|
|
|
|
|
struct1 *s;
|
|
|
|
|
union union2 u;
|
2016-10-09 01:52:57 +03:00
|
|
|
|
struct Large ls;
|
2002-01-05 20:03:02 +03:00
|
|
|
|
|
|
|
|
|
printf("struct:\n");
|
|
|
|
|
printf("sizes: %d %d %d %d\n",
|
|
|
|
|
sizeof(struct struct1),
|
|
|
|
|
sizeof(struct struct2),
|
|
|
|
|
sizeof(union union1),
|
|
|
|
|
sizeof(union union2));
|
2016-10-09 01:52:57 +03:00
|
|
|
|
printf("offsets: %d\n", (int)((char*)&st1.u.v1 - (char*)&st1));
|
2002-01-05 20:03:02 +03:00
|
|
|
|
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)st1.str - (int)&st1.f1);
|
2002-11-24 18:58:28 +03:00
|
|
|
|
|
|
|
|
|
/* 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));
|
2016-10-09 01:52:57 +03:00
|
|
|
|
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));
|
2016-10-09 03:41:34 +03:00
|
|
|
|
printf("aligntest8 sizeof=%d alignof=%d\n",
|
|
|
|
|
sizeof(struct aligntest8), __alignof__(struct aligntest8));
|
2016-10-17 21:27:23 +03:00
|
|
|
|
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));
|
2016-10-09 01:52:57 +03:00
|
|
|
|
printf("altest5 sizeof=%d alignof=%d\n",
|
|
|
|
|
sizeof(altest5), __alignof__(altest5));
|
|
|
|
|
printf("altest6 sizeof=%d alignof=%d\n",
|
|
|
|
|
sizeof(altest6), __alignof__(altest6));
|
2017-07-09 13:38:59 +03:00
|
|
|
|
printf("altest7 sizeof=%d alignof=%d\n",
|
|
|
|
|
sizeof(altest7), __alignof__(altest7));
|
2015-07-29 23:53:57 +03:00
|
|
|
|
|
2002-11-24 18:58:28 +03:00
|
|
|
|
/* empty structures (GCC extension) */
|
|
|
|
|
printf("sizeof(struct empty) = %d\n", sizeof(struct empty));
|
|
|
|
|
printf("alignof(struct empty) = %d\n", __alignof__(struct empty));
|
2016-10-09 01:52:57 +03:00
|
|
|
|
|
|
|
|
|
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));
|
2002-01-05 20:03:02 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* XXX: depend on endianness */
|
|
|
|
|
void char_short_test()
|
|
|
|
|
{
|
|
|
|
|
int var1, var2;
|
|
|
|
|
|
|
|
|
|
printf("char_short:\n");
|
|
|
|
|
|
|
|
|
|
var1 = 0x01020304;
|
|
|
|
|
var2 = 0xfffefdfc;
|
2015-07-29 23:53:57 +03:00
|
|
|
|
printf("s8=%d %d\n",
|
2002-01-05 20:03:02 +03:00
|
|
|
|
*(char *)&var1, *(char *)&var2);
|
2015-07-29 23:53:57 +03:00
|
|
|
|
printf("u8=%d %d\n",
|
2002-01-05 20:03:02 +03:00
|
|
|
|
*(unsigned char *)&var1, *(unsigned char *)&var2);
|
2015-07-29 23:53:57 +03:00
|
|
|
|
printf("s16=%d %d\n",
|
2002-01-05 20:03:02 +03:00
|
|
|
|
*(short *)&var1, *(short *)&var2);
|
2015-07-29 23:53:57 +03:00
|
|
|
|
printf("u16=%d %d\n",
|
2002-01-05 20:03:02 +03:00
|
|
|
|
*(unsigned short *)&var1, *(unsigned short *)&var2);
|
2015-07-29 23:53:57 +03:00
|
|
|
|
printf("s32=%d %d\n",
|
2002-01-05 20:03:02 +03:00
|
|
|
|
*(int *)&var1, *(int *)&var2);
|
2015-07-29 23:53:57 +03:00
|
|
|
|
printf("u32=%d %d\n",
|
2002-01-05 20:03:02 +03:00
|
|
|
|
*(unsigned int *)&var1, *(unsigned int *)&var2);
|
|
|
|
|
*(char *)&var1 = 0x08;
|
|
|
|
|
printf("var1=%x\n", var1);
|
|
|
|
|
*(short *)&var1 = 0x0809;
|
|
|
|
|
printf("var1=%x\n", var1);
|
|
|
|
|
*(int *)&var1 = 0x08090a0b;
|
|
|
|
|
printf("var1=%x\n", var1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/******************/
|
|
|
|
|
|
|
|
|
|
typedef struct Sym {
|
|
|
|
|
int v;
|
|
|
|
|
int t;
|
|
|
|
|
int c;
|
|
|
|
|
struct Sym *next;
|
|
|
|
|
struct Sym *prev;
|
|
|
|
|
} Sym;
|
|
|
|
|
|
2002-11-24 18:58:28 +03:00
|
|
|
|
#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
|
|
|
|
|
#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
|
|
|
|
|
|
|
|
|
|
static int toupper1(int a)
|
|
|
|
|
{
|
|
|
|
|
return TOUPPER(a);
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-04 00:23:13 +03:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2002-01-05 20:03:02 +03:00
|
|
|
|
void bool_test()
|
|
|
|
|
{
|
2002-11-24 18:58:28 +03:00
|
|
|
|
int *s, a, b, t, f, i;
|
2002-01-05 20:03:02 +03:00
|
|
|
|
|
|
|
|
|
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));
|
2002-07-13 21:24:30 +04:00
|
|
|
|
|
|
|
|
|
/* test register spilling */
|
|
|
|
|
a = 10;
|
|
|
|
|
b = 10;
|
|
|
|
|
a = (a + b) * ((a < b) ?
|
|
|
|
|
((b - a) * (a - b)): a + b);
|
|
|
|
|
printf("a=%d\n", a);
|
2002-09-09 01:56:11 +04:00
|
|
|
|
|
|
|
|
|
/* 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));
|
|
|
|
|
|
|
|
|
|
/* 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);
|
|
|
|
|
}
|
|
|
|
|
}
|
2002-11-24 18:58:28 +03:00
|
|
|
|
|
2003-01-06 23:19:20 +03:00
|
|
|
|
/* test ? : GCC extension */
|
|
|
|
|
{
|
|
|
|
|
static int v1 = 34 ? : -1; /* constant case */
|
|
|
|
|
static int v2 = 0 ? : -1; /* constant case */
|
|
|
|
|
int a = 30;
|
2015-07-29 23:53:57 +03:00
|
|
|
|
|
2003-01-06 23:19:20 +03:00
|
|
|
|
printf("%d %d\n", v1, v2);
|
|
|
|
|
printf("%d %d\n", a - 30 ? : a * 2, a + 1 ? : a * 2);
|
|
|
|
|
}
|
|
|
|
|
|
2002-11-24 18:58:28 +03:00
|
|
|
|
/* again complex expression */
|
|
|
|
|
for(i=0;i<256;i++) {
|
|
|
|
|
if (toupper1 (i) != TOUPPER (i))
|
|
|
|
|
printf("error %d\n", i);
|
|
|
|
|
}
|
2016-09-04 00:23:13 +03:00
|
|
|
|
printf ("bits = 0x%x\n", calc_vm_flags (0x1));
|
2002-01-05 20:03:02 +03:00
|
|
|
|
}
|
|
|
|
|
|
2016-09-19 19:38:12 +03:00
|
|
|
|
extern int undefined_function(void);
|
|
|
|
|
extern int defined_function(void);
|
|
|
|
|
|
2016-09-26 23:31:19 +03:00
|
|
|
|
static inline void refer_to_undefined(void)
|
|
|
|
|
{
|
|
|
|
|
undefined_function();
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-19 19:38:12 +03:00
|
|
|
|
void optimize_out(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());
|
2016-09-26 21:31:24 +03:00
|
|
|
|
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;
|
|
|
|
|
}
|
2019-01-31 02:37:49 +03:00
|
|
|
|
j = 1;
|
|
|
|
|
while (j) {
|
|
|
|
|
j--;
|
|
|
|
|
continue;
|
|
|
|
|
printf("ool7:%d\n", undefined_function());
|
|
|
|
|
}
|
2016-09-26 22:21:42 +03:00
|
|
|
|
|
|
|
|
|
/* 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();
|
|
|
|
|
|
2016-09-26 23:31:19 +03:00
|
|
|
|
if (defined_function() && 0)
|
|
|
|
|
refer_to_undefined();
|
|
|
|
|
|
2016-12-20 06:49:22 +03:00
|
|
|
|
if (0) {
|
|
|
|
|
(void)sizeof( ({
|
|
|
|
|
do { } while (0);
|
|
|
|
|
0;
|
|
|
|
|
}) );
|
|
|
|
|
undefined_function();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Leave the "if(1)return; printf()" in this order and last in the function */
|
2016-09-26 21:31:24 +03:00
|
|
|
|
if (1)
|
|
|
|
|
return;
|
|
|
|
|
printf ("oor:%d\n", undefined_function());
|
2016-09-19 19:38:12 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int defined_function(void)
|
|
|
|
|
{
|
|
|
|
|
static int i = 40;
|
|
|
|
|
return i++;
|
|
|
|
|
}
|
|
|
|
|
|
2003-01-06 23:19:20 +03:00
|
|
|
|
/* GCC accepts that */
|
|
|
|
|
static int tab_reinit[];
|
|
|
|
|
static int tab_reinit[10];
|
2002-01-05 20:03:02 +03:00
|
|
|
|
|
2019-06-17 04:34:03 +03:00
|
|
|
|
static int tentative_ar[];
|
|
|
|
|
static int tentative_ar[] = {1,2,3};
|
|
|
|
|
|
2003-01-06 23:19:20 +03:00
|
|
|
|
//int cinit1; /* a global variable can be defined several times without error ! */
|
2015-07-29 23:53:57 +03:00
|
|
|
|
int cinit1;
|
|
|
|
|
int cinit1;
|
2002-01-05 20:03:02 +03:00
|
|
|
|
int cinit1 = 0;
|
|
|
|
|
int *cinit2 = (int []){3, 2, 1};
|
|
|
|
|
|
|
|
|
|
void compound_literal_test(void)
|
|
|
|
|
{
|
|
|
|
|
int *p, i;
|
|
|
|
|
char *q, *q3;
|
|
|
|
|
|
|
|
|
|
printf("compound_test:\n");
|
|
|
|
|
|
|
|
|
|
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};
|
2015-07-29 23:53:57 +03:00
|
|
|
|
printf("%d %d %d\n",
|
2002-01-05 20:03:02 +03:00
|
|
|
|
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("kr_test:\n");
|
|
|
|
|
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;
|
2015-07-29 23:53:57 +03:00
|
|
|
|
tab = (char*)malloc(20);
|
2002-01-05 20:03:02 +03:00
|
|
|
|
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");
|
2011-02-02 03:05:57 +03:00
|
|
|
|
free(tab);
|
2002-01-05 20:03:02 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* structure assignment tests */
|
|
|
|
|
struct structa1 {
|
|
|
|
|
int f1;
|
|
|
|
|
char f2;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct structa1 ssta1;
|
|
|
|
|
|
2010-08-26 20:28:52 +04:00
|
|
|
|
void struct_assign_test1(struct structa1 s1, int t, float f)
|
2002-01-05 20:03:02 +03:00
|
|
|
|
{
|
2010-08-26 20:28:52 +04:00
|
|
|
|
printf("%d %d %d %f\n", s1.f1, s1.f2, t, f);
|
2002-01-05 20:03:02 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct structa1 struct_assign_test2(struct structa1 s1, int t)
|
|
|
|
|
{
|
|
|
|
|
s1.f1 += t;
|
|
|
|
|
s1.f2 -= t;
|
|
|
|
|
return s1;
|
|
|
|
|
}
|
|
|
|
|
|
2002-07-13 21:24:30 +04:00
|
|
|
|
void struct_assign_test(void)
|
2002-01-05 20:03:02 +03:00
|
|
|
|
{
|
2012-04-15 07:12:43 +04:00
|
|
|
|
struct S {
|
|
|
|
|
struct structa1 lsta1, lsta2;
|
|
|
|
|
int i;
|
|
|
|
|
} s, *ps;
|
2015-07-29 23:53:57 +03:00
|
|
|
|
|
2012-04-15 07:12:43 +04:00
|
|
|
|
ps = &s;
|
|
|
|
|
ps->i = 4;
|
2002-07-13 21:24:30 +04:00
|
|
|
|
#if 0
|
2002-01-05 20:03:02 +03:00
|
|
|
|
printf("struct_assign_test:\n");
|
|
|
|
|
|
2012-04-15 07:12:43 +04:00
|
|
|
|
s.lsta1.f1 = 1;
|
|
|
|
|
s.lsta1.f2 = 2;
|
|
|
|
|
printf("%d %d\n", s.lsta1.f1, s.lsta1.f2);
|
|
|
|
|
s.lsta2 = s.lsta1;
|
|
|
|
|
printf("%d %d\n", s.lsta2.f1, s.lsta2.f2);
|
2002-07-13 21:24:30 +04:00
|
|
|
|
#else
|
2012-04-15 07:12:43 +04:00
|
|
|
|
s.lsta2.f1 = 1;
|
|
|
|
|
s.lsta2.f2 = 2;
|
2002-07-13 21:24:30 +04:00
|
|
|
|
#endif
|
2012-04-15 07:12:43 +04:00
|
|
|
|
struct_assign_test1(ps->lsta2, 3, 4.5);
|
2015-07-29 23:53:57 +03:00
|
|
|
|
|
2012-04-15 07:12:43 +04:00
|
|
|
|
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);
|
2010-08-31 03:35:31 +04:00
|
|
|
|
|
|
|
|
|
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);
|
2002-01-05 20:03:02 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 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;
|
2002-07-13 21:24:30 +04:00
|
|
|
|
char c;
|
|
|
|
|
char tab[10];
|
2006-10-28 18:47:14 +04:00
|
|
|
|
unsigned b,d;
|
|
|
|
|
short s;
|
2009-04-15 20:32:16 +04:00
|
|
|
|
char *p = NULL;
|
2019-07-22 07:45:03 +03:00
|
|
|
|
unsigned long ul = 0x80000000UL;
|
2009-04-15 20:32:16 +04:00
|
|
|
|
p -= 0x700000000042;
|
2002-01-05 20:03:02 +03:00
|
|
|
|
|
|
|
|
|
printf("cast_test:\n");
|
|
|
|
|
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);
|
2015-07-29 23:53:57 +03:00
|
|
|
|
|
2002-07-13 21:24:30 +04:00
|
|
|
|
printf("sizeof(c) = %d, sizeof((int)c) = %d\n", sizeof(c), sizeof((int)c));
|
2015-07-29 23:53:57 +03:00
|
|
|
|
|
2006-10-28 18:47:14 +04:00
|
|
|
|
/* 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);
|
2015-07-29 23:53:57 +03:00
|
|
|
|
|
2002-07-13 21:24:30 +04:00
|
|
|
|
/* test implicit int casting for array accesses */
|
|
|
|
|
c = 0;
|
|
|
|
|
tab[1] = 2;
|
|
|
|
|
tab[c] = 1;
|
|
|
|
|
printf("%d %d\n", tab[0], tab[1]);
|
2002-07-27 18:06:23 +04:00
|
|
|
|
|
|
|
|
|
/* 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'));
|
2009-04-15 20:32:16 +04:00
|
|
|
|
|
|
|
|
|
/* from pointer to integer types */
|
2009-04-15 21:34:59 +04:00
|
|
|
|
printf("%d %d %ld %ld %lld %lld\n",
|
2009-04-15 20:32:16 +04:00
|
|
|
|
(int)p, (unsigned int)p,
|
|
|
|
|
(long)p, (unsigned long)p,
|
|
|
|
|
(long long)p, (unsigned long long)p);
|
2009-04-16 20:01:23 +04:00
|
|
|
|
|
|
|
|
|
/* from integers to pointers */
|
|
|
|
|
printf("%p %p %p %p\n",
|
|
|
|
|
(void *)a, (void *)b, (void *)c, (void *)d);
|
2019-07-22 07:45:03 +03:00
|
|
|
|
|
|
|
|
|
/* int to int with sign set */
|
|
|
|
|
printf("0x%lx\n", (unsigned long)(int)ul);
|
2002-01-05 20:03:02 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 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 };
|
2015-07-29 23:53:57 +03:00
|
|
|
|
struct structinit1 sinit11 = { .f2 = 2, 3, .f1 = 1,
|
2002-01-05 20:03:02 +03:00
|
|
|
|
#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" };
|
2002-07-13 21:24:30 +04:00
|
|
|
|
int sinit15[3] = { sizeof(sinit15), 1, 2 };
|
2002-01-05 20:03:02 +03:00
|
|
|
|
|
2002-11-24 18:58:28 +03:00
|
|
|
|
struct { int a[3], b; } sinit16[] = { { 1 }, 2 };
|
|
|
|
|
|
|
|
|
|
struct bar {
|
|
|
|
|
char *s;
|
|
|
|
|
int len;
|
|
|
|
|
} sinit17[] = {
|
|
|
|
|
"a1", 4,
|
|
|
|
|
"a2", 1
|
|
|
|
|
};
|
|
|
|
|
|
2003-01-06 23:19:20 +03:00
|
|
|
|
int sinit18[10] = {
|
|
|
|
|
[2 ... 5] = 20,
|
|
|
|
|
2,
|
|
|
|
|
[8] = 10,
|
|
|
|
|
};
|
|
|
|
|
|
2011-02-22 13:26:45 +03:00
|
|
|
|
struct complexinit0 {
|
|
|
|
|
int a;
|
|
|
|
|
int b;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct complexinit {
|
|
|
|
|
int a;
|
2011-02-22 15:55:21 +03:00
|
|
|
|
const struct complexinit0 *b;
|
2011-02-22 13:26:45 +03:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const static struct complexinit cix[] = {
|
|
|
|
|
[0] = {
|
|
|
|
|
.a = 2000,
|
|
|
|
|
.b = (const struct complexinit0[]) {
|
|
|
|
|
{ 2001, 2002 },
|
|
|
|
|
{ 2003, 2003 },
|
|
|
|
|
{}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct complexinit2 {
|
|
|
|
|
int a;
|
|
|
|
|
int b[];
|
|
|
|
|
};
|
|
|
|
|
|
2011-07-11 11:18:36 +04:00
|
|
|
|
struct complexinit2 cix20;
|
|
|
|
|
|
2011-02-22 13:26:45 +03:00
|
|
|
|
struct complexinit2 cix21 = {
|
|
|
|
|
.a = 3000,
|
|
|
|
|
.b = { 3001, 3002, 3003 }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct complexinit2 cix22 = {
|
|
|
|
|
.a = 4000,
|
|
|
|
|
.b = { 4001, 4002, 4003, 4004, 4005, 4006 }
|
|
|
|
|
};
|
|
|
|
|
|
2016-07-13 18:39:15 +03:00
|
|
|
|
typedef int arrtype1[];
|
|
|
|
|
arrtype1 sinit19 = {1};
|
|
|
|
|
arrtype1 sinit20 = {2,3};
|
|
|
|
|
typedef int arrtype2[3];
|
|
|
|
|
arrtype2 sinit21 = {4};
|
|
|
|
|
arrtype2 sinit22 = {5,6,7};
|
|
|
|
|
|
2016-08-15 06:19:12 +03:00
|
|
|
|
/* Address comparisons of non-weak symbols with zero can be const-folded */
|
|
|
|
|
int sinit23[2] = { "astring" ? sizeof("astring") : -1,
|
|
|
|
|
&sinit23 ? 42 : -1 };
|
|
|
|
|
|
2017-05-07 09:10:06 +03:00
|
|
|
|
extern int external_inited = 42;
|
|
|
|
|
|
2002-01-05 20:03:02 +03:00
|
|
|
|
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 };
|
2002-07-13 21:24:30 +04:00
|
|
|
|
int linit17 = sizeof(linit17);
|
2016-08-15 06:19:12 +03:00
|
|
|
|
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 };
|
2015-07-29 23:53:57 +03:00
|
|
|
|
|
2002-01-05 20:03:02 +03:00
|
|
|
|
printf("init_test:\n");
|
|
|
|
|
|
|
|
|
|
printf("sinit1=%d\n", sinit1);
|
|
|
|
|
printf("sinit2=%d\n", sinit2);
|
2015-07-29 23:53:57 +03:00
|
|
|
|
printf("sinit3=%d %d %d %d\n",
|
2002-01-05 20:03:02 +03:00
|
|
|
|
sizeof(sinit3),
|
|
|
|
|
sinit3[0],
|
|
|
|
|
sinit3[1],
|
|
|
|
|
sinit3[2]
|
|
|
|
|
);
|
|
|
|
|
printf("sinit6=%d\n", sizeof(sinit6));
|
2015-07-29 23:53:57 +03:00
|
|
|
|
printf("sinit7=%d %d %d %d\n",
|
2002-01-05 20:03:02 +03:00
|
|
|
|
sizeof(sinit7),
|
|
|
|
|
sinit7[0],
|
|
|
|
|
sinit7[1],
|
|
|
|
|
sinit7[2]
|
|
|
|
|
);
|
|
|
|
|
printf("sinit8=%s\n", sinit8);
|
2015-07-29 23:53:57 +03:00
|
|
|
|
printf("sinit9=%d %d %d\n",
|
2002-01-05 20:03:02 +03:00
|
|
|
|
sinit9.f1,
|
|
|
|
|
sinit9.f2,
|
|
|
|
|
sinit9.f3
|
|
|
|
|
);
|
2015-07-29 23:53:57 +03:00
|
|
|
|
printf("sinit10=%d %d %d\n",
|
2002-01-05 20:03:02 +03:00
|
|
|
|
sinit10.f1,
|
|
|
|
|
sinit10.f2,
|
|
|
|
|
sinit10.f3
|
|
|
|
|
);
|
2015-07-29 23:53:57 +03:00
|
|
|
|
printf("sinit11=%d %d %d %d %d %d\n",
|
2002-01-05 20:03:02 +03:00
|
|
|
|
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++)
|
2015-07-29 23:53:57 +03:00
|
|
|
|
printf("[%d][%d] = %d %d %d\n",
|
2002-01-05 20:03:02 +03:00
|
|
|
|
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",
|
2015-07-29 23:53:57 +03:00
|
|
|
|
sizeof(sinit13),
|
2002-01-05 20:03:02 +03:00
|
|
|
|
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");
|
2015-07-29 23:53:57 +03:00
|
|
|
|
printf("%d %d %d %d\n",
|
2002-01-05 20:03:02 +03:00
|
|
|
|
linit16.a1,
|
|
|
|
|
linit16.a2,
|
|
|
|
|
linit16.a3,
|
|
|
|
|
linit16.a4);
|
2002-07-13 21:24:30 +04:00
|
|
|
|
/* test that initialisation is done after variable declare */
|
|
|
|
|
printf("linit17=%d\n", linit17);
|
|
|
|
|
printf("sinit15=%d\n", sinit15[0]);
|
2002-11-24 18:58:28 +03:00
|
|
|
|
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);
|
2003-01-06 23:19:20 +03:00
|
|
|
|
for(i=0;i<10;i++)
|
|
|
|
|
printf("%x ", sinit18[i]);
|
|
|
|
|
printf("\n");
|
2011-02-22 13:26:45 +03:00
|
|
|
|
/* 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]);
|
2011-07-11 11:18:36 +04:00
|
|
|
|
printf("sizeof cix20 %d, cix21 %d, sizeof cix22 %d\n", sizeof cix20, sizeof cix21, sizeof cix22);
|
2016-07-13 18:39:15 +03:00
|
|
|
|
|
|
|
|
|
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));
|
2016-08-15 06:19:12 +03:00
|
|
|
|
|
|
|
|
|
printf("sinit23= %d %d\n", sinit23[0], sinit23[1]);
|
|
|
|
|
printf("linit18= %d %d\n", linit18[0], linit18[1]);
|
2002-01-05 20:03:02 +03:00
|
|
|
|
}
|
|
|
|
|
|
2016-11-06 07:02:11 +03:00
|
|
|
|
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");
|
|
|
|
|
}
|
|
|
|
|
}
|
2003-01-06 23:19:20 +03:00
|
|
|
|
|
2002-01-05 20:03:02 +03:00
|
|
|
|
void switch_test()
|
|
|
|
|
{
|
|
|
|
|
int i;
|
2016-11-06 07:02:11 +03:00
|
|
|
|
unsigned long long ull;
|
|
|
|
|
long long ll;
|
2002-01-05 20:03:02 +03:00
|
|
|
|
|
|
|
|
|
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;
|
2016-10-03 10:40:37 +03:00
|
|
|
|
case 0xc33c6b9fU:
|
|
|
|
|
case 0x7c9eeeb9U:
|
|
|
|
|
break;
|
2002-01-05 20:03:02 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
printf("\n");
|
2016-11-06 07:02:11 +03:00
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
}
|
2002-01-05 20:03:02 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ISOC99 _Bool type */
|
|
|
|
|
void c99_bool_test(void)
|
|
|
|
|
{
|
|
|
|
|
#ifdef BOOL_ISOC99
|
|
|
|
|
int a;
|
|
|
|
|
_Bool b;
|
|
|
|
|
|
|
|
|
|
printf("bool_test:\n");
|
|
|
|
|
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);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void bitfield_test(void)
|
|
|
|
|
{
|
|
|
|
|
int a;
|
2012-04-15 03:06:46 +04:00
|
|
|
|
short sa;
|
|
|
|
|
unsigned char ca;
|
2002-01-05 20:03:02 +03:00
|
|
|
|
struct sbf1 {
|
|
|
|
|
int f1 : 3;
|
|
|
|
|
int : 2;
|
|
|
|
|
int f2 : 1;
|
|
|
|
|
int : 0;
|
|
|
|
|
int f3 : 5;
|
|
|
|
|
int f4 : 7;
|
|
|
|
|
unsigned int f5 : 7;
|
|
|
|
|
} st1;
|
|
|
|
|
printf("bitfield_test:");
|
|
|
|
|
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);
|
2012-04-15 03:06:46 +04:00
|
|
|
|
sa = st1.f5;
|
|
|
|
|
ca = st1.f5;
|
|
|
|
|
printf("%d %d\n", sa, ca);
|
2004-10-18 04:20:41 +04:00
|
|
|
|
|
|
|
|
|
st1.f1 = 7;
|
2015-07-29 23:53:57 +03:00
|
|
|
|
if (st1.f1 == -1)
|
2004-10-18 04:20:41 +04:00
|
|
|
|
printf("st1.f1 == -1\n");
|
2015-07-29 23:53:57 +03:00
|
|
|
|
else
|
2004-10-18 04:20:41 +04:00
|
|
|
|
printf("st1.f1 != -1\n");
|
2015-07-29 23:53:57 +03:00
|
|
|
|
if (st1.f2 == -1)
|
2004-10-18 04:20:41 +04:00
|
|
|
|
printf("st1.f2 == -1\n");
|
2015-07-29 23:53:57 +03:00
|
|
|
|
else
|
2004-10-18 04:20:41 +04:00
|
|
|
|
printf("st1.f2 != -1\n");
|
2009-03-15 20:24:45 +03:00
|
|
|
|
|
|
|
|
|
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);
|
2017-05-07 13:41:29 +03:00
|
|
|
|
|
2016-12-15 19:41:16 +03:00
|
|
|
|
#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
|
2017-05-07 13:41:29 +03:00
|
|
|
|
|
2017-04-29 22:23:43 +03:00
|
|
|
|
struct sbf4 {
|
|
|
|
|
int x : 31;
|
|
|
|
|
char y : 2;
|
|
|
|
|
} st4;
|
|
|
|
|
st4.y = 1;
|
|
|
|
|
printf("st4.y == %d\n", st4.y);
|
2017-04-29 23:09:10 +03:00
|
|
|
|
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);
|
2017-05-01 07:18:48 +03:00
|
|
|
|
struct sbf6 {
|
|
|
|
|
short x : 12;
|
|
|
|
|
unsigned char y : 2;
|
|
|
|
|
} st6;
|
|
|
|
|
st6.y = 1;
|
|
|
|
|
printf("st6.y == %d\n", st6.y);
|
2002-01-05 20:03:02 +03:00
|
|
|
|
}
|
|
|
|
|
|
2008-12-01 21:22:57 +03:00
|
|
|
|
#ifdef __x86_64__
|
|
|
|
|
#define FLOAT_FMT "%f\n"
|
|
|
|
|
#else
|
|
|
|
|
/* x86's float isn't compatible with GCC */
|
|
|
|
|
#define FLOAT_FMT "%.5f\n"
|
|
|
|
|
#endif
|
|
|
|
|
|
2009-04-13 20:12:29 +04:00
|
|
|
|
/* declare strto* functions as they are C99 */
|
|
|
|
|
double strtod(const char *nptr, char **endptr);
|
2013-04-17 23:32:07 +04:00
|
|
|
|
|
|
|
|
|
#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
|
2009-04-13 20:12:29 +04:00
|
|
|
|
float strtof(const char *nptr, char **endptr);
|
2013-04-17 23:32:07 +04:00
|
|
|
|
LONG_DOUBLE strtold(const char *nptr, char **endptr);
|
|
|
|
|
#endif
|
2009-04-13 20:12:29 +04:00
|
|
|
|
|
2013-04-17 23:32:07 +04:00
|
|
|
|
#define FTEST(prefix, typename, type, fmt)\
|
2002-01-05 20:03:02 +03:00
|
|
|
|
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);\
|
2009-04-12 23:02:52 +04:00
|
|
|
|
b = 0;\
|
|
|
|
|
printf("%d %d\n", !a, !b);\
|
2002-01-05 20:03:02 +03:00
|
|
|
|
}\
|
|
|
|
|
void prefix ## fcast(type a)\
|
|
|
|
|
{\
|
|
|
|
|
float fa;\
|
|
|
|
|
double da;\
|
2013-04-17 23:32:07 +04:00
|
|
|
|
LONG_DOUBLE la;\
|
2002-01-05 20:03:02 +03:00
|
|
|
|
int ia;\
|
2014-02-05 11:26:46 +04:00
|
|
|
|
long long llia;\
|
2002-01-05 20:03:02 +03:00
|
|
|
|
unsigned int ua;\
|
2014-02-01 11:26:48 +04:00
|
|
|
|
unsigned long long llua;\
|
2002-01-05 20:03:02 +03:00
|
|
|
|
type b;\
|
|
|
|
|
fa = a;\
|
|
|
|
|
da = a;\
|
|
|
|
|
la = a;\
|
|
|
|
|
printf("ftof: %f %f %Lf\n", fa, da, la);\
|
|
|
|
|
ia = (int)a;\
|
2014-02-05 11:26:46 +04:00
|
|
|
|
llia = (long long)a;\
|
|
|
|
|
a = (a >= 0) ? a : -a;\
|
2002-01-05 20:03:02 +03:00
|
|
|
|
ua = (unsigned int)a;\
|
2014-02-01 11:26:48 +04:00
|
|
|
|
llua = (unsigned long long)a;\
|
2014-02-05 11:26:46 +04:00
|
|
|
|
printf("ftoi: %d %u %lld %llu\n", ia, ua, llia, llua);\
|
2002-01-05 20:03:02 +03:00
|
|
|
|
ia = -1234;\
|
|
|
|
|
ua = 0x81234500;\
|
2014-02-05 11:26:46 +04:00
|
|
|
|
llia = -0x123456789012345LL;\
|
|
|
|
|
llua = 0xf123456789012345LLU;\
|
2002-01-05 20:03:02 +03:00
|
|
|
|
b = ia;\
|
|
|
|
|
printf("itof: " fmt "\n", b);\
|
|
|
|
|
b = ua;\
|
|
|
|
|
printf("utof: " fmt "\n", b);\
|
2014-02-05 11:26:46 +04:00
|
|
|
|
b = llia;\
|
|
|
|
|
printf("lltof: " fmt "\n", b);\
|
2014-02-01 11:26:48 +04:00
|
|
|
|
b = llua;\
|
|
|
|
|
printf("ulltof: " fmt "\n", b);\
|
2002-01-05 20:03:02 +03:00
|
|
|
|
}\
|
|
|
|
|
\
|
2008-12-01 21:22:57 +03:00
|
|
|
|
float prefix ## retf(type a) { return a; }\
|
|
|
|
|
double prefix ## retd(type a) { return a; }\
|
2013-04-17 23:32:07 +04:00
|
|
|
|
LONG_DOUBLE prefix ## retld(type a) { return a; }\
|
2008-12-01 21:22:57 +03:00
|
|
|
|
\
|
|
|
|
|
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));\
|
2009-04-13 20:12:29 +04:00
|
|
|
|
printf("strto%s: %f\n", #prefix, (double)strto ## prefix("1.2", NULL));\
|
2008-12-01 21:22:57 +03:00
|
|
|
|
}\
|
|
|
|
|
\
|
2014-01-12 07:44:27 +04:00
|
|
|
|
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");\
|
2014-01-12 07:53:29 +04:00
|
|
|
|
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");\
|
2014-01-12 07:44:27 +04:00
|
|
|
|
}\
|
2002-01-05 20:03:02 +03:00
|
|
|
|
void prefix ## test(void)\
|
|
|
|
|
{\
|
2013-04-17 23:32:07 +04:00
|
|
|
|
printf("testing '%s'\n", #typename);\
|
2002-01-05 20:03:02 +03:00
|
|
|
|
prefix ## cmp(1, 2.5);\
|
|
|
|
|
prefix ## cmp(2, 1.5);\
|
|
|
|
|
prefix ## cmp(1, 1);\
|
|
|
|
|
prefix ## fcast(234.6);\
|
|
|
|
|
prefix ## fcast(-2334.6);\
|
2008-12-01 21:22:57 +03:00
|
|
|
|
prefix ## call();\
|
2014-01-12 07:44:27 +04:00
|
|
|
|
prefix ## signed_zeros();\
|
2002-01-05 20:03:02 +03:00
|
|
|
|
}
|
|
|
|
|
|
2013-04-17 23:32:07 +04:00
|
|
|
|
FTEST(f, float, float, "%f")
|
|
|
|
|
FTEST(d, double, double, "%f")
|
|
|
|
|
FTEST(ld, long double, LONG_DOUBLE, "%Lf")
|
2002-01-05 20:03:02 +03:00
|
|
|
|
|
2002-03-17 14:41:27 +03:00
|
|
|
|
double ftab1[3] = { 1.2, 3.4, -5.6 };
|
2002-01-05 20:03:02 +03:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void float_test(void)
|
|
|
|
|
{
|
2015-03-03 17:28:13 +03:00
|
|
|
|
#if !defined(__arm__) || defined(__ARM_PCS_VFP)
|
2002-01-05 20:03:02 +03:00
|
|
|
|
float fa, fb;
|
|
|
|
|
double da, db;
|
|
|
|
|
int a;
|
|
|
|
|
unsigned int b;
|
2017-12-25 14:44:29 +03:00
|
|
|
|
static double nan2 = 0.0/0.0;
|
|
|
|
|
static double inf1 = 1.0/0.0;
|
|
|
|
|
static double inf2 = 1e5000;
|
2002-01-05 20:03:02 +03:00
|
|
|
|
|
|
|
|
|
printf("float_test:\n");
|
|
|
|
|
printf("sizeof(float) = %d\n", sizeof(float));
|
|
|
|
|
printf("sizeof(double) = %d\n", sizeof(double));
|
2013-04-17 23:32:07 +04:00
|
|
|
|
printf("sizeof(long double) = %d\n", sizeof(LONG_DOUBLE));
|
2002-01-05 20:03:02 +03:00
|
|
|
|
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);
|
2017-12-25 14:44:29 +03:00
|
|
|
|
printf("nan != nan = %d, inf1 = %f, inf2 = %f\n", nan2 != nan2, inf1, inf2);
|
2015-03-03 17:28:13 +03:00
|
|
|
|
#endif
|
2002-01-05 20:03:02 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int fib(int n)
|
|
|
|
|
{
|
|
|
|
|
if (n <= 2)
|
|
|
|
|
return 1;
|
|
|
|
|
else
|
|
|
|
|
return fib(n-1) + fib(n-2);
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-07 00:01:45 +03:00
|
|
|
|
void __attribute__((aligned(16))) aligned_function(int i) {}
|
|
|
|
|
|
2002-01-05 20:03:02 +03:00
|
|
|
|
void funcptr_test()
|
|
|
|
|
{
|
|
|
|
|
void (*func)(int);
|
|
|
|
|
int a;
|
|
|
|
|
struct {
|
|
|
|
|
int dummy;
|
|
|
|
|
void (*func)(int);
|
|
|
|
|
} st1;
|
2016-07-14 05:09:49 +03:00
|
|
|
|
long diff;
|
2002-01-05 20:03:02 +03:00
|
|
|
|
|
|
|
|
|
printf("funcptr:\n");
|
|
|
|
|
func = #
|
|
|
|
|
(*func)(12345);
|
|
|
|
|
func = num;
|
|
|
|
|
a = 1;
|
|
|
|
|
a = 1;
|
|
|
|
|
func(12345);
|
|
|
|
|
/* more complicated pointer computation */
|
|
|
|
|
st1.func = num;
|
|
|
|
|
st1.func(12346);
|
|
|
|
|
printf("sizeof1 = %d\n", sizeof(funcptr_test));
|
|
|
|
|
printf("sizeof2 = %d\n", sizeof funcptr_test);
|
|
|
|
|
printf("sizeof3 = %d\n", sizeof(&funcptr_test));
|
|
|
|
|
printf("sizeof4 = %d\n", sizeof &funcptr_test);
|
2016-07-14 05:09:49 +03:00
|
|
|
|
a = 0;
|
|
|
|
|
func = num + a;
|
|
|
|
|
diff = func - num;
|
|
|
|
|
func(42);
|
|
|
|
|
(func + diff)(42);
|
|
|
|
|
(num + a)(43);
|
2018-04-07 00:01:45 +03:00
|
|
|
|
|
|
|
|
|
/* Check that we can align functions */
|
|
|
|
|
func = aligned_function;
|
|
|
|
|
printf("aligned_function (should be zero): %d\n", ((int)func) & 15);
|
2002-01-05 20:03:02 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void lloptest(long long a, long long b)
|
|
|
|
|
{
|
|
|
|
|
unsigned long long ua, ub;
|
|
|
|
|
|
|
|
|
|
ua = a;
|
|
|
|
|
ub = b;
|
|
|
|
|
/* arith */
|
2013-04-26 04:27:04 +04:00
|
|
|
|
printf("arith: " LONG_LONG_FORMAT " " LONG_LONG_FORMAT " " LONG_LONG_FORMAT "\n",
|
2002-01-05 20:03:02 +03:00
|
|
|
|
a + b,
|
|
|
|
|
a - b,
|
2002-11-24 18:58:28 +03:00
|
|
|
|
a * b);
|
2015-07-29 23:53:57 +03:00
|
|
|
|
|
2002-11-24 18:58:28 +03:00
|
|
|
|
if (b != 0) {
|
2013-04-26 04:27:04 +04:00
|
|
|
|
printf("arith1: " LONG_LONG_FORMAT " " LONG_LONG_FORMAT "\n",
|
2002-01-05 20:03:02 +03:00
|
|
|
|
a / b,
|
|
|
|
|
a % b);
|
2002-11-24 18:58:28 +03:00
|
|
|
|
}
|
|
|
|
|
|
2002-01-05 20:03:02 +03:00
|
|
|
|
/* binary */
|
2013-04-26 04:27:04 +04:00
|
|
|
|
printf("bin: " LONG_LONG_FORMAT " " LONG_LONG_FORMAT " " LONG_LONG_FORMAT "\n",
|
2002-01-05 20:03:02 +03:00
|
|
|
|
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);
|
2015-07-29 23:53:57 +03:00
|
|
|
|
|
2002-01-05 20:03:02 +03:00
|
|
|
|
printf("utest: %d %d %d %d %d %d\n",
|
|
|
|
|
ua == ub,
|
|
|
|
|
ua != ub,
|
|
|
|
|
ua < ub,
|
|
|
|
|
ua > ub,
|
|
|
|
|
ua >= ub,
|
|
|
|
|
ua <= ub);
|
|
|
|
|
|
|
|
|
|
/* arith2 */
|
|
|
|
|
a++;
|
|
|
|
|
b++;
|
2013-04-26 04:27:04 +04:00
|
|
|
|
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);
|
2009-04-12 23:02:52 +04:00
|
|
|
|
b = ub = 0;
|
|
|
|
|
printf("not: %d %d %d %d\n", !a, !ua, !b, !ub);
|
2002-01-05 20:03:02 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void llshift(long long a, int b)
|
|
|
|
|
{
|
2013-04-26 04:27:04 +04:00
|
|
|
|
printf("shift: " LONG_LONG_FORMAT " " LONG_LONG_FORMAT " " LONG_LONG_FORMAT "\n",
|
2002-01-05 20:03:02 +03:00
|
|
|
|
(unsigned long long)a >> b,
|
|
|
|
|
a >> b,
|
|
|
|
|
a << b);
|
2013-04-26 04:27:04 +04:00
|
|
|
|
printf("shiftc: " LONG_LONG_FORMAT " " LONG_LONG_FORMAT " " LONG_LONG_FORMAT "\n",
|
2002-01-05 20:03:02 +03:00
|
|
|
|
(unsigned long long)a >> 3,
|
|
|
|
|
a >> 3,
|
|
|
|
|
a << 3);
|
2013-04-26 04:27:04 +04:00
|
|
|
|
printf("shiftc: " LONG_LONG_FORMAT " " LONG_LONG_FORMAT " " LONG_LONG_FORMAT "\n",
|
2002-01-05 20:03:02 +03:00
|
|
|
|
(unsigned long long)a >> 35,
|
|
|
|
|
a >> 35,
|
|
|
|
|
a << 35);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void llfloat(void)
|
|
|
|
|
{
|
|
|
|
|
float fa;
|
|
|
|
|
double da;
|
2013-04-17 23:32:07 +04:00
|
|
|
|
LONG_DOUBLE lda;
|
2002-01-05 20:03:02 +03:00
|
|
|
|
long long la, lb, lc;
|
|
|
|
|
unsigned long long ula, ulb, ulc;
|
|
|
|
|
la = 0x12345678;
|
|
|
|
|
ula = 0x72345678;
|
|
|
|
|
la = (la << 20) | 0x12345;
|
|
|
|
|
ula = ula << 33;
|
2013-04-26 04:27:04 +04:00
|
|
|
|
printf("la=" LONG_LONG_FORMAT " ula=" ULONG_LONG_FORMAT "\n", la, ula);
|
2002-01-05 20:03:02 +03:00
|
|
|
|
|
|
|
|
|
fa = la;
|
|
|
|
|
da = la;
|
|
|
|
|
lda = la;
|
|
|
|
|
printf("lltof: %f %f %Lf\n", fa, da, lda);
|
|
|
|
|
|
|
|
|
|
la = fa;
|
|
|
|
|
lb = da;
|
|
|
|
|
lc = lda;
|
2013-04-26 04:27:04 +04:00
|
|
|
|
printf("ftoll: " LONG_LONG_FORMAT " " LONG_LONG_FORMAT " " LONG_LONG_FORMAT "\n", la, lb, lc);
|
2002-01-05 20:03:02 +03:00
|
|
|
|
|
|
|
|
|
fa = ula;
|
|
|
|
|
da = ula;
|
|
|
|
|
lda = ula;
|
|
|
|
|
printf("ulltof: %f %f %Lf\n", fa, da, lda);
|
|
|
|
|
|
|
|
|
|
ula = fa;
|
|
|
|
|
ulb = da;
|
|
|
|
|
ulc = lda;
|
2013-04-26 04:27:04 +04:00
|
|
|
|
printf("ftoull: " ULONG_LONG_FORMAT " " ULONG_LONG_FORMAT " " ULONG_LONG_FORMAT "\n", ula, ulb, ulc);
|
2002-01-05 20:03:02 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
long long llfunc1(int a)
|
|
|
|
|
{
|
2002-11-02 17:14:50 +03:00
|
|
|
|
return a * 2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct S {
|
2015-07-29 23:53:57 +03:00
|
|
|
|
int id;
|
2002-11-02 17:14:50 +03:00
|
|
|
|
char item;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
long long int value(struct S *v)
|
|
|
|
|
{
|
|
|
|
|
return ((long long int)v->item);
|
2002-01-05 20:03:02 +03:00
|
|
|
|
}
|
|
|
|
|
|
tccgen: arm/i386: save_reg_upstack
tccgen.c:gv() when loading long long from lvalue, before
was saving all registers which caused problems in the arm
function call register parameter preparation, as with
void foo(long long y, int x);
int main(void)
{
unsigned int *xx[1], x;
unsigned long long *yy[1], y;
foo(**yy, **xx);
return 0;
}
Now only the modified register is saved if necessary,
as in this case where it is used to store the result
of the post-inc:
long long *p, v, **pp;
v = 1;
p = &v;
p[0]++;
printf("another long long spill test : %lld\n", *p);
i386-gen.c :
- found a similar problem with TOK_UMULL caused by the
vstack juggle in tccgen:gen_opl()
(bug seen only when using EBX as 4th register)
2016-10-04 18:36:51 +03:00
|
|
|
|
long long llfunc2(long long x, long long y, int z)
|
|
|
|
|
{
|
|
|
|
|
return x * y * z;
|
|
|
|
|
}
|
|
|
|
|
|
2018-06-08 16:31:40 +03:00
|
|
|
|
void check_opl_save_regs(char *a, long long b, int c)
|
|
|
|
|
{
|
|
|
|
|
*a = b < 0 && !c;
|
|
|
|
|
}
|
|
|
|
|
|
2002-01-05 20:03:02 +03:00
|
|
|
|
void longlong_test(void)
|
|
|
|
|
{
|
|
|
|
|
long long a, b, c;
|
|
|
|
|
int ia;
|
|
|
|
|
unsigned int ua;
|
|
|
|
|
printf("longlong_test:\n");
|
|
|
|
|
printf("sizeof(long long) = %d\n", sizeof(long long));
|
|
|
|
|
ia = -1;
|
|
|
|
|
ua = -2;
|
|
|
|
|
a = ia;
|
|
|
|
|
b = ua;
|
2013-04-26 04:27:04 +04:00
|
|
|
|
printf(LONG_LONG_FORMAT " " LONG_LONG_FORMAT "\n", a, b);
|
2015-07-29 23:53:57 +03:00
|
|
|
|
printf(LONG_LONG_FORMAT " " LONG_LONG_FORMAT " " LONG_LONG_FORMAT " %Lx\n",
|
|
|
|
|
(long long)1,
|
2002-01-05 20:03:02 +03:00
|
|
|
|
(long long)-2,
|
|
|
|
|
1LL,
|
|
|
|
|
0x1234567812345679);
|
|
|
|
|
a = llfunc1(-3);
|
2013-04-26 04:27:04 +04:00
|
|
|
|
printf(LONG_LONG_FORMAT "\n", a);
|
2002-01-05 20:03:02 +03:00
|
|
|
|
|
|
|
|
|
lloptest(1000, 23);
|
|
|
|
|
lloptest(0xff, 0x1234);
|
|
|
|
|
b = 0x72345678 << 10;
|
|
|
|
|
lloptest(-3, b);
|
|
|
|
|
llshift(0x123, 5);
|
|
|
|
|
llshift(-23, 5);
|
2002-11-02 17:14:50 +03:00
|
|
|
|
b = 0x72345678LL << 10;
|
2002-01-05 20:03:02 +03:00
|
|
|
|
llshift(b, 47);
|
|
|
|
|
|
|
|
|
|
llfloat();
|
|
|
|
|
#if 1
|
|
|
|
|
b = 0x12345678;
|
|
|
|
|
a = -1;
|
|
|
|
|
c = a + b;
|
|
|
|
|
printf("%Lx\n", c);
|
|
|
|
|
#endif
|
2002-11-02 17:14:50 +03:00
|
|
|
|
|
|
|
|
|
/* long long reg spill test */
|
|
|
|
|
{
|
|
|
|
|
struct S a;
|
|
|
|
|
|
|
|
|
|
a.item = 3;
|
|
|
|
|
printf("%lld\n", value(&a));
|
|
|
|
|
}
|
2002-11-24 18:58:28 +03:00
|
|
|
|
lloptest(0x80000000, 0);
|
2004-10-24 02:52:58 +04:00
|
|
|
|
|
|
|
|
|
{
|
tccgen: arm/i386: save_reg_upstack
tccgen.c:gv() when loading long long from lvalue, before
was saving all registers which caused problems in the arm
function call register parameter preparation, as with
void foo(long long y, int x);
int main(void)
{
unsigned int *xx[1], x;
unsigned long long *yy[1], y;
foo(**yy, **xx);
return 0;
}
Now only the modified register is saved if necessary,
as in this case where it is used to store the result
of the post-inc:
long long *p, v, **pp;
v = 1;
p = &v;
p[0]++;
printf("another long long spill test : %lld\n", *p);
i386-gen.c :
- found a similar problem with TOK_UMULL caused by the
vstack juggle in tccgen:gen_opl()
(bug seen only when using EBX as 4th register)
2016-10-04 18:36:51 +03:00
|
|
|
|
long long *p, v, **pp;
|
2004-10-24 02:52:58 +04:00
|
|
|
|
v = 1;
|
|
|
|
|
p = &v;
|
|
|
|
|
p[0]++;
|
tccgen: arm/i386: save_reg_upstack
tccgen.c:gv() when loading long long from lvalue, before
was saving all registers which caused problems in the arm
function call register parameter preparation, as with
void foo(long long y, int x);
int main(void)
{
unsigned int *xx[1], x;
unsigned long long *yy[1], y;
foo(**yy, **xx);
return 0;
}
Now only the modified register is saved if necessary,
as in this case where it is used to store the result
of the post-inc:
long long *p, v, **pp;
v = 1;
p = &v;
p[0]++;
printf("another long long spill test : %lld\n", *p);
i386-gen.c :
- found a similar problem with TOK_UMULL caused by the
vstack juggle in tccgen:gen_opl()
(bug seen only when using EBX as 4th register)
2016-10-04 18:36:51 +03:00
|
|
|
|
printf("another long long spill test : %lld\n", *p);
|
|
|
|
|
pp = &p;
|
2008-12-01 21:22:57 +03:00
|
|
|
|
|
tccgen: arm/i386: save_reg_upstack
tccgen.c:gv() when loading long long from lvalue, before
was saving all registers which caused problems in the arm
function call register parameter preparation, as with
void foo(long long y, int x);
int main(void)
{
unsigned int *xx[1], x;
unsigned long long *yy[1], y;
foo(**yy, **xx);
return 0;
}
Now only the modified register is saved if necessary,
as in this case where it is used to store the result
of the post-inc:
long long *p, v, **pp;
v = 1;
p = &v;
p[0]++;
printf("another long long spill test : %lld\n", *p);
i386-gen.c :
- found a similar problem with TOK_UMULL caused by the
vstack juggle in tccgen:gen_opl()
(bug seen only when using EBX as 4th register)
2016-10-04 18:36:51 +03:00
|
|
|
|
v = llfunc2(**pp, **pp, ia);
|
|
|
|
|
printf("a long long function (arm-)reg-args test : %lld\n", v);
|
|
|
|
|
}
|
2008-12-01 21:22:57 +03:00
|
|
|
|
a = 68719476720LL;
|
|
|
|
|
b = 4294967295LL;
|
|
|
|
|
printf("%d %d %d %d\n", a > b, a < b, a >= b, a <= b);
|
2009-03-15 08:50:38 +03:00
|
|
|
|
|
2013-04-26 04:27:04 +04:00
|
|
|
|
printf(LONG_LONG_FORMAT "\n", 0x123456789LLU);
|
Incorrect function call code on ARMv6
On 2016-08-11 09:24 +0100, Balazs Kezes wrote:
> I think it's just that that copy_params() never restores the spilled
> registers. Maybe it needs some extra code at the end to see if any
> parameters have been spilled to stack and then restore them?
I've spent some time on this and I've found an alternative solution.
Although I'm not entirely sure about it but I've attached a patch
nevertheless.
And while poking at that I've found another problem affecting the
unsigned long long division on arm and I've attached a patch for that
too.
More details in the patches themselves. Please review and consider them
for merging! Thank you!
--
Balazs
[PATCH 1/2] Fix slow unsigned long long division on ARM
The macro AEABI_UXDIVMOD expands to this bit:
#define AEABI_UXDIVMOD(name,type, rettype, typemacro) \
...
while (num >= den) { \
...
while ((q << 1) * den <= num && q * den <= typemacro ## _MAX / 2) \
q <<= 1; \
...
With the current ULONG_MAX version the inner loop goes only until 4
billion so the outer loop will progress very slowly if num is large.
With ULLONG_MAX the inner loop works as expected. The current version is
probably a result of a typo.
The following bash snippet demonstrates the bug:
$ uname -a
Linux eper 4.4.16-2-ARCH #1 Wed Aug 10 20:03:13 MDT 2016 armv6l GNU/Linux
$ cat div.c
int printf(const char *, ...);
int main(void) {
unsigned long long num, denom;
num = 12345678901234567ULL;
denom = 7;
printf("%lld\n", num / denom);
return 0;
}
$ time tcc -run div.c
1763668414462081
real 0m16.291s
user 0m15.860s
sys 0m0.020s
[PATCH 2/2] Fix long long dereference during argument passing on ARMv6
For some reason the code spills the register to the stack. copy_params
in arm-gen.c doesn't expect this so bad code is generated. It's not
entirely clear why the saving part is necessary. It was added in commit
59c35638 with the comment "fixed long long code gen bug" with no further
clarification. Given that tcctest.c passes without this, maybe it's no
longer needed? Let's remove it.
Also add a new testcase just for this. After I've managed to make the
tests compile on a raspberry pi, I get the following diff without this
patch:
--- test.ref 2016-08-22 22:12:43.380000000 +0100
+++ test.out3 2016-08-22 22:12:49.990000000 +0100
@@ -499,7 +499,7 @@
2
1 0 1 0
4886718345
-shift: 9 9 9312
+shift: 291 291 291
shiftc: 36 36 2328
shiftc: 0 0 9998683865088
manyarg_test:
More discussion on this thread:
https://lists.nongnu.org/archive/html/tinycc-devel/2016-08/msg00004.html
2016-08-25 12:06:51 +03:00
|
|
|
|
|
|
|
|
|
/* long long pointer deref in argument passing test */
|
|
|
|
|
a = 0x123;
|
|
|
|
|
long long *p = &a;
|
|
|
|
|
llshift(*p, 5);
|
2018-03-31 22:52:20 +03:00
|
|
|
|
|
|
|
|
|
/* shortening followed by widening */
|
|
|
|
|
unsigned long long u = 0x8000000000000001ULL;
|
|
|
|
|
u = (unsigned)(u + 1);
|
|
|
|
|
printf("long long u=" ULONG_LONG_FORMAT "\n", u);
|
2018-06-08 16:31:40 +03:00
|
|
|
|
|
|
|
|
|
/* 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);
|
2008-12-01 21:22:57 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void manyarg_test(void)
|
|
|
|
|
{
|
2013-04-17 23:32:07 +04:00
|
|
|
|
LONG_DOUBLE ld = 1234567891234LL;
|
2008-12-01 21:22:57 +03:00
|
|
|
|
printf("manyarg_test:\n");
|
|
|
|
|
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 "
|
2013-04-26 04:27:04 +04:00
|
|
|
|
LONG_LONG_FORMAT " " LONG_LONG_FORMAT " %f %f\n",
|
2008-12-01 21:22:57 +03:00
|
|
|
|
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 "
|
2013-04-26 04:27:04 +04:00
|
|
|
|
LONG_LONG_FORMAT " " LONG_LONG_FORMAT " %f %f\n",
|
2008-12-01 21:22:57 +03:00
|
|
|
|
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 "
|
2013-04-26 04:27:04 +04:00
|
|
|
|
LONG_LONG_FORMAT " " LONG_LONG_FORMAT "%f %f %Lf\n",
|
2008-12-01 21:22:57 +03:00
|
|
|
|
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 "
|
2013-04-26 04:27:04 +04:00
|
|
|
|
"%Lf " LONG_LONG_FORMAT " " LONG_LONG_FORMAT " %f %f %Lf\n",
|
2008-12-01 21:22:57 +03:00
|
|
|
|
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);
|
2002-01-05 20:03:02 +03:00
|
|
|
|
}
|
|
|
|
|
|
2002-08-31 16:45:26 +04:00
|
|
|
|
void vprintf1(const char *fmt, ...)
|
|
|
|
|
{
|
2010-12-28 11:53:56 +03:00
|
|
|
|
va_list ap, aq;
|
2002-08-31 16:45:26 +04:00
|
|
|
|
const char *p;
|
|
|
|
|
int c, i;
|
|
|
|
|
double d;
|
|
|
|
|
long long ll;
|
2013-04-17 23:32:07 +04:00
|
|
|
|
LONG_DOUBLE ld;
|
2002-08-31 16:45:26 +04:00
|
|
|
|
|
2010-12-28 11:53:56 +03:00
|
|
|
|
va_start(aq, fmt);
|
|
|
|
|
va_copy(ap, aq);
|
2015-07-29 23:53:57 +03:00
|
|
|
|
|
2002-08-31 16:45:26 +04:00
|
|
|
|
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);
|
2013-04-26 04:27:04 +04:00
|
|
|
|
printf(LONG_LONG_FORMAT, ll);
|
2002-08-31 16:45:26 +04:00
|
|
|
|
break;
|
2008-12-01 21:22:57 +03:00
|
|
|
|
case 'F':
|
2013-04-17 23:32:07 +04:00
|
|
|
|
ld = va_arg(ap, LONG_DOUBLE);
|
2008-12-01 21:22:57 +03:00
|
|
|
|
printf("%Lf", ld);
|
|
|
|
|
break;
|
2002-08-31 16:45:26 +04:00
|
|
|
|
}
|
|
|
|
|
p++;
|
|
|
|
|
} else {
|
|
|
|
|
putchar(c);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
the_end:
|
2010-12-28 11:53:56 +03:00
|
|
|
|
va_end(aq);
|
2002-08-31 16:45:26 +04:00
|
|
|
|
va_end(ap);
|
|
|
|
|
}
|
|
|
|
|
|
2010-12-28 13:32:40 +03:00
|
|
|
|
struct myspace {
|
|
|
|
|
short int profile;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
void stdarg_for_struct(struct myspace bob, ...)
|
|
|
|
|
{
|
|
|
|
|
struct myspace george, bill;
|
|
|
|
|
va_list ap;
|
|
|
|
|
short int validate;
|
|
|
|
|
|
|
|
|
|
va_start(ap, bob);
|
|
|
|
|
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\n",
|
|
|
|
|
bob.profile, bill.profile, george.profile, validate);
|
|
|
|
|
va_end(ap);
|
|
|
|
|
}
|
2002-08-31 16:45:26 +04:00
|
|
|
|
|
2016-07-10 21:44:49 +03:00
|
|
|
|
void stdarg_for_libc(const char *fmt, ...)
|
|
|
|
|
{
|
|
|
|
|
va_list args;
|
|
|
|
|
va_start(args, fmt);
|
|
|
|
|
vprintf(fmt, args);
|
|
|
|
|
va_end(args);
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-14 17:39:52 +03:00
|
|
|
|
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));
|
|
|
|
|
}
|
|
|
|
|
|
2002-08-31 16:45:26 +04:00
|
|
|
|
void stdarg_test(void)
|
|
|
|
|
{
|
2013-04-17 23:32:07 +04:00
|
|
|
|
LONG_DOUBLE ld = 1234567891234LL;
|
2010-12-28 13:32:40 +03:00
|
|
|
|
struct myspace bob;
|
|
|
|
|
|
2002-08-31 16:45:26 +04:00
|
|
|
|
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);
|
2013-04-17 23:32:07 +04:00
|
|
|
|
vprintf1("%F %F %F\n", LONG_DOUBLE_LITERAL(1.2), LONG_DOUBLE_LITERAL(2.3), LONG_DOUBLE_LITERAL(3.4));
|
2008-12-01 21:22:57 +03:00
|
|
|
|
vprintf1("%d %f %l %F %d %f %l %F\n",
|
2013-04-26 04:27:04 +04:00
|
|
|
|
1, 1.2, 3LL, LONG_DOUBLE_LITERAL(4.5), 6, 7.8, 9LL, LONG_DOUBLE_LITERAL(0.1));
|
2008-12-01 21:22:57 +03:00
|
|
|
|
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);
|
2010-12-28 13:32:40 +03:00
|
|
|
|
|
|
|
|
|
bob.profile = 42;
|
|
|
|
|
stdarg_for_struct(bob, bob, bob, bob.profile);
|
2016-07-10 21:44:49 +03:00
|
|
|
|
stdarg_for_libc("stdarg_for_libc: %s %.2f %d\n", "string", 1.23, 456);
|
2019-03-14 17:39:52 +03:00
|
|
|
|
stdarg_syntax(1, 17);
|
2002-08-31 16:45:26 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void whitespace_test(void)
|
|
|
|
|
{
|
|
|
|
|
char *str;
|
|
|
|
|
|
|
|
|
|
#if 1
|
|
|
|
|
pri\
|
|
|
|
|
ntf("whitspace:\n");
|
|
|
|
|
#endif
|
|
|
|
|
pf("N=%d\n", 2);
|
2002-12-08 17:37:00 +03:00
|
|
|
|
|
|
|
|
|
#ifdef CORRECT_CR_HANDLING
|
2002-08-31 16:45:26 +04:00
|
|
|
|
pri\
|
|
|
|
|
ntf("aaa=%d\n", 3);
|
2002-12-08 17:37:00 +03:00
|
|
|
|
#endif
|
2002-08-31 16:45:26 +04:00
|
|
|
|
|
|
|
|
|
pri\
|
|
|
|
|
\
|
|
|
|
|
ntf("min=%d\n", 4);
|
2004-10-29 01:13:47 +04:00
|
|
|
|
|
|
|
|
|
#ifdef ACCEPT_CR_IN_STRINGS
|
2002-08-31 16:45:26 +04:00
|
|
|
|
printf("len1=%d\n", strlen("
|
|
|
|
|
"));
|
2002-12-08 17:37:00 +03:00
|
|
|
|
#ifdef CORRECT_CR_HANDLING
|
2002-08-31 16:45:26 +04:00
|
|
|
|
str = "
|
|
|
|
|
";
|
|
|
|
|
printf("len1=%d str[0]=%d\n", strlen(str), str[0]);
|
2002-12-08 17:37:00 +03:00
|
|
|
|
#endif
|
2002-08-31 16:45:26 +04:00
|
|
|
|
printf("len1=%d\n", strlen("
a
|
|
|
|
|
"));
|
2004-10-29 01:13:47 +04:00
|
|
|
|
#endif /* ACCEPT_CR_IN_STRINGS */
|
2002-08-31 16:45:26 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int reltab[3] = { 1, 2, 3 };
|
|
|
|
|
|
|
|
|
|
int *rel1 = &reltab[1];
|
|
|
|
|
int *rel2 = &reltab[2];
|
|
|
|
|
|
2016-12-20 20:05:33 +03:00
|
|
|
|
#ifdef _WIN64
|
|
|
|
|
void relocation_test(void) {}
|
|
|
|
|
#else
|
2016-07-11 17:26:36 +03:00
|
|
|
|
void getmyaddress(void)
|
|
|
|
|
{
|
|
|
|
|
printf("in getmyaddress\n");
|
|
|
|
|
}
|
2016-10-09 01:44:22 +03:00
|
|
|
|
|
|
|
|
|
#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
|
|
|
|
|
|
2016-07-11 17:26:36 +03:00
|
|
|
|
unsigned long theaddress = (unsigned long)getmyaddress;
|
2002-08-31 16:45:26 +04:00
|
|
|
|
void relocation_test(void)
|
|
|
|
|
{
|
2016-07-11 17:26:36 +03:00
|
|
|
|
void (*fptr)(void) = (void (*)(void))theaddress;
|
2002-08-31 16:45:26 +04:00
|
|
|
|
printf("*rel1=%d\n", *rel1);
|
|
|
|
|
printf("*rel2=%d\n", *rel2);
|
2016-07-11 17:26:36 +03:00
|
|
|
|
fptr();
|
2016-10-09 01:44:22 +03:00
|
|
|
|
#ifdef __LP64__
|
|
|
|
|
printf("pa_symbol=0x%lx\n", __pa_symbol() >> 63);
|
|
|
|
|
#endif
|
2002-08-31 16:45:26 +04:00
|
|
|
|
}
|
2016-12-20 20:05:33 +03:00
|
|
|
|
#endif
|
2002-11-02 23:46:36 +03:00
|
|
|
|
|
|
|
|
|
void old_style_f(a,b,c)
|
|
|
|
|
int a, b;
|
|
|
|
|
double c;
|
|
|
|
|
{
|
|
|
|
|
printf("a=%d b=%d b=%f\n", a, b, c);
|
|
|
|
|
}
|
|
|
|
|
|
2003-04-13 23:48:52 +04:00
|
|
|
|
void decl_func1(int cmpfn())
|
|
|
|
|
{
|
|
|
|
|
printf("cmpfn=%lx\n", (long)cmpfn);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void decl_func2(cmpfn)
|
|
|
|
|
int cmpfn();
|
|
|
|
|
{
|
|
|
|
|
printf("cmpfn=%lx\n", (long)cmpfn);
|
|
|
|
|
}
|
|
|
|
|
|
2002-11-02 23:46:36 +03:00
|
|
|
|
void old_style_function(void)
|
|
|
|
|
{
|
|
|
|
|
old_style_f((void *)1, 2, 3.0);
|
2003-04-13 23:48:52 +04:00
|
|
|
|
decl_func1(NULL);
|
|
|
|
|
decl_func2(NULL);
|
2002-11-02 23:46:36 +03:00
|
|
|
|
}
|
|
|
|
|
|
2009-05-17 00:30:13 +04:00
|
|
|
|
void alloca_test()
|
|
|
|
|
{
|
2014-04-06 00:54:11 +04:00
|
|
|
|
#if defined __i386__ || defined __x86_64__ || defined __arm__
|
2009-05-17 00:30:13 +04:00
|
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-07 02:27:45 +04:00
|
|
|
|
void *bounds_checking_is_enabled()
|
|
|
|
|
{
|
|
|
|
|
char ca[10], *cp = ca-1;
|
|
|
|
|
return (ca != cp + 1) ? cp : NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2011-07-22 13:09:28 +04:00
|
|
|
|
typedef int constant_negative_array_size_as_compile_time_assertion_idiom[(1 ? 2 : 0) - 1];
|
|
|
|
|
|
2011-04-06 20:17:03 +04:00
|
|
|
|
void c99_vla_test(int size1, int size2)
|
|
|
|
|
{
|
|
|
|
|
#if defined __i386__ || defined __x86_64__
|
2011-04-08 12:07:17 +04:00
|
|
|
|
int size = size1 * size2;
|
|
|
|
|
int tab1[size][2], tab2[10][2];
|
2011-04-07 02:27:45 +04:00
|
|
|
|
void *tab1_ptr, *tab2_ptr, *bad_ptr;
|
2011-04-06 20:17:03 +04:00
|
|
|
|
|
2015-07-29 23:53:57 +03:00
|
|
|
|
/* "size" should have been 'captured' at tab1 declaration,
|
2011-04-08 12:07:17 +04:00
|
|
|
|
so modifying it should have no effect on VLA behaviour. */
|
|
|
|
|
size = size-1;
|
2015-07-29 23:53:57 +03:00
|
|
|
|
|
2011-04-06 20:17:03 +04:00
|
|
|
|
printf("Test C99 VLA 1 (sizeof): ");
|
|
|
|
|
printf("%s\n", (sizeof tab1 == size1 * size2 * 2 * sizeof(int)) ? "PASSED" : "FAILED");
|
|
|
|
|
tab1_ptr = tab1;
|
|
|
|
|
tab2_ptr = tab2;
|
2014-04-07 15:31:00 +04:00
|
|
|
|
printf("Test C99 VLA 2 (ptrs subtract): ");
|
2011-04-06 20:17:03 +04:00
|
|
|
|
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");
|
2011-04-07 02:27:45 +04:00
|
|
|
|
|
|
|
|
|
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");
|
2011-04-06 20:17:03 +04:00
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-05 21:04:00 +03:00
|
|
|
|
#ifndef __TINYC__
|
2012-04-16 03:13:25 +04:00
|
|
|
|
typedef __SIZE_TYPE__ uintptr_t;
|
2016-05-05 21:04:00 +03:00
|
|
|
|
#endif
|
2012-04-16 03:13:25 +04:00
|
|
|
|
|
2002-11-02 23:46:36 +03:00
|
|
|
|
void sizeof_test(void)
|
|
|
|
|
{
|
|
|
|
|
int a;
|
|
|
|
|
int **ptr;
|
|
|
|
|
|
|
|
|
|
printf("sizeof(int) = %d\n", sizeof(int));
|
|
|
|
|
printf("sizeof(unsigned int) = %d\n", sizeof(unsigned int));
|
2008-12-01 21:22:57 +03:00
|
|
|
|
printf("sizeof(long) = %d\n", sizeof(long));
|
|
|
|
|
printf("sizeof(unsigned long) = %d\n", sizeof(unsigned long));
|
2002-11-02 23:46:36 +03:00
|
|
|
|
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));
|
|
|
|
|
|
2012-04-16 03:13:25 +04:00
|
|
|
|
/* 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++;
|
2015-07-29 23:53:57 +03:00
|
|
|
|
/* This checks that sizeof really can be used to manipulate
|
2012-04-16 03:13:25 +04:00
|
|
|
|
uintptr_t objects, without truncation. */
|
|
|
|
|
t2 = t & -sizeof(uintptr_t);
|
|
|
|
|
printf ("%lu %lu\n", t, t2);
|
|
|
|
|
|
2002-11-02 23:46:36 +03:00
|
|
|
|
/* 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());
|
2016-09-04 00:55:54 +03:00
|
|
|
|
|
|
|
|
|
/* 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} );
|
2016-09-26 22:21:42 +03:00
|
|
|
|
|
|
|
|
|
/* 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));
|
2002-11-02 23:46:36 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
}
|
2003-01-06 23:19:20 +03:00
|
|
|
|
|
2016-08-15 06:09:31 +03:00
|
|
|
|
|
|
|
|
|
struct hlist_node;
|
|
|
|
|
struct hlist_head {
|
|
|
|
|
struct hlist_node *first, *last;
|
|
|
|
|
};
|
|
|
|
|
|
2017-07-10 23:25:11 +03:00
|
|
|
|
void consume_ulong (unsigned long i)
|
|
|
|
|
{
|
|
|
|
|
i = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2003-01-06 23:19:20 +03:00
|
|
|
|
void statement_expr_test(void)
|
|
|
|
|
{
|
|
|
|
|
int a, i;
|
|
|
|
|
|
2016-08-15 06:09:31 +03:00
|
|
|
|
/* Basic stmt expr test */
|
2003-01-06 23:19:20 +03:00
|
|
|
|
a = 0;
|
|
|
|
|
for(i=0;i<10;i++) {
|
2015-07-29 23:53:57 +03:00
|
|
|
|
a += 1 +
|
|
|
|
|
( { int b, j;
|
|
|
|
|
b = 0;
|
|
|
|
|
for(j=0;j<5;j++)
|
|
|
|
|
b += j; b;
|
2003-01-06 23:19:20 +03:00
|
|
|
|
} );
|
|
|
|
|
}
|
|
|
|
|
printf("a=%d\n", a);
|
2015-07-29 23:53:57 +03:00
|
|
|
|
|
2016-08-15 06:09:31 +03:00
|
|
|
|
/* 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);
|
2017-07-10 23:25:11 +03:00
|
|
|
|
|
|
|
|
|
/* Test that we can give out addresses of local labels. */
|
|
|
|
|
consume_ulong(({ __label__ __here; __here: (unsigned long)&&__here; }));
|
2003-01-06 23:19:20 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void local_label_test(void)
|
|
|
|
|
{
|
|
|
|
|
int a;
|
|
|
|
|
goto l1;
|
|
|
|
|
l2:
|
|
|
|
|
a = 1 + ({
|
2005-09-04 13:27:53 +04:00
|
|
|
|
__label__ l1, l2, l3, l4;
|
2003-01-06 23:19:20 +03:00
|
|
|
|
goto l1;
|
2005-09-04 13:27:53 +04:00
|
|
|
|
l4:
|
|
|
|
|
printf("aa1\n");
|
|
|
|
|
goto l3;
|
2003-01-06 23:19:20 +03:00
|
|
|
|
l2:
|
|
|
|
|
printf("aa3\n");
|
2005-09-04 13:27:53 +04:00
|
|
|
|
goto l4;
|
2003-01-06 23:19:20 +03:00
|
|
|
|
l1:
|
|
|
|
|
printf("aa2\n");
|
|
|
|
|
goto l2;
|
|
|
|
|
l3:;
|
|
|
|
|
1;
|
|
|
|
|
});
|
|
|
|
|
printf("a=%d\n", a);
|
|
|
|
|
return;
|
2005-09-04 13:27:53 +04:00
|
|
|
|
l4:
|
2003-01-06 23:19:20 +03:00
|
|
|
|
printf("bb1\n");
|
|
|
|
|
goto l2;
|
2005-09-04 13:27:53 +04:00
|
|
|
|
l1:
|
2003-01-06 23:19:20 +03:00
|
|
|
|
printf("bb2\n");
|
2005-09-04 13:27:53 +04:00
|
|
|
|
goto l4;
|
2003-01-06 23:19:20 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* inline assembler test */
|
2016-05-10 04:33:14 +03:00
|
|
|
|
#if defined(__i386__) || defined(__x86_64__)
|
2003-01-06 23:19:20 +03:00
|
|
|
|
|
|
|
|
|
/* from linux kernel */
|
|
|
|
|
static char * strncat1(char * dest,const char * src,size_t count)
|
|
|
|
|
{
|
2016-05-10 04:33:14 +03:00
|
|
|
|
long d0, d1, d2, d3;
|
2003-01-06 23:19:20 +03:00
|
|
|
|
__asm__ __volatile__(
|
|
|
|
|
"repne\n\t"
|
|
|
|
|
"scasb\n\t"
|
2016-05-10 04:33:14 +03:00
|
|
|
|
"dec %1\n\t"
|
|
|
|
|
"mov %8,%3\n"
|
|
|
|
|
"1:\tdec %3\n\t"
|
2003-01-06 23:19:20 +03:00
|
|
|
|
"js 2f\n\t"
|
|
|
|
|
"lodsb\n\t"
|
|
|
|
|
"stosb\n\t"
|
|
|
|
|
"testb %%al,%%al\n\t"
|
|
|
|
|
"jne 1b\n"
|
2016-05-10 04:33:14 +03:00
|
|
|
|
"2:\txor %2,%2\n\t"
|
2003-01-06 23:19:20 +03:00
|
|
|
|
"stosb"
|
|
|
|
|
: "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3)
|
|
|
|
|
: "0" (src),"1" (dest),"2" (0),"3" (0xffffffff), "g" (count)
|
|
|
|
|
: "memory");
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
2011-02-02 02:37:58 +03:00
|
|
|
|
static char * strncat2(char * dest,const char * src,size_t count)
|
|
|
|
|
{
|
2016-05-10 04:33:14 +03:00
|
|
|
|
long d0, d1, d2, d3;
|
2011-02-02 02:37:58 +03:00
|
|
|
|
__asm__ __volatile__(
|
|
|
|
|
"repne scasb\n\t" /* one-line repne prefix + string op */
|
2016-05-10 04:33:14 +03:00
|
|
|
|
"dec %1\n\t"
|
|
|
|
|
"mov %8,%3\n"
|
|
|
|
|
"1:\tdec %3\n\t"
|
2011-02-02 02:37:58 +03:00
|
|
|
|
"js 2f\n\t"
|
|
|
|
|
"lodsb\n\t"
|
|
|
|
|
"stosb\n\t"
|
|
|
|
|
"testb %%al,%%al\n\t"
|
|
|
|
|
"jne 1b\n"
|
2016-05-10 04:33:14 +03:00
|
|
|
|
"2:\txor %2,%2\n\t"
|
2011-02-02 02:37:58 +03:00
|
|
|
|
"stosb"
|
|
|
|
|
: "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3)
|
|
|
|
|
: "0" (src),"1" (dest),"2" (0),"3" (0xffffffff), "g" (count)
|
|
|
|
|
: "memory");
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
2003-01-06 23:19:20 +03:00
|
|
|
|
static inline void * memcpy1(void * to, const void * from, size_t n)
|
|
|
|
|
{
|
2016-05-10 04:33:14 +03:00
|
|
|
|
long d0, d1, d2;
|
2003-01-06 23:19:20 +03:00
|
|
|
|
__asm__ __volatile__(
|
|
|
|
|
"rep ; movsl\n\t"
|
|
|
|
|
"testb $2,%b4\n\t"
|
|
|
|
|
"je 1f\n\t"
|
|
|
|
|
"movsw\n"
|
|
|
|
|
"1:\ttestb $1,%b4\n\t"
|
|
|
|
|
"je 2f\n\t"
|
|
|
|
|
"movsb\n"
|
|
|
|
|
"2:"
|
|
|
|
|
: "=&c" (d0), "=&D" (d1), "=&S" (d2)
|
|
|
|
|
:"0" (n/4), "q" (n),"1" ((long) to),"2" ((long) from)
|
|
|
|
|
: "memory");
|
|
|
|
|
return (to);
|
|
|
|
|
}
|
|
|
|
|
|
2011-02-02 02:37:58 +03:00
|
|
|
|
static inline void * memcpy2(void * to, const void * from, size_t n)
|
|
|
|
|
{
|
2016-05-10 04:33:14 +03:00
|
|
|
|
long d0, d1, d2;
|
2011-02-02 02:37:58 +03:00
|
|
|
|
__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" ((long) to),"2" ((long) from)
|
|
|
|
|
: "memory");
|
|
|
|
|
return (to);
|
|
|
|
|
}
|
|
|
|
|
|
2003-01-06 23:19:20 +03:00
|
|
|
|
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)
|
|
|
|
|
{
|
2016-08-02 18:45:40 +03:00
|
|
|
|
asm("btrl %1,%0" : "=m"(*set) : "Ir"(_sig - 1) : "cc", "flags");
|
2003-01-06 23:19:20 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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 */
|
2016-07-11 17:42:18 +03:00
|
|
|
|
:"=" "q" (x)
|
2003-01-06 23:19:20 +03:00
|
|
|
|
: "0" (x));
|
|
|
|
|
return x;
|
|
|
|
|
}
|
|
|
|
|
|
2003-04-15 02:23:55 +04:00
|
|
|
|
static __inline__ unsigned long long mul64(unsigned int a, unsigned int b)
|
|
|
|
|
{
|
|
|
|
|
unsigned long long res;
|
2016-05-10 04:33:14 +03:00
|
|
|
|
#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
|
2003-04-15 02:23:55 +04:00
|
|
|
|
__asm__("mull %2" : "=A" (res) : "a" (a), "r" (b));
|
2016-05-10 04:33:14 +03:00
|
|
|
|
#endif
|
2003-04-15 02:23:55 +04:00
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static __inline__ unsigned long long inc64(unsigned long long a)
|
|
|
|
|
{
|
|
|
|
|
unsigned long long res;
|
2016-05-10 04:33:14 +03:00
|
|
|
|
#ifdef __x86_64__
|
|
|
|
|
/* Using the A constraint is wrong, and increments are tested
|
2017-09-25 04:03:26 +03:00
|
|
|
|
elsewhere. */
|
2016-05-10 04:33:14 +03:00
|
|
|
|
res = a + 1;
|
|
|
|
|
#else
|
2003-04-15 02:23:55 +04:00
|
|
|
|
__asm__("addl $1, %%eax ; adcl $0, %%edx" : "=A" (res) : "A" (a));
|
2016-05-10 04:33:14 +03:00
|
|
|
|
#endif
|
2003-04-15 02:23:55 +04:00
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
2016-11-20 16:50:56 +03:00
|
|
|
|
struct struct123 {
|
|
|
|
|
int a;
|
|
|
|
|
int b;
|
|
|
|
|
};
|
|
|
|
|
struct struct1231 {
|
|
|
|
|
unsigned long addr;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
unsigned long mconstraint_test(struct struct1231 *r)
|
|
|
|
|
{
|
|
|
|
|
unsigned long 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];
|
|
|
|
|
}
|
|
|
|
|
|
2016-06-27 21:21:57 +03:00
|
|
|
|
#ifdef __x86_64__
|
|
|
|
|
int fls64(unsigned long long x)
|
|
|
|
|
{
|
|
|
|
|
int bitpos = -1;
|
|
|
|
|
asm("bsrq %1,%q0"
|
|
|
|
|
: "+r" (bitpos)
|
|
|
|
|
: "rm" (x));
|
|
|
|
|
return bitpos + 1;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2016-06-29 19:31:45 +03:00
|
|
|
|
void other_constraints_test(void)
|
|
|
|
|
{
|
|
|
|
|
unsigned long ret;
|
|
|
|
|
int var;
|
2016-12-20 20:05:33 +03:00
|
|
|
|
#ifndef _WIN64
|
2016-12-15 19:41:16 +03:00
|
|
|
|
__asm__ volatile ("mov %P1,%0" : "=r" (ret) : "p" (&var));
|
2016-06-29 19:31:45 +03:00
|
|
|
|
printf ("oc1: %d\n", ret == (unsigned long)&var);
|
2016-12-20 20:05:33 +03:00
|
|
|
|
#endif
|
2016-06-29 19:31:45 +03:00
|
|
|
|
}
|
|
|
|
|
|
2016-12-19 00:05:42 +03:00
|
|
|
|
#ifndef _WIN32
|
2016-08-07 06:37:43 +03:00
|
|
|
|
/* Test global asm blocks playing with aliases. */
|
|
|
|
|
void base_func(void)
|
|
|
|
|
{
|
|
|
|
|
printf ("asmc: base\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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");
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-26 19:11:19 +03:00
|
|
|
|
/* 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)
|
|
|
|
|
{
|
|
|
|
|
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;
|
|
|
|
|
}
|
2017-07-10 23:29:28 +03:00
|
|
|
|
|
|
|
|
|
/* 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]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 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);
|
|
|
|
|
}
|
2016-12-19 00:05:42 +03:00
|
|
|
|
#endif
|
2016-08-26 19:11:19 +03:00
|
|
|
|
|
various stuff
win32/Makefile ("for cygwin") removed
- On cygwin, the normal ./configure && make can be used with either
cygwin's "GCC for Win32 Toolchain"
./configure --cross-prefix=i686-w64-mingw32-
or with an existing tcc:
./configure --cc=<old-tccdir>/tcc.exe
tcctest.c:
- exclude test_high_clobbers() on _WIN64 (does not work)
tests2/95_bitfield.c:
- use 'signed char' for ARM (where default 'char' is unsigned)
tests:
- remove -I "expr" diff option to allow tests with
busybox-diff.
libtcc.c, tcc.c:
- removed -iwithprefix option. It is supposed to be
combined with -iprefix which we don't have either.
tccgen.c:
- fix assignments and return of 'void', as in
void f() {
void *p, *q;
*p = *q:
return *p;
}
This appears to be allowed but should do nothing.
tcc.h, libtcc.c, tccpp.c:
- Revert "Introduce VIP sysinclude paths which are always searched first"
This reverts commit 1d5e386b0a78393ac6b670c209a185849ec798a1.
The patch was giving tcc's system includes priority over -I which
is not how it should be.
tccelf.c:
- add DT_TEXTREL tag only if text relocations are actually
used (which is likely not the case on x86_64)
- prepare_dynamic_rel(): avoid relocation of unresolved
(weak) symbols
tccrun.c:
- for HAVE_SELINUX, use two mappings to the same (real) file.
(it was so once except the RX mapping wasn't used at all).
tccpe.c:
- fix relocation constant used for x86_64 (by Andrei E. Warentin)
- #ifndef _WIN32 do "chmod 755 ..." to get runnable exes on cygwin.
tccasm.c:
- keep forward asm labels static, otherwise they will endup
in dynsym eventually.
configure, Makefile:
- mingw32: respect ./configure options --bindir --docdir --libdir
- allow overriding tcc when building libtcc1.a and libtcc.def with
make XTCC=<tcc program to use>
- use $(wildcard ...) for install to allow installing just
a cross compiler for example
make cross-arm
make install
- use name <target>-libtcc1.a
build-tcc.bat:
- add options: -clean, -b bindir
2017-10-11 19:13:43 +03:00
|
|
|
|
static
|
2003-01-06 23:19:20 +03:00
|
|
|
|
unsigned int set;
|
|
|
|
|
|
2016-10-03 06:34:01 +03:00
|
|
|
|
void fancy_copy (unsigned *in, unsigned *out)
|
|
|
|
|
{
|
|
|
|
|
asm volatile ("" : "=r" (*out) : "0" (*in));
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-03 21:39:48 +03:00
|
|
|
|
void fancy_copy2 (unsigned *in, unsigned *out)
|
|
|
|
|
{
|
|
|
|
|
asm volatile ("mov %0,(%1)" : : "r" (*in), "r" (out) : "memory");
|
|
|
|
|
}
|
|
|
|
|
|
various stuff
win32/Makefile ("for cygwin") removed
- On cygwin, the normal ./configure && make can be used with either
cygwin's "GCC for Win32 Toolchain"
./configure --cross-prefix=i686-w64-mingw32-
or with an existing tcc:
./configure --cc=<old-tccdir>/tcc.exe
tcctest.c:
- exclude test_high_clobbers() on _WIN64 (does not work)
tests2/95_bitfield.c:
- use 'signed char' for ARM (where default 'char' is unsigned)
tests:
- remove -I "expr" diff option to allow tests with
busybox-diff.
libtcc.c, tcc.c:
- removed -iwithprefix option. It is supposed to be
combined with -iprefix which we don't have either.
tccgen.c:
- fix assignments and return of 'void', as in
void f() {
void *p, *q;
*p = *q:
return *p;
}
This appears to be allowed but should do nothing.
tcc.h, libtcc.c, tccpp.c:
- Revert "Introduce VIP sysinclude paths which are always searched first"
This reverts commit 1d5e386b0a78393ac6b670c209a185849ec798a1.
The patch was giving tcc's system includes priority over -I which
is not how it should be.
tccelf.c:
- add DT_TEXTREL tag only if text relocations are actually
used (which is likely not the case on x86_64)
- prepare_dynamic_rel(): avoid relocation of unresolved
(weak) symbols
tccrun.c:
- for HAVE_SELINUX, use two mappings to the same (real) file.
(it was so once except the RX mapping wasn't used at all).
tccpe.c:
- fix relocation constant used for x86_64 (by Andrei E. Warentin)
- #ifndef _WIN32 do "chmod 755 ..." to get runnable exes on cygwin.
tccasm.c:
- keep forward asm labels static, otherwise they will endup
in dynsym eventually.
configure, Makefile:
- mingw32: respect ./configure options --bindir --docdir --libdir
- allow overriding tcc when building libtcc1.a and libtcc.def with
make XTCC=<tcc program to use>
- use $(wildcard ...) for install to allow installing just
a cross compiler for example
make cross-arm
make install
- use name <target>-libtcc1.a
build-tcc.bat:
- add options: -clean, -b bindir
2017-10-11 19:13:43 +03:00
|
|
|
|
#if defined __x86_64__ && !defined _WIN64
|
2016-10-08 23:50:16 +03:00
|
|
|
|
void clobber_r12(void)
|
|
|
|
|
{
|
|
|
|
|
asm volatile("mov $1, %%r12" ::: "r12");
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
void test_high_clobbers(void)
|
|
|
|
|
{
|
various stuff
win32/Makefile ("for cygwin") removed
- On cygwin, the normal ./configure && make can be used with either
cygwin's "GCC for Win32 Toolchain"
./configure --cross-prefix=i686-w64-mingw32-
or with an existing tcc:
./configure --cc=<old-tccdir>/tcc.exe
tcctest.c:
- exclude test_high_clobbers() on _WIN64 (does not work)
tests2/95_bitfield.c:
- use 'signed char' for ARM (where default 'char' is unsigned)
tests:
- remove -I "expr" diff option to allow tests with
busybox-diff.
libtcc.c, tcc.c:
- removed -iwithprefix option. It is supposed to be
combined with -iprefix which we don't have either.
tccgen.c:
- fix assignments and return of 'void', as in
void f() {
void *p, *q;
*p = *q:
return *p;
}
This appears to be allowed but should do nothing.
tcc.h, libtcc.c, tccpp.c:
- Revert "Introduce VIP sysinclude paths which are always searched first"
This reverts commit 1d5e386b0a78393ac6b670c209a185849ec798a1.
The patch was giving tcc's system includes priority over -I which
is not how it should be.
tccelf.c:
- add DT_TEXTREL tag only if text relocations are actually
used (which is likely not the case on x86_64)
- prepare_dynamic_rel(): avoid relocation of unresolved
(weak) symbols
tccrun.c:
- for HAVE_SELINUX, use two mappings to the same (real) file.
(it was so once except the RX mapping wasn't used at all).
tccpe.c:
- fix relocation constant used for x86_64 (by Andrei E. Warentin)
- #ifndef _WIN32 do "chmod 755 ..." to get runnable exes on cygwin.
tccasm.c:
- keep forward asm labels static, otherwise they will endup
in dynsym eventually.
configure, Makefile:
- mingw32: respect ./configure options --bindir --docdir --libdir
- allow overriding tcc when building libtcc1.a and libtcc.def with
make XTCC=<tcc program to use>
- use $(wildcard ...) for install to allow installing just
a cross compiler for example
make cross-arm
make install
- use name <target>-libtcc1.a
build-tcc.bat:
- add options: -clean, -b bindir
2017-10-11 19:13:43 +03:00
|
|
|
|
#if defined __x86_64__ && !defined _WIN64
|
2016-10-08 23:50:16 +03:00
|
|
|
|
register long val asm("r12");
|
|
|
|
|
long 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
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-18 04:31:14 +03:00
|
|
|
|
static long cpu_number;
|
|
|
|
|
void trace_console(long len, long len2)
|
|
|
|
|
{
|
2016-12-15 19:41:16 +03:00
|
|
|
|
#ifdef __x86_64__
|
2016-10-18 04:31:14 +03:00
|
|
|
|
/* 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");
|
|
|
|
|
}
|
2016-12-15 19:41:16 +03:00
|
|
|
|
#endif
|
2016-10-18 04:31:14 +03:00
|
|
|
|
}
|
2016-12-20 06:49:22 +03:00
|
|
|
|
|
|
|
|
|
void test_asm_dead_code(void)
|
|
|
|
|
{
|
|
|
|
|
long 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;
|
|
|
|
|
}));
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-16 15:29:59 +03:00
|
|
|
|
void test_asm_call(void)
|
|
|
|
|
{
|
|
|
|
|
#if defined __x86_64__ && !defined _WIN64
|
|
|
|
|
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 */
|
2017-11-19 17:36:47 +03:00
|
|
|
|
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"
|
2017-11-16 15:29:59 +03:00
|
|
|
|
: "=a" (s) : "r" (str));
|
|
|
|
|
printf("asmd: %s\n", s);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-12 19:57:20 +03:00
|
|
|
|
#if defined __x86_64__
|
|
|
|
|
# define RX "(%rip)"
|
|
|
|
|
#else
|
|
|
|
|
# define RX
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
void asm_dot_test(void)
|
|
|
|
|
{
|
|
|
|
|
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:
|
|
|
|
|
asm(".text; jmp .+6; .int 123; mov .-4"RX",%eax; jmp p0");
|
|
|
|
|
case 3:
|
2019-06-24 06:18:08 +03:00
|
|
|
|
#ifndef _WIN32
|
2019-05-30 22:31:35 +03:00
|
|
|
|
asm(".pushsection \".data\"; Y=.; .int 999; X=Y; .int 456; X=.-4; .popsection");
|
2019-06-24 06:18:08 +03:00
|
|
|
|
#else
|
|
|
|
|
asm(".data; Y=.; .int 999; X=Y; .int 456; X=.-4; .text");
|
|
|
|
|
#endif
|
2017-12-12 19:57:20 +03:00
|
|
|
|
asm(".text; mov X"RX",%eax; jmp p0");
|
|
|
|
|
case 4:
|
2019-06-24 06:18:08 +03:00
|
|
|
|
#ifndef _WIN32
|
2019-05-30 22:31:35 +03:00
|
|
|
|
asm(".data; X=.; .int 789; Y=.; .int 999; .previous");
|
2019-06-24 06:18:08 +03:00
|
|
|
|
#else
|
|
|
|
|
asm(".data; X=.; .int 789; Y=.; .int 999; .text");
|
|
|
|
|
#endif
|
2017-12-12 19:57:20 +03:00
|
|
|
|
asm(".text; mov X"RX",%eax; X=Y; jmp p0");
|
|
|
|
|
case 0:
|
|
|
|
|
asm(".text; p0=.; mov %%eax,%0;" : "=m"(r)); break;
|
|
|
|
|
}
|
|
|
|
|
if (r == x)
|
|
|
|
|
break;
|
|
|
|
|
printf("asm_dot_test %d: %d\n", x, r);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2003-01-06 23:19:20 +03:00
|
|
|
|
void asm_test(void)
|
|
|
|
|
{
|
|
|
|
|
char buf[128];
|
2016-10-03 06:34:01 +03:00
|
|
|
|
unsigned int val, val2;
|
2016-11-20 16:50:56 +03:00
|
|
|
|
struct struct123 s1;
|
|
|
|
|
struct struct1231 s2 = { (unsigned long)&s1 };
|
2016-08-07 06:37:43 +03:00
|
|
|
|
/* 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);
|
2016-08-08 21:18:11 +03:00
|
|
|
|
unsigned long asmret;
|
2016-08-08 21:46:16 +03:00
|
|
|
|
#ifdef BOOL_ISOC99
|
|
|
|
|
_Bool somebool;
|
|
|
|
|
#endif
|
2016-10-06 05:05:30 +03:00
|
|
|
|
register int regvar asm("%esi");
|
2003-01-06 23:19:20 +03:00
|
|
|
|
|
|
|
|
|
printf("inline asm:\n");
|
2016-10-09 21:33:14 +03:00
|
|
|
|
|
|
|
|
|
// parse 0x1E-1 as 3 tokens in asm mode
|
|
|
|
|
asm volatile ("mov $0x1E-1,%eax");
|
|
|
|
|
|
2003-04-15 02:23:55 +04:00
|
|
|
|
/* test the no operand case */
|
|
|
|
|
asm volatile ("xorl %eax, %eax");
|
|
|
|
|
|
2003-01-06 23:19:20 +03:00
|
|
|
|
memcpy1(buf, "hello", 6);
|
|
|
|
|
strncat1(buf, " worldXXXXX", 3);
|
|
|
|
|
printf("%s\n", buf);
|
|
|
|
|
|
2011-02-02 02:37:58 +03:00
|
|
|
|
memcpy2(buf, "hello", 6);
|
|
|
|
|
strncat2(buf, " worldXXXXX", 3);
|
|
|
|
|
printf("%s\n", buf);
|
|
|
|
|
|
2003-04-15 02:23:55 +04:00
|
|
|
|
/* 'A' constraint test */
|
|
|
|
|
printf("mul64=0x%Lx\n", mul64(0x12345678, 0xabcd1234));
|
|
|
|
|
printf("inc64=0x%Lx\n", inc64(0x12345678ffffffff));
|
|
|
|
|
|
2016-11-20 16:50:56 +03:00
|
|
|
|
s1.a = 42;
|
|
|
|
|
s1.b = 43;
|
|
|
|
|
printf("mconstraint: %d", mconstraint_test(&s2));
|
|
|
|
|
printf(" %d %d\n", s1.a, s1.b);
|
2016-06-29 19:31:45 +03:00
|
|
|
|
other_constraints_test();
|
2003-01-06 23:19:20 +03:00
|
|
|
|
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));
|
2016-12-19 00:05:42 +03:00
|
|
|
|
#ifndef _WIN32
|
2016-08-07 06:37:43 +03:00
|
|
|
|
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();
|
2016-12-19 00:05:42 +03:00
|
|
|
|
printf("asmstr: %s\n", get_asm_string());
|
2017-07-10 23:29:28 +03:00
|
|
|
|
asm_local_label_diff();
|
|
|
|
|
asm_local_statics();
|
2016-12-19 00:05:42 +03:00
|
|
|
|
#endif
|
2016-08-08 21:18:11 +03:00
|
|
|
|
/* 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");
|
2016-08-08 21:46:16 +03:00
|
|
|
|
#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
|
2016-10-03 06:34:01 +03:00
|
|
|
|
val = 43;
|
|
|
|
|
fancy_copy (&val, &val2);
|
|
|
|
|
printf ("fancycpy(%d)=%d\n", val, val2);
|
2016-10-03 21:39:48 +03:00
|
|
|
|
val = 44;
|
|
|
|
|
fancy_copy2 (&val, &val2);
|
|
|
|
|
printf ("fancycpy2(%d)=%d\n", val, val2);
|
2016-10-06 05:05:30 +03:00
|
|
|
|
asm volatile ("mov $0x4243, %%esi" : "=r" (regvar));
|
|
|
|
|
printf ("regvar=%x\n", regvar);
|
2016-10-08 23:50:16 +03:00
|
|
|
|
test_high_clobbers();
|
2016-10-18 04:31:14 +03:00
|
|
|
|
trace_console(8, 8);
|
2016-12-20 06:49:22 +03:00
|
|
|
|
test_asm_dead_code();
|
2017-11-16 15:29:59 +03:00
|
|
|
|
test_asm_call();
|
2017-12-12 19:57:20 +03:00
|
|
|
|
asm_dot_test();
|
2003-01-06 23:19:20 +03:00
|
|
|
|
return;
|
|
|
|
|
label1:
|
|
|
|
|
goto label2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
|
|
void asm_test(void)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif
|
2003-04-27 15:45:54 +04:00
|
|
|
|
|
|
|
|
|
#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;
|
|
|
|
|
|
|
|
|
|
void builtin_test(void)
|
|
|
|
|
{
|
2016-07-13 16:11:40 +03:00
|
|
|
|
short s;
|
|
|
|
|
int i;
|
|
|
|
|
long long ll;
|
2003-04-27 15:45:54 +04:00
|
|
|
|
#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 *);
|
2015-02-24 22:35:31 +03:00
|
|
|
|
COMPAT_TYPE(char *, signed char *);
|
|
|
|
|
COMPAT_TYPE(char *, char *);
|
2003-04-27 15:45:54 +04:00
|
|
|
|
/* space is needed because tcc preprocessor introduces a space between each token */
|
2015-07-29 23:53:57 +03:00
|
|
|
|
COMPAT_TYPE(char * *, void *);
|
2003-04-27 15:45:54 +04:00
|
|
|
|
#endif
|
|
|
|
|
printf("res = %d\n", __builtin_constant_p(1));
|
|
|
|
|
printf("res = %d\n", __builtin_constant_p(1 + 2));
|
|
|
|
|
printf("res = %d\n", __builtin_constant_p(&constant_p_var));
|
|
|
|
|
printf("res = %d\n", __builtin_constant_p(constant_p_var));
|
2016-09-04 00:23:13 +03:00
|
|
|
|
printf("res = %d\n", __builtin_constant_p(100000 / constant_p_var));
|
2016-07-13 16:11:40 +03:00
|
|
|
|
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);
|
2016-09-26 22:52:57 +03:00
|
|
|
|
|
2017-02-18 11:55:34 +03:00
|
|
|
|
//printf("bera: %p\n", __builtin_extract_return_addr((void*)43));
|
2003-04-27 15:45:54 +04:00
|
|
|
|
}
|
2003-06-03 00:31:46 +04:00
|
|
|
|
|
2013-02-05 17:27:38 +04:00
|
|
|
|
#ifndef _WIN32
|
2011-02-01 11:37:53 +03:00
|
|
|
|
extern int __attribute__((weak)) weak_f1(void);
|
|
|
|
|
extern int __attribute__((weak)) weak_f2(void);
|
2011-02-01 20:41:03 +03:00
|
|
|
|
extern int weak_f3(void);
|
2011-02-01 11:37:53 +03:00
|
|
|
|
extern int __attribute__((weak)) weak_v1;
|
|
|
|
|
extern int __attribute__((weak)) weak_v2;
|
2011-02-01 20:41:03 +03:00
|
|
|
|
extern int weak_v3;
|
2011-02-01 11:37:53 +03:00
|
|
|
|
|
2011-03-03 00:31:09 +03:00
|
|
|
|
extern int (*weak_fpa)() __attribute__((weak));
|
|
|
|
|
extern int __attribute__((weak)) (*weak_fpb)();
|
|
|
|
|
extern __attribute__((weak)) int (*weak_fpc)();
|
|
|
|
|
|
2011-03-03 11:55:02 +03:00
|
|
|
|
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));
|
|
|
|
|
|
2011-03-07 09:32:35 +03:00
|
|
|
|
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;
|
|
|
|
|
|
2011-03-07 11:25:27 +03:00
|
|
|
|
int some_lib_func(void);
|
|
|
|
|
int dummy_impl_of_slf(void) { return 444; }
|
|
|
|
|
int some_lib_func(void) __attribute__((weak, alias("dummy_impl_of_slf")));
|
|
|
|
|
|
2011-03-07 12:05:09 +03:00
|
|
|
|
int weak_toolate() __attribute__((weak));
|
2011-08-06 18:08:21 +04:00
|
|
|
|
int weak_toolate() { return 0; }
|
2011-03-07 12:05:09 +03:00
|
|
|
|
|
2011-02-01 11:37:53 +03:00
|
|
|
|
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);
|
2011-02-01 20:41:03 +03:00
|
|
|
|
printf("weak_f3=%d\n", weak_f3 ? weak_f3() : 123);
|
2011-02-01 11:37:53 +03:00
|
|
|
|
printf("weak_v1=%d\n",&weak_v1 ? weak_v1 : 123);
|
|
|
|
|
printf("weak_v2=%d\n",&weak_v2 ? weak_v2 : 123);
|
2011-02-01 20:41:03 +03:00
|
|
|
|
printf("weak_v3=%d\n",&weak_v3 ? weak_v3 : 123);
|
2011-03-03 00:31:09 +03:00
|
|
|
|
|
|
|
|
|
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);
|
2015-07-29 23:53:57 +03:00
|
|
|
|
|
2011-03-03 11:55:02 +03:00
|
|
|
|
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);
|
2016-09-04 01:19:47 +03:00
|
|
|
|
printf("some_lib_func=%d\n", &some_lib_func ? some_lib_func() : 0);
|
2011-02-01 11:37:53 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int __attribute__((weak)) weak_f2() { return 222; }
|
2011-02-01 20:41:03 +03:00
|
|
|
|
int __attribute__((weak)) weak_f3() { return 333; }
|
2011-02-01 11:37:53 +03:00
|
|
|
|
int __attribute__((weak)) weak_v2 = 222;
|
2011-02-01 20:41:03 +03:00
|
|
|
|
int __attribute__((weak)) weak_v3 = 333;
|
2013-02-05 17:27:38 +04:00
|
|
|
|
#endif
|
2011-02-01 11:37:53 +03:00
|
|
|
|
|
2003-06-03 00:31:46 +04:00
|
|
|
|
void const_func(const int a)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void const_warn_test(void)
|
|
|
|
|
{
|
|
|
|
|
const_func(1);
|
|
|
|
|
}
|
2012-04-15 01:50:21 +04:00
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
2012-04-15 21:29:45 +04:00
|
|
|
|
|
|
|
|
|
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]);
|
|
|
|
|
}
|
2012-04-16 04:52:15 +04:00
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
}
|
2012-05-13 04:21:51 +04:00
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
2019-04-29 14:53:07 +03:00
|
|
|
|
return 0;
|
2012-05-13 04:21:51 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void math_cmp_test(void)
|
|
|
|
|
{
|
|
|
|
|
double nan = 0.0/0.0;
|
|
|
|
|
double one = 1.0;
|
|
|
|
|
double two = 2.0;
|
|
|
|
|
int comp = 0;
|
jump optimizations
This unifies VT_CMP with VT_JMP(i) by using mostly VT_CMP
with both a positive and a negative jump target list.
Such we can delay putting the non-inverted or inverted jump
until we can see which one is nore suitable (in most cases).
example:
if (a && b || c && d)
e = 0;
before this patch:
a: 8b 45 fc mov 0xfffffffc(%ebp),%eax
d: 83 f8 00 cmp $0x0,%eax
10: 0f 84 11 00 00 00 je 27 <main+0x27>
16: 8b 45 f8 mov 0xfffffff8(%ebp),%eax
19: 83 f8 00 cmp $0x0,%eax
1c: 0f 84 05 00 00 00 je 27 <main+0x27>
22: e9 22 00 00 00 jmp 49 <main+0x49>
27: 8b 45 f4 mov 0xfffffff4(%ebp),%eax
2a: 83 f8 00 cmp $0x0,%eax
2d: 0f 84 11 00 00 00 je 44 <main+0x44>
33: 8b 45 f0 mov 0xfffffff0(%ebp),%eax
36: 83 f8 00 cmp $0x0,%eax
39: 0f 84 05 00 00 00 je 44 <main+0x44>
3f: e9 05 00 00 00 jmp 49 <main+0x49>
44: e9 08 00 00 00 jmp 51 <main+0x51>
49: b8 00 00 00 00 mov $0x0,%eax
4e: 89 45 ec mov %eax,0xffffffec(%ebp)
51: ...
with this patch:
a: 8b 45 fc mov 0xfffffffc(%ebp),%eax
d: 83 f8 00 cmp $0x0,%eax
10: 0f 84 0c 00 00 00 je 22 <main+0x22>
16: 8b 45 f8 mov 0xfffffff8(%ebp),%eax
19: 83 f8 00 cmp $0x0,%eax
1c: 0f 85 18 00 00 00 jne 3a <main+0x3a>
22: 8b 45 f4 mov 0xfffffff4(%ebp),%eax
25: 83 f8 00 cmp $0x0,%eax
28: 0f 84 14 00 00 00 je 42 <main+0x42>
2e: 8b 45 f0 mov 0xfffffff0(%ebp),%eax
31: 83 f8 00 cmp $0x0,%eax
34: 0f 84 08 00 00 00 je 42 <main+0x42>
3a: b8 00 00 00 00 mov $0x0,%eax
3f: 89 45 ec mov %eax,0xffffffec(%ebp)
42: ...
2019-06-22 12:45:35 +03:00
|
|
|
|
int v;
|
2012-05-13 04:21:51 +04:00
|
|
|
|
#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 \
|
jump optimizations
This unifies VT_CMP with VT_JMP(i) by using mostly VT_CMP
with both a positive and a negative jump target list.
Such we can delay putting the non-inverted or inverted jump
until we can see which one is nore suitable (in most cases).
example:
if (a && b || c && d)
e = 0;
before this patch:
a: 8b 45 fc mov 0xfffffffc(%ebp),%eax
d: 83 f8 00 cmp $0x0,%eax
10: 0f 84 11 00 00 00 je 27 <main+0x27>
16: 8b 45 f8 mov 0xfffffff8(%ebp),%eax
19: 83 f8 00 cmp $0x0,%eax
1c: 0f 84 05 00 00 00 je 27 <main+0x27>
22: e9 22 00 00 00 jmp 49 <main+0x49>
27: 8b 45 f4 mov 0xfffffff4(%ebp),%eax
2a: 83 f8 00 cmp $0x0,%eax
2d: 0f 84 11 00 00 00 je 44 <main+0x44>
33: 8b 45 f0 mov 0xfffffff0(%ebp),%eax
36: 83 f8 00 cmp $0x0,%eax
39: 0f 84 05 00 00 00 je 44 <main+0x44>
3f: e9 05 00 00 00 jmp 49 <main+0x49>
44: e9 08 00 00 00 jmp 51 <main+0x51>
49: b8 00 00 00 00 mov $0x0,%eax
4e: 89 45 ec mov %eax,0xffffffec(%ebp)
51: ...
with this patch:
a: 8b 45 fc mov 0xfffffffc(%ebp),%eax
d: 83 f8 00 cmp $0x0,%eax
10: 0f 84 0c 00 00 00 je 22 <main+0x22>
16: 8b 45 f8 mov 0xfffffff8(%ebp),%eax
19: 83 f8 00 cmp $0x0,%eax
1c: 0f 85 18 00 00 00 jne 3a <main+0x3a>
22: 8b 45 f4 mov 0xfffffff4(%ebp),%eax
25: 83 f8 00 cmp $0x0,%eax
28: 0f 84 14 00 00 00 je 42 <main+0x42>
2e: 8b 45 f0 mov 0xfffffff0(%ebp),%eax
31: 83 f8 00 cmp $0x0,%eax
34: 0f 84 08 00 00 00 je 42 <main+0x42>
3a: b8 00 00 00 00 mov $0x0,%eax
3f: 89 45 ec mov %eax,0xffffffec(%ebp)
42: ...
2019-06-22 12:45:35 +03:00
|
|
|
|
bug (a,b,op,iop,5); \
|
|
|
|
|
if (v = !(a op b), !v) bug(a,b,op,iop,7);
|
2012-05-13 04:21:51 +04:00
|
|
|
|
|
|
|
|
|
/* 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);
|
|
|
|
|
}
|
2012-06-10 11:01:13 +04:00
|
|
|
|
|
|
|
|
|
double get100 () { return 100.0; }
|
|
|
|
|
|
|
|
|
|
void callsave_test(void)
|
|
|
|
|
{
|
2014-04-06 00:54:11 +04:00
|
|
|
|
#if defined __i386__ || defined __x86_64__ || defined __arm__
|
2012-06-10 11:01:13 +04:00
|
|
|
|
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);
|
2012-07-30 18:51:32 +04:00
|
|
|
|
#endif
|
2012-06-10 11:01:13 +04:00
|
|
|
|
}
|
Add support for __builtin_frame_address(level)
Continuing d6072d37 (Add __builtin_frame_address(0)) implement
__builtin_frame_address for levels greater than zero, in order for
tinycc to be able to compile its own lib/bcheck.c after
cffb7af9 (lib/bcheck: Prevent __bound_local_new / __bound_local_delete
from being miscompiled).
I'm new to the internals, and used the most simple way to do it.
Generated code is not very good for levels >= 2, compare
gcc tcc
level=0 mov %ebp,%eax lea 0x0(%ebp),%eax
level=1 mov 0x0(%ebp),%eax mov 0x0(%ebp),%eax
level=2 mov 0x0(%ebp),%eax mov 0x0(%ebp),%eax
mov (%eax),%eax mov %eax,-0x10(%ebp)
mov -0x10(%ebp),%eax
mov (%eax),%eax
level=3 mov 0x0(%ebp),%eax mov 0x0(%ebp),%eax
mov (%eax),%eax mov (%eax),%ecx
mov (%eax),%eax mov (%ecx),%eax
But this is still an improvement and for bcheck we need level=1 for
which the code is good.
For the tests I had to force gcc use -O0 to not inline the functions.
And -fno-omit-frame-pointer just in case.
If someone knows how to improve the generated code - help is
appreciated.
Thanks,
Kirill
Cc: Michael Matz <matz@suse.de>
Cc: Shinichiro Hamaji <shinichiro.hamaji@gmail.com>
2012-11-15 03:31:49 +04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
{
|
2014-02-03 08:26:49 +04:00
|
|
|
|
/* builtin_frame_address fails on ARM with gcc which make test3 fail */
|
|
|
|
|
#ifndef __arm__
|
Add support for __builtin_frame_address(level)
Continuing d6072d37 (Add __builtin_frame_address(0)) implement
__builtin_frame_address for levels greater than zero, in order for
tinycc to be able to compile its own lib/bcheck.c after
cffb7af9 (lib/bcheck: Prevent __bound_local_new / __bound_local_delete
from being miscompiled).
I'm new to the internals, and used the most simple way to do it.
Generated code is not very good for levels >= 2, compare
gcc tcc
level=0 mov %ebp,%eax lea 0x0(%ebp),%eax
level=1 mov 0x0(%ebp),%eax mov 0x0(%ebp),%eax
level=2 mov 0x0(%ebp),%eax mov 0x0(%ebp),%eax
mov (%eax),%eax mov %eax,-0x10(%ebp)
mov -0x10(%ebp),%eax
mov (%eax),%eax
level=3 mov 0x0(%ebp),%eax mov 0x0(%ebp),%eax
mov (%eax),%eax mov (%eax),%ecx
mov (%eax),%eax mov (%ecx),%eax
But this is still an improvement and for bcheck we need level=1 for
which the code is good.
For the tests I had to force gcc use -O0 to not inline the functions.
And -fno-omit-frame-pointer just in case.
If someone knows how to improve the generated code - help is
appreciated.
Thanks,
Kirill
Cc: Michael Matz <matz@suse.de>
Cc: Shinichiro Hamaji <shinichiro.hamaji@gmail.com>
2012-11-15 03:31:49 +04:00
|
|
|
|
char str[] = "__builtin_frame_address";
|
|
|
|
|
char *fp0 = __builtin_frame_address(0);
|
|
|
|
|
|
|
|
|
|
printf("str: %s\n", str);
|
2019-06-23 03:10:10 +03:00
|
|
|
|
#ifndef __riscv
|
Add support for __builtin_frame_address(level)
Continuing d6072d37 (Add __builtin_frame_address(0)) implement
__builtin_frame_address for levels greater than zero, in order for
tinycc to be able to compile its own lib/bcheck.c after
cffb7af9 (lib/bcheck: Prevent __bound_local_new / __bound_local_delete
from being miscompiled).
I'm new to the internals, and used the most simple way to do it.
Generated code is not very good for levels >= 2, compare
gcc tcc
level=0 mov %ebp,%eax lea 0x0(%ebp),%eax
level=1 mov 0x0(%ebp),%eax mov 0x0(%ebp),%eax
level=2 mov 0x0(%ebp),%eax mov 0x0(%ebp),%eax
mov (%eax),%eax mov %eax,-0x10(%ebp)
mov -0x10(%ebp),%eax
mov (%eax),%eax
level=3 mov 0x0(%ebp),%eax mov 0x0(%ebp),%eax
mov (%eax),%eax mov (%eax),%ecx
mov (%eax),%eax mov (%ecx),%eax
But this is still an improvement and for bcheck we need level=1 for
which the code is good.
For the tests I had to force gcc use -O0 to not inline the functions.
And -fno-omit-frame-pointer just in case.
If someone knows how to improve the generated code - help is
appreciated.
Thanks,
Kirill
Cc: Michael Matz <matz@suse.de>
Cc: Shinichiro Hamaji <shinichiro.hamaji@gmail.com>
2012-11-15 03:31:49 +04:00
|
|
|
|
bfa1(str-fp0);
|
2014-02-03 08:26:49 +04:00
|
|
|
|
#endif
|
2019-06-23 03:10:10 +03:00
|
|
|
|
#endif
|
Add support for __builtin_frame_address(level)
Continuing d6072d37 (Add __builtin_frame_address(0)) implement
__builtin_frame_address for levels greater than zero, in order for
tinycc to be able to compile its own lib/bcheck.c after
cffb7af9 (lib/bcheck: Prevent __bound_local_new / __bound_local_delete
from being miscompiled).
I'm new to the internals, and used the most simple way to do it.
Generated code is not very good for levels >= 2, compare
gcc tcc
level=0 mov %ebp,%eax lea 0x0(%ebp),%eax
level=1 mov 0x0(%ebp),%eax mov 0x0(%ebp),%eax
level=2 mov 0x0(%ebp),%eax mov 0x0(%ebp),%eax
mov (%eax),%eax mov %eax,-0x10(%ebp)
mov -0x10(%ebp),%eax
mov (%eax),%eax
level=3 mov 0x0(%ebp),%eax mov 0x0(%ebp),%eax
mov (%eax),%eax mov (%eax),%ecx
mov (%eax),%eax mov (%ecx),%eax
But this is still an improvement and for bcheck we need level=1 for
which the code is good.
For the tests I had to force gcc use -O0 to not inline the functions.
And -fno-omit-frame-pointer just in case.
If someone knows how to improve the generated code - help is
appreciated.
Thanks,
Kirill
Cc: Michael Matz <matz@suse.de>
Cc: Shinichiro Hamaji <shinichiro.hamaji@gmail.com>
2012-11-15 03:31:49 +04:00
|
|
|
|
}
|
2016-03-26 19:57:22 +03:00
|
|
|
|
|
|
|
|
|
char via_volatile (char i)
|
|
|
|
|
{
|
|
|
|
|
char volatile vi;
|
|
|
|
|
vi = i;
|
|
|
|
|
return vi;
|
|
|
|
|
}
|
2016-07-11 19:38:00 +03:00
|
|
|
|
|
|
|
|
|
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;
|
2016-10-09 01:52:57 +03:00
|
|
|
|
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;
|
2016-07-11 19:38:00 +03:00
|
|
|
|
void attrib_test(void)
|
|
|
|
|
{
|
2016-12-19 00:05:42 +03:00
|
|
|
|
#ifndef _WIN32
|
2016-07-11 19:38:00 +03:00
|
|
|
|
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));
|
2016-10-09 01:52:57 +03:00
|
|
|
|
printf("attr: %d %d\n", sizeof(gate_desc), sizeof(a_gate_desc));
|
2016-12-19 00:05:42 +03:00
|
|
|
|
#endif
|
2016-07-11 19:38:00 +03:00
|
|
|
|
}
|
2016-07-15 18:56:20 +03:00
|
|
|
|
extern __attribute__((__unused__)) char * __attribute__((__unused__)) *
|
|
|
|
|
strange_attrib_placement (void);
|
|
|
|
|
|
|
|
|
|
void * __attribute__((__unused__)) get_void_ptr (void *a)
|
|
|
|
|
{
|
|
|
|
|
return a;
|
|
|
|
|
}
|
2017-03-06 23:45:41 +03:00
|
|
|
|
|
|
|
|
|
/* 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);
|
|
|
|
|
}
|
2019-12-10 10:07:25 +03:00
|
|
|
|
|
2019-12-11 14:07:48 +03:00
|
|
|
|
#define pv(m) printf(sizeof (s->m + 0) == 8 ? "%016llx\n" : "%02x\n", s->m)
|
2019-12-10 10:07:25 +03:00
|
|
|
|
|
|
|
|
|
/* 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);
|
|
|
|
|
}
|