riscv: Support $ in identifiers in extended asm.
[tinycc.git] / tests / libtcc_test_mt.c
blobf9c90bd6d5160b8da06aff4fd40185de87c86c7d
1 /*
2 * Multi-thread Test for libtcc
3 */
5 #ifndef FIB
6 #include <stdlib.h>
7 #include <stdio.h>
8 #include <string.h>
9 #include <setjmp.h>
10 #include "libtcc.h"
12 #define M 20 /* number of states */
13 #define F(n) (n % 20 + 2) /* fib argument */
15 #ifdef _WIN32
16 #include <windows.h>
17 #define TF_TYPE(func, param) DWORD WINAPI func(void *param)
18 typedef TF_TYPE(ThreadFunc, x);
19 HANDLE hh[M];
20 void create_thread(ThreadFunc f, int n)
22 DWORD tid;
23 hh[n] = CreateThread(NULL, 0, f, (void*)(size_t)n, 0, &tid);
25 void wait_threads(int n)
27 WaitForMultipleObjects(n, hh, TRUE, INFINITE);
28 while (n)
29 CloseHandle(hh[--n]);
31 void sleep_ms(unsigned n)
33 Sleep(n);
35 #else
36 #include <sys/time.h>
37 #include <unistd.h>
38 #include <pthread.h>
39 #define TF_TYPE(func, param) void* func(void *param)
40 typedef TF_TYPE(ThreadFunc, x);
41 pthread_t hh[M];
42 void create_thread(ThreadFunc f, int n)
44 pthread_create(&hh[n], NULL, f, (void*)(size_t)n);
46 void wait_threads(int n)
48 while (n)
49 pthread_join(hh[--n], NULL);
52 void sleep_ms(unsigned n)
54 usleep(n * 1000);
56 #endif
58 void handle_error(void *opaque, const char *msg)
60 fprintf(opaque, "%s\n", msg);
63 /* this function is called by the generated code */
64 int add(int a, int b)
66 return a + b;
69 #define _str(s) #s
70 #define str(s) _str(s)
71 /* as a trick, prepend #line directive for better error/warning messages */
72 #define PROG(lbl) \
73 char lbl[] = "#line " str(__LINE__) " " str(__FILE__) "\n\n"
75 PROG(my_program)
76 "#include <tcclib.h>\n" /* include the "Simple libc header for TCC" */
77 "int add(int a, int b);\n"
78 "int fib(int n)\n"
79 "{\n"
80 " if (n <= 2)\n"
81 " return 1;\n"
82 " else\n"
83 " return add(fib(n-1),fib(n-2));\n"
84 "}\n"
85 "\n"
86 "void bar(void) { *(void**)0 = 0; }\n"
87 "\n"
88 "int foo(int n)\n"
89 "{\n"
90 " printf(\" %d\", fib(n));\n"
91 " if (n >= N_CRASH && n < N_CRASH + 8)\n"
92 " bar();\n"
93 " return 0;\n"
94 "# warning is this the correct file:line...\n"
95 "}\n";
97 int g_argc; char **g_argv;
99 void parse_args(TCCState *s)
101 int i;
102 /* if tcclib.h and libtcc1.a are not installed, where can we find them */
103 for (i = 1; i < g_argc; ++i) {
104 char *a = g_argv[i];
105 if (a[0] == '-') {
106 if (a[1] == 'B')
107 tcc_set_lib_path(s, a+2);
108 else if (a[1] == 'I')
109 tcc_add_include_path(s, a+2);
110 else if (a[1] == 'L')
111 tcc_add_library_path(s, a+2);
112 else if (a[1] == 'D')
113 tcc_define_symbol(s, a+2, NULL);
118 int backtrace_func(
119 void *ud,
120 void *pc,
121 const char *file,
122 int line,
123 const char *func,
124 const char *msg)
126 #if 0
127 printf("\n *** %p %s %s:%d in '%s'",
129 msg ? "at" : "by",
130 file ? file : "?",
131 line,
132 func ? func : "?");
133 return 1; // want more backtrace levels
134 #else
135 //printf(" [%d]", *(int*)ud);
136 printf("!");
137 return 0; // cancel backtrace
138 #endif
141 TCCState *new_state(int w)
143 TCCState *s = tcc_new();
144 if (!s) {
145 fprintf(stderr, __FILE__ ": could not create tcc state\n");
146 exit(1);
148 tcc_set_error_func(s, stdout, handle_error);
149 parse_args(s);
150 if (0 == (w & 1))
151 tcc_set_options(s, "-w");
152 if (w & 2) {
153 tcc_set_options(s, "-bt");
154 tcc_define_symbol(s, "N_CRASH", str(M/2));
155 } else
156 tcc_define_symbol(s, "N_CRASH", "-1000");
157 tcc_set_output_type(s, TCC_OUTPUT_MEMORY);
158 return s;
161 void *reloc_state(TCCState *s, const char *entry)
163 void *func;
164 tcc_add_symbol(s, "add", add);
165 if (tcc_relocate(s) < 0) {
166 fprintf(stderr, __FILE__ ": could not relocate tcc state.\n");
167 return NULL;
169 func = tcc_get_symbol(s, entry);
170 if (!func)
171 fprintf(stderr, __FILE__ ": could not get entry symbol.\n");
172 return func;
175 /* work with several states at the same time */
176 int state_test(int w)
178 TCCState *s[M];
179 int (*funcs[M])(int);
180 int n;
181 jmp_buf jb;
183 for (n = 0; n < M + 4; ++n) {
184 unsigned a = n, b = n - 1, c = n - 2, d = n - 3, e = n - 4;
185 if (a < M)
186 s[a] = new_state(w);
187 if (b < M)
188 if (tcc_compile_string(s[b], my_program) == -1)
189 break;
190 if (c < M)
191 funcs[c] = reloc_state(s[c], "foo");
192 if (d < M && funcs[d]) {
193 tcc_set_backtrace_func(s[d], &d, backtrace_func);
194 if (0 == tcc_setjmp(s[d], jb, funcs[d]))
195 funcs[d](F(d));
197 if (e < M)
198 tcc_delete(s[e]);
200 return 0;
203 /* simple compilation in threads */
204 TF_TYPE(thread_test_simple, vn)
206 TCCState *s;
207 int (*func)(int);
208 int ret;
209 int n = (size_t)vn;
210 jmp_buf jb;
212 s = new_state(0); /* '2' for exceptions */
213 sleep_ms(1);
214 ret = tcc_compile_string(s, my_program);
215 sleep_ms(1);
216 if (ret >= 0) {
217 func = reloc_state(s, "foo");
218 tcc_set_backtrace_func(s, &n, backtrace_func);
219 if (func) {
220 if (0 == tcc_setjmp(s, jb, func))
221 func(F(n));
224 tcc_delete(s);
225 return 0;
228 /* more complex compilation in threads */
229 TF_TYPE(thread_test_complex, vn)
231 TCCState *s;
232 int ret;
233 int n = (size_t)vn;
234 char *argv[30], b[10];
235 int argc = 0, i;
237 sprintf(b, "%d", F(n));
239 for (i = 1; i < g_argc; ++i) argv[argc++] = g_argv[i];
240 #if 0
241 argv[argc++] = "-run";
242 for (i = 1; i < g_argc; ++i) argv[argc++] = g_argv[i];
243 #endif
244 argv[argc++] = "-DFIB";
245 argv[argc++] = "-run";
246 argv[argc++] = __FILE__;
247 argv[argc++] = b;
248 argv[argc] = NULL;
250 s = new_state(1);
251 sleep_ms(2);
252 ret = tcc_add_file(s, argv[0]);
253 sleep_ms(3);
254 if (ret == 0)
255 tcc_run(s, argc, argv);
256 tcc_delete(s);
257 fflush(stdout);
258 return 0;
261 void time_tcc(int n, const char *src)
263 TCCState *s;
264 int ret, i = 0;
265 while (i++ < n) {
266 s = new_state(1);
267 printf(" %d", i), fflush(stdout);
268 ret = tcc_add_file(s, src);
269 tcc_delete(s);
270 if (ret < 0)
271 exit(1);
275 static unsigned getclock_ms(void)
277 #ifdef _WIN32
278 return GetTickCount();
279 #else
280 struct timeval tv;
281 gettimeofday(&tv, NULL);
282 return tv.tv_sec*1000 + (tv.tv_usec+500)/1000;
283 #endif
286 int main(int argc, char **argv)
288 int n;
289 unsigned t;
291 g_argc = argc;
292 g_argv = argv;
294 if (argc < 2) {
295 fprintf(stderr, "usage: libtcc_test_mt tcc.c <options>\n");
296 return 1;
299 #if 1
300 printf("running fib with mixed calls\n "), fflush(stdout);
301 t = getclock_ms();
302 state_test(0);
303 printf("\n (%u ms)\n", getclock_ms() - t);
304 #endif
305 #if 1
306 printf("producing some exceptions (!)\n "), fflush(stdout);
307 t = getclock_ms();
308 state_test(2);
309 printf("\n (%u ms)\n", getclock_ms() - t);
310 #endif
311 #if 1
312 //{ int i; for (i = 0; i < 100; ++i) { printf("(%d) ", i);
313 printf("running fib in threads\n "), fflush(stdout);
314 t = getclock_ms();
315 for (n = 0; n < M; ++n)
316 create_thread(thread_test_simple, n);
317 wait_threads(n);
318 printf("\n (%u ms)\n", getclock_ms() - t);
319 //}}
320 #endif
321 #if 1
322 printf("running tcc.c in threads to run fib\n "), fflush(stdout);
323 t = getclock_ms();
324 for (n = 0; n < M; ++n)
325 create_thread(thread_test_complex, n);
326 wait_threads(n);
327 printf("\n (%u ms)\n", getclock_ms() - t);
328 #endif
329 #if 1
330 printf("compiling tcc.c 10 times\n "), fflush(stdout);
331 t = getclock_ms();
332 time_tcc(10, argv[1]);
333 printf("\n (%u ms)\n", getclock_ms() - t), fflush(stdout);
334 #endif
335 return 0;
338 #else
339 #include <tcclib.h>
341 unsigned int sleep(unsigned int seconds);
343 int fib(n)
345 return (n <= 2) ? 1 : fib(n-1) + fib(n-2);
348 int main(int argc, char **argv)
350 sleep(1);
351 printf(" %d", fib(atoi(argv[1])));
352 return 0;
354 #endif