move preprocessor to tccpp.c
[tinycc.git] / tcc.c
blob41affbe85ffa8682ec85207aa6235e5f037406af
1 /*
2 * TCC - Tiny C Compiler
3 *
4 * Copyright (c) 2001-2004 Fabrice Bellard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "tcc.h"
23 #ifdef TCC_TARGET_I386
24 #include "i386-gen.c"
25 #endif
27 #ifdef TCC_TARGET_ARM
28 #include "arm-gen.c"
29 #endif
31 #ifdef TCC_TARGET_C67
32 #include "c67-gen.c"
33 #endif
35 #ifdef TCC_TARGET_X86_64
36 #include "x86_64-gen.c"
37 #endif
39 #ifdef CONFIG_TCC_STATIC
41 #define RTLD_LAZY 0x001
42 #define RTLD_NOW 0x002
43 #define RTLD_GLOBAL 0x100
44 #define RTLD_DEFAULT NULL
46 /* dummy function for profiling */
47 void *dlopen(const char *filename, int flag)
49 return NULL;
52 void dlclose(void *p)
56 const char *dlerror(void)
58 return "error";
61 typedef struct TCCSyms {
62 char *str;
63 void *ptr;
64 } TCCSyms;
66 #define TCCSYM(a) { #a, &a, },
68 /* add the symbol you want here if no dynamic linking is done */
69 static TCCSyms tcc_syms[] = {
70 #if !defined(CONFIG_TCCBOOT)
71 TCCSYM(printf)
72 TCCSYM(fprintf)
73 TCCSYM(fopen)
74 TCCSYM(fclose)
75 #endif
76 { NULL, NULL },
79 void *resolve_sym(TCCState *s1, const char *symbol, int type)
81 TCCSyms *p;
82 p = tcc_syms;
83 while (p->str != NULL) {
84 if (!strcmp(p->str, symbol))
85 return p->ptr;
86 p++;
88 return NULL;
91 #elif !defined(_WIN32)
93 #include <dlfcn.h>
95 void *resolve_sym(TCCState *s1, const char *sym, int type)
97 return dlsym(RTLD_DEFAULT, sym);
100 #endif
102 /********************************************************/
104 /* we use our own 'finite' function to avoid potential problems with
105 non standard math libs */
106 /* XXX: endianness dependent */
107 int ieee_finite(double d)
109 int *p = (int *)&d;
110 return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31;
113 /* copy a string and truncate it. */
114 static char *pstrcpy(char *buf, int buf_size, const char *s)
116 char *q, *q_end;
117 int c;
119 if (buf_size > 0) {
120 q = buf;
121 q_end = buf + buf_size - 1;
122 while (q < q_end) {
123 c = *s++;
124 if (c == '\0')
125 break;
126 *q++ = c;
128 *q = '\0';
130 return buf;
133 /* strcat and truncate. */
134 static char *pstrcat(char *buf, int buf_size, const char *s)
136 int len;
137 len = strlen(buf);
138 if (len < buf_size)
139 pstrcpy(buf + len, buf_size - len, s);
140 return buf;
143 #ifndef LIBTCC
144 static int strstart(const char *str, const char *val, const char **ptr)
146 const char *p, *q;
147 p = str;
148 q = val;
149 while (*q != '\0') {
150 if (*p != *q)
151 return 0;
152 p++;
153 q++;
155 if (ptr)
156 *ptr = p;
157 return 1;
159 #endif
161 #ifdef _WIN32
162 #define IS_PATHSEP(c) (c == '/' || c == '\\')
163 #define IS_ABSPATH(p) (IS_PATHSEP(p[0]) || (p[0] && p[1] == ':' && IS_PATHSEP(p[2])))
164 #define PATHCMP stricmp
165 #else
166 #define IS_PATHSEP(c) (c == '/')
167 #define IS_ABSPATH(p) IS_PATHSEP(p[0])
168 #define PATHCMP strcmp
169 #endif
171 /* extract the basename of a file */
172 static char *tcc_basename(const char *name)
174 char *p = strchr(name, 0);
175 while (p > name && !IS_PATHSEP(p[-1]))
176 --p;
177 return p;
180 static char *tcc_fileextension (const char *name)
182 char *b = tcc_basename(name);
183 char *e = strrchr(b, '.');
184 return e ? e : strchr(b, 0);
187 #ifdef _WIN32
188 char *normalize_slashes(char *path)
190 char *p;
191 for (p = path; *p; ++p)
192 if (*p == '\\')
193 *p = '/';
194 return path;
197 void tcc_set_lib_path_w32(TCCState *s)
199 /* on win32, we suppose the lib and includes are at the location
200 of 'tcc.exe' */
201 char path[1024], *p;
202 GetModuleFileNameA(NULL, path, sizeof path);
203 p = tcc_basename(normalize_slashes(strlwr(path)));
204 if (p - 5 > path && 0 == strncmp(p - 5, "/bin/", 5))
205 p -= 5;
206 else if (p > path)
207 p--;
208 *p = 0;
209 tcc_set_lib_path(s, path);
211 #endif
213 void set_pages_executable(void *ptr, unsigned long length)
215 #ifdef _WIN32
216 unsigned long old_protect;
217 VirtualProtect(ptr, length, PAGE_EXECUTE_READWRITE, &old_protect);
218 #else
219 unsigned long start, end;
220 start = (unsigned long)ptr & ~(PAGESIZE - 1);
221 end = (unsigned long)ptr + length;
222 end = (end + PAGESIZE - 1) & ~(PAGESIZE - 1);
223 mprotect((void *)start, end - start, PROT_READ | PROT_WRITE | PROT_EXEC);
224 #endif
227 /* memory management */
228 #ifdef MEM_DEBUG
229 int mem_cur_size;
230 int mem_max_size;
231 unsigned malloc_usable_size(void*);
232 #endif
234 static inline void tcc_free(void *ptr)
236 #ifdef MEM_DEBUG
237 mem_cur_size -= malloc_usable_size(ptr);
238 #endif
239 free(ptr);
242 static void *tcc_malloc(unsigned long size)
244 void *ptr;
245 ptr = malloc(size);
246 if (!ptr && size)
247 error("memory full");
248 #ifdef MEM_DEBUG
249 mem_cur_size += malloc_usable_size(ptr);
250 if (mem_cur_size > mem_max_size)
251 mem_max_size = mem_cur_size;
252 #endif
253 return ptr;
256 static void *tcc_mallocz(unsigned long size)
258 void *ptr;
259 ptr = tcc_malloc(size);
260 memset(ptr, 0, size);
261 return ptr;
264 static inline void *tcc_realloc(void *ptr, unsigned long size)
266 void *ptr1;
267 #ifdef MEM_DEBUG
268 mem_cur_size -= malloc_usable_size(ptr);
269 #endif
270 ptr1 = realloc(ptr, size);
271 #ifdef MEM_DEBUG
272 /* NOTE: count not correct if alloc error, but not critical */
273 mem_cur_size += malloc_usable_size(ptr1);
274 if (mem_cur_size > mem_max_size)
275 mem_max_size = mem_cur_size;
276 #endif
277 return ptr1;
280 static char *tcc_strdup(const char *str)
282 char *ptr;
283 ptr = tcc_malloc(strlen(str) + 1);
284 strcpy(ptr, str);
285 return ptr;
288 #define free(p) use_tcc_free(p)
289 #define malloc(s) use_tcc_malloc(s)
290 #define realloc(p, s) use_tcc_realloc(p, s)
292 static void dynarray_add(void ***ptab, int *nb_ptr, void *data)
294 int nb, nb_alloc;
295 void **pp;
297 nb = *nb_ptr;
298 pp = *ptab;
299 /* every power of two we double array size */
300 if ((nb & (nb - 1)) == 0) {
301 if (!nb)
302 nb_alloc = 1;
303 else
304 nb_alloc = nb * 2;
305 pp = tcc_realloc(pp, nb_alloc * sizeof(void *));
306 if (!pp)
307 error("memory full");
308 *ptab = pp;
310 pp[nb++] = data;
311 *nb_ptr = nb;
314 static void dynarray_reset(void *pp, int *n)
316 void **p;
317 for (p = *(void***)pp; *n; ++p, --*n)
318 if (*p)
319 tcc_free(*p);
320 tcc_free(*(void**)pp);
321 *(void**)pp = NULL;
324 /* symbol allocator */
325 static Sym *__sym_malloc(void)
327 Sym *sym_pool, *sym, *last_sym;
328 int i;
330 sym_pool = tcc_malloc(SYM_POOL_NB * sizeof(Sym));
331 dynarray_add(&sym_pools, &nb_sym_pools, sym_pool);
333 last_sym = sym_free_first;
334 sym = sym_pool;
335 for(i = 0; i < SYM_POOL_NB; i++) {
336 sym->next = last_sym;
337 last_sym = sym;
338 sym++;
340 sym_free_first = last_sym;
341 return last_sym;
344 static inline Sym *sym_malloc(void)
346 Sym *sym;
347 sym = sym_free_first;
348 if (!sym)
349 sym = __sym_malloc();
350 sym_free_first = sym->next;
351 return sym;
354 static inline void sym_free(Sym *sym)
356 sym->next = sym_free_first;
357 sym_free_first = sym;
360 Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags)
362 Section *sec;
364 sec = tcc_mallocz(sizeof(Section) + strlen(name));
365 strcpy(sec->name, name);
366 sec->sh_type = sh_type;
367 sec->sh_flags = sh_flags;
368 switch(sh_type) {
369 case SHT_HASH:
370 case SHT_REL:
371 case SHT_RELA:
372 case SHT_DYNSYM:
373 case SHT_SYMTAB:
374 case SHT_DYNAMIC:
375 sec->sh_addralign = 4;
376 break;
377 case SHT_STRTAB:
378 sec->sh_addralign = 1;
379 break;
380 default:
381 sec->sh_addralign = 32; /* default conservative alignment */
382 break;
385 if (sh_flags & SHF_PRIVATE) {
386 dynarray_add((void ***)&s1->priv_sections, &s1->nb_priv_sections, sec);
387 } else {
388 sec->sh_num = s1->nb_sections;
389 dynarray_add((void ***)&s1->sections, &s1->nb_sections, sec);
392 return sec;
395 static void free_section(Section *s)
397 tcc_free(s->data);
400 /* realloc section and set its content to zero */
401 static void section_realloc(Section *sec, unsigned long new_size)
403 unsigned long size;
404 unsigned char *data;
406 size = sec->data_allocated;
407 if (size == 0)
408 size = 1;
409 while (size < new_size)
410 size = size * 2;
411 data = tcc_realloc(sec->data, size);
412 if (!data)
413 error("memory full");
414 memset(data + sec->data_allocated, 0, size - sec->data_allocated);
415 sec->data = data;
416 sec->data_allocated = size;
419 /* reserve at least 'size' bytes in section 'sec' from
420 sec->data_offset. */
421 static void *section_ptr_add(Section *sec, unsigned long size)
423 unsigned long offset, offset1;
425 offset = sec->data_offset;
426 offset1 = offset + size;
427 if (offset1 > sec->data_allocated)
428 section_realloc(sec, offset1);
429 sec->data_offset = offset1;
430 return sec->data + offset;
433 /* return a reference to a section, and create it if it does not
434 exists */
435 Section *find_section(TCCState *s1, const char *name)
437 Section *sec;
438 int i;
439 for(i = 1; i < s1->nb_sections; i++) {
440 sec = s1->sections[i];
441 if (!strcmp(name, sec->name))
442 return sec;
444 /* sections are created as PROGBITS */
445 return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC);
448 #define SECTION_ABS ((void *)1)
450 /* update sym->c so that it points to an external symbol in section
451 'section' with value 'value' */
452 static void put_extern_sym2(Sym *sym, Section *section,
453 unsigned long value, unsigned long size,
454 int can_add_underscore)
456 int sym_type, sym_bind, sh_num, info, other, attr;
457 ElfW(Sym) *esym;
458 const char *name;
459 char buf1[256];
461 if (section == NULL)
462 sh_num = SHN_UNDEF;
463 else if (section == SECTION_ABS)
464 sh_num = SHN_ABS;
465 else
466 sh_num = section->sh_num;
468 other = attr = 0;
470 if ((sym->type.t & VT_BTYPE) == VT_FUNC) {
471 sym_type = STT_FUNC;
472 #ifdef TCC_TARGET_PE
473 if (sym->type.ref)
474 attr = sym->type.ref->r;
475 if (FUNC_EXPORT(attr))
476 other |= 1;
477 if (FUNC_CALL(attr) == FUNC_STDCALL)
478 other |= 2;
479 #endif
480 } else {
481 sym_type = STT_OBJECT;
484 if (sym->type.t & VT_STATIC)
485 sym_bind = STB_LOCAL;
486 else
487 sym_bind = STB_GLOBAL;
489 if (!sym->c) {
490 name = get_tok_str(sym->v, NULL);
491 #ifdef CONFIG_TCC_BCHECK
492 if (do_bounds_check) {
493 char buf[32];
495 /* XXX: avoid doing that for statics ? */
496 /* if bound checking is activated, we change some function
497 names by adding the "__bound" prefix */
498 switch(sym->v) {
499 #if 0
500 /* XXX: we rely only on malloc hooks */
501 case TOK_malloc:
502 case TOK_free:
503 case TOK_realloc:
504 case TOK_memalign:
505 case TOK_calloc:
506 #endif
507 case TOK_memcpy:
508 case TOK_memmove:
509 case TOK_memset:
510 case TOK_strlen:
511 case TOK_strcpy:
512 case TOK__alloca:
513 strcpy(buf, "__bound_");
514 strcat(buf, name);
515 name = buf;
516 break;
519 #endif
521 #ifdef TCC_TARGET_PE
522 if ((other & 2) && can_add_underscore) {
523 sprintf(buf1, "_%s@%d", name, FUNC_ARGS(attr));
524 name = buf1;
525 } else
526 #endif
527 if (tcc_state->leading_underscore && can_add_underscore) {
528 buf1[0] = '_';
529 pstrcpy(buf1 + 1, sizeof(buf1) - 1, name);
530 name = buf1;
532 info = ELFW(ST_INFO)(sym_bind, sym_type);
533 sym->c = add_elf_sym(symtab_section, value, size, info, other, sh_num, name);
534 } else {
535 esym = &((ElfW(Sym) *)symtab_section->data)[sym->c];
536 esym->st_value = value;
537 esym->st_size = size;
538 esym->st_shndx = sh_num;
539 esym->st_other |= other;
543 static void put_extern_sym(Sym *sym, Section *section,
544 unsigned long value, unsigned long size)
546 put_extern_sym2(sym, section, value, size, 1);
549 /* add a new relocation entry to symbol 'sym' in section 's' */
550 static void greloc(Section *s, Sym *sym, unsigned long offset, int type)
552 if (!sym->c)
553 put_extern_sym(sym, NULL, 0, 0);
554 /* now we can add ELF relocation info */
555 put_elf_reloc(symtab_section, s, offset, type, sym->c);
558 static inline int isid(int c)
560 return (c >= 'a' && c <= 'z') ||
561 (c >= 'A' && c <= 'Z') ||
562 c == '_';
565 static inline int isnum(int c)
567 return c >= '0' && c <= '9';
570 static inline int isoct(int c)
572 return c >= '0' && c <= '7';
575 static inline int toup(int c)
577 if (c >= 'a' && c <= 'z')
578 return c - 'a' + 'A';
579 else
580 return c;
583 static void strcat_vprintf(char *buf, int buf_size, const char *fmt, va_list ap)
585 int len;
586 len = strlen(buf);
587 vsnprintf(buf + len, buf_size - len, fmt, ap);
590 static void strcat_printf(char *buf, int buf_size, const char *fmt, ...)
592 va_list ap;
593 va_start(ap, fmt);
594 strcat_vprintf(buf, buf_size, fmt, ap);
595 va_end(ap);
598 void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap)
600 char buf[2048];
601 BufferedFile **f;
603 buf[0] = '\0';
604 if (file) {
605 for(f = s1->include_stack; f < s1->include_stack_ptr; f++)
606 strcat_printf(buf, sizeof(buf), "In file included from %s:%d:\n",
607 (*f)->filename, (*f)->line_num);
608 if (file->line_num > 0) {
609 strcat_printf(buf, sizeof(buf),
610 "%s:%d: ", file->filename, file->line_num);
611 } else {
612 strcat_printf(buf, sizeof(buf),
613 "%s: ", file->filename);
615 } else {
616 strcat_printf(buf, sizeof(buf),
617 "tcc: ");
619 if (is_warning)
620 strcat_printf(buf, sizeof(buf), "warning: ");
621 strcat_vprintf(buf, sizeof(buf), fmt, ap);
623 if (!s1->error_func) {
624 /* default case: stderr */
625 fprintf(stderr, "%s\n", buf);
626 } else {
627 s1->error_func(s1->error_opaque, buf);
629 if (!is_warning || s1->warn_error)
630 s1->nb_errors++;
633 #ifdef LIBTCC
634 void tcc_set_error_func(TCCState *s, void *error_opaque,
635 void (*error_func)(void *opaque, const char *msg))
637 s->error_opaque = error_opaque;
638 s->error_func = error_func;
640 #endif
642 /* error without aborting current compilation */
643 void error_noabort(const char *fmt, ...)
645 TCCState *s1 = tcc_state;
646 va_list ap;
648 va_start(ap, fmt);
649 error1(s1, 0, fmt, ap);
650 va_end(ap);
653 void error(const char *fmt, ...)
655 TCCState *s1 = tcc_state;
656 va_list ap;
658 va_start(ap, fmt);
659 error1(s1, 0, fmt, ap);
660 va_end(ap);
661 /* better than nothing: in some cases, we accept to handle errors */
662 if (s1->error_set_jmp_enabled) {
663 longjmp(s1->error_jmp_buf, 1);
664 } else {
665 /* XXX: eliminate this someday */
666 exit(1);
670 void expect(const char *msg)
672 error("%s expected", msg);
675 void warning(const char *fmt, ...)
677 TCCState *s1 = tcc_state;
678 va_list ap;
680 if (s1->warn_none)
681 return;
683 va_start(ap, fmt);
684 error1(s1, 1, fmt, ap);
685 va_end(ap);
688 void skip(int c)
690 if (tok != c)
691 error("'%c' expected", c);
692 next();
695 static void test_lvalue(void)
697 if (!(vtop->r & VT_LVAL))
698 expect("lvalue");
701 /* allocate a new token */
702 static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len)
704 TokenSym *ts, **ptable;
705 int i;
707 if (tok_ident >= SYM_FIRST_ANOM)
708 error("memory full");
710 /* expand token table if needed */
711 i = tok_ident - TOK_IDENT;
712 if ((i % TOK_ALLOC_INCR) == 0) {
713 ptable = tcc_realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
714 if (!ptable)
715 error("memory full");
716 table_ident = ptable;
719 ts = tcc_malloc(sizeof(TokenSym) + len);
720 table_ident[i] = ts;
721 ts->tok = tok_ident++;
722 ts->sym_define = NULL;
723 ts->sym_label = NULL;
724 ts->sym_struct = NULL;
725 ts->sym_identifier = NULL;
726 ts->len = len;
727 ts->hash_next = NULL;
728 memcpy(ts->str, str, len);
729 ts->str[len] = '\0';
730 *pts = ts;
731 return ts;
734 #define TOK_HASH_INIT 1
735 #define TOK_HASH_FUNC(h, c) ((h) * 263 + (c))
737 /* find a token and add it if not found */
738 static TokenSym *tok_alloc(const char *str, int len)
740 TokenSym *ts, **pts;
741 int i;
742 unsigned int h;
744 h = TOK_HASH_INIT;
745 for(i=0;i<len;i++)
746 h = TOK_HASH_FUNC(h, ((unsigned char *)str)[i]);
747 h &= (TOK_HASH_SIZE - 1);
749 pts = &hash_ident[h];
750 for(;;) {
751 ts = *pts;
752 if (!ts)
753 break;
754 if (ts->len == len && !memcmp(ts->str, str, len))
755 return ts;
756 pts = &(ts->hash_next);
758 return tok_alloc_new(pts, str, len);
761 /* CString handling */
763 static void cstr_realloc(CString *cstr, int new_size)
765 int size;
766 void *data;
768 size = cstr->size_allocated;
769 if (size == 0)
770 size = 8; /* no need to allocate a too small first string */
771 while (size < new_size)
772 size = size * 2;
773 data = tcc_realloc(cstr->data_allocated, size);
774 if (!data)
775 error("memory full");
776 cstr->data_allocated = data;
777 cstr->size_allocated = size;
778 cstr->data = data;
781 /* add a byte */
782 static inline void cstr_ccat(CString *cstr, int ch)
784 int size;
785 size = cstr->size + 1;
786 if (size > cstr->size_allocated)
787 cstr_realloc(cstr, size);
788 ((unsigned char *)cstr->data)[size - 1] = ch;
789 cstr->size = size;
792 static void cstr_cat(CString *cstr, const char *str)
794 int c;
795 for(;;) {
796 c = *str;
797 if (c == '\0')
798 break;
799 cstr_ccat(cstr, c);
800 str++;
804 /* add a wide char */
805 static void cstr_wccat(CString *cstr, int ch)
807 int size;
808 size = cstr->size + sizeof(nwchar_t);
809 if (size > cstr->size_allocated)
810 cstr_realloc(cstr, size);
811 *(nwchar_t *)(((unsigned char *)cstr->data) + size - sizeof(nwchar_t)) = ch;
812 cstr->size = size;
815 static void cstr_new(CString *cstr)
817 memset(cstr, 0, sizeof(CString));
820 /* free string and reset it to NULL */
821 static void cstr_free(CString *cstr)
823 tcc_free(cstr->data_allocated);
824 cstr_new(cstr);
827 #define cstr_reset(cstr) cstr_free(cstr)
829 /* XXX: unicode ? */
830 static void add_char(CString *cstr, int c)
832 if (c == '\'' || c == '\"' || c == '\\') {
833 /* XXX: could be more precise if char or string */
834 cstr_ccat(cstr, '\\');
836 if (c >= 32 && c <= 126) {
837 cstr_ccat(cstr, c);
838 } else {
839 cstr_ccat(cstr, '\\');
840 if (c == '\n') {
841 cstr_ccat(cstr, 'n');
842 } else {
843 cstr_ccat(cstr, '0' + ((c >> 6) & 7));
844 cstr_ccat(cstr, '0' + ((c >> 3) & 7));
845 cstr_ccat(cstr, '0' + (c & 7));
850 /* XXX: buffer overflow */
851 /* XXX: float tokens */
852 char *get_tok_str(int v, CValue *cv)
854 static char buf[STRING_MAX_SIZE + 1];
855 static CString cstr_buf;
856 CString *cstr;
857 unsigned char *q;
858 char *p;
859 int i, len;
861 /* NOTE: to go faster, we give a fixed buffer for small strings */
862 cstr_reset(&cstr_buf);
863 cstr_buf.data = buf;
864 cstr_buf.size_allocated = sizeof(buf);
865 p = buf;
867 switch(v) {
868 case TOK_CINT:
869 case TOK_CUINT:
870 /* XXX: not quite exact, but only useful for testing */
871 sprintf(p, "%u", cv->ui);
872 break;
873 case TOK_CLLONG:
874 case TOK_CULLONG:
875 /* XXX: not quite exact, but only useful for testing */
876 sprintf(p, "%Lu", cv->ull);
877 break;
878 case TOK_LCHAR:
879 cstr_ccat(&cstr_buf, 'L');
880 case TOK_CCHAR:
881 cstr_ccat(&cstr_buf, '\'');
882 add_char(&cstr_buf, cv->i);
883 cstr_ccat(&cstr_buf, '\'');
884 cstr_ccat(&cstr_buf, '\0');
885 break;
886 case TOK_PPNUM:
887 cstr = cv->cstr;
888 len = cstr->size - 1;
889 for(i=0;i<len;i++)
890 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
891 cstr_ccat(&cstr_buf, '\0');
892 break;
893 case TOK_LSTR:
894 cstr_ccat(&cstr_buf, 'L');
895 case TOK_STR:
896 cstr = cv->cstr;
897 cstr_ccat(&cstr_buf, '\"');
898 if (v == TOK_STR) {
899 len = cstr->size - 1;
900 for(i=0;i<len;i++)
901 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
902 } else {
903 len = (cstr->size / sizeof(nwchar_t)) - 1;
904 for(i=0;i<len;i++)
905 add_char(&cstr_buf, ((nwchar_t *)cstr->data)[i]);
907 cstr_ccat(&cstr_buf, '\"');
908 cstr_ccat(&cstr_buf, '\0');
909 break;
910 case TOK_LT:
911 v = '<';
912 goto addv;
913 case TOK_GT:
914 v = '>';
915 goto addv;
916 case TOK_DOTS:
917 return strcpy(p, "...");
918 case TOK_A_SHL:
919 return strcpy(p, "<<=");
920 case TOK_A_SAR:
921 return strcpy(p, ">>=");
922 default:
923 if (v < TOK_IDENT) {
924 /* search in two bytes table */
925 q = tok_two_chars;
926 while (*q) {
927 if (q[2] == v) {
928 *p++ = q[0];
929 *p++ = q[1];
930 *p = '\0';
931 return buf;
933 q += 3;
935 addv:
936 *p++ = v;
937 *p = '\0';
938 } else if (v < tok_ident) {
939 return table_ident[v - TOK_IDENT]->str;
940 } else if (v >= SYM_FIRST_ANOM) {
941 /* special name for anonymous symbol */
942 sprintf(p, "L.%u", v - SYM_FIRST_ANOM);
943 } else {
944 /* should never happen */
945 return NULL;
947 break;
949 return cstr_buf.data;
952 /* push, without hashing */
953 static Sym *sym_push2(Sym **ps, int v, int t, long c)
955 Sym *s;
956 s = sym_malloc();
957 s->v = v;
958 s->type.t = t;
959 s->c = c;
960 s->next = NULL;
961 /* add in stack */
962 s->prev = *ps;
963 *ps = s;
964 return s;
967 /* find a symbol and return its associated structure. 's' is the top
968 of the symbol stack */
969 static Sym *sym_find2(Sym *s, int v)
971 while (s) {
972 if (s->v == v)
973 return s;
974 s = s->prev;
976 return NULL;
979 /* structure lookup */
980 static inline Sym *struct_find(int v)
982 v -= TOK_IDENT;
983 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
984 return NULL;
985 return table_ident[v]->sym_struct;
988 /* find an identifier */
989 static inline Sym *sym_find(int v)
991 v -= TOK_IDENT;
992 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
993 return NULL;
994 return table_ident[v]->sym_identifier;
997 /* push a given symbol on the symbol stack */
998 static Sym *sym_push(int v, CType *type, int r, int c)
1000 Sym *s, **ps;
1001 TokenSym *ts;
1003 if (local_stack)
1004 ps = &local_stack;
1005 else
1006 ps = &global_stack;
1007 s = sym_push2(ps, v, type->t, c);
1008 s->type.ref = type->ref;
1009 s->r = r;
1010 /* don't record fields or anonymous symbols */
1011 /* XXX: simplify */
1012 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1013 /* record symbol in token array */
1014 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1015 if (v & SYM_STRUCT)
1016 ps = &ts->sym_struct;
1017 else
1018 ps = &ts->sym_identifier;
1019 s->prev_tok = *ps;
1020 *ps = s;
1022 return s;
1025 /* push a global identifier */
1026 static Sym *global_identifier_push(int v, int t, int c)
1028 Sym *s, **ps;
1029 s = sym_push2(&global_stack, v, t, c);
1030 /* don't record anonymous symbol */
1031 if (v < SYM_FIRST_ANOM) {
1032 ps = &table_ident[v - TOK_IDENT]->sym_identifier;
1033 /* modify the top most local identifier, so that
1034 sym_identifier will point to 's' when popped */
1035 while (*ps != NULL)
1036 ps = &(*ps)->prev_tok;
1037 s->prev_tok = NULL;
1038 *ps = s;
1040 return s;
1043 /* pop symbols until top reaches 'b' */
1044 static void sym_pop(Sym **ptop, Sym *b)
1046 Sym *s, *ss, **ps;
1047 TokenSym *ts;
1048 int v;
1050 s = *ptop;
1051 while(s != b) {
1052 ss = s->prev;
1053 v = s->v;
1054 /* remove symbol in token array */
1055 /* XXX: simplify */
1056 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1057 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1058 if (v & SYM_STRUCT)
1059 ps = &ts->sym_struct;
1060 else
1061 ps = &ts->sym_identifier;
1062 *ps = s->prev_tok;
1064 sym_free(s);
1065 s = ss;
1067 *ptop = b;
1070 /* I/O layer */
1072 BufferedFile *tcc_open(TCCState *s1, const char *filename)
1074 int fd;
1075 BufferedFile *bf;
1077 if (strcmp(filename, "-") == 0)
1078 fd = 0, filename = "stdin";
1079 else
1080 fd = open(filename, O_RDONLY | O_BINARY);
1081 if ((verbose == 2 && fd >= 0) || verbose == 3)
1082 printf("%s %*s%s\n", fd < 0 ? "nf":"->",
1083 (s1->include_stack_ptr - s1->include_stack), "", filename);
1084 if (fd < 0)
1085 return NULL;
1086 bf = tcc_malloc(sizeof(BufferedFile));
1087 bf->fd = fd;
1088 bf->buf_ptr = bf->buffer;
1089 bf->buf_end = bf->buffer;
1090 bf->buffer[0] = CH_EOB; /* put eob symbol */
1091 pstrcpy(bf->filename, sizeof(bf->filename), filename);
1092 #ifdef _WIN32
1093 normalize_slashes(bf->filename);
1094 #endif
1095 bf->line_num = 1;
1096 bf->ifndef_macro = 0;
1097 bf->ifdef_stack_ptr = s1->ifdef_stack_ptr;
1098 // printf("opening '%s'\n", filename);
1099 return bf;
1102 void tcc_close(BufferedFile *bf)
1104 total_lines += bf->line_num;
1105 close(bf->fd);
1106 tcc_free(bf);
1109 #include "tccpp.c"
1111 void swap(int *p, int *q)
1113 int t;
1114 t = *p;
1115 *p = *q;
1116 *q = t;
1119 void vsetc(CType *type, int r, CValue *vc)
1121 int v;
1123 if (vtop >= vstack + (VSTACK_SIZE - 1))
1124 error("memory full");
1125 /* cannot let cpu flags if other instruction are generated. Also
1126 avoid leaving VT_JMP anywhere except on the top of the stack
1127 because it would complicate the code generator. */
1128 if (vtop >= vstack) {
1129 v = vtop->r & VT_VALMASK;
1130 if (v == VT_CMP || (v & ~1) == VT_JMP)
1131 gv(RC_INT);
1133 vtop++;
1134 vtop->type = *type;
1135 vtop->r = r;
1136 vtop->r2 = VT_CONST;
1137 vtop->c = *vc;
1140 /* push integer constant */
1141 void vpushi(int v)
1143 CValue cval;
1144 cval.i = v;
1145 vsetc(&int_type, VT_CONST, &cval);
1148 /* push long long constant */
1149 void vpushll(long long v)
1151 CValue cval;
1152 CType ctype;
1153 ctype.t = VT_LLONG;
1154 cval.ull = v;
1155 vsetc(&ctype, VT_CONST, &cval);
1158 /* Return a static symbol pointing to a section */
1159 static Sym *get_sym_ref(CType *type, Section *sec,
1160 unsigned long offset, unsigned long size)
1162 int v;
1163 Sym *sym;
1165 v = anon_sym++;
1166 sym = global_identifier_push(v, type->t | VT_STATIC, 0);
1167 sym->type.ref = type->ref;
1168 sym->r = VT_CONST | VT_SYM;
1169 put_extern_sym(sym, sec, offset, size);
1170 return sym;
1173 /* push a reference to a section offset by adding a dummy symbol */
1174 static void vpush_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
1176 CValue cval;
1178 cval.ul = 0;
1179 vsetc(type, VT_CONST | VT_SYM, &cval);
1180 vtop->sym = get_sym_ref(type, sec, offset, size);
1183 /* define a new external reference to a symbol 'v' of type 'u' */
1184 static Sym *external_global_sym(int v, CType *type, int r)
1186 Sym *s;
1188 s = sym_find(v);
1189 if (!s) {
1190 /* push forward reference */
1191 s = global_identifier_push(v, type->t | VT_EXTERN, 0);
1192 s->type.ref = type->ref;
1193 s->r = r | VT_CONST | VT_SYM;
1195 return s;
1198 /* define a new external reference to a symbol 'v' of type 'u' */
1199 static Sym *external_sym(int v, CType *type, int r)
1201 Sym *s;
1203 s = sym_find(v);
1204 if (!s) {
1205 /* push forward reference */
1206 s = sym_push(v, type, r | VT_CONST | VT_SYM, 0);
1207 s->type.t |= VT_EXTERN;
1208 } else {
1209 if (!is_compatible_types(&s->type, type))
1210 error("incompatible types for redefinition of '%s'",
1211 get_tok_str(v, NULL));
1213 return s;
1216 /* push a reference to global symbol v */
1217 static void vpush_global_sym(CType *type, int v)
1219 Sym *sym;
1220 CValue cval;
1222 sym = external_global_sym(v, type, 0);
1223 cval.ul = 0;
1224 vsetc(type, VT_CONST | VT_SYM, &cval);
1225 vtop->sym = sym;
1228 void vset(CType *type, int r, int v)
1230 CValue cval;
1232 cval.i = v;
1233 vsetc(type, r, &cval);
1236 void vseti(int r, int v)
1238 CType type;
1239 type.t = VT_INT;
1240 vset(&type, r, v);
1243 void vswap(void)
1245 SValue tmp;
1247 tmp = vtop[0];
1248 vtop[0] = vtop[-1];
1249 vtop[-1] = tmp;
1252 void vpushv(SValue *v)
1254 if (vtop >= vstack + (VSTACK_SIZE - 1))
1255 error("memory full");
1256 vtop++;
1257 *vtop = *v;
1260 void vdup(void)
1262 vpushv(vtop);
1265 /* save r to the memory stack, and mark it as being free */
1266 void save_reg(int r)
1268 int l, saved, size, align;
1269 SValue *p, sv;
1270 CType *type;
1272 /* modify all stack values */
1273 saved = 0;
1274 l = 0;
1275 for(p=vstack;p<=vtop;p++) {
1276 if ((p->r & VT_VALMASK) == r ||
1277 ((p->type.t & VT_BTYPE) == VT_LLONG && (p->r2 & VT_VALMASK) == r)) {
1278 /* must save value on stack if not already done */
1279 if (!saved) {
1280 /* NOTE: must reload 'r' because r might be equal to r2 */
1281 r = p->r & VT_VALMASK;
1282 /* store register in the stack */
1283 type = &p->type;
1284 if ((p->r & VT_LVAL) ||
1285 (!is_float(type->t) && (type->t & VT_BTYPE) != VT_LLONG))
1286 #ifdef TCC_TARGET_X86_64
1287 type = &char_pointer_type;
1288 #else
1289 type = &int_type;
1290 #endif
1291 size = type_size(type, &align);
1292 loc = (loc - size) & -align;
1293 sv.type.t = type->t;
1294 sv.r = VT_LOCAL | VT_LVAL;
1295 sv.c.ul = loc;
1296 store(r, &sv);
1297 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
1298 /* x86 specific: need to pop fp register ST0 if saved */
1299 if (r == TREG_ST0) {
1300 o(0xd9dd); /* fstp %st(1) */
1302 #endif
1303 #ifndef TCC_TARGET_X86_64
1304 /* special long long case */
1305 if ((type->t & VT_BTYPE) == VT_LLONG) {
1306 sv.c.ul += 4;
1307 store(p->r2, &sv);
1309 #endif
1310 l = loc;
1311 saved = 1;
1313 /* mark that stack entry as being saved on the stack */
1314 if (p->r & VT_LVAL) {
1315 /* also clear the bounded flag because the
1316 relocation address of the function was stored in
1317 p->c.ul */
1318 p->r = (p->r & ~(VT_VALMASK | VT_BOUNDED)) | VT_LLOCAL;
1319 } else {
1320 p->r = lvalue_type(p->type.t) | VT_LOCAL;
1322 p->r2 = VT_CONST;
1323 p->c.ul = l;
1328 /* find a register of class 'rc2' with at most one reference on stack.
1329 * If none, call get_reg(rc) */
1330 int get_reg_ex(int rc, int rc2)
1332 int r;
1333 SValue *p;
1335 for(r=0;r<NB_REGS;r++) {
1336 if (reg_classes[r] & rc2) {
1337 int n;
1338 n=0;
1339 for(p = vstack; p <= vtop; p++) {
1340 if ((p->r & VT_VALMASK) == r ||
1341 (p->r2 & VT_VALMASK) == r)
1342 n++;
1344 if (n <= 1)
1345 return r;
1348 return get_reg(rc);
1351 /* find a free register of class 'rc'. If none, save one register */
1352 int get_reg(int rc)
1354 int r;
1355 SValue *p;
1357 /* find a free register */
1358 for(r=0;r<NB_REGS;r++) {
1359 if (reg_classes[r] & rc) {
1360 for(p=vstack;p<=vtop;p++) {
1361 if ((p->r & VT_VALMASK) == r ||
1362 (p->r2 & VT_VALMASK) == r)
1363 goto notfound;
1365 return r;
1367 notfound: ;
1370 /* no register left : free the first one on the stack (VERY
1371 IMPORTANT to start from the bottom to ensure that we don't
1372 spill registers used in gen_opi()) */
1373 for(p=vstack;p<=vtop;p++) {
1374 r = p->r & VT_VALMASK;
1375 if (r < VT_CONST && (reg_classes[r] & rc))
1376 goto save_found;
1377 /* also look at second register (if long long) */
1378 r = p->r2 & VT_VALMASK;
1379 if (r < VT_CONST && (reg_classes[r] & rc)) {
1380 save_found:
1381 save_reg(r);
1382 return r;
1385 /* Should never comes here */
1386 return -1;
1389 /* save registers up to (vtop - n) stack entry */
1390 void save_regs(int n)
1392 int r;
1393 SValue *p, *p1;
1394 p1 = vtop - n;
1395 for(p = vstack;p <= p1; p++) {
1396 r = p->r & VT_VALMASK;
1397 if (r < VT_CONST) {
1398 save_reg(r);
1403 /* move register 's' to 'r', and flush previous value of r to memory
1404 if needed */
1405 void move_reg(int r, int s)
1407 SValue sv;
1409 if (r != s) {
1410 save_reg(r);
1411 sv.type.t = VT_INT;
1412 sv.r = s;
1413 sv.c.ul = 0;
1414 load(r, &sv);
1418 /* get address of vtop (vtop MUST BE an lvalue) */
1419 void gaddrof(void)
1421 vtop->r &= ~VT_LVAL;
1422 /* tricky: if saved lvalue, then we can go back to lvalue */
1423 if ((vtop->r & VT_VALMASK) == VT_LLOCAL)
1424 vtop->r = (vtop->r & ~(VT_VALMASK | VT_LVAL_TYPE)) | VT_LOCAL | VT_LVAL;
1427 #ifdef CONFIG_TCC_BCHECK
1428 /* generate lvalue bound code */
1429 void gbound(void)
1431 int lval_type;
1432 CType type1;
1434 vtop->r &= ~VT_MUSTBOUND;
1435 /* if lvalue, then use checking code before dereferencing */
1436 if (vtop->r & VT_LVAL) {
1437 /* if not VT_BOUNDED value, then make one */
1438 if (!(vtop->r & VT_BOUNDED)) {
1439 lval_type = vtop->r & (VT_LVAL_TYPE | VT_LVAL);
1440 /* must save type because we must set it to int to get pointer */
1441 type1 = vtop->type;
1442 vtop->type.t = VT_INT;
1443 gaddrof();
1444 vpushi(0);
1445 gen_bounded_ptr_add();
1446 vtop->r |= lval_type;
1447 vtop->type = type1;
1449 /* then check for dereferencing */
1450 gen_bounded_ptr_deref();
1453 #endif
1455 /* store vtop a register belonging to class 'rc'. lvalues are
1456 converted to values. Cannot be used if cannot be converted to
1457 register value (such as structures). */
1458 int gv(int rc)
1460 int r, rc2, bit_pos, bit_size, size, align, i;
1462 /* NOTE: get_reg can modify vstack[] */
1463 if (vtop->type.t & VT_BITFIELD) {
1464 CType type;
1465 int bits = 32;
1466 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
1467 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
1468 /* remove bit field info to avoid loops */
1469 vtop->type.t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
1470 /* cast to int to propagate signedness in following ops */
1471 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
1472 type.t = VT_LLONG;
1473 bits = 64;
1474 } else
1475 type.t = VT_INT;
1476 if((vtop->type.t & VT_UNSIGNED) ||
1477 (vtop->type.t & VT_BTYPE) == VT_BOOL)
1478 type.t |= VT_UNSIGNED;
1479 gen_cast(&type);
1480 /* generate shifts */
1481 vpushi(bits - (bit_pos + bit_size));
1482 gen_op(TOK_SHL);
1483 vpushi(bits - bit_size);
1484 /* NOTE: transformed to SHR if unsigned */
1485 gen_op(TOK_SAR);
1486 r = gv(rc);
1487 } else {
1488 if (is_float(vtop->type.t) &&
1489 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
1490 Sym *sym;
1491 int *ptr;
1492 unsigned long offset;
1493 #if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP)
1494 CValue check;
1495 #endif
1497 /* XXX: unify with initializers handling ? */
1498 /* CPUs usually cannot use float constants, so we store them
1499 generically in data segment */
1500 size = type_size(&vtop->type, &align);
1501 offset = (data_section->data_offset + align - 1) & -align;
1502 data_section->data_offset = offset;
1503 /* XXX: not portable yet */
1504 #if defined(__i386__) || defined(__x86_64__)
1505 /* Zero pad x87 tenbyte long doubles */
1506 if (size == LDOUBLE_SIZE)
1507 vtop->c.tab[2] &= 0xffff;
1508 #endif
1509 ptr = section_ptr_add(data_section, size);
1510 size = size >> 2;
1511 #if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP)
1512 check.d = 1;
1513 if(check.tab[0])
1514 for(i=0;i<size;i++)
1515 ptr[i] = vtop->c.tab[size-1-i];
1516 else
1517 #endif
1518 for(i=0;i<size;i++)
1519 ptr[i] = vtop->c.tab[i];
1520 sym = get_sym_ref(&vtop->type, data_section, offset, size << 2);
1521 vtop->r |= VT_LVAL | VT_SYM;
1522 vtop->sym = sym;
1523 vtop->c.ul = 0;
1525 #ifdef CONFIG_TCC_BCHECK
1526 if (vtop->r & VT_MUSTBOUND)
1527 gbound();
1528 #endif
1530 r = vtop->r & VT_VALMASK;
1531 rc2 = RC_INT;
1532 if (rc == RC_IRET)
1533 rc2 = RC_LRET;
1534 /* need to reload if:
1535 - constant
1536 - lvalue (need to dereference pointer)
1537 - already a register, but not in the right class */
1538 if (r >= VT_CONST ||
1539 (vtop->r & VT_LVAL) ||
1540 !(reg_classes[r] & rc) ||
1541 ((vtop->type.t & VT_BTYPE) == VT_LLONG &&
1542 !(reg_classes[vtop->r2] & rc2))) {
1543 r = get_reg(rc);
1544 #ifndef TCC_TARGET_X86_64
1545 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
1546 int r2;
1547 unsigned long long ll;
1548 /* two register type load : expand to two words
1549 temporarily */
1550 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
1551 /* load constant */
1552 ll = vtop->c.ull;
1553 vtop->c.ui = ll; /* first word */
1554 load(r, vtop);
1555 vtop->r = r; /* save register value */
1556 vpushi(ll >> 32); /* second word */
1557 } else if (r >= VT_CONST || /* XXX: test to VT_CONST incorrect ? */
1558 (vtop->r & VT_LVAL)) {
1559 /* We do not want to modifier the long long
1560 pointer here, so the safest (and less
1561 efficient) is to save all the other registers
1562 in the stack. XXX: totally inefficient. */
1563 save_regs(1);
1564 /* load from memory */
1565 load(r, vtop);
1566 vdup();
1567 vtop[-1].r = r; /* save register value */
1568 /* increment pointer to get second word */
1569 vtop->type.t = VT_INT;
1570 gaddrof();
1571 vpushi(4);
1572 gen_op('+');
1573 vtop->r |= VT_LVAL;
1574 } else {
1575 /* move registers */
1576 load(r, vtop);
1577 vdup();
1578 vtop[-1].r = r; /* save register value */
1579 vtop->r = vtop[-1].r2;
1581 /* allocate second register */
1582 r2 = get_reg(rc2);
1583 load(r2, vtop);
1584 vpop();
1585 /* write second register */
1586 vtop->r2 = r2;
1587 } else
1588 #endif
1589 if ((vtop->r & VT_LVAL) && !is_float(vtop->type.t)) {
1590 int t1, t;
1591 /* lvalue of scalar type : need to use lvalue type
1592 because of possible cast */
1593 t = vtop->type.t;
1594 t1 = t;
1595 /* compute memory access type */
1596 if (vtop->r & VT_LVAL_BYTE)
1597 t = VT_BYTE;
1598 else if (vtop->r & VT_LVAL_SHORT)
1599 t = VT_SHORT;
1600 if (vtop->r & VT_LVAL_UNSIGNED)
1601 t |= VT_UNSIGNED;
1602 vtop->type.t = t;
1603 load(r, vtop);
1604 /* restore wanted type */
1605 vtop->type.t = t1;
1606 } else {
1607 /* one register type load */
1608 load(r, vtop);
1611 vtop->r = r;
1612 #ifdef TCC_TARGET_C67
1613 /* uses register pairs for doubles */
1614 if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)
1615 vtop->r2 = r+1;
1616 #endif
1618 return r;
1621 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
1622 void gv2(int rc1, int rc2)
1624 int v;
1626 /* generate more generic register first. But VT_JMP or VT_CMP
1627 values must be generated first in all cases to avoid possible
1628 reload errors */
1629 v = vtop[0].r & VT_VALMASK;
1630 if (v != VT_CMP && (v & ~1) != VT_JMP && rc1 <= rc2) {
1631 vswap();
1632 gv(rc1);
1633 vswap();
1634 gv(rc2);
1635 /* test if reload is needed for first register */
1636 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
1637 vswap();
1638 gv(rc1);
1639 vswap();
1641 } else {
1642 gv(rc2);
1643 vswap();
1644 gv(rc1);
1645 vswap();
1646 /* test if reload is needed for first register */
1647 if ((vtop[0].r & VT_VALMASK) >= VT_CONST) {
1648 gv(rc2);
1653 /* wrapper around RC_FRET to return a register by type */
1654 int rc_fret(int t)
1656 #ifdef TCC_TARGET_X86_64
1657 if (t == VT_LDOUBLE) {
1658 return RC_ST0;
1660 #endif
1661 return RC_FRET;
1664 /* wrapper around REG_FRET to return a register by type */
1665 int reg_fret(int t)
1667 #ifdef TCC_TARGET_X86_64
1668 if (t == VT_LDOUBLE) {
1669 return TREG_ST0;
1671 #endif
1672 return REG_FRET;
1675 /* expand long long on stack in two int registers */
1676 void lexpand(void)
1678 int u;
1680 u = vtop->type.t & VT_UNSIGNED;
1681 gv(RC_INT);
1682 vdup();
1683 vtop[0].r = vtop[-1].r2;
1684 vtop[0].r2 = VT_CONST;
1685 vtop[-1].r2 = VT_CONST;
1686 vtop[0].type.t = VT_INT | u;
1687 vtop[-1].type.t = VT_INT | u;
1690 #ifdef TCC_TARGET_ARM
1691 /* expand long long on stack */
1692 void lexpand_nr(void)
1694 int u,v;
1696 u = vtop->type.t & VT_UNSIGNED;
1697 vdup();
1698 vtop->r2 = VT_CONST;
1699 vtop->type.t = VT_INT | u;
1700 v=vtop[-1].r & (VT_VALMASK | VT_LVAL);
1701 if (v == VT_CONST) {
1702 vtop[-1].c.ui = vtop->c.ull;
1703 vtop->c.ui = vtop->c.ull >> 32;
1704 vtop->r = VT_CONST;
1705 } else if (v == (VT_LVAL|VT_CONST) || v == (VT_LVAL|VT_LOCAL)) {
1706 vtop->c.ui += 4;
1707 vtop->r = vtop[-1].r;
1708 } else if (v > VT_CONST) {
1709 vtop--;
1710 lexpand();
1711 } else
1712 vtop->r = vtop[-1].r2;
1713 vtop[-1].r2 = VT_CONST;
1714 vtop[-1].type.t = VT_INT | u;
1716 #endif
1718 /* build a long long from two ints */
1719 void lbuild(int t)
1721 gv2(RC_INT, RC_INT);
1722 vtop[-1].r2 = vtop[0].r;
1723 vtop[-1].type.t = t;
1724 vpop();
1727 /* rotate n first stack elements to the bottom
1728 I1 ... In -> I2 ... In I1 [top is right]
1730 void vrotb(int n)
1732 int i;
1733 SValue tmp;
1735 tmp = vtop[-n + 1];
1736 for(i=-n+1;i!=0;i++)
1737 vtop[i] = vtop[i+1];
1738 vtop[0] = tmp;
1741 /* rotate n first stack elements to the top
1742 I1 ... In -> In I1 ... I(n-1) [top is right]
1744 void vrott(int n)
1746 int i;
1747 SValue tmp;
1749 tmp = vtop[0];
1750 for(i = 0;i < n - 1; i++)
1751 vtop[-i] = vtop[-i - 1];
1752 vtop[-n + 1] = tmp;
1755 #ifdef TCC_TARGET_ARM
1756 /* like vrott but in other direction
1757 In ... I1 -> I(n-1) ... I1 In [top is right]
1759 void vnrott(int n)
1761 int i;
1762 SValue tmp;
1764 tmp = vtop[-n + 1];
1765 for(i = n - 1; i > 0; i--)
1766 vtop[-i] = vtop[-i + 1];
1767 vtop[0] = tmp;
1769 #endif
1771 /* pop stack value */
1772 void vpop(void)
1774 int v;
1775 v = vtop->r & VT_VALMASK;
1776 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
1777 /* for x86, we need to pop the FP stack */
1778 if (v == TREG_ST0 && !nocode_wanted) {
1779 o(0xd9dd); /* fstp %st(1) */
1780 } else
1781 #endif
1782 if (v == VT_JMP || v == VT_JMPI) {
1783 /* need to put correct jump if && or || without test */
1784 gsym(vtop->c.ul);
1786 vtop--;
1789 /* convert stack entry to register and duplicate its value in another
1790 register */
1791 void gv_dup(void)
1793 int rc, t, r, r1;
1794 SValue sv;
1796 t = vtop->type.t;
1797 if ((t & VT_BTYPE) == VT_LLONG) {
1798 lexpand();
1799 gv_dup();
1800 vswap();
1801 vrotb(3);
1802 gv_dup();
1803 vrotb(4);
1804 /* stack: H L L1 H1 */
1805 lbuild(t);
1806 vrotb(3);
1807 vrotb(3);
1808 vswap();
1809 lbuild(t);
1810 vswap();
1811 } else {
1812 /* duplicate value */
1813 rc = RC_INT;
1814 sv.type.t = VT_INT;
1815 if (is_float(t)) {
1816 rc = RC_FLOAT;
1817 #ifdef TCC_TARGET_X86_64
1818 if ((t & VT_BTYPE) == VT_LDOUBLE) {
1819 rc = RC_ST0;
1821 #endif
1822 sv.type.t = t;
1824 r = gv(rc);
1825 r1 = get_reg(rc);
1826 sv.r = r;
1827 sv.c.ul = 0;
1828 load(r1, &sv); /* move r to r1 */
1829 vdup();
1830 /* duplicates value */
1831 vtop->r = r1;
1835 #ifndef TCC_TARGET_X86_64
1836 /* generate CPU independent (unsigned) long long operations */
1837 void gen_opl(int op)
1839 int t, a, b, op1, c, i;
1840 int func;
1841 unsigned short reg_iret = REG_IRET;
1842 unsigned short reg_lret = REG_LRET;
1843 SValue tmp;
1845 switch(op) {
1846 case '/':
1847 case TOK_PDIV:
1848 func = TOK___divdi3;
1849 goto gen_func;
1850 case TOK_UDIV:
1851 func = TOK___udivdi3;
1852 goto gen_func;
1853 case '%':
1854 func = TOK___moddi3;
1855 goto gen_mod_func;
1856 case TOK_UMOD:
1857 func = TOK___umoddi3;
1858 gen_mod_func:
1859 #ifdef TCC_ARM_EABI
1860 reg_iret = TREG_R2;
1861 reg_lret = TREG_R3;
1862 #endif
1863 gen_func:
1864 /* call generic long long function */
1865 vpush_global_sym(&func_old_type, func);
1866 vrott(3);
1867 gfunc_call(2);
1868 vpushi(0);
1869 vtop->r = reg_iret;
1870 vtop->r2 = reg_lret;
1871 break;
1872 case '^':
1873 case '&':
1874 case '|':
1875 case '*':
1876 case '+':
1877 case '-':
1878 t = vtop->type.t;
1879 vswap();
1880 lexpand();
1881 vrotb(3);
1882 lexpand();
1883 /* stack: L1 H1 L2 H2 */
1884 tmp = vtop[0];
1885 vtop[0] = vtop[-3];
1886 vtop[-3] = tmp;
1887 tmp = vtop[-2];
1888 vtop[-2] = vtop[-3];
1889 vtop[-3] = tmp;
1890 vswap();
1891 /* stack: H1 H2 L1 L2 */
1892 if (op == '*') {
1893 vpushv(vtop - 1);
1894 vpushv(vtop - 1);
1895 gen_op(TOK_UMULL);
1896 lexpand();
1897 /* stack: H1 H2 L1 L2 ML MH */
1898 for(i=0;i<4;i++)
1899 vrotb(6);
1900 /* stack: ML MH H1 H2 L1 L2 */
1901 tmp = vtop[0];
1902 vtop[0] = vtop[-2];
1903 vtop[-2] = tmp;
1904 /* stack: ML MH H1 L2 H2 L1 */
1905 gen_op('*');
1906 vrotb(3);
1907 vrotb(3);
1908 gen_op('*');
1909 /* stack: ML MH M1 M2 */
1910 gen_op('+');
1911 gen_op('+');
1912 } else if (op == '+' || op == '-') {
1913 /* XXX: add non carry method too (for MIPS or alpha) */
1914 if (op == '+')
1915 op1 = TOK_ADDC1;
1916 else
1917 op1 = TOK_SUBC1;
1918 gen_op(op1);
1919 /* stack: H1 H2 (L1 op L2) */
1920 vrotb(3);
1921 vrotb(3);
1922 gen_op(op1 + 1); /* TOK_xxxC2 */
1923 } else {
1924 gen_op(op);
1925 /* stack: H1 H2 (L1 op L2) */
1926 vrotb(3);
1927 vrotb(3);
1928 /* stack: (L1 op L2) H1 H2 */
1929 gen_op(op);
1930 /* stack: (L1 op L2) (H1 op H2) */
1932 /* stack: L H */
1933 lbuild(t);
1934 break;
1935 case TOK_SAR:
1936 case TOK_SHR:
1937 case TOK_SHL:
1938 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
1939 t = vtop[-1].type.t;
1940 vswap();
1941 lexpand();
1942 vrotb(3);
1943 /* stack: L H shift */
1944 c = (int)vtop->c.i;
1945 /* constant: simpler */
1946 /* NOTE: all comments are for SHL. the other cases are
1947 done by swaping words */
1948 vpop();
1949 if (op != TOK_SHL)
1950 vswap();
1951 if (c >= 32) {
1952 /* stack: L H */
1953 vpop();
1954 if (c > 32) {
1955 vpushi(c - 32);
1956 gen_op(op);
1958 if (op != TOK_SAR) {
1959 vpushi(0);
1960 } else {
1961 gv_dup();
1962 vpushi(31);
1963 gen_op(TOK_SAR);
1965 vswap();
1966 } else {
1967 vswap();
1968 gv_dup();
1969 /* stack: H L L */
1970 vpushi(c);
1971 gen_op(op);
1972 vswap();
1973 vpushi(32 - c);
1974 if (op == TOK_SHL)
1975 gen_op(TOK_SHR);
1976 else
1977 gen_op(TOK_SHL);
1978 vrotb(3);
1979 /* stack: L L H */
1980 vpushi(c);
1981 if (op == TOK_SHL)
1982 gen_op(TOK_SHL);
1983 else
1984 gen_op(TOK_SHR);
1985 gen_op('|');
1987 if (op != TOK_SHL)
1988 vswap();
1989 lbuild(t);
1990 } else {
1991 /* XXX: should provide a faster fallback on x86 ? */
1992 switch(op) {
1993 case TOK_SAR:
1994 func = TOK___ashrdi3;
1995 goto gen_func;
1996 case TOK_SHR:
1997 func = TOK___lshrdi3;
1998 goto gen_func;
1999 case TOK_SHL:
2000 func = TOK___ashldi3;
2001 goto gen_func;
2004 break;
2005 default:
2006 /* compare operations */
2007 t = vtop->type.t;
2008 vswap();
2009 lexpand();
2010 vrotb(3);
2011 lexpand();
2012 /* stack: L1 H1 L2 H2 */
2013 tmp = vtop[-1];
2014 vtop[-1] = vtop[-2];
2015 vtop[-2] = tmp;
2016 /* stack: L1 L2 H1 H2 */
2017 /* compare high */
2018 op1 = op;
2019 /* when values are equal, we need to compare low words. since
2020 the jump is inverted, we invert the test too. */
2021 if (op1 == TOK_LT)
2022 op1 = TOK_LE;
2023 else if (op1 == TOK_GT)
2024 op1 = TOK_GE;
2025 else if (op1 == TOK_ULT)
2026 op1 = TOK_ULE;
2027 else if (op1 == TOK_UGT)
2028 op1 = TOK_UGE;
2029 a = 0;
2030 b = 0;
2031 gen_op(op1);
2032 if (op1 != TOK_NE) {
2033 a = gtst(1, 0);
2035 if (op != TOK_EQ) {
2036 /* generate non equal test */
2037 /* XXX: NOT PORTABLE yet */
2038 if (a == 0) {
2039 b = gtst(0, 0);
2040 } else {
2041 #if defined(TCC_TARGET_I386)
2042 b = psym(0x850f, 0);
2043 #elif defined(TCC_TARGET_ARM)
2044 b = ind;
2045 o(0x1A000000 | encbranch(ind, 0, 1));
2046 #elif defined(TCC_TARGET_C67)
2047 error("not implemented");
2048 #else
2049 #error not supported
2050 #endif
2053 /* compare low. Always unsigned */
2054 op1 = op;
2055 if (op1 == TOK_LT)
2056 op1 = TOK_ULT;
2057 else if (op1 == TOK_LE)
2058 op1 = TOK_ULE;
2059 else if (op1 == TOK_GT)
2060 op1 = TOK_UGT;
2061 else if (op1 == TOK_GE)
2062 op1 = TOK_UGE;
2063 gen_op(op1);
2064 a = gtst(1, a);
2065 gsym(b);
2066 vseti(VT_JMPI, a);
2067 break;
2070 #endif
2072 /* handle integer constant optimizations and various machine
2073 independent opt */
2074 void gen_opic(int op)
2076 int c1, c2, t1, t2, n;
2077 SValue *v1, *v2;
2078 long long l1, l2;
2079 typedef unsigned long long U;
2081 v1 = vtop - 1;
2082 v2 = vtop;
2083 t1 = v1->type.t & VT_BTYPE;
2084 t2 = v2->type.t & VT_BTYPE;
2086 if (t1 == VT_LLONG)
2087 l1 = v1->c.ll;
2088 else if (v1->type.t & VT_UNSIGNED)
2089 l1 = v1->c.ui;
2090 else
2091 l1 = v1->c.i;
2093 if (t2 == VT_LLONG)
2094 l2 = v2->c.ll;
2095 else if (v2->type.t & VT_UNSIGNED)
2096 l2 = v2->c.ui;
2097 else
2098 l2 = v2->c.i;
2100 /* currently, we cannot do computations with forward symbols */
2101 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
2102 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
2103 if (c1 && c2) {
2104 switch(op) {
2105 case '+': l1 += l2; break;
2106 case '-': l1 -= l2; break;
2107 case '&': l1 &= l2; break;
2108 case '^': l1 ^= l2; break;
2109 case '|': l1 |= l2; break;
2110 case '*': l1 *= l2; break;
2112 case TOK_PDIV:
2113 case '/':
2114 case '%':
2115 case TOK_UDIV:
2116 case TOK_UMOD:
2117 /* if division by zero, generate explicit division */
2118 if (l2 == 0) {
2119 if (const_wanted)
2120 error("division by zero in constant");
2121 goto general_case;
2123 switch(op) {
2124 default: l1 /= l2; break;
2125 case '%': l1 %= l2; break;
2126 case TOK_UDIV: l1 = (U)l1 / l2; break;
2127 case TOK_UMOD: l1 = (U)l1 % l2; break;
2129 break;
2130 case TOK_SHL: l1 <<= l2; break;
2131 case TOK_SHR: l1 = (U)l1 >> l2; break;
2132 case TOK_SAR: l1 >>= l2; break;
2133 /* tests */
2134 case TOK_ULT: l1 = (U)l1 < (U)l2; break;
2135 case TOK_UGE: l1 = (U)l1 >= (U)l2; break;
2136 case TOK_EQ: l1 = l1 == l2; break;
2137 case TOK_NE: l1 = l1 != l2; break;
2138 case TOK_ULE: l1 = (U)l1 <= (U)l2; break;
2139 case TOK_UGT: l1 = (U)l1 > (U)l2; break;
2140 case TOK_LT: l1 = l1 < l2; break;
2141 case TOK_GE: l1 = l1 >= l2; break;
2142 case TOK_LE: l1 = l1 <= l2; break;
2143 case TOK_GT: l1 = l1 > l2; break;
2144 /* logical */
2145 case TOK_LAND: l1 = l1 && l2; break;
2146 case TOK_LOR: l1 = l1 || l2; break;
2147 default:
2148 goto general_case;
2150 v1->c.ll = l1;
2151 vtop--;
2152 } else {
2153 /* if commutative ops, put c2 as constant */
2154 if (c1 && (op == '+' || op == '&' || op == '^' ||
2155 op == '|' || op == '*')) {
2156 vswap();
2157 c2 = c1; //c = c1, c1 = c2, c2 = c;
2158 l2 = l1; //l = l1, l1 = l2, l2 = l;
2160 /* Filter out NOP operations like x*1, x-0, x&-1... */
2161 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
2162 op == TOK_PDIV) &&
2163 l2 == 1) ||
2164 ((op == '+' || op == '-' || op == '|' || op == '^' ||
2165 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
2166 l2 == 0) ||
2167 (op == '&' &&
2168 l2 == -1))) {
2169 /* nothing to do */
2170 vtop--;
2171 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
2172 /* try to use shifts instead of muls or divs */
2173 if (l2 > 0 && (l2 & (l2 - 1)) == 0) {
2174 n = -1;
2175 while (l2) {
2176 l2 >>= 1;
2177 n++;
2179 vtop->c.ll = n;
2180 if (op == '*')
2181 op = TOK_SHL;
2182 else if (op == TOK_PDIV)
2183 op = TOK_SAR;
2184 else
2185 op = TOK_SHR;
2187 goto general_case;
2188 } else if (c2 && (op == '+' || op == '-') &&
2189 ((vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) ==
2190 (VT_CONST | VT_SYM) ||
2191 (vtop[-1].r & (VT_VALMASK | VT_LVAL)) == VT_LOCAL)) {
2192 /* symbol + constant case */
2193 if (op == '-')
2194 l2 = -l2;
2195 vtop--;
2196 vtop->c.ll += l2;
2197 } else {
2198 general_case:
2199 if (!nocode_wanted) {
2200 /* call low level op generator */
2201 if (t1 == VT_LLONG || t2 == VT_LLONG)
2202 gen_opl(op);
2203 else
2204 gen_opi(op);
2205 } else {
2206 vtop--;
2212 /* generate a floating point operation with constant propagation */
2213 void gen_opif(int op)
2215 int c1, c2;
2216 SValue *v1, *v2;
2217 long double f1, f2;
2219 v1 = vtop - 1;
2220 v2 = vtop;
2221 /* currently, we cannot do computations with forward symbols */
2222 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
2223 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
2224 if (c1 && c2) {
2225 if (v1->type.t == VT_FLOAT) {
2226 f1 = v1->c.f;
2227 f2 = v2->c.f;
2228 } else if (v1->type.t == VT_DOUBLE) {
2229 f1 = v1->c.d;
2230 f2 = v2->c.d;
2231 } else {
2232 f1 = v1->c.ld;
2233 f2 = v2->c.ld;
2236 /* NOTE: we only do constant propagation if finite number (not
2237 NaN or infinity) (ANSI spec) */
2238 if (!ieee_finite(f1) || !ieee_finite(f2))
2239 goto general_case;
2241 switch(op) {
2242 case '+': f1 += f2; break;
2243 case '-': f1 -= f2; break;
2244 case '*': f1 *= f2; break;
2245 case '/':
2246 if (f2 == 0.0) {
2247 if (const_wanted)
2248 error("division by zero in constant");
2249 goto general_case;
2251 f1 /= f2;
2252 break;
2253 /* XXX: also handles tests ? */
2254 default:
2255 goto general_case;
2257 /* XXX: overflow test ? */
2258 if (v1->type.t == VT_FLOAT) {
2259 v1->c.f = f1;
2260 } else if (v1->type.t == VT_DOUBLE) {
2261 v1->c.d = f1;
2262 } else {
2263 v1->c.ld = f1;
2265 vtop--;
2266 } else {
2267 general_case:
2268 if (!nocode_wanted) {
2269 gen_opf(op);
2270 } else {
2271 vtop--;
2276 static int pointed_size(CType *type)
2278 int align;
2279 return type_size(pointed_type(type), &align);
2282 static inline int is_null_pointer(SValue *p)
2284 if ((p->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
2285 return 0;
2286 return ((p->type.t & VT_BTYPE) == VT_INT && p->c.i == 0) ||
2287 ((p->type.t & VT_BTYPE) == VT_LLONG && p->c.ll == 0);
2290 static inline int is_integer_btype(int bt)
2292 return (bt == VT_BYTE || bt == VT_SHORT ||
2293 bt == VT_INT || bt == VT_LLONG);
2296 /* check types for comparison or substraction of pointers */
2297 static void check_comparison_pointer_types(SValue *p1, SValue *p2, int op)
2299 CType *type1, *type2, tmp_type1, tmp_type2;
2300 int bt1, bt2;
2302 /* null pointers are accepted for all comparisons as gcc */
2303 if (is_null_pointer(p1) || is_null_pointer(p2))
2304 return;
2305 type1 = &p1->type;
2306 type2 = &p2->type;
2307 bt1 = type1->t & VT_BTYPE;
2308 bt2 = type2->t & VT_BTYPE;
2309 /* accept comparison between pointer and integer with a warning */
2310 if ((is_integer_btype(bt1) || is_integer_btype(bt2)) && op != '-') {
2311 if (op != TOK_LOR && op != TOK_LAND )
2312 warning("comparison between pointer and integer");
2313 return;
2316 /* both must be pointers or implicit function pointers */
2317 if (bt1 == VT_PTR) {
2318 type1 = pointed_type(type1);
2319 } else if (bt1 != VT_FUNC)
2320 goto invalid_operands;
2322 if (bt2 == VT_PTR) {
2323 type2 = pointed_type(type2);
2324 } else if (bt2 != VT_FUNC) {
2325 invalid_operands:
2326 error("invalid operands to binary %s", get_tok_str(op, NULL));
2328 if ((type1->t & VT_BTYPE) == VT_VOID ||
2329 (type2->t & VT_BTYPE) == VT_VOID)
2330 return;
2331 tmp_type1 = *type1;
2332 tmp_type2 = *type2;
2333 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
2334 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
2335 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
2336 /* gcc-like error if '-' is used */
2337 if (op == '-')
2338 goto invalid_operands;
2339 else
2340 warning("comparison of distinct pointer types lacks a cast");
2344 /* generic gen_op: handles types problems */
2345 void gen_op(int op)
2347 int u, t1, t2, bt1, bt2, t;
2348 CType type1;
2350 t1 = vtop[-1].type.t;
2351 t2 = vtop[0].type.t;
2352 bt1 = t1 & VT_BTYPE;
2353 bt2 = t2 & VT_BTYPE;
2355 if (bt1 == VT_PTR || bt2 == VT_PTR) {
2356 /* at least one operand is a pointer */
2357 /* relationnal op: must be both pointers */
2358 if (op >= TOK_ULT && op <= TOK_LOR) {
2359 check_comparison_pointer_types(vtop - 1, vtop, op);
2360 /* pointers are handled are unsigned */
2361 #ifdef TCC_TARGET_X86_64
2362 t = VT_LLONG | VT_UNSIGNED;
2363 #else
2364 t = VT_INT | VT_UNSIGNED;
2365 #endif
2366 goto std_op;
2368 /* if both pointers, then it must be the '-' op */
2369 if (bt1 == VT_PTR && bt2 == VT_PTR) {
2370 if (op != '-')
2371 error("cannot use pointers here");
2372 check_comparison_pointer_types(vtop - 1, vtop, op);
2373 /* XXX: check that types are compatible */
2374 u = pointed_size(&vtop[-1].type);
2375 gen_opic(op);
2376 /* set to integer type */
2377 #ifdef TCC_TARGET_X86_64
2378 vtop->type.t = VT_LLONG;
2379 #else
2380 vtop->type.t = VT_INT;
2381 #endif
2382 vpushi(u);
2383 gen_op(TOK_PDIV);
2384 } else {
2385 /* exactly one pointer : must be '+' or '-'. */
2386 if (op != '-' && op != '+')
2387 error("cannot use pointers here");
2388 /* Put pointer as first operand */
2389 if (bt2 == VT_PTR) {
2390 vswap();
2391 swap(&t1, &t2);
2393 type1 = vtop[-1].type;
2394 #ifdef TCC_TARGET_X86_64
2395 vpushll(pointed_size(&vtop[-1].type));
2396 #else
2397 /* XXX: cast to int ? (long long case) */
2398 vpushi(pointed_size(&vtop[-1].type));
2399 #endif
2400 gen_op('*');
2401 #ifdef CONFIG_TCC_BCHECK
2402 /* if evaluating constant expression, no code should be
2403 generated, so no bound check */
2404 if (do_bounds_check && !const_wanted) {
2405 /* if bounded pointers, we generate a special code to
2406 test bounds */
2407 if (op == '-') {
2408 vpushi(0);
2409 vswap();
2410 gen_op('-');
2412 gen_bounded_ptr_add();
2413 } else
2414 #endif
2416 gen_opic(op);
2418 /* put again type if gen_opic() swaped operands */
2419 vtop->type = type1;
2421 } else if (is_float(bt1) || is_float(bt2)) {
2422 /* compute bigger type and do implicit casts */
2423 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
2424 t = VT_LDOUBLE;
2425 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
2426 t = VT_DOUBLE;
2427 } else {
2428 t = VT_FLOAT;
2430 /* floats can only be used for a few operations */
2431 if (op != '+' && op != '-' && op != '*' && op != '/' &&
2432 (op < TOK_ULT || op > TOK_GT))
2433 error("invalid operands for binary operation");
2434 goto std_op;
2435 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
2436 /* cast to biggest op */
2437 t = VT_LLONG;
2438 /* convert to unsigned if it does not fit in a long long */
2439 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
2440 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
2441 t |= VT_UNSIGNED;
2442 goto std_op;
2443 } else {
2444 /* integer operations */
2445 t = VT_INT;
2446 /* convert to unsigned if it does not fit in an integer */
2447 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
2448 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
2449 t |= VT_UNSIGNED;
2450 std_op:
2451 /* XXX: currently, some unsigned operations are explicit, so
2452 we modify them here */
2453 if (t & VT_UNSIGNED) {
2454 if (op == TOK_SAR)
2455 op = TOK_SHR;
2456 else if (op == '/')
2457 op = TOK_UDIV;
2458 else if (op == '%')
2459 op = TOK_UMOD;
2460 else if (op == TOK_LT)
2461 op = TOK_ULT;
2462 else if (op == TOK_GT)
2463 op = TOK_UGT;
2464 else if (op == TOK_LE)
2465 op = TOK_ULE;
2466 else if (op == TOK_GE)
2467 op = TOK_UGE;
2469 vswap();
2470 type1.t = t;
2471 gen_cast(&type1);
2472 vswap();
2473 /* special case for shifts and long long: we keep the shift as
2474 an integer */
2475 if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
2476 type1.t = VT_INT;
2477 gen_cast(&type1);
2478 if (is_float(t))
2479 gen_opif(op);
2480 else
2481 gen_opic(op);
2482 if (op >= TOK_ULT && op <= TOK_GT) {
2483 /* relationnal op: the result is an int */
2484 vtop->type.t = VT_INT;
2485 } else {
2486 vtop->type.t = t;
2491 #ifndef TCC_TARGET_ARM
2492 /* generic itof for unsigned long long case */
2493 void gen_cvt_itof1(int t)
2495 if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
2496 (VT_LLONG | VT_UNSIGNED)) {
2498 if (t == VT_FLOAT)
2499 vpush_global_sym(&func_old_type, TOK___floatundisf);
2500 #if LDOUBLE_SIZE != 8
2501 else if (t == VT_LDOUBLE)
2502 vpush_global_sym(&func_old_type, TOK___floatundixf);
2503 #endif
2504 else
2505 vpush_global_sym(&func_old_type, TOK___floatundidf);
2506 vrott(2);
2507 gfunc_call(1);
2508 vpushi(0);
2509 vtop->r = reg_fret(t);
2510 } else {
2511 gen_cvt_itof(t);
2514 #endif
2516 /* generic ftoi for unsigned long long case */
2517 void gen_cvt_ftoi1(int t)
2519 int st;
2521 if (t == (VT_LLONG | VT_UNSIGNED)) {
2522 /* not handled natively */
2523 st = vtop->type.t & VT_BTYPE;
2524 if (st == VT_FLOAT)
2525 vpush_global_sym(&func_old_type, TOK___fixunssfdi);
2526 #if LDOUBLE_SIZE != 8
2527 else if (st == VT_LDOUBLE)
2528 vpush_global_sym(&func_old_type, TOK___fixunsxfdi);
2529 #endif
2530 else
2531 vpush_global_sym(&func_old_type, TOK___fixunsdfdi);
2532 vrott(2);
2533 gfunc_call(1);
2534 vpushi(0);
2535 vtop->r = REG_IRET;
2536 vtop->r2 = REG_LRET;
2537 } else {
2538 gen_cvt_ftoi(t);
2542 /* force char or short cast */
2543 void force_charshort_cast(int t)
2545 int bits, dbt;
2546 dbt = t & VT_BTYPE;
2547 /* XXX: add optimization if lvalue : just change type and offset */
2548 if (dbt == VT_BYTE)
2549 bits = 8;
2550 else
2551 bits = 16;
2552 if (t & VT_UNSIGNED) {
2553 vpushi((1 << bits) - 1);
2554 gen_op('&');
2555 } else {
2556 bits = 32 - bits;
2557 vpushi(bits);
2558 gen_op(TOK_SHL);
2559 /* result must be signed or the SAR is converted to an SHL
2560 This was not the case when "t" was a signed short
2561 and the last value on the stack was an unsigned int */
2562 vtop->type.t &= ~VT_UNSIGNED;
2563 vpushi(bits);
2564 gen_op(TOK_SAR);
2568 /* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */
2569 static void gen_cast(CType *type)
2571 int sbt, dbt, sf, df, c, p;
2573 /* special delayed cast for char/short */
2574 /* XXX: in some cases (multiple cascaded casts), it may still
2575 be incorrect */
2576 if (vtop->r & VT_MUSTCAST) {
2577 vtop->r &= ~VT_MUSTCAST;
2578 force_charshort_cast(vtop->type.t);
2581 /* bitfields first get cast to ints */
2582 if (vtop->type.t & VT_BITFIELD) {
2583 gv(RC_INT);
2586 dbt = type->t & (VT_BTYPE | VT_UNSIGNED);
2587 sbt = vtop->type.t & (VT_BTYPE | VT_UNSIGNED);
2589 if (sbt != dbt) {
2590 sf = is_float(sbt);
2591 df = is_float(dbt);
2592 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
2593 p = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == (VT_CONST | VT_SYM);
2594 if (c) {
2595 /* constant case: we can do it now */
2596 /* XXX: in ISOC, cannot do it if error in convert */
2597 if (sbt == VT_FLOAT)
2598 vtop->c.ld = vtop->c.f;
2599 else if (sbt == VT_DOUBLE)
2600 vtop->c.ld = vtop->c.d;
2602 if (df) {
2603 if ((sbt & VT_BTYPE) == VT_LLONG) {
2604 if (sbt & VT_UNSIGNED)
2605 vtop->c.ld = vtop->c.ull;
2606 else
2607 vtop->c.ld = vtop->c.ll;
2608 } else if(!sf) {
2609 if (sbt & VT_UNSIGNED)
2610 vtop->c.ld = vtop->c.ui;
2611 else
2612 vtop->c.ld = vtop->c.i;
2615 if (dbt == VT_FLOAT)
2616 vtop->c.f = (float)vtop->c.ld;
2617 else if (dbt == VT_DOUBLE)
2618 vtop->c.d = (double)vtop->c.ld;
2619 } else if (sf && dbt == (VT_LLONG|VT_UNSIGNED)) {
2620 vtop->c.ull = (unsigned long long)vtop->c.ld;
2621 } else if (sf && dbt == VT_BOOL) {
2622 vtop->c.i = (vtop->c.ld != 0);
2623 } else {
2624 if(sf)
2625 vtop->c.ll = (long long)vtop->c.ld;
2626 else if (sbt == (VT_LLONG|VT_UNSIGNED))
2627 vtop->c.ll = vtop->c.ull;
2628 else if (sbt & VT_UNSIGNED)
2629 vtop->c.ll = vtop->c.ui;
2630 else if (sbt != VT_LLONG)
2631 vtop->c.ll = vtop->c.i;
2633 if (dbt == (VT_LLONG|VT_UNSIGNED))
2634 vtop->c.ull = vtop->c.ll;
2635 else if (dbt == VT_BOOL)
2636 vtop->c.i = (vtop->c.ll != 0);
2637 else if (dbt != VT_LLONG) {
2638 int s = 0;
2639 if ((dbt & VT_BTYPE) == VT_BYTE)
2640 s = 24;
2641 else if ((dbt & VT_BTYPE) == VT_SHORT)
2642 s = 16;
2644 if(dbt & VT_UNSIGNED)
2645 vtop->c.ui = ((unsigned int)vtop->c.ll << s) >> s;
2646 else
2647 vtop->c.i = ((int)vtop->c.ll << s) >> s;
2650 } else if (p && dbt == VT_BOOL) {
2651 vtop->r = VT_CONST;
2652 vtop->c.i = 1;
2653 } else if (!nocode_wanted) {
2654 /* non constant case: generate code */
2655 if (sf && df) {
2656 /* convert from fp to fp */
2657 gen_cvt_ftof(dbt);
2658 } else if (df) {
2659 /* convert int to fp */
2660 gen_cvt_itof1(dbt);
2661 } else if (sf) {
2662 /* convert fp to int */
2663 if (dbt == VT_BOOL) {
2664 vpushi(0);
2665 gen_op(TOK_NE);
2666 } else {
2667 /* we handle char/short/etc... with generic code */
2668 if (dbt != (VT_INT | VT_UNSIGNED) &&
2669 dbt != (VT_LLONG | VT_UNSIGNED) &&
2670 dbt != VT_LLONG)
2671 dbt = VT_INT;
2672 gen_cvt_ftoi1(dbt);
2673 if (dbt == VT_INT && (type->t & (VT_BTYPE | VT_UNSIGNED)) != dbt) {
2674 /* additional cast for char/short... */
2675 vtop->type.t = dbt;
2676 gen_cast(type);
2679 #ifndef TCC_TARGET_X86_64
2680 } else if ((dbt & VT_BTYPE) == VT_LLONG) {
2681 if ((sbt & VT_BTYPE) != VT_LLONG) {
2682 /* scalar to long long */
2683 /* machine independent conversion */
2684 gv(RC_INT);
2685 /* generate high word */
2686 if (sbt == (VT_INT | VT_UNSIGNED)) {
2687 vpushi(0);
2688 gv(RC_INT);
2689 } else {
2690 if (sbt == VT_PTR) {
2691 /* cast from pointer to int before we apply
2692 shift operation, which pointers don't support*/
2693 gen_cast(&int_type);
2695 gv_dup();
2696 vpushi(31);
2697 gen_op(TOK_SAR);
2699 /* patch second register */
2700 vtop[-1].r2 = vtop->r;
2701 vpop();
2703 #else
2704 } else if ((dbt & VT_BTYPE) == VT_LLONG ||
2705 (dbt & VT_BTYPE) == VT_PTR) {
2706 /* XXX: not sure if this is perfect... need more tests */
2707 if ((sbt & VT_BTYPE) != VT_LLONG) {
2708 int r = gv(RC_INT);
2709 if (sbt != (VT_INT | VT_UNSIGNED) &&
2710 sbt != VT_PTR && sbt != VT_FUNC) {
2711 /* x86_64 specific: movslq */
2712 o(0x6348);
2713 o(0xc0 + (REG_VALUE(r) << 3) + REG_VALUE(r));
2716 #endif
2717 } else if (dbt == VT_BOOL) {
2718 /* scalar to bool */
2719 vpushi(0);
2720 gen_op(TOK_NE);
2721 } else if ((dbt & VT_BTYPE) == VT_BYTE ||
2722 (dbt & VT_BTYPE) == VT_SHORT) {
2723 if (sbt == VT_PTR) {
2724 vtop->type.t = VT_INT;
2725 warning("nonportable conversion from pointer to char/short");
2727 force_charshort_cast(dbt);
2728 } else if ((dbt & VT_BTYPE) == VT_INT) {
2729 /* scalar to int */
2730 if (sbt == VT_LLONG) {
2731 /* from long long: just take low order word */
2732 lexpand();
2733 vpop();
2735 /* if lvalue and single word type, nothing to do because
2736 the lvalue already contains the real type size (see
2737 VT_LVAL_xxx constants) */
2740 } else if ((dbt & VT_BTYPE) == VT_PTR && !(vtop->r & VT_LVAL)) {
2741 /* if we are casting between pointer types,
2742 we must update the VT_LVAL_xxx size */
2743 vtop->r = (vtop->r & ~VT_LVAL_TYPE)
2744 | (lvalue_type(type->ref->type.t) & VT_LVAL_TYPE);
2746 vtop->type = *type;
2749 /* return type size. Put alignment at 'a' */
2750 static int type_size(CType *type, int *a)
2752 Sym *s;
2753 int bt;
2755 bt = type->t & VT_BTYPE;
2756 if (bt == VT_STRUCT) {
2757 /* struct/union */
2758 s = type->ref;
2759 *a = s->r;
2760 return s->c;
2761 } else if (bt == VT_PTR) {
2762 if (type->t & VT_ARRAY) {
2763 int ts;
2765 s = type->ref;
2766 ts = type_size(&s->type, a);
2768 if (ts < 0 && s->c < 0)
2769 ts = -ts;
2771 return ts * s->c;
2772 } else {
2773 *a = PTR_SIZE;
2774 return PTR_SIZE;
2776 } else if (bt == VT_LDOUBLE) {
2777 *a = LDOUBLE_ALIGN;
2778 return LDOUBLE_SIZE;
2779 } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
2780 #ifdef TCC_TARGET_I386
2781 #ifdef TCC_TARGET_PE
2782 *a = 8;
2783 #else
2784 *a = 4;
2785 #endif
2786 #elif defined(TCC_TARGET_ARM)
2787 #ifdef TCC_ARM_EABI
2788 *a = 8;
2789 #else
2790 *a = 4;
2791 #endif
2792 #else
2793 *a = 8;
2794 #endif
2795 return 8;
2796 } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
2797 *a = 4;
2798 return 4;
2799 } else if (bt == VT_SHORT) {
2800 *a = 2;
2801 return 2;
2802 } else {
2803 /* char, void, function, _Bool */
2804 *a = 1;
2805 return 1;
2809 /* return the pointed type of t */
2810 static inline CType *pointed_type(CType *type)
2812 return &type->ref->type;
2815 /* modify type so that its it is a pointer to type. */
2816 static void mk_pointer(CType *type)
2818 Sym *s;
2819 s = sym_push(SYM_FIELD, type, 0, -1);
2820 type->t = VT_PTR | (type->t & ~VT_TYPE);
2821 type->ref = s;
2824 /* compare function types. OLD functions match any new functions */
2825 static int is_compatible_func(CType *type1, CType *type2)
2827 Sym *s1, *s2;
2829 s1 = type1->ref;
2830 s2 = type2->ref;
2831 if (!is_compatible_types(&s1->type, &s2->type))
2832 return 0;
2833 /* check func_call */
2834 if (FUNC_CALL(s1->r) != FUNC_CALL(s2->r))
2835 return 0;
2836 /* XXX: not complete */
2837 if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
2838 return 1;
2839 if (s1->c != s2->c)
2840 return 0;
2841 while (s1 != NULL) {
2842 if (s2 == NULL)
2843 return 0;
2844 if (!is_compatible_parameter_types(&s1->type, &s2->type))
2845 return 0;
2846 s1 = s1->next;
2847 s2 = s2->next;
2849 if (s2)
2850 return 0;
2851 return 1;
2854 /* return true if type1 and type2 are the same. If unqualified is
2855 true, qualifiers on the types are ignored.
2857 - enums are not checked as gcc __builtin_types_compatible_p ()
2859 static int compare_types(CType *type1, CType *type2, int unqualified)
2861 int bt1, t1, t2;
2863 t1 = type1->t & VT_TYPE;
2864 t2 = type2->t & VT_TYPE;
2865 if (unqualified) {
2866 /* strip qualifiers before comparing */
2867 t1 &= ~(VT_CONSTANT | VT_VOLATILE);
2868 t2 &= ~(VT_CONSTANT | VT_VOLATILE);
2870 /* XXX: bitfields ? */
2871 if (t1 != t2)
2872 return 0;
2873 /* test more complicated cases */
2874 bt1 = t1 & VT_BTYPE;
2875 if (bt1 == VT_PTR) {
2876 type1 = pointed_type(type1);
2877 type2 = pointed_type(type2);
2878 return is_compatible_types(type1, type2);
2879 } else if (bt1 == VT_STRUCT) {
2880 return (type1->ref == type2->ref);
2881 } else if (bt1 == VT_FUNC) {
2882 return is_compatible_func(type1, type2);
2883 } else {
2884 return 1;
2888 /* return true if type1 and type2 are exactly the same (including
2889 qualifiers).
2891 static int is_compatible_types(CType *type1, CType *type2)
2893 return compare_types(type1,type2,0);
2896 /* return true if type1 and type2 are the same (ignoring qualifiers).
2898 static int is_compatible_parameter_types(CType *type1, CType *type2)
2900 return compare_types(type1,type2,1);
2903 /* print a type. If 'varstr' is not NULL, then the variable is also
2904 printed in the type */
2905 /* XXX: union */
2906 /* XXX: add array and function pointers */
2907 void type_to_str(char *buf, int buf_size,
2908 CType *type, const char *varstr)
2910 int bt, v, t;
2911 Sym *s, *sa;
2912 char buf1[256];
2913 const char *tstr;
2915 t = type->t & VT_TYPE;
2916 bt = t & VT_BTYPE;
2917 buf[0] = '\0';
2918 if (t & VT_CONSTANT)
2919 pstrcat(buf, buf_size, "const ");
2920 if (t & VT_VOLATILE)
2921 pstrcat(buf, buf_size, "volatile ");
2922 if (t & VT_UNSIGNED)
2923 pstrcat(buf, buf_size, "unsigned ");
2924 switch(bt) {
2925 case VT_VOID:
2926 tstr = "void";
2927 goto add_tstr;
2928 case VT_BOOL:
2929 tstr = "_Bool";
2930 goto add_tstr;
2931 case VT_BYTE:
2932 tstr = "char";
2933 goto add_tstr;
2934 case VT_SHORT:
2935 tstr = "short";
2936 goto add_tstr;
2937 case VT_INT:
2938 tstr = "int";
2939 goto add_tstr;
2940 case VT_LONG:
2941 tstr = "long";
2942 goto add_tstr;
2943 case VT_LLONG:
2944 tstr = "long long";
2945 goto add_tstr;
2946 case VT_FLOAT:
2947 tstr = "float";
2948 goto add_tstr;
2949 case VT_DOUBLE:
2950 tstr = "double";
2951 goto add_tstr;
2952 case VT_LDOUBLE:
2953 tstr = "long double";
2954 add_tstr:
2955 pstrcat(buf, buf_size, tstr);
2956 break;
2957 case VT_ENUM:
2958 case VT_STRUCT:
2959 if (bt == VT_STRUCT)
2960 tstr = "struct ";
2961 else
2962 tstr = "enum ";
2963 pstrcat(buf, buf_size, tstr);
2964 v = type->ref->v & ~SYM_STRUCT;
2965 if (v >= SYM_FIRST_ANOM)
2966 pstrcat(buf, buf_size, "<anonymous>");
2967 else
2968 pstrcat(buf, buf_size, get_tok_str(v, NULL));
2969 break;
2970 case VT_FUNC:
2971 s = type->ref;
2972 type_to_str(buf, buf_size, &s->type, varstr);
2973 pstrcat(buf, buf_size, "(");
2974 sa = s->next;
2975 while (sa != NULL) {
2976 type_to_str(buf1, sizeof(buf1), &sa->type, NULL);
2977 pstrcat(buf, buf_size, buf1);
2978 sa = sa->next;
2979 if (sa)
2980 pstrcat(buf, buf_size, ", ");
2982 pstrcat(buf, buf_size, ")");
2983 goto no_var;
2984 case VT_PTR:
2985 s = type->ref;
2986 pstrcpy(buf1, sizeof(buf1), "*");
2987 if (varstr)
2988 pstrcat(buf1, sizeof(buf1), varstr);
2989 type_to_str(buf, buf_size, &s->type, buf1);
2990 goto no_var;
2992 if (varstr) {
2993 pstrcat(buf, buf_size, " ");
2994 pstrcat(buf, buf_size, varstr);
2996 no_var: ;
2999 /* verify type compatibility to store vtop in 'dt' type, and generate
3000 casts if needed. */
3001 static void gen_assign_cast(CType *dt)
3003 CType *st, *type1, *type2, tmp_type1, tmp_type2;
3004 char buf1[256], buf2[256];
3005 int dbt, sbt;
3007 st = &vtop->type; /* source type */
3008 dbt = dt->t & VT_BTYPE;
3009 sbt = st->t & VT_BTYPE;
3010 if (dt->t & VT_CONSTANT)
3011 warning("assignment of read-only location");
3012 switch(dbt) {
3013 case VT_PTR:
3014 /* special cases for pointers */
3015 /* '0' can also be a pointer */
3016 if (is_null_pointer(vtop))
3017 goto type_ok;
3018 /* accept implicit pointer to integer cast with warning */
3019 if (is_integer_btype(sbt)) {
3020 warning("assignment makes pointer from integer without a cast");
3021 goto type_ok;
3023 type1 = pointed_type(dt);
3024 /* a function is implicitely a function pointer */
3025 if (sbt == VT_FUNC) {
3026 if ((type1->t & VT_BTYPE) != VT_VOID &&
3027 !is_compatible_types(pointed_type(dt), st))
3028 goto error;
3029 else
3030 goto type_ok;
3032 if (sbt != VT_PTR)
3033 goto error;
3034 type2 = pointed_type(st);
3035 if ((type1->t & VT_BTYPE) == VT_VOID ||
3036 (type2->t & VT_BTYPE) == VT_VOID) {
3037 /* void * can match anything */
3038 } else {
3039 /* exact type match, except for unsigned */
3040 tmp_type1 = *type1;
3041 tmp_type2 = *type2;
3042 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
3043 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
3044 if (!is_compatible_types(&tmp_type1, &tmp_type2))
3045 warning("assignment from incompatible pointer type");
3047 /* check const and volatile */
3048 if ((!(type1->t & VT_CONSTANT) && (type2->t & VT_CONSTANT)) ||
3049 (!(type1->t & VT_VOLATILE) && (type2->t & VT_VOLATILE)))
3050 warning("assignment discards qualifiers from pointer target type");
3051 break;
3052 case VT_BYTE:
3053 case VT_SHORT:
3054 case VT_INT:
3055 case VT_LLONG:
3056 if (sbt == VT_PTR || sbt == VT_FUNC) {
3057 warning("assignment makes integer from pointer without a cast");
3059 /* XXX: more tests */
3060 break;
3061 case VT_STRUCT:
3062 tmp_type1 = *dt;
3063 tmp_type2 = *st;
3064 tmp_type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
3065 tmp_type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
3066 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
3067 error:
3068 type_to_str(buf1, sizeof(buf1), st, NULL);
3069 type_to_str(buf2, sizeof(buf2), dt, NULL);
3070 error("cannot cast '%s' to '%s'", buf1, buf2);
3072 break;
3074 type_ok:
3075 gen_cast(dt);
3078 /* store vtop in lvalue pushed on stack */
3079 void vstore(void)
3081 int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
3083 ft = vtop[-1].type.t;
3084 sbt = vtop->type.t & VT_BTYPE;
3085 dbt = ft & VT_BTYPE;
3086 if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
3087 (sbt == VT_INT && dbt == VT_SHORT)) {
3088 /* optimize char/short casts */
3089 delayed_cast = VT_MUSTCAST;
3090 vtop->type.t = ft & (VT_TYPE & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT)));
3091 /* XXX: factorize */
3092 if (ft & VT_CONSTANT)
3093 warning("assignment of read-only location");
3094 } else {
3095 delayed_cast = 0;
3096 if (!(ft & VT_BITFIELD))
3097 gen_assign_cast(&vtop[-1].type);
3100 if (sbt == VT_STRUCT) {
3101 /* if structure, only generate pointer */
3102 /* structure assignment : generate memcpy */
3103 /* XXX: optimize if small size */
3104 if (!nocode_wanted) {
3105 size = type_size(&vtop->type, &align);
3107 #ifdef TCC_ARM_EABI
3108 if(!(align & 7))
3109 vpush_global_sym(&func_old_type, TOK_memcpy8);
3110 else if(!(align & 3))
3111 vpush_global_sym(&func_old_type, TOK_memcpy4);
3112 else
3113 #endif
3114 vpush_global_sym(&func_old_type, TOK_memcpy);
3116 /* destination */
3117 vpushv(vtop - 2);
3118 vtop->type.t = VT_PTR;
3119 gaddrof();
3120 /* source */
3121 vpushv(vtop - 2);
3122 vtop->type.t = VT_PTR;
3123 gaddrof();
3124 /* type size */
3125 vpushi(size);
3126 gfunc_call(3);
3128 vswap();
3129 vpop();
3130 } else {
3131 vswap();
3132 vpop();
3134 /* leave source on stack */
3135 } else if (ft & VT_BITFIELD) {
3136 /* bitfield store handling */
3137 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
3138 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
3139 /* remove bit field info to avoid loops */
3140 vtop[-1].type.t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
3142 /* duplicate source into other register */
3143 gv_dup();
3144 vswap();
3145 vrott(3);
3147 if((ft & VT_BTYPE) == VT_BOOL) {
3148 gen_cast(&vtop[-1].type);
3149 vtop[-1].type.t = (vtop[-1].type.t & ~VT_BTYPE) | (VT_BYTE | VT_UNSIGNED);
3152 /* duplicate destination */
3153 vdup();
3154 vtop[-1] = vtop[-2];
3156 /* mask and shift source */
3157 if((ft & VT_BTYPE) != VT_BOOL) {
3158 if((ft & VT_BTYPE) == VT_LLONG) {
3159 vpushll((1ULL << bit_size) - 1ULL);
3160 } else {
3161 vpushi((1 << bit_size) - 1);
3163 gen_op('&');
3165 vpushi(bit_pos);
3166 gen_op(TOK_SHL);
3167 /* load destination, mask and or with source */
3168 vswap();
3169 if((ft & VT_BTYPE) == VT_LLONG) {
3170 vpushll(~(((1ULL << bit_size) - 1ULL) << bit_pos));
3171 } else {
3172 vpushi(~(((1 << bit_size) - 1) << bit_pos));
3174 gen_op('&');
3175 gen_op('|');
3176 /* store result */
3177 vstore();
3179 /* pop off shifted source from "duplicate source..." above */
3180 vpop();
3182 } else {
3183 #ifdef CONFIG_TCC_BCHECK
3184 /* bound check case */
3185 if (vtop[-1].r & VT_MUSTBOUND) {
3186 vswap();
3187 gbound();
3188 vswap();
3190 #endif
3191 if (!nocode_wanted) {
3192 rc = RC_INT;
3193 if (is_float(ft)) {
3194 rc = RC_FLOAT;
3195 #ifdef TCC_TARGET_X86_64
3196 if ((ft & VT_BTYPE) == VT_LDOUBLE) {
3197 rc = RC_ST0;
3199 #endif
3201 r = gv(rc); /* generate value */
3202 /* if lvalue was saved on stack, must read it */
3203 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
3204 SValue sv;
3205 t = get_reg(RC_INT);
3206 #ifdef TCC_TARGET_X86_64
3207 sv.type.t = VT_PTR;
3208 #else
3209 sv.type.t = VT_INT;
3210 #endif
3211 sv.r = VT_LOCAL | VT_LVAL;
3212 sv.c.ul = vtop[-1].c.ul;
3213 load(t, &sv);
3214 vtop[-1].r = t | VT_LVAL;
3216 store(r, vtop - 1);
3217 #ifndef TCC_TARGET_X86_64
3218 /* two word case handling : store second register at word + 4 */
3219 if ((ft & VT_BTYPE) == VT_LLONG) {
3220 vswap();
3221 /* convert to int to increment easily */
3222 vtop->type.t = VT_INT;
3223 gaddrof();
3224 vpushi(4);
3225 gen_op('+');
3226 vtop->r |= VT_LVAL;
3227 vswap();
3228 /* XXX: it works because r2 is spilled last ! */
3229 store(vtop->r2, vtop - 1);
3231 #endif
3233 vswap();
3234 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
3235 vtop->r |= delayed_cast;
3239 /* post defines POST/PRE add. c is the token ++ or -- */
3240 void inc(int post, int c)
3242 test_lvalue();
3243 vdup(); /* save lvalue */
3244 if (post) {
3245 gv_dup(); /* duplicate value */
3246 vrotb(3);
3247 vrotb(3);
3249 /* add constant */
3250 vpushi(c - TOK_MID);
3251 gen_op('+');
3252 vstore(); /* store value */
3253 if (post)
3254 vpop(); /* if post op, return saved value */
3257 /* Parse GNUC __attribute__ extension. Currently, the following
3258 extensions are recognized:
3259 - aligned(n) : set data/function alignment.
3260 - packed : force data alignment to 1
3261 - section(x) : generate data/code in this section.
3262 - unused : currently ignored, but may be used someday.
3263 - regparm(n) : pass function parameters in registers (i386 only)
3265 static void parse_attribute(AttributeDef *ad)
3267 int t, n;
3269 while (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) {
3270 next();
3271 skip('(');
3272 skip('(');
3273 while (tok != ')') {
3274 if (tok < TOK_IDENT)
3275 expect("attribute name");
3276 t = tok;
3277 next();
3278 switch(t) {
3279 case TOK_SECTION1:
3280 case TOK_SECTION2:
3281 skip('(');
3282 if (tok != TOK_STR)
3283 expect("section name");
3284 ad->section = find_section(tcc_state, (char *)tokc.cstr->data);
3285 next();
3286 skip(')');
3287 break;
3288 case TOK_ALIGNED1:
3289 case TOK_ALIGNED2:
3290 if (tok == '(') {
3291 next();
3292 n = expr_const();
3293 if (n <= 0 || (n & (n - 1)) != 0)
3294 error("alignment must be a positive power of two");
3295 skip(')');
3296 } else {
3297 n = MAX_ALIGN;
3299 ad->aligned = n;
3300 break;
3301 case TOK_PACKED1:
3302 case TOK_PACKED2:
3303 ad->packed = 1;
3304 break;
3305 case TOK_UNUSED1:
3306 case TOK_UNUSED2:
3307 /* currently, no need to handle it because tcc does not
3308 track unused objects */
3309 break;
3310 case TOK_NORETURN1:
3311 case TOK_NORETURN2:
3312 /* currently, no need to handle it because tcc does not
3313 track unused objects */
3314 break;
3315 case TOK_CDECL1:
3316 case TOK_CDECL2:
3317 case TOK_CDECL3:
3318 FUNC_CALL(ad->func_attr) = FUNC_CDECL;
3319 break;
3320 case TOK_STDCALL1:
3321 case TOK_STDCALL2:
3322 case TOK_STDCALL3:
3323 FUNC_CALL(ad->func_attr) = FUNC_STDCALL;
3324 break;
3325 #ifdef TCC_TARGET_I386
3326 case TOK_REGPARM1:
3327 case TOK_REGPARM2:
3328 skip('(');
3329 n = expr_const();
3330 if (n > 3)
3331 n = 3;
3332 else if (n < 0)
3333 n = 0;
3334 if (n > 0)
3335 FUNC_CALL(ad->func_attr) = FUNC_FASTCALL1 + n - 1;
3336 skip(')');
3337 break;
3338 case TOK_FASTCALL1:
3339 case TOK_FASTCALL2:
3340 case TOK_FASTCALL3:
3341 FUNC_CALL(ad->func_attr) = FUNC_FASTCALLW;
3342 break;
3343 #endif
3344 case TOK_DLLEXPORT:
3345 FUNC_EXPORT(ad->func_attr) = 1;
3346 break;
3347 default:
3348 if (tcc_state->warn_unsupported)
3349 warning("'%s' attribute ignored", get_tok_str(t, NULL));
3350 /* skip parameters */
3351 if (tok == '(') {
3352 int parenthesis = 0;
3353 do {
3354 if (tok == '(')
3355 parenthesis++;
3356 else if (tok == ')')
3357 parenthesis--;
3358 next();
3359 } while (parenthesis && tok != -1);
3361 break;
3363 if (tok != ',')
3364 break;
3365 next();
3367 skip(')');
3368 skip(')');
3372 /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
3373 static void struct_decl(CType *type, int u)
3375 int a, v, size, align, maxalign, c, offset;
3376 int bit_size, bit_pos, bsize, bt, lbit_pos, prevbt;
3377 Sym *s, *ss, *ass, **ps;
3378 AttributeDef ad;
3379 CType type1, btype;
3381 a = tok; /* save decl type */
3382 next();
3383 if (tok != '{') {
3384 v = tok;
3385 next();
3386 /* struct already defined ? return it */
3387 if (v < TOK_IDENT)
3388 expect("struct/union/enum name");
3389 s = struct_find(v);
3390 if (s) {
3391 if (s->type.t != a)
3392 error("invalid type");
3393 goto do_decl;
3395 } else {
3396 v = anon_sym++;
3398 type1.t = a;
3399 /* we put an undefined size for struct/union */
3400 s = sym_push(v | SYM_STRUCT, &type1, 0, -1);
3401 s->r = 0; /* default alignment is zero as gcc */
3402 /* put struct/union/enum name in type */
3403 do_decl:
3404 type->t = u;
3405 type->ref = s;
3407 if (tok == '{') {
3408 next();
3409 if (s->c != -1)
3410 error("struct/union/enum already defined");
3411 /* cannot be empty */
3412 c = 0;
3413 /* non empty enums are not allowed */
3414 if (a == TOK_ENUM) {
3415 for(;;) {
3416 v = tok;
3417 if (v < TOK_UIDENT)
3418 expect("identifier");
3419 next();
3420 if (tok == '=') {
3421 next();
3422 c = expr_const();
3424 /* enum symbols have static storage */
3425 ss = sym_push(v, &int_type, VT_CONST, c);
3426 ss->type.t |= VT_STATIC;
3427 if (tok != ',')
3428 break;
3429 next();
3430 c++;
3431 /* NOTE: we accept a trailing comma */
3432 if (tok == '}')
3433 break;
3435 skip('}');
3436 } else {
3437 maxalign = 1;
3438 ps = &s->next;
3439 prevbt = VT_INT;
3440 bit_pos = 0;
3441 offset = 0;
3442 while (tok != '}') {
3443 parse_btype(&btype, &ad);
3444 while (1) {
3445 bit_size = -1;
3446 v = 0;
3447 type1 = btype;
3448 if (tok != ':') {
3449 type_decl(&type1, &ad, &v, TYPE_DIRECT | TYPE_ABSTRACT);
3450 if (v == 0 && (type1.t & VT_BTYPE) != VT_STRUCT)
3451 expect("identifier");
3452 if ((type1.t & VT_BTYPE) == VT_FUNC ||
3453 (type1.t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN | VT_INLINE)))
3454 error("invalid type for '%s'",
3455 get_tok_str(v, NULL));
3457 if (tok == ':') {
3458 next();
3459 bit_size = expr_const();
3460 /* XXX: handle v = 0 case for messages */
3461 if (bit_size < 0)
3462 error("negative width in bit-field '%s'",
3463 get_tok_str(v, NULL));
3464 if (v && bit_size == 0)
3465 error("zero width for bit-field '%s'",
3466 get_tok_str(v, NULL));
3468 size = type_size(&type1, &align);
3469 if (ad.aligned) {
3470 if (align < ad.aligned)
3471 align = ad.aligned;
3472 } else if (ad.packed) {
3473 align = 1;
3474 } else if (*tcc_state->pack_stack_ptr) {
3475 if (align > *tcc_state->pack_stack_ptr)
3476 align = *tcc_state->pack_stack_ptr;
3478 lbit_pos = 0;
3479 if (bit_size >= 0) {
3480 bt = type1.t & VT_BTYPE;
3481 if (bt != VT_INT &&
3482 bt != VT_BYTE &&
3483 bt != VT_SHORT &&
3484 bt != VT_BOOL &&
3485 bt != VT_ENUM &&
3486 bt != VT_LLONG)
3487 error("bitfields must have scalar type");
3488 bsize = size * 8;
3489 if (bit_size > bsize) {
3490 error("width of '%s' exceeds its type",
3491 get_tok_str(v, NULL));
3492 } else if (bit_size == bsize) {
3493 /* no need for bit fields */
3494 bit_pos = 0;
3495 } else if (bit_size == 0) {
3496 /* XXX: what to do if only padding in a
3497 structure ? */
3498 /* zero size: means to pad */
3499 bit_pos = 0;
3500 } else {
3501 /* we do not have enough room ?
3502 did the type change?
3503 is it a union? */
3504 if ((bit_pos + bit_size) > bsize ||
3505 bt != prevbt || a == TOK_UNION)
3506 bit_pos = 0;
3507 lbit_pos = bit_pos;
3508 /* XXX: handle LSB first */
3509 type1.t |= VT_BITFIELD |
3510 (bit_pos << VT_STRUCT_SHIFT) |
3511 (bit_size << (VT_STRUCT_SHIFT + 6));
3512 bit_pos += bit_size;
3514 prevbt = bt;
3515 } else {
3516 bit_pos = 0;
3518 if (v != 0 || (type1.t & VT_BTYPE) == VT_STRUCT) {
3519 /* add new memory data only if starting
3520 bit field */
3521 if (lbit_pos == 0) {
3522 if (a == TOK_STRUCT) {
3523 c = (c + align - 1) & -align;
3524 offset = c;
3525 if (size > 0)
3526 c += size;
3527 } else {
3528 offset = 0;
3529 if (size > c)
3530 c = size;
3532 if (align > maxalign)
3533 maxalign = align;
3535 #if 0
3536 printf("add field %s offset=%d",
3537 get_tok_str(v, NULL), offset);
3538 if (type1.t & VT_BITFIELD) {
3539 printf(" pos=%d size=%d",
3540 (type1.t >> VT_STRUCT_SHIFT) & 0x3f,
3541 (type1.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
3543 printf("\n");
3544 #endif
3546 if (v == 0 && (type1.t & VT_BTYPE) == VT_STRUCT) {
3547 ass = type1.ref;
3548 while ((ass = ass->next) != NULL) {
3549 ss = sym_push(ass->v, &ass->type, 0, offset + ass->c);
3550 *ps = ss;
3551 ps = &ss->next;
3553 } else if (v) {
3554 ss = sym_push(v | SYM_FIELD, &type1, 0, offset);
3555 *ps = ss;
3556 ps = &ss->next;
3558 if (tok == ';' || tok == TOK_EOF)
3559 break;
3560 skip(',');
3562 skip(';');
3564 skip('}');
3565 /* store size and alignment */
3566 s->c = (c + maxalign - 1) & -maxalign;
3567 s->r = maxalign;
3572 /* return 0 if no type declaration. otherwise, return the basic type
3573 and skip it.
3575 static int parse_btype(CType *type, AttributeDef *ad)
3577 int t, u, type_found, typespec_found, typedef_found;
3578 Sym *s;
3579 CType type1;
3581 memset(ad, 0, sizeof(AttributeDef));
3582 type_found = 0;
3583 typespec_found = 0;
3584 typedef_found = 0;
3585 t = 0;
3586 while(1) {
3587 switch(tok) {
3588 case TOK_EXTENSION:
3589 /* currently, we really ignore extension */
3590 next();
3591 continue;
3593 /* basic types */
3594 case TOK_CHAR:
3595 u = VT_BYTE;
3596 basic_type:
3597 next();
3598 basic_type1:
3599 if ((t & VT_BTYPE) != 0)
3600 error("too many basic types");
3601 t |= u;
3602 typespec_found = 1;
3603 break;
3604 case TOK_VOID:
3605 u = VT_VOID;
3606 goto basic_type;
3607 case TOK_SHORT:
3608 u = VT_SHORT;
3609 goto basic_type;
3610 case TOK_INT:
3611 next();
3612 typespec_found = 1;
3613 break;
3614 case TOK_LONG:
3615 next();
3616 if ((t & VT_BTYPE) == VT_DOUBLE) {
3617 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
3618 } else if ((t & VT_BTYPE) == VT_LONG) {
3619 t = (t & ~VT_BTYPE) | VT_LLONG;
3620 } else {
3621 u = VT_LONG;
3622 goto basic_type1;
3624 break;
3625 case TOK_BOOL:
3626 u = VT_BOOL;
3627 goto basic_type;
3628 case TOK_FLOAT:
3629 u = VT_FLOAT;
3630 goto basic_type;
3631 case TOK_DOUBLE:
3632 next();
3633 if ((t & VT_BTYPE) == VT_LONG) {
3634 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
3635 } else {
3636 u = VT_DOUBLE;
3637 goto basic_type1;
3639 break;
3640 case TOK_ENUM:
3641 struct_decl(&type1, VT_ENUM);
3642 basic_type2:
3643 u = type1.t;
3644 type->ref = type1.ref;
3645 goto basic_type1;
3646 case TOK_STRUCT:
3647 case TOK_UNION:
3648 struct_decl(&type1, VT_STRUCT);
3649 goto basic_type2;
3651 /* type modifiers */
3652 case TOK_CONST1:
3653 case TOK_CONST2:
3654 case TOK_CONST3:
3655 t |= VT_CONSTANT;
3656 next();
3657 break;
3658 case TOK_VOLATILE1:
3659 case TOK_VOLATILE2:
3660 case TOK_VOLATILE3:
3661 t |= VT_VOLATILE;
3662 next();
3663 break;
3664 case TOK_SIGNED1:
3665 case TOK_SIGNED2:
3666 case TOK_SIGNED3:
3667 typespec_found = 1;
3668 t |= VT_SIGNED;
3669 next();
3670 break;
3671 case TOK_REGISTER:
3672 case TOK_AUTO:
3673 case TOK_RESTRICT1:
3674 case TOK_RESTRICT2:
3675 case TOK_RESTRICT3:
3676 next();
3677 break;
3678 case TOK_UNSIGNED:
3679 t |= VT_UNSIGNED;
3680 next();
3681 typespec_found = 1;
3682 break;
3684 /* storage */
3685 case TOK_EXTERN:
3686 t |= VT_EXTERN;
3687 next();
3688 break;
3689 case TOK_STATIC:
3690 t |= VT_STATIC;
3691 next();
3692 break;
3693 case TOK_TYPEDEF:
3694 t |= VT_TYPEDEF;
3695 next();
3696 break;
3697 case TOK_INLINE1:
3698 case TOK_INLINE2:
3699 case TOK_INLINE3:
3700 t |= VT_INLINE;
3701 next();
3702 break;
3704 /* GNUC attribute */
3705 case TOK_ATTRIBUTE1:
3706 case TOK_ATTRIBUTE2:
3707 parse_attribute(ad);
3708 break;
3709 /* GNUC typeof */
3710 case TOK_TYPEOF1:
3711 case TOK_TYPEOF2:
3712 case TOK_TYPEOF3:
3713 next();
3714 parse_expr_type(&type1);
3715 goto basic_type2;
3716 default:
3717 if (typespec_found || typedef_found)
3718 goto the_end;
3719 s = sym_find(tok);
3720 if (!s || !(s->type.t & VT_TYPEDEF))
3721 goto the_end;
3722 typedef_found = 1;
3723 t |= (s->type.t & ~VT_TYPEDEF);
3724 type->ref = s->type.ref;
3725 next();
3726 typespec_found = 1;
3727 break;
3729 type_found = 1;
3731 the_end:
3732 if ((t & (VT_SIGNED|VT_UNSIGNED)) == (VT_SIGNED|VT_UNSIGNED))
3733 error("signed and unsigned modifier");
3734 if (tcc_state->char_is_unsigned) {
3735 if ((t & (VT_SIGNED|VT_UNSIGNED|VT_BTYPE)) == VT_BYTE)
3736 t |= VT_UNSIGNED;
3738 t &= ~VT_SIGNED;
3740 /* long is never used as type */
3741 if ((t & VT_BTYPE) == VT_LONG)
3742 #ifndef TCC_TARGET_X86_64
3743 t = (t & ~VT_BTYPE) | VT_INT;
3744 #else
3745 t = (t & ~VT_BTYPE) | VT_LLONG;
3746 #endif
3747 type->t = t;
3748 return type_found;
3751 /* convert a function parameter type (array to pointer and function to
3752 function pointer) */
3753 static inline void convert_parameter_type(CType *pt)
3755 /* remove const and volatile qualifiers (XXX: const could be used
3756 to indicate a const function parameter */
3757 pt->t &= ~(VT_CONSTANT | VT_VOLATILE);
3758 /* array must be transformed to pointer according to ANSI C */
3759 pt->t &= ~VT_ARRAY;
3760 if ((pt->t & VT_BTYPE) == VT_FUNC) {
3761 mk_pointer(pt);
3765 static void post_type(CType *type, AttributeDef *ad)
3767 int n, l, t1, arg_size, align;
3768 Sym **plast, *s, *first;
3769 AttributeDef ad1;
3770 CType pt;
3772 if (tok == '(') {
3773 /* function declaration */
3774 next();
3775 l = 0;
3776 first = NULL;
3777 plast = &first;
3778 arg_size = 0;
3779 if (tok != ')') {
3780 for(;;) {
3781 /* read param name and compute offset */
3782 if (l != FUNC_OLD) {
3783 if (!parse_btype(&pt, &ad1)) {
3784 if (l) {
3785 error("invalid type");
3786 } else {
3787 l = FUNC_OLD;
3788 goto old_proto;
3791 l = FUNC_NEW;
3792 if ((pt.t & VT_BTYPE) == VT_VOID && tok == ')')
3793 break;
3794 type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT);
3795 if ((pt.t & VT_BTYPE) == VT_VOID)
3796 error("parameter declared as void");
3797 arg_size += (type_size(&pt, &align) + 3) & ~3;
3798 } else {
3799 old_proto:
3800 n = tok;
3801 if (n < TOK_UIDENT)
3802 expect("identifier");
3803 pt.t = VT_INT;
3804 next();
3806 convert_parameter_type(&pt);
3807 s = sym_push(n | SYM_FIELD, &pt, 0, 0);
3808 *plast = s;
3809 plast = &s->next;
3810 if (tok == ')')
3811 break;
3812 skip(',');
3813 if (l == FUNC_NEW && tok == TOK_DOTS) {
3814 l = FUNC_ELLIPSIS;
3815 next();
3816 break;
3820 /* if no parameters, then old type prototype */
3821 if (l == 0)
3822 l = FUNC_OLD;
3823 skip(')');
3824 t1 = type->t & VT_STORAGE;
3825 /* NOTE: const is ignored in returned type as it has a special
3826 meaning in gcc / C++ */
3827 type->t &= ~(VT_STORAGE | VT_CONSTANT);
3828 post_type(type, ad);
3829 /* we push a anonymous symbol which will contain the function prototype */
3830 FUNC_ARGS(ad->func_attr) = arg_size;
3831 s = sym_push(SYM_FIELD, type, ad->func_attr, l);
3832 s->next = first;
3833 type->t = t1 | VT_FUNC;
3834 type->ref = s;
3835 } else if (tok == '[') {
3836 /* array definition */
3837 next();
3838 if (tok == TOK_RESTRICT1)
3839 next();
3840 n = -1;
3841 if (tok != ']') {
3842 n = expr_const();
3843 if (n < 0)
3844 error("invalid array size");
3846 skip(']');
3847 /* parse next post type */
3848 t1 = type->t & VT_STORAGE;
3849 type->t &= ~VT_STORAGE;
3850 post_type(type, ad);
3852 /* we push a anonymous symbol which will contain the array
3853 element type */
3854 s = sym_push(SYM_FIELD, type, 0, n);
3855 type->t = t1 | VT_ARRAY | VT_PTR;
3856 type->ref = s;
3860 /* Parse a type declaration (except basic type), and return the type
3861 in 'type'. 'td' is a bitmask indicating which kind of type decl is
3862 expected. 'type' should contain the basic type. 'ad' is the
3863 attribute definition of the basic type. It can be modified by
3864 type_decl().
3866 static void type_decl(CType *type, AttributeDef *ad, int *v, int td)
3868 Sym *s;
3869 CType type1, *type2;
3870 int qualifiers;
3872 while (tok == '*') {
3873 qualifiers = 0;
3874 redo:
3875 next();
3876 switch(tok) {
3877 case TOK_CONST1:
3878 case TOK_CONST2:
3879 case TOK_CONST3:
3880 qualifiers |= VT_CONSTANT;
3881 goto redo;
3882 case TOK_VOLATILE1:
3883 case TOK_VOLATILE2:
3884 case TOK_VOLATILE3:
3885 qualifiers |= VT_VOLATILE;
3886 goto redo;
3887 case TOK_RESTRICT1:
3888 case TOK_RESTRICT2:
3889 case TOK_RESTRICT3:
3890 goto redo;
3892 mk_pointer(type);
3893 type->t |= qualifiers;
3896 /* XXX: clarify attribute handling */
3897 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
3898 parse_attribute(ad);
3900 /* recursive type */
3901 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
3902 type1.t = 0; /* XXX: same as int */
3903 if (tok == '(') {
3904 next();
3905 /* XXX: this is not correct to modify 'ad' at this point, but
3906 the syntax is not clear */
3907 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
3908 parse_attribute(ad);
3909 type_decl(&type1, ad, v, td);
3910 skip(')');
3911 } else {
3912 /* type identifier */
3913 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
3914 *v = tok;
3915 next();
3916 } else {
3917 if (!(td & TYPE_ABSTRACT))
3918 expect("identifier");
3919 *v = 0;
3922 post_type(type, ad);
3923 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
3924 parse_attribute(ad);
3925 if (!type1.t)
3926 return;
3927 /* append type at the end of type1 */
3928 type2 = &type1;
3929 for(;;) {
3930 s = type2->ref;
3931 type2 = &s->type;
3932 if (!type2->t) {
3933 *type2 = *type;
3934 break;
3937 *type = type1;
3940 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
3941 static int lvalue_type(int t)
3943 int bt, r;
3944 r = VT_LVAL;
3945 bt = t & VT_BTYPE;
3946 if (bt == VT_BYTE || bt == VT_BOOL)
3947 r |= VT_LVAL_BYTE;
3948 else if (bt == VT_SHORT)
3949 r |= VT_LVAL_SHORT;
3950 else
3951 return r;
3952 if (t & VT_UNSIGNED)
3953 r |= VT_LVAL_UNSIGNED;
3954 return r;
3957 /* indirection with full error checking and bound check */
3958 static void indir(void)
3960 if ((vtop->type.t & VT_BTYPE) != VT_PTR) {
3961 if ((vtop->type.t & VT_BTYPE) == VT_FUNC)
3962 return;
3963 expect("pointer");
3965 if ((vtop->r & VT_LVAL) && !nocode_wanted)
3966 gv(RC_INT);
3967 vtop->type = *pointed_type(&vtop->type);
3968 /* Arrays and functions are never lvalues */
3969 if (!(vtop->type.t & VT_ARRAY)
3970 && (vtop->type.t & VT_BTYPE) != VT_FUNC) {
3971 vtop->r |= lvalue_type(vtop->type.t);
3972 /* if bound checking, the referenced pointer must be checked */
3973 if (do_bounds_check)
3974 vtop->r |= VT_MUSTBOUND;
3978 /* pass a parameter to a function and do type checking and casting */
3979 static void gfunc_param_typed(Sym *func, Sym *arg)
3981 int func_type;
3982 CType type;
3984 func_type = func->c;
3985 if (func_type == FUNC_OLD ||
3986 (func_type == FUNC_ELLIPSIS && arg == NULL)) {
3987 /* default casting : only need to convert float to double */
3988 if ((vtop->type.t & VT_BTYPE) == VT_FLOAT) {
3989 type.t = VT_DOUBLE;
3990 gen_cast(&type);
3992 } else if (arg == NULL) {
3993 error("too many arguments to function");
3994 } else {
3995 type = arg->type;
3996 type.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
3997 gen_assign_cast(&type);
4001 /* parse an expression of the form '(type)' or '(expr)' and return its
4002 type */
4003 static void parse_expr_type(CType *type)
4005 int n;
4006 AttributeDef ad;
4008 skip('(');
4009 if (parse_btype(type, &ad)) {
4010 type_decl(type, &ad, &n, TYPE_ABSTRACT);
4011 } else {
4012 expr_type(type);
4014 skip(')');
4017 static void parse_type(CType *type)
4019 AttributeDef ad;
4020 int n;
4022 if (!parse_btype(type, &ad)) {
4023 expect("type");
4025 type_decl(type, &ad, &n, TYPE_ABSTRACT);
4028 static void vpush_tokc(int t)
4030 CType type;
4031 type.t = t;
4032 vsetc(&type, VT_CONST, &tokc);
4035 static void unary(void)
4037 int n, t, align, size, r;
4038 CType type;
4039 Sym *s;
4040 AttributeDef ad;
4042 /* XXX: GCC 2.95.3 does not generate a table although it should be
4043 better here */
4044 tok_next:
4045 switch(tok) {
4046 case TOK_EXTENSION:
4047 next();
4048 goto tok_next;
4049 case TOK_CINT:
4050 case TOK_CCHAR:
4051 case TOK_LCHAR:
4052 vpushi(tokc.i);
4053 next();
4054 break;
4055 case TOK_CUINT:
4056 vpush_tokc(VT_INT | VT_UNSIGNED);
4057 next();
4058 break;
4059 case TOK_CLLONG:
4060 vpush_tokc(VT_LLONG);
4061 next();
4062 break;
4063 case TOK_CULLONG:
4064 vpush_tokc(VT_LLONG | VT_UNSIGNED);
4065 next();
4066 break;
4067 case TOK_CFLOAT:
4068 vpush_tokc(VT_FLOAT);
4069 next();
4070 break;
4071 case TOK_CDOUBLE:
4072 vpush_tokc(VT_DOUBLE);
4073 next();
4074 break;
4075 case TOK_CLDOUBLE:
4076 vpush_tokc(VT_LDOUBLE);
4077 next();
4078 break;
4079 case TOK___FUNCTION__:
4080 if (!gnu_ext)
4081 goto tok_identifier;
4082 /* fall thru */
4083 case TOK___FUNC__:
4085 void *ptr;
4086 int len;
4087 /* special function name identifier */
4088 len = strlen(funcname) + 1;
4089 /* generate char[len] type */
4090 type.t = VT_BYTE;
4091 mk_pointer(&type);
4092 type.t |= VT_ARRAY;
4093 type.ref->c = len;
4094 vpush_ref(&type, data_section, data_section->data_offset, len);
4095 ptr = section_ptr_add(data_section, len);
4096 memcpy(ptr, funcname, len);
4097 next();
4099 break;
4100 case TOK_LSTR:
4101 #ifdef TCC_TARGET_PE
4102 t = VT_SHORT | VT_UNSIGNED;
4103 #else
4104 t = VT_INT;
4105 #endif
4106 goto str_init;
4107 case TOK_STR:
4108 /* string parsing */
4109 t = VT_BYTE;
4110 str_init:
4111 if (tcc_state->warn_write_strings)
4112 t |= VT_CONSTANT;
4113 type.t = t;
4114 mk_pointer(&type);
4115 type.t |= VT_ARRAY;
4116 memset(&ad, 0, sizeof(AttributeDef));
4117 decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, 0);
4118 break;
4119 case '(':
4120 next();
4121 /* cast ? */
4122 if (parse_btype(&type, &ad)) {
4123 type_decl(&type, &ad, &n, TYPE_ABSTRACT);
4124 skip(')');
4125 /* check ISOC99 compound literal */
4126 if (tok == '{') {
4127 /* data is allocated locally by default */
4128 if (global_expr)
4129 r = VT_CONST;
4130 else
4131 r = VT_LOCAL;
4132 /* all except arrays are lvalues */
4133 if (!(type.t & VT_ARRAY))
4134 r |= lvalue_type(type.t);
4135 memset(&ad, 0, sizeof(AttributeDef));
4136 decl_initializer_alloc(&type, &ad, r, 1, 0, 0);
4137 } else {
4138 unary();
4139 gen_cast(&type);
4141 } else if (tok == '{') {
4142 /* save all registers */
4143 save_regs(0);
4144 /* statement expression : we do not accept break/continue
4145 inside as GCC does */
4146 block(NULL, NULL, NULL, NULL, 0, 1);
4147 skip(')');
4148 } else {
4149 gexpr();
4150 skip(')');
4152 break;
4153 case '*':
4154 next();
4155 unary();
4156 indir();
4157 break;
4158 case '&':
4159 next();
4160 unary();
4161 /* functions names must be treated as function pointers,
4162 except for unary '&' and sizeof. Since we consider that
4163 functions are not lvalues, we only have to handle it
4164 there and in function calls. */
4165 /* arrays can also be used although they are not lvalues */
4166 if ((vtop->type.t & VT_BTYPE) != VT_FUNC &&
4167 !(vtop->type.t & VT_ARRAY) && !(vtop->type.t & VT_LLOCAL))
4168 test_lvalue();
4169 mk_pointer(&vtop->type);
4170 gaddrof();
4171 break;
4172 case '!':
4173 next();
4174 unary();
4175 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
4176 CType boolean;
4177 boolean.t = VT_BOOL;
4178 gen_cast(&boolean);
4179 vtop->c.i = !vtop->c.i;
4180 } else if ((vtop->r & VT_VALMASK) == VT_CMP)
4181 vtop->c.i = vtop->c.i ^ 1;
4182 else {
4183 save_regs(1);
4184 vseti(VT_JMP, gtst(1, 0));
4186 break;
4187 case '~':
4188 next();
4189 unary();
4190 vpushi(-1);
4191 gen_op('^');
4192 break;
4193 case '+':
4194 next();
4195 /* in order to force cast, we add zero */
4196 unary();
4197 if ((vtop->type.t & VT_BTYPE) == VT_PTR)
4198 error("pointer not accepted for unary plus");
4199 vpushi(0);
4200 gen_op('+');
4201 break;
4202 case TOK_SIZEOF:
4203 case TOK_ALIGNOF1:
4204 case TOK_ALIGNOF2:
4205 t = tok;
4206 next();
4207 if (tok == '(') {
4208 parse_expr_type(&type);
4209 } else {
4210 unary_type(&type);
4212 size = type_size(&type, &align);
4213 if (t == TOK_SIZEOF) {
4214 if (size < 0)
4215 error("sizeof applied to an incomplete type");
4216 vpushi(size);
4217 } else {
4218 vpushi(align);
4220 vtop->type.t |= VT_UNSIGNED;
4221 break;
4223 case TOK_builtin_types_compatible_p:
4225 CType type1, type2;
4226 next();
4227 skip('(');
4228 parse_type(&type1);
4229 skip(',');
4230 parse_type(&type2);
4231 skip(')');
4232 type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
4233 type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
4234 vpushi(is_compatible_types(&type1, &type2));
4236 break;
4237 case TOK_builtin_constant_p:
4239 int saved_nocode_wanted, res;
4240 next();
4241 skip('(');
4242 saved_nocode_wanted = nocode_wanted;
4243 nocode_wanted = 1;
4244 gexpr();
4245 res = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
4246 vpop();
4247 nocode_wanted = saved_nocode_wanted;
4248 skip(')');
4249 vpushi(res);
4251 break;
4252 case TOK_builtin_frame_address:
4254 CType type;
4255 next();
4256 skip('(');
4257 if (tok != TOK_CINT) {
4258 error("__builtin_frame_address only takes integers");
4260 if (tokc.i != 0) {
4261 error("TCC only supports __builtin_frame_address(0)");
4263 next();
4264 skip(')');
4265 type.t = VT_VOID;
4266 mk_pointer(&type);
4267 vset(&type, VT_LOCAL, 0);
4269 break;
4270 #ifdef TCC_TARGET_X86_64
4271 case TOK_builtin_malloc:
4272 tok = TOK_malloc;
4273 goto tok_identifier;
4274 case TOK_builtin_free:
4275 tok = TOK_free;
4276 goto tok_identifier;
4277 #endif
4278 case TOK_INC:
4279 case TOK_DEC:
4280 t = tok;
4281 next();
4282 unary();
4283 inc(0, t);
4284 break;
4285 case '-':
4286 next();
4287 vpushi(0);
4288 unary();
4289 gen_op('-');
4290 break;
4291 case TOK_LAND:
4292 if (!gnu_ext)
4293 goto tok_identifier;
4294 next();
4295 /* allow to take the address of a label */
4296 if (tok < TOK_UIDENT)
4297 expect("label identifier");
4298 s = label_find(tok);
4299 if (!s) {
4300 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
4301 } else {
4302 if (s->r == LABEL_DECLARED)
4303 s->r = LABEL_FORWARD;
4305 if (!s->type.t) {
4306 s->type.t = VT_VOID;
4307 mk_pointer(&s->type);
4308 s->type.t |= VT_STATIC;
4310 vset(&s->type, VT_CONST | VT_SYM, 0);
4311 vtop->sym = s;
4312 next();
4313 break;
4314 default:
4315 tok_identifier:
4316 t = tok;
4317 next();
4318 if (t < TOK_UIDENT)
4319 expect("identifier");
4320 s = sym_find(t);
4321 if (!s) {
4322 if (tok != '(')
4323 error("'%s' undeclared", get_tok_str(t, NULL));
4324 /* for simple function calls, we tolerate undeclared
4325 external reference to int() function */
4326 if (tcc_state->warn_implicit_function_declaration)
4327 warning("implicit declaration of function '%s'",
4328 get_tok_str(t, NULL));
4329 s = external_global_sym(t, &func_old_type, 0);
4331 if ((s->type.t & (VT_STATIC | VT_INLINE | VT_BTYPE)) ==
4332 (VT_STATIC | VT_INLINE | VT_FUNC)) {
4333 /* if referencing an inline function, then we generate a
4334 symbol to it if not already done. It will have the
4335 effect to generate code for it at the end of the
4336 compilation unit. Inline function as always
4337 generated in the text section. */
4338 if (!s->c)
4339 put_extern_sym(s, text_section, 0, 0);
4340 r = VT_SYM | VT_CONST;
4341 } else {
4342 r = s->r;
4344 vset(&s->type, r, s->c);
4345 /* if forward reference, we must point to s */
4346 if (vtop->r & VT_SYM) {
4347 vtop->sym = s;
4348 vtop->c.ul = 0;
4350 break;
4353 /* post operations */
4354 while (1) {
4355 if (tok == TOK_INC || tok == TOK_DEC) {
4356 inc(1, tok);
4357 next();
4358 } else if (tok == '.' || tok == TOK_ARROW) {
4359 /* field */
4360 if (tok == TOK_ARROW)
4361 indir();
4362 test_lvalue();
4363 gaddrof();
4364 next();
4365 /* expect pointer on structure */
4366 if ((vtop->type.t & VT_BTYPE) != VT_STRUCT)
4367 expect("struct or union");
4368 s = vtop->type.ref;
4369 /* find field */
4370 tok |= SYM_FIELD;
4371 while ((s = s->next) != NULL) {
4372 if (s->v == tok)
4373 break;
4375 if (!s)
4376 error("field not found: %s", get_tok_str(tok & ~SYM_FIELD, NULL));
4377 /* add field offset to pointer */
4378 vtop->type = char_pointer_type; /* change type to 'char *' */
4379 vpushi(s->c);
4380 gen_op('+');
4381 /* change type to field type, and set to lvalue */
4382 vtop->type = s->type;
4383 /* an array is never an lvalue */
4384 if (!(vtop->type.t & VT_ARRAY)) {
4385 vtop->r |= lvalue_type(vtop->type.t);
4386 /* if bound checking, the referenced pointer must be checked */
4387 if (do_bounds_check)
4388 vtop->r |= VT_MUSTBOUND;
4390 next();
4391 } else if (tok == '[') {
4392 next();
4393 gexpr();
4394 gen_op('+');
4395 indir();
4396 skip(']');
4397 } else if (tok == '(') {
4398 SValue ret;
4399 Sym *sa;
4400 int nb_args;
4402 /* function call */
4403 if ((vtop->type.t & VT_BTYPE) != VT_FUNC) {
4404 /* pointer test (no array accepted) */
4405 if ((vtop->type.t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
4406 vtop->type = *pointed_type(&vtop->type);
4407 if ((vtop->type.t & VT_BTYPE) != VT_FUNC)
4408 goto error_func;
4409 } else {
4410 error_func:
4411 expect("function pointer");
4413 } else {
4414 vtop->r &= ~VT_LVAL; /* no lvalue */
4416 /* get return type */
4417 s = vtop->type.ref;
4418 next();
4419 sa = s->next; /* first parameter */
4420 nb_args = 0;
4421 ret.r2 = VT_CONST;
4422 /* compute first implicit argument if a structure is returned */
4423 if ((s->type.t & VT_BTYPE) == VT_STRUCT) {
4424 /* get some space for the returned structure */
4425 size = type_size(&s->type, &align);
4426 loc = (loc - size) & -align;
4427 ret.type = s->type;
4428 ret.r = VT_LOCAL | VT_LVAL;
4429 /* pass it as 'int' to avoid structure arg passing
4430 problems */
4431 vseti(VT_LOCAL, loc);
4432 ret.c = vtop->c;
4433 nb_args++;
4434 } else {
4435 ret.type = s->type;
4436 /* return in register */
4437 if (is_float(ret.type.t)) {
4438 ret.r = reg_fret(ret.type.t);
4439 } else {
4440 if ((ret.type.t & VT_BTYPE) == VT_LLONG)
4441 ret.r2 = REG_LRET;
4442 ret.r = REG_IRET;
4444 ret.c.i = 0;
4446 if (tok != ')') {
4447 for(;;) {
4448 expr_eq();
4449 gfunc_param_typed(s, sa);
4450 nb_args++;
4451 if (sa)
4452 sa = sa->next;
4453 if (tok == ')')
4454 break;
4455 skip(',');
4458 if (sa)
4459 error("too few arguments to function");
4460 skip(')');
4461 if (!nocode_wanted) {
4462 gfunc_call(nb_args);
4463 } else {
4464 vtop -= (nb_args + 1);
4466 /* return value */
4467 vsetc(&ret.type, ret.r, &ret.c);
4468 vtop->r2 = ret.r2;
4469 } else {
4470 break;
4475 static void uneq(void)
4477 int t;
4479 unary();
4480 if (tok == '=' ||
4481 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
4482 tok == TOK_A_XOR || tok == TOK_A_OR ||
4483 tok == TOK_A_SHL || tok == TOK_A_SAR) {
4484 test_lvalue();
4485 t = tok;
4486 next();
4487 if (t == '=') {
4488 expr_eq();
4489 } else {
4490 vdup();
4491 expr_eq();
4492 gen_op(t & 0x7f);
4494 vstore();
4498 static void expr_prod(void)
4500 int t;
4502 uneq();
4503 while (tok == '*' || tok == '/' || tok == '%') {
4504 t = tok;
4505 next();
4506 uneq();
4507 gen_op(t);
4511 static void expr_sum(void)
4513 int t;
4515 expr_prod();
4516 while (tok == '+' || tok == '-') {
4517 t = tok;
4518 next();
4519 expr_prod();
4520 gen_op(t);
4524 static void expr_shift(void)
4526 int t;
4528 expr_sum();
4529 while (tok == TOK_SHL || tok == TOK_SAR) {
4530 t = tok;
4531 next();
4532 expr_sum();
4533 gen_op(t);
4537 static void expr_cmp(void)
4539 int t;
4541 expr_shift();
4542 while ((tok >= TOK_ULE && tok <= TOK_GT) ||
4543 tok == TOK_ULT || tok == TOK_UGE) {
4544 t = tok;
4545 next();
4546 expr_shift();
4547 gen_op(t);
4551 static void expr_cmpeq(void)
4553 int t;
4555 expr_cmp();
4556 while (tok == TOK_EQ || tok == TOK_NE) {
4557 t = tok;
4558 next();
4559 expr_cmp();
4560 gen_op(t);
4564 static void expr_and(void)
4566 expr_cmpeq();
4567 while (tok == '&') {
4568 next();
4569 expr_cmpeq();
4570 gen_op('&');
4574 static void expr_xor(void)
4576 expr_and();
4577 while (tok == '^') {
4578 next();
4579 expr_and();
4580 gen_op('^');
4584 static void expr_or(void)
4586 expr_xor();
4587 while (tok == '|') {
4588 next();
4589 expr_xor();
4590 gen_op('|');
4594 /* XXX: fix this mess */
4595 static void expr_land_const(void)
4597 expr_or();
4598 while (tok == TOK_LAND) {
4599 next();
4600 expr_or();
4601 gen_op(TOK_LAND);
4605 /* XXX: fix this mess */
4606 static void expr_lor_const(void)
4608 expr_land_const();
4609 while (tok == TOK_LOR) {
4610 next();
4611 expr_land_const();
4612 gen_op(TOK_LOR);
4616 /* only used if non constant */
4617 static void expr_land(void)
4619 int t;
4621 expr_or();
4622 if (tok == TOK_LAND) {
4623 t = 0;
4624 save_regs(1);
4625 for(;;) {
4626 t = gtst(1, t);
4627 if (tok != TOK_LAND) {
4628 vseti(VT_JMPI, t);
4629 break;
4631 next();
4632 expr_or();
4637 static void expr_lor(void)
4639 int t;
4641 expr_land();
4642 if (tok == TOK_LOR) {
4643 t = 0;
4644 save_regs(1);
4645 for(;;) {
4646 t = gtst(0, t);
4647 if (tok != TOK_LOR) {
4648 vseti(VT_JMP, t);
4649 break;
4651 next();
4652 expr_land();
4657 /* XXX: better constant handling */
4658 static void expr_eq(void)
4660 int tt, u, r1, r2, rc, t1, t2, bt1, bt2;
4661 SValue sv;
4662 CType type, type1, type2;
4664 if (const_wanted) {
4665 expr_lor_const();
4666 if (tok == '?') {
4667 CType boolean;
4668 int c;
4669 boolean.t = VT_BOOL;
4670 vdup();
4671 gen_cast(&boolean);
4672 c = vtop->c.i;
4673 vpop();
4674 next();
4675 if (tok != ':' || !gnu_ext) {
4676 vpop();
4677 gexpr();
4679 if (!c)
4680 vpop();
4681 skip(':');
4682 expr_eq();
4683 if (c)
4684 vpop();
4686 } else {
4687 expr_lor();
4688 if (tok == '?') {
4689 next();
4690 if (vtop != vstack) {
4691 /* needed to avoid having different registers saved in
4692 each branch */
4693 if (is_float(vtop->type.t)) {
4694 rc = RC_FLOAT;
4695 #ifdef TCC_TARGET_X86_64
4696 if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE) {
4697 rc = RC_ST0;
4699 #endif
4701 else
4702 rc = RC_INT;
4703 gv(rc);
4704 save_regs(1);
4706 if (tok == ':' && gnu_ext) {
4707 gv_dup();
4708 tt = gtst(1, 0);
4709 } else {
4710 tt = gtst(1, 0);
4711 gexpr();
4713 type1 = vtop->type;
4714 sv = *vtop; /* save value to handle it later */
4715 vtop--; /* no vpop so that FP stack is not flushed */
4716 skip(':');
4717 u = gjmp(0);
4718 gsym(tt);
4719 expr_eq();
4720 type2 = vtop->type;
4722 t1 = type1.t;
4723 bt1 = t1 & VT_BTYPE;
4724 t2 = type2.t;
4725 bt2 = t2 & VT_BTYPE;
4726 /* cast operands to correct type according to ISOC rules */
4727 if (is_float(bt1) || is_float(bt2)) {
4728 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
4729 type.t = VT_LDOUBLE;
4730 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
4731 type.t = VT_DOUBLE;
4732 } else {
4733 type.t = VT_FLOAT;
4735 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
4736 /* cast to biggest op */
4737 type.t = VT_LLONG;
4738 /* convert to unsigned if it does not fit in a long long */
4739 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
4740 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
4741 type.t |= VT_UNSIGNED;
4742 } else if (bt1 == VT_PTR || bt2 == VT_PTR) {
4743 /* XXX: test pointer compatibility */
4744 type = type1;
4745 } else if (bt1 == VT_FUNC || bt2 == VT_FUNC) {
4746 /* XXX: test function pointer compatibility */
4747 type = type1;
4748 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
4749 /* XXX: test structure compatibility */
4750 type = type1;
4751 } else if (bt1 == VT_VOID || bt2 == VT_VOID) {
4752 /* NOTE: as an extension, we accept void on only one side */
4753 type.t = VT_VOID;
4754 } else {
4755 /* integer operations */
4756 type.t = VT_INT;
4757 /* convert to unsigned if it does not fit in an integer */
4758 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
4759 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
4760 type.t |= VT_UNSIGNED;
4763 /* now we convert second operand */
4764 gen_cast(&type);
4765 if (VT_STRUCT == (vtop->type.t & VT_BTYPE))
4766 gaddrof();
4767 rc = RC_INT;
4768 if (is_float(type.t)) {
4769 rc = RC_FLOAT;
4770 #ifdef TCC_TARGET_X86_64
4771 if ((type.t & VT_BTYPE) == VT_LDOUBLE) {
4772 rc = RC_ST0;
4774 #endif
4775 } else if ((type.t & VT_BTYPE) == VT_LLONG) {
4776 /* for long longs, we use fixed registers to avoid having
4777 to handle a complicated move */
4778 rc = RC_IRET;
4781 r2 = gv(rc);
4782 /* this is horrible, but we must also convert first
4783 operand */
4784 tt = gjmp(0);
4785 gsym(u);
4786 /* put again first value and cast it */
4787 *vtop = sv;
4788 gen_cast(&type);
4789 if (VT_STRUCT == (vtop->type.t & VT_BTYPE))
4790 gaddrof();
4791 r1 = gv(rc);
4792 move_reg(r2, r1);
4793 vtop->r = r2;
4794 gsym(tt);
4799 static void gexpr(void)
4801 while (1) {
4802 expr_eq();
4803 if (tok != ',')
4804 break;
4805 vpop();
4806 next();
4810 /* parse an expression and return its type without any side effect. */
4811 static void expr_type(CType *type)
4813 int saved_nocode_wanted;
4815 saved_nocode_wanted = nocode_wanted;
4816 nocode_wanted = 1;
4817 gexpr();
4818 *type = vtop->type;
4819 vpop();
4820 nocode_wanted = saved_nocode_wanted;
4823 /* parse a unary expression and return its type without any side
4824 effect. */
4825 static void unary_type(CType *type)
4827 int a;
4829 a = nocode_wanted;
4830 nocode_wanted = 1;
4831 unary();
4832 *type = vtop->type;
4833 vpop();
4834 nocode_wanted = a;
4837 /* parse a constant expression and return value in vtop. */
4838 static void expr_const1(void)
4840 int a;
4841 a = const_wanted;
4842 const_wanted = 1;
4843 expr_eq();
4844 const_wanted = a;
4847 /* parse an integer constant and return its value. */
4848 static int expr_const(void)
4850 int c;
4851 expr_const1();
4852 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
4853 expect("constant expression");
4854 c = vtop->c.i;
4855 vpop();
4856 return c;
4859 /* return the label token if current token is a label, otherwise
4860 return zero */
4861 static int is_label(void)
4863 int last_tok;
4865 /* fast test first */
4866 if (tok < TOK_UIDENT)
4867 return 0;
4868 /* no need to save tokc because tok is an identifier */
4869 last_tok = tok;
4870 next();
4871 if (tok == ':') {
4872 next();
4873 return last_tok;
4874 } else {
4875 unget_tok(last_tok);
4876 return 0;
4880 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
4881 int case_reg, int is_expr)
4883 int a, b, c, d;
4884 Sym *s;
4886 /* generate line number info */
4887 if (do_debug &&
4888 (last_line_num != file->line_num || last_ind != ind)) {
4889 put_stabn(N_SLINE, 0, file->line_num, ind - func_ind);
4890 last_ind = ind;
4891 last_line_num = file->line_num;
4894 if (is_expr) {
4895 /* default return value is (void) */
4896 vpushi(0);
4897 vtop->type.t = VT_VOID;
4900 if (tok == TOK_IF) {
4901 /* if test */
4902 next();
4903 skip('(');
4904 gexpr();
4905 skip(')');
4906 a = gtst(1, 0);
4907 block(bsym, csym, case_sym, def_sym, case_reg, 0);
4908 c = tok;
4909 if (c == TOK_ELSE) {
4910 next();
4911 d = gjmp(0);
4912 gsym(a);
4913 block(bsym, csym, case_sym, def_sym, case_reg, 0);
4914 gsym(d); /* patch else jmp */
4915 } else
4916 gsym(a);
4917 } else if (tok == TOK_WHILE) {
4918 next();
4919 d = ind;
4920 skip('(');
4921 gexpr();
4922 skip(')');
4923 a = gtst(1, 0);
4924 b = 0;
4925 block(&a, &b, case_sym, def_sym, case_reg, 0);
4926 gjmp_addr(d);
4927 gsym(a);
4928 gsym_addr(b, d);
4929 } else if (tok == '{') {
4930 Sym *llabel;
4932 next();
4933 /* record local declaration stack position */
4934 s = local_stack;
4935 llabel = local_label_stack;
4936 /* handle local labels declarations */
4937 if (tok == TOK_LABEL) {
4938 next();
4939 for(;;) {
4940 if (tok < TOK_UIDENT)
4941 expect("label identifier");
4942 label_push(&local_label_stack, tok, LABEL_DECLARED);
4943 next();
4944 if (tok == ',') {
4945 next();
4946 } else {
4947 skip(';');
4948 break;
4952 while (tok != '}') {
4953 decl(VT_LOCAL);
4954 if (tok != '}') {
4955 if (is_expr)
4956 vpop();
4957 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
4960 /* pop locally defined labels */
4961 label_pop(&local_label_stack, llabel);
4962 /* pop locally defined symbols */
4963 if(is_expr) {
4964 /* XXX: this solution makes only valgrind happy...
4965 triggered by gcc.c-torture/execute/20000917-1.c */
4966 Sym *p;
4967 switch(vtop->type.t & VT_BTYPE) {
4968 case VT_PTR:
4969 case VT_STRUCT:
4970 case VT_ENUM:
4971 case VT_FUNC:
4972 for(p=vtop->type.ref;p;p=p->prev)
4973 if(p->prev==s)
4974 error("unsupported expression type");
4977 sym_pop(&local_stack, s);
4978 next();
4979 } else if (tok == TOK_RETURN) {
4980 next();
4981 if (tok != ';') {
4982 gexpr();
4983 gen_assign_cast(&func_vt);
4984 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
4985 CType type;
4986 /* if returning structure, must copy it to implicit
4987 first pointer arg location */
4988 #ifdef TCC_ARM_EABI
4989 int align, size;
4990 size = type_size(&func_vt,&align);
4991 if(size <= 4)
4993 if((vtop->r != (VT_LOCAL | VT_LVAL) || (vtop->c.i & 3))
4994 && (align & 3))
4996 int addr;
4997 loc = (loc - size) & -4;
4998 addr = loc;
4999 type = func_vt;
5000 vset(&type, VT_LOCAL | VT_LVAL, addr);
5001 vswap();
5002 vstore();
5003 vset(&int_type, VT_LOCAL | VT_LVAL, addr);
5005 vtop->type = int_type;
5006 gv(RC_IRET);
5007 } else {
5008 #endif
5009 type = func_vt;
5010 mk_pointer(&type);
5011 vset(&type, VT_LOCAL | VT_LVAL, func_vc);
5012 indir();
5013 vswap();
5014 /* copy structure value to pointer */
5015 vstore();
5016 #ifdef TCC_ARM_EABI
5018 #endif
5019 } else if (is_float(func_vt.t)) {
5020 gv(rc_fret(func_vt.t));
5021 } else {
5022 gv(RC_IRET);
5024 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
5026 skip(';');
5027 rsym = gjmp(rsym); /* jmp */
5028 } else if (tok == TOK_BREAK) {
5029 /* compute jump */
5030 if (!bsym)
5031 error("cannot break");
5032 *bsym = gjmp(*bsym);
5033 next();
5034 skip(';');
5035 } else if (tok == TOK_CONTINUE) {
5036 /* compute jump */
5037 if (!csym)
5038 error("cannot continue");
5039 *csym = gjmp(*csym);
5040 next();
5041 skip(';');
5042 } else if (tok == TOK_FOR) {
5043 int e;
5044 next();
5045 skip('(');
5046 if (tok != ';') {
5047 gexpr();
5048 vpop();
5050 skip(';');
5051 d = ind;
5052 c = ind;
5053 a = 0;
5054 b = 0;
5055 if (tok != ';') {
5056 gexpr();
5057 a = gtst(1, 0);
5059 skip(';');
5060 if (tok != ')') {
5061 e = gjmp(0);
5062 c = ind;
5063 gexpr();
5064 vpop();
5065 gjmp_addr(d);
5066 gsym(e);
5068 skip(')');
5069 block(&a, &b, case_sym, def_sym, case_reg, 0);
5070 gjmp_addr(c);
5071 gsym(a);
5072 gsym_addr(b, c);
5073 } else
5074 if (tok == TOK_DO) {
5075 next();
5076 a = 0;
5077 b = 0;
5078 d = ind;
5079 block(&a, &b, case_sym, def_sym, case_reg, 0);
5080 skip(TOK_WHILE);
5081 skip('(');
5082 gsym(b);
5083 gexpr();
5084 c = gtst(0, 0);
5085 gsym_addr(c, d);
5086 skip(')');
5087 gsym(a);
5088 skip(';');
5089 } else
5090 if (tok == TOK_SWITCH) {
5091 next();
5092 skip('(');
5093 gexpr();
5094 /* XXX: other types than integer */
5095 case_reg = gv(RC_INT);
5096 vpop();
5097 skip(')');
5098 a = 0;
5099 b = gjmp(0); /* jump to first case */
5100 c = 0;
5101 block(&a, csym, &b, &c, case_reg, 0);
5102 /* if no default, jmp after switch */
5103 if (c == 0)
5104 c = ind;
5105 /* default label */
5106 gsym_addr(b, c);
5107 /* break label */
5108 gsym(a);
5109 } else
5110 if (tok == TOK_CASE) {
5111 int v1, v2;
5112 if (!case_sym)
5113 expect("switch");
5114 next();
5115 v1 = expr_const();
5116 v2 = v1;
5117 if (gnu_ext && tok == TOK_DOTS) {
5118 next();
5119 v2 = expr_const();
5120 if (v2 < v1)
5121 warning("empty case range");
5123 /* since a case is like a label, we must skip it with a jmp */
5124 b = gjmp(0);
5125 gsym(*case_sym);
5126 vseti(case_reg, 0);
5127 vpushi(v1);
5128 if (v1 == v2) {
5129 gen_op(TOK_EQ);
5130 *case_sym = gtst(1, 0);
5131 } else {
5132 gen_op(TOK_GE);
5133 *case_sym = gtst(1, 0);
5134 vseti(case_reg, 0);
5135 vpushi(v2);
5136 gen_op(TOK_LE);
5137 *case_sym = gtst(1, *case_sym);
5139 gsym(b);
5140 skip(':');
5141 is_expr = 0;
5142 goto block_after_label;
5143 } else
5144 if (tok == TOK_DEFAULT) {
5145 next();
5146 skip(':');
5147 if (!def_sym)
5148 expect("switch");
5149 if (*def_sym)
5150 error("too many 'default'");
5151 *def_sym = ind;
5152 is_expr = 0;
5153 goto block_after_label;
5154 } else
5155 if (tok == TOK_GOTO) {
5156 next();
5157 if (tok == '*' && gnu_ext) {
5158 /* computed goto */
5159 next();
5160 gexpr();
5161 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
5162 expect("pointer");
5163 ggoto();
5164 } else if (tok >= TOK_UIDENT) {
5165 s = label_find(tok);
5166 /* put forward definition if needed */
5167 if (!s) {
5168 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
5169 } else {
5170 if (s->r == LABEL_DECLARED)
5171 s->r = LABEL_FORWARD;
5173 /* label already defined */
5174 if (s->r & LABEL_FORWARD)
5175 s->next = (void *)gjmp((long)s->next);
5176 else
5177 gjmp_addr((long)s->next);
5178 next();
5179 } else {
5180 expect("label identifier");
5182 skip(';');
5183 } else if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) {
5184 asm_instr();
5185 } else {
5186 b = is_label();
5187 if (b) {
5188 /* label case */
5189 s = label_find(b);
5190 if (s) {
5191 if (s->r == LABEL_DEFINED)
5192 error("duplicate label '%s'", get_tok_str(s->v, NULL));
5193 gsym((long)s->next);
5194 s->r = LABEL_DEFINED;
5195 } else {
5196 s = label_push(&global_label_stack, b, LABEL_DEFINED);
5198 s->next = (void *)ind;
5199 /* we accept this, but it is a mistake */
5200 block_after_label:
5201 if (tok == '}') {
5202 warning("deprecated use of label at end of compound statement");
5203 } else {
5204 if (is_expr)
5205 vpop();
5206 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
5208 } else {
5209 /* expression case */
5210 if (tok != ';') {
5211 if (is_expr) {
5212 vpop();
5213 gexpr();
5214 } else {
5215 gexpr();
5216 vpop();
5219 skip(';');
5224 /* t is the array or struct type. c is the array or struct
5225 address. cur_index/cur_field is the pointer to the current
5226 value. 'size_only' is true if only size info is needed (only used
5227 in arrays) */
5228 static void decl_designator(CType *type, Section *sec, unsigned long c,
5229 int *cur_index, Sym **cur_field,
5230 int size_only)
5232 Sym *s, *f;
5233 int notfirst, index, index_last, align, l, nb_elems, elem_size;
5234 CType type1;
5236 notfirst = 0;
5237 elem_size = 0;
5238 nb_elems = 1;
5239 if (gnu_ext && (l = is_label()) != 0)
5240 goto struct_field;
5241 while (tok == '[' || tok == '.') {
5242 if (tok == '[') {
5243 if (!(type->t & VT_ARRAY))
5244 expect("array type");
5245 s = type->ref;
5246 next();
5247 index = expr_const();
5248 if (index < 0 || (s->c >= 0 && index >= s->c))
5249 expect("invalid index");
5250 if (tok == TOK_DOTS && gnu_ext) {
5251 next();
5252 index_last = expr_const();
5253 if (index_last < 0 ||
5254 (s->c >= 0 && index_last >= s->c) ||
5255 index_last < index)
5256 expect("invalid index");
5257 } else {
5258 index_last = index;
5260 skip(']');
5261 if (!notfirst)
5262 *cur_index = index_last;
5263 type = pointed_type(type);
5264 elem_size = type_size(type, &align);
5265 c += index * elem_size;
5266 /* NOTE: we only support ranges for last designator */
5267 nb_elems = index_last - index + 1;
5268 if (nb_elems != 1) {
5269 notfirst = 1;
5270 break;
5272 } else {
5273 next();
5274 l = tok;
5275 next();
5276 struct_field:
5277 if ((type->t & VT_BTYPE) != VT_STRUCT)
5278 expect("struct/union type");
5279 s = type->ref;
5280 l |= SYM_FIELD;
5281 f = s->next;
5282 while (f) {
5283 if (f->v == l)
5284 break;
5285 f = f->next;
5287 if (!f)
5288 expect("field");
5289 if (!notfirst)
5290 *cur_field = f;
5291 /* XXX: fix this mess by using explicit storage field */
5292 type1 = f->type;
5293 type1.t |= (type->t & ~VT_TYPE);
5294 type = &type1;
5295 c += f->c;
5297 notfirst = 1;
5299 if (notfirst) {
5300 if (tok == '=') {
5301 next();
5302 } else {
5303 if (!gnu_ext)
5304 expect("=");
5306 } else {
5307 if (type->t & VT_ARRAY) {
5308 index = *cur_index;
5309 type = pointed_type(type);
5310 c += index * type_size(type, &align);
5311 } else {
5312 f = *cur_field;
5313 if (!f)
5314 error("too many field init");
5315 /* XXX: fix this mess by using explicit storage field */
5316 type1 = f->type;
5317 type1.t |= (type->t & ~VT_TYPE);
5318 type = &type1;
5319 c += f->c;
5322 decl_initializer(type, sec, c, 0, size_only);
5324 /* XXX: make it more general */
5325 if (!size_only && nb_elems > 1) {
5326 unsigned long c_end;
5327 uint8_t *src, *dst;
5328 int i;
5330 if (!sec)
5331 error("range init not supported yet for dynamic storage");
5332 c_end = c + nb_elems * elem_size;
5333 if (c_end > sec->data_allocated)
5334 section_realloc(sec, c_end);
5335 src = sec->data + c;
5336 dst = src;
5337 for(i = 1; i < nb_elems; i++) {
5338 dst += elem_size;
5339 memcpy(dst, src, elem_size);
5344 #define EXPR_VAL 0
5345 #define EXPR_CONST 1
5346 #define EXPR_ANY 2
5348 /* store a value or an expression directly in global data or in local array */
5349 static void init_putv(CType *type, Section *sec, unsigned long c,
5350 int v, int expr_type)
5352 int saved_global_expr, bt, bit_pos, bit_size;
5353 void *ptr;
5354 unsigned long long bit_mask;
5355 CType dtype;
5357 switch(expr_type) {
5358 case EXPR_VAL:
5359 vpushi(v);
5360 break;
5361 case EXPR_CONST:
5362 /* compound literals must be allocated globally in this case */
5363 saved_global_expr = global_expr;
5364 global_expr = 1;
5365 expr_const1();
5366 global_expr = saved_global_expr;
5367 /* NOTE: symbols are accepted */
5368 if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
5369 error("initializer element is not constant");
5370 break;
5371 case EXPR_ANY:
5372 expr_eq();
5373 break;
5376 dtype = *type;
5377 dtype.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
5379 if (sec) {
5380 /* XXX: not portable */
5381 /* XXX: generate error if incorrect relocation */
5382 gen_assign_cast(&dtype);
5383 bt = type->t & VT_BTYPE;
5384 /* we'll write at most 12 bytes */
5385 if (c + 12 > sec->data_allocated) {
5386 section_realloc(sec, c + 12);
5388 ptr = sec->data + c;
5389 /* XXX: make code faster ? */
5390 if (!(type->t & VT_BITFIELD)) {
5391 bit_pos = 0;
5392 bit_size = 32;
5393 bit_mask = -1LL;
5394 } else {
5395 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
5396 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
5397 bit_mask = (1LL << bit_size) - 1;
5399 if ((vtop->r & VT_SYM) &&
5400 (bt == VT_BYTE ||
5401 bt == VT_SHORT ||
5402 bt == VT_DOUBLE ||
5403 bt == VT_LDOUBLE ||
5404 bt == VT_LLONG ||
5405 (bt == VT_INT && bit_size != 32)))
5406 error("initializer element is not computable at load time");
5407 switch(bt) {
5408 case VT_BOOL:
5409 vtop->c.i = (vtop->c.i != 0);
5410 case VT_BYTE:
5411 *(char *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
5412 break;
5413 case VT_SHORT:
5414 *(short *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
5415 break;
5416 case VT_DOUBLE:
5417 *(double *)ptr = vtop->c.d;
5418 break;
5419 case VT_LDOUBLE:
5420 *(long double *)ptr = vtop->c.ld;
5421 break;
5422 case VT_LLONG:
5423 *(long long *)ptr |= (vtop->c.ll & bit_mask) << bit_pos;
5424 break;
5425 default:
5426 if (vtop->r & VT_SYM) {
5427 greloc(sec, vtop->sym, c, R_DATA_32);
5429 *(int *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
5430 break;
5432 vtop--;
5433 } else {
5434 vset(&dtype, VT_LOCAL|VT_LVAL, c);
5435 vswap();
5436 vstore();
5437 vpop();
5441 /* put zeros for variable based init */
5442 static void init_putz(CType *t, Section *sec, unsigned long c, int size)
5444 if (sec) {
5445 /* nothing to do because globals are already set to zero */
5446 } else {
5447 vpush_global_sym(&func_old_type, TOK_memset);
5448 vseti(VT_LOCAL, c);
5449 vpushi(0);
5450 vpushi(size);
5451 gfunc_call(3);
5455 /* 't' contains the type and storage info. 'c' is the offset of the
5456 object in section 'sec'. If 'sec' is NULL, it means stack based
5457 allocation. 'first' is true if array '{' must be read (multi
5458 dimension implicit array init handling). 'size_only' is true if
5459 size only evaluation is wanted (only for arrays). */
5460 static void decl_initializer(CType *type, Section *sec, unsigned long c,
5461 int first, int size_only)
5463 int index, array_length, n, no_oblock, nb, parlevel, i;
5464 int size1, align1, expr_type;
5465 Sym *s, *f;
5466 CType *t1;
5468 if (type->t & VT_ARRAY) {
5469 s = type->ref;
5470 n = s->c;
5471 array_length = 0;
5472 t1 = pointed_type(type);
5473 size1 = type_size(t1, &align1);
5475 no_oblock = 1;
5476 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
5477 tok == '{') {
5478 skip('{');
5479 no_oblock = 0;
5482 /* only parse strings here if correct type (otherwise: handle
5483 them as ((w)char *) expressions */
5484 if ((tok == TOK_LSTR &&
5485 #ifdef TCC_TARGET_PE
5486 (t1->t & VT_BTYPE) == VT_SHORT && (t1->t & VT_UNSIGNED)
5487 #else
5488 (t1->t & VT_BTYPE) == VT_INT
5489 #endif
5490 ) || (tok == TOK_STR && (t1->t & VT_BTYPE) == VT_BYTE)) {
5491 while (tok == TOK_STR || tok == TOK_LSTR) {
5492 int cstr_len, ch;
5493 CString *cstr;
5495 cstr = tokc.cstr;
5496 /* compute maximum number of chars wanted */
5497 if (tok == TOK_STR)
5498 cstr_len = cstr->size;
5499 else
5500 cstr_len = cstr->size / sizeof(nwchar_t);
5501 cstr_len--;
5502 nb = cstr_len;
5503 if (n >= 0 && nb > (n - array_length))
5504 nb = n - array_length;
5505 if (!size_only) {
5506 if (cstr_len > nb)
5507 warning("initializer-string for array is too long");
5508 /* in order to go faster for common case (char
5509 string in global variable, we handle it
5510 specifically */
5511 if (sec && tok == TOK_STR && size1 == 1) {
5512 memcpy(sec->data + c + array_length, cstr->data, nb);
5513 } else {
5514 for(i=0;i<nb;i++) {
5515 if (tok == TOK_STR)
5516 ch = ((unsigned char *)cstr->data)[i];
5517 else
5518 ch = ((nwchar_t *)cstr->data)[i];
5519 init_putv(t1, sec, c + (array_length + i) * size1,
5520 ch, EXPR_VAL);
5524 array_length += nb;
5525 next();
5527 /* only add trailing zero if enough storage (no
5528 warning in this case since it is standard) */
5529 if (n < 0 || array_length < n) {
5530 if (!size_only) {
5531 init_putv(t1, sec, c + (array_length * size1), 0, EXPR_VAL);
5533 array_length++;
5535 } else {
5536 index = 0;
5537 while (tok != '}') {
5538 decl_designator(type, sec, c, &index, NULL, size_only);
5539 if (n >= 0 && index >= n)
5540 error("index too large");
5541 /* must put zero in holes (note that doing it that way
5542 ensures that it even works with designators) */
5543 if (!size_only && array_length < index) {
5544 init_putz(t1, sec, c + array_length * size1,
5545 (index - array_length) * size1);
5547 index++;
5548 if (index > array_length)
5549 array_length = index;
5550 /* special test for multi dimensional arrays (may not
5551 be strictly correct if designators are used at the
5552 same time) */
5553 if (index >= n && no_oblock)
5554 break;
5555 if (tok == '}')
5556 break;
5557 skip(',');
5560 if (!no_oblock)
5561 skip('}');
5562 /* put zeros at the end */
5563 if (!size_only && n >= 0 && array_length < n) {
5564 init_putz(t1, sec, c + array_length * size1,
5565 (n - array_length) * size1);
5567 /* patch type size if needed */
5568 if (n < 0)
5569 s->c = array_length;
5570 } else if ((type->t & VT_BTYPE) == VT_STRUCT &&
5571 (sec || !first || tok == '{')) {
5572 int par_count;
5574 /* NOTE: the previous test is a specific case for automatic
5575 struct/union init */
5576 /* XXX: union needs only one init */
5578 /* XXX: this test is incorrect for local initializers
5579 beginning with ( without {. It would be much more difficult
5580 to do it correctly (ideally, the expression parser should
5581 be used in all cases) */
5582 par_count = 0;
5583 if (tok == '(') {
5584 AttributeDef ad1;
5585 CType type1;
5586 next();
5587 while (tok == '(') {
5588 par_count++;
5589 next();
5591 if (!parse_btype(&type1, &ad1))
5592 expect("cast");
5593 type_decl(&type1, &ad1, &n, TYPE_ABSTRACT);
5594 #if 0
5595 if (!is_assignable_types(type, &type1))
5596 error("invalid type for cast");
5597 #endif
5598 skip(')');
5600 no_oblock = 1;
5601 if (first || tok == '{') {
5602 skip('{');
5603 no_oblock = 0;
5605 s = type->ref;
5606 f = s->next;
5607 array_length = 0;
5608 index = 0;
5609 n = s->c;
5610 while (tok != '}') {
5611 decl_designator(type, sec, c, NULL, &f, size_only);
5612 index = f->c;
5613 if (!size_only && array_length < index) {
5614 init_putz(type, sec, c + array_length,
5615 index - array_length);
5617 index = index + type_size(&f->type, &align1);
5618 if (index > array_length)
5619 array_length = index;
5620 f = f->next;
5621 if (no_oblock && f == NULL)
5622 break;
5623 if (tok == '}')
5624 break;
5625 skip(',');
5627 /* put zeros at the end */
5628 if (!size_only && array_length < n) {
5629 init_putz(type, sec, c + array_length,
5630 n - array_length);
5632 if (!no_oblock)
5633 skip('}');
5634 while (par_count) {
5635 skip(')');
5636 par_count--;
5638 } else if (tok == '{') {
5639 next();
5640 decl_initializer(type, sec, c, first, size_only);
5641 skip('}');
5642 } else if (size_only) {
5643 /* just skip expression */
5644 parlevel = 0;
5645 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
5646 tok != -1) {
5647 if (tok == '(')
5648 parlevel++;
5649 else if (tok == ')')
5650 parlevel--;
5651 next();
5653 } else {
5654 /* currently, we always use constant expression for globals
5655 (may change for scripting case) */
5656 expr_type = EXPR_CONST;
5657 if (!sec)
5658 expr_type = EXPR_ANY;
5659 init_putv(type, sec, c, 0, expr_type);
5663 /* parse an initializer for type 't' if 'has_init' is non zero, and
5664 allocate space in local or global data space ('r' is either
5665 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
5666 variable 'v' of scope 'scope' is declared before initializers are
5667 parsed. If 'v' is zero, then a reference to the new object is put
5668 in the value stack. If 'has_init' is 2, a special parsing is done
5669 to handle string constants. */
5670 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
5671 int has_init, int v, int scope)
5673 int size, align, addr, data_offset;
5674 int level;
5675 ParseState saved_parse_state = {0};
5676 TokenString init_str;
5677 Section *sec;
5679 size = type_size(type, &align);
5680 /* If unknown size, we must evaluate it before
5681 evaluating initializers because
5682 initializers can generate global data too
5683 (e.g. string pointers or ISOC99 compound
5684 literals). It also simplifies local
5685 initializers handling */
5686 tok_str_new(&init_str);
5687 if (size < 0) {
5688 if (!has_init)
5689 error("unknown type size");
5690 /* get all init string */
5691 if (has_init == 2) {
5692 /* only get strings */
5693 while (tok == TOK_STR || tok == TOK_LSTR) {
5694 tok_str_add_tok(&init_str);
5695 next();
5697 } else {
5698 level = 0;
5699 while (level > 0 || (tok != ',' && tok != ';')) {
5700 if (tok < 0)
5701 error("unexpected end of file in initializer");
5702 tok_str_add_tok(&init_str);
5703 if (tok == '{')
5704 level++;
5705 else if (tok == '}') {
5706 level--;
5707 if (level <= 0) {
5708 next();
5709 break;
5712 next();
5715 tok_str_add(&init_str, -1);
5716 tok_str_add(&init_str, 0);
5718 /* compute size */
5719 save_parse_state(&saved_parse_state);
5721 macro_ptr = init_str.str;
5722 next();
5723 decl_initializer(type, NULL, 0, 1, 1);
5724 /* prepare second initializer parsing */
5725 macro_ptr = init_str.str;
5726 next();
5728 /* if still unknown size, error */
5729 size = type_size(type, &align);
5730 if (size < 0)
5731 error("unknown type size");
5733 /* take into account specified alignment if bigger */
5734 if (ad->aligned) {
5735 if (ad->aligned > align)
5736 align = ad->aligned;
5737 } else if (ad->packed) {
5738 align = 1;
5740 if ((r & VT_VALMASK) == VT_LOCAL) {
5741 sec = NULL;
5742 if (do_bounds_check && (type->t & VT_ARRAY))
5743 loc--;
5744 loc = (loc - size) & -align;
5745 addr = loc;
5746 /* handles bounds */
5747 /* XXX: currently, since we do only one pass, we cannot track
5748 '&' operators, so we add only arrays */
5749 if (do_bounds_check && (type->t & VT_ARRAY)) {
5750 unsigned long *bounds_ptr;
5751 /* add padding between regions */
5752 loc--;
5753 /* then add local bound info */
5754 bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(unsigned long));
5755 bounds_ptr[0] = addr;
5756 bounds_ptr[1] = size;
5758 if (v) {
5759 /* local variable */
5760 sym_push(v, type, r, addr);
5761 } else {
5762 /* push local reference */
5763 vset(type, r, addr);
5765 } else {
5766 Sym *sym;
5768 sym = NULL;
5769 if (v && scope == VT_CONST) {
5770 /* see if the symbol was already defined */
5771 sym = sym_find(v);
5772 if (sym) {
5773 if (!is_compatible_types(&sym->type, type))
5774 error("incompatible types for redefinition of '%s'",
5775 get_tok_str(v, NULL));
5776 if (sym->type.t & VT_EXTERN) {
5777 /* if the variable is extern, it was not allocated */
5778 sym->type.t &= ~VT_EXTERN;
5779 /* set array size if it was ommited in extern
5780 declaration */
5781 if ((sym->type.t & VT_ARRAY) &&
5782 sym->type.ref->c < 0 &&
5783 type->ref->c >= 0)
5784 sym->type.ref->c = type->ref->c;
5785 } else {
5786 /* we accept several definitions of the same
5787 global variable. this is tricky, because we
5788 must play with the SHN_COMMON type of the symbol */
5789 /* XXX: should check if the variable was already
5790 initialized. It is incorrect to initialized it
5791 twice */
5792 /* no init data, we won't add more to the symbol */
5793 if (!has_init)
5794 goto no_alloc;
5799 /* allocate symbol in corresponding section */
5800 sec = ad->section;
5801 if (!sec) {
5802 if (has_init)
5803 sec = data_section;
5804 else if (tcc_state->nocommon)
5805 sec = bss_section;
5807 if (sec) {
5808 data_offset = sec->data_offset;
5809 data_offset = (data_offset + align - 1) & -align;
5810 addr = data_offset;
5811 /* very important to increment global pointer at this time
5812 because initializers themselves can create new initializers */
5813 data_offset += size;
5814 /* add padding if bound check */
5815 if (do_bounds_check)
5816 data_offset++;
5817 sec->data_offset = data_offset;
5818 /* allocate section space to put the data */
5819 if (sec->sh_type != SHT_NOBITS &&
5820 data_offset > sec->data_allocated)
5821 section_realloc(sec, data_offset);
5822 /* align section if needed */
5823 if (align > sec->sh_addralign)
5824 sec->sh_addralign = align;
5825 } else {
5826 addr = 0; /* avoid warning */
5829 if (v) {
5830 if (scope != VT_CONST || !sym) {
5831 sym = sym_push(v, type, r | VT_SYM, 0);
5833 /* update symbol definition */
5834 if (sec) {
5835 put_extern_sym(sym, sec, addr, size);
5836 } else {
5837 ElfW(Sym) *esym;
5838 /* put a common area */
5839 put_extern_sym(sym, NULL, align, size);
5840 /* XXX: find a nicer way */
5841 esym = &((ElfW(Sym) *)symtab_section->data)[sym->c];
5842 esym->st_shndx = SHN_COMMON;
5844 } else {
5845 CValue cval;
5847 /* push global reference */
5848 sym = get_sym_ref(type, sec, addr, size);
5849 cval.ul = 0;
5850 vsetc(type, VT_CONST | VT_SYM, &cval);
5851 vtop->sym = sym;
5854 /* handles bounds now because the symbol must be defined
5855 before for the relocation */
5856 if (do_bounds_check) {
5857 unsigned long *bounds_ptr;
5859 greloc(bounds_section, sym, bounds_section->data_offset, R_DATA_32);
5860 /* then add global bound info */
5861 bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(long));
5862 bounds_ptr[0] = 0; /* relocated */
5863 bounds_ptr[1] = size;
5866 if (has_init) {
5867 decl_initializer(type, sec, addr, 1, 0);
5868 /* restore parse state if needed */
5869 if (init_str.str) {
5870 tok_str_free(init_str.str);
5871 restore_parse_state(&saved_parse_state);
5874 no_alloc: ;
5877 void put_func_debug(Sym *sym)
5879 char buf[512];
5881 /* stabs info */
5882 /* XXX: we put here a dummy type */
5883 snprintf(buf, sizeof(buf), "%s:%c1",
5884 funcname, sym->type.t & VT_STATIC ? 'f' : 'F');
5885 put_stabs_r(buf, N_FUN, 0, file->line_num, 0,
5886 cur_text_section, sym->c);
5887 /* //gr gdb wants a line at the function */
5888 put_stabn(N_SLINE, 0, file->line_num, 0);
5889 last_ind = 0;
5890 last_line_num = 0;
5893 /* parse an old style function declaration list */
5894 /* XXX: check multiple parameter */
5895 static void func_decl_list(Sym *func_sym)
5897 AttributeDef ad;
5898 int v;
5899 Sym *s;
5900 CType btype, type;
5902 /* parse each declaration */
5903 while (tok != '{' && tok != ';' && tok != ',' && tok != TOK_EOF) {
5904 if (!parse_btype(&btype, &ad))
5905 expect("declaration list");
5906 if (((btype.t & VT_BTYPE) == VT_ENUM ||
5907 (btype.t & VT_BTYPE) == VT_STRUCT) &&
5908 tok == ';') {
5909 /* we accept no variable after */
5910 } else {
5911 for(;;) {
5912 type = btype;
5913 type_decl(&type, &ad, &v, TYPE_DIRECT);
5914 /* find parameter in function parameter list */
5915 s = func_sym->next;
5916 while (s != NULL) {
5917 if ((s->v & ~SYM_FIELD) == v)
5918 goto found;
5919 s = s->next;
5921 error("declaration for parameter '%s' but no such parameter",
5922 get_tok_str(v, NULL));
5923 found:
5924 /* check that no storage specifier except 'register' was given */
5925 if (type.t & VT_STORAGE)
5926 error("storage class specified for '%s'", get_tok_str(v, NULL));
5927 convert_parameter_type(&type);
5928 /* we can add the type (NOTE: it could be local to the function) */
5929 s->type = type;
5930 /* accept other parameters */
5931 if (tok == ',')
5932 next();
5933 else
5934 break;
5937 skip(';');
5941 /* parse a function defined by symbol 'sym' and generate its code in
5942 'cur_text_section' */
5943 static void gen_function(Sym *sym)
5945 int saved_nocode_wanted = nocode_wanted;
5946 nocode_wanted = 0;
5947 ind = cur_text_section->data_offset;
5948 /* NOTE: we patch the symbol size later */
5949 put_extern_sym(sym, cur_text_section, ind, 0);
5950 funcname = get_tok_str(sym->v, NULL);
5951 func_ind = ind;
5952 /* put debug symbol */
5953 if (do_debug)
5954 put_func_debug(sym);
5955 /* push a dummy symbol to enable local sym storage */
5956 sym_push2(&local_stack, SYM_FIELD, 0, 0);
5957 gfunc_prolog(&sym->type);
5958 rsym = 0;
5959 block(NULL, NULL, NULL, NULL, 0, 0);
5960 gsym(rsym);
5961 gfunc_epilog();
5962 cur_text_section->data_offset = ind;
5963 label_pop(&global_label_stack, NULL);
5964 sym_pop(&local_stack, NULL); /* reset local stack */
5965 /* end of function */
5966 /* patch symbol size */
5967 ((ElfW(Sym) *)symtab_section->data)[sym->c].st_size =
5968 ind - func_ind;
5969 if (do_debug) {
5970 put_stabn(N_FUN, 0, 0, ind - func_ind);
5972 /* It's better to crash than to generate wrong code */
5973 cur_text_section = NULL;
5974 funcname = ""; /* for safety */
5975 func_vt.t = VT_VOID; /* for safety */
5976 ind = 0; /* for safety */
5977 nocode_wanted = saved_nocode_wanted;
5980 static void gen_inline_functions(void)
5982 Sym *sym;
5983 CType *type;
5984 int *str, inline_generated;
5986 /* iterate while inline function are referenced */
5987 for(;;) {
5988 inline_generated = 0;
5989 for(sym = global_stack; sym != NULL; sym = sym->prev) {
5990 type = &sym->type;
5991 if (((type->t & VT_BTYPE) == VT_FUNC) &&
5992 (type->t & (VT_STATIC | VT_INLINE)) ==
5993 (VT_STATIC | VT_INLINE) &&
5994 sym->c != 0) {
5995 /* the function was used: generate its code and
5996 convert it to a normal function */
5997 str = INLINE_DEF(sym->r);
5998 sym->r = VT_SYM | VT_CONST;
5999 sym->type.t &= ~VT_INLINE;
6001 macro_ptr = str;
6002 next();
6003 cur_text_section = text_section;
6004 gen_function(sym);
6005 macro_ptr = NULL; /* fail safe */
6007 tok_str_free(str);
6008 inline_generated = 1;
6011 if (!inline_generated)
6012 break;
6015 /* free all remaining inline function tokens */
6016 for(sym = global_stack; sym != NULL; sym = sym->prev) {
6017 type = &sym->type;
6018 if (((type->t & VT_BTYPE) == VT_FUNC) &&
6019 (type->t & (VT_STATIC | VT_INLINE)) ==
6020 (VT_STATIC | VT_INLINE)) {
6021 //gr printf("sym %d %s\n", sym->r, get_tok_str(sym->v, NULL));
6022 if (sym->r == (VT_SYM | VT_CONST)) //gr beware!
6023 continue;
6024 str = INLINE_DEF(sym->r);
6025 tok_str_free(str);
6026 sym->r = 0; /* fail safe */
6031 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
6032 static void decl(int l)
6034 int v, has_init, r;
6035 CType type, btype;
6036 Sym *sym;
6037 AttributeDef ad;
6039 while (1) {
6040 if (!parse_btype(&btype, &ad)) {
6041 /* skip redundant ';' */
6042 /* XXX: find more elegant solution */
6043 if (tok == ';') {
6044 next();
6045 continue;
6047 if (l == VT_CONST &&
6048 (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3)) {
6049 /* global asm block */
6050 asm_global_instr();
6051 continue;
6053 /* special test for old K&R protos without explicit int
6054 type. Only accepted when defining global data */
6055 if (l == VT_LOCAL || tok < TOK_DEFINE)
6056 break;
6057 btype.t = VT_INT;
6059 if (((btype.t & VT_BTYPE) == VT_ENUM ||
6060 (btype.t & VT_BTYPE) == VT_STRUCT) &&
6061 tok == ';') {
6062 /* we accept no variable after */
6063 next();
6064 continue;
6066 while (1) { /* iterate thru each declaration */
6067 type = btype;
6068 type_decl(&type, &ad, &v, TYPE_DIRECT);
6069 #if 0
6071 char buf[500];
6072 type_to_str(buf, sizeof(buf), t, get_tok_str(v, NULL));
6073 printf("type = '%s'\n", buf);
6075 #endif
6076 if ((type.t & VT_BTYPE) == VT_FUNC) {
6077 /* if old style function prototype, we accept a
6078 declaration list */
6079 sym = type.ref;
6080 if (sym->c == FUNC_OLD)
6081 func_decl_list(sym);
6084 if (tok == '{') {
6085 if (l == VT_LOCAL)
6086 error("cannot use local functions");
6087 if ((type.t & VT_BTYPE) != VT_FUNC)
6088 expect("function definition");
6090 /* reject abstract declarators in function definition */
6091 sym = type.ref;
6092 while ((sym = sym->next) != NULL)
6093 if (!(sym->v & ~SYM_FIELD))
6094 expect("identifier");
6096 /* XXX: cannot do better now: convert extern line to static inline */
6097 if ((type.t & (VT_EXTERN | VT_INLINE)) == (VT_EXTERN | VT_INLINE))
6098 type.t = (type.t & ~VT_EXTERN) | VT_STATIC;
6100 sym = sym_find(v);
6101 if (sym) {
6102 if ((sym->type.t & VT_BTYPE) != VT_FUNC)
6103 goto func_error1;
6104 /* specific case: if not func_call defined, we put
6105 the one of the prototype */
6106 /* XXX: should have default value */
6107 r = sym->type.ref->r;
6108 if (FUNC_CALL(r) != FUNC_CDECL
6109 && FUNC_CALL(type.ref->r) == FUNC_CDECL)
6110 FUNC_CALL(type.ref->r) = FUNC_CALL(r);
6111 if (FUNC_EXPORT(r))
6112 FUNC_EXPORT(type.ref->r) = 1;
6114 if (!is_compatible_types(&sym->type, &type)) {
6115 func_error1:
6116 error("incompatible types for redefinition of '%s'",
6117 get_tok_str(v, NULL));
6119 /* if symbol is already defined, then put complete type */
6120 sym->type = type;
6121 } else {
6122 /* put function symbol */
6123 sym = global_identifier_push(v, type.t, 0);
6124 sym->type.ref = type.ref;
6127 /* static inline functions are just recorded as a kind
6128 of macro. Their code will be emitted at the end of
6129 the compilation unit only if they are used */
6130 if ((type.t & (VT_INLINE | VT_STATIC)) ==
6131 (VT_INLINE | VT_STATIC)) {
6132 TokenString func_str;
6133 int block_level;
6135 tok_str_new(&func_str);
6137 block_level = 0;
6138 for(;;) {
6139 int t;
6140 if (tok == TOK_EOF)
6141 error("unexpected end of file");
6142 tok_str_add_tok(&func_str);
6143 t = tok;
6144 next();
6145 if (t == '{') {
6146 block_level++;
6147 } else if (t == '}') {
6148 block_level--;
6149 if (block_level == 0)
6150 break;
6153 tok_str_add(&func_str, -1);
6154 tok_str_add(&func_str, 0);
6155 INLINE_DEF(sym->r) = func_str.str;
6156 } else {
6157 /* compute text section */
6158 cur_text_section = ad.section;
6159 if (!cur_text_section)
6160 cur_text_section = text_section;
6161 sym->r = VT_SYM | VT_CONST;
6162 gen_function(sym);
6164 break;
6165 } else {
6166 if (btype.t & VT_TYPEDEF) {
6167 /* save typedefed type */
6168 /* XXX: test storage specifiers ? */
6169 sym = sym_push(v, &type, 0, 0);
6170 sym->type.t |= VT_TYPEDEF;
6171 } else if ((type.t & VT_BTYPE) == VT_FUNC) {
6172 /* external function definition */
6173 /* specific case for func_call attribute */
6174 if (ad.func_attr)
6175 type.ref->r = ad.func_attr;
6176 external_sym(v, &type, 0);
6177 } else {
6178 /* not lvalue if array */
6179 r = 0;
6180 if (!(type.t & VT_ARRAY))
6181 r |= lvalue_type(type.t);
6182 has_init = (tok == '=');
6183 if ((btype.t & VT_EXTERN) ||
6184 ((type.t & VT_ARRAY) && (type.t & VT_STATIC) &&
6185 !has_init && l == VT_CONST && type.ref->c < 0)) {
6186 /* external variable */
6187 /* NOTE: as GCC, uninitialized global static
6188 arrays of null size are considered as
6189 extern */
6190 external_sym(v, &type, r);
6191 } else {
6192 type.t |= (btype.t & VT_STATIC); /* Retain "static". */
6193 if (type.t & VT_STATIC)
6194 r |= VT_CONST;
6195 else
6196 r |= l;
6197 if (has_init)
6198 next();
6199 decl_initializer_alloc(&type, &ad, r,
6200 has_init, v, l);
6203 if (tok != ',') {
6204 skip(';');
6205 break;
6207 next();
6213 /* better than nothing, but needs extension to handle '-E' option
6214 correctly too */
6215 static void preprocess_init(TCCState *s1)
6217 s1->include_stack_ptr = s1->include_stack;
6218 /* XXX: move that before to avoid having to initialize
6219 file->ifdef_stack_ptr ? */
6220 s1->ifdef_stack_ptr = s1->ifdef_stack;
6221 file->ifdef_stack_ptr = s1->ifdef_stack_ptr;
6223 /* XXX: not ANSI compliant: bound checking says error */
6224 vtop = vstack - 1;
6225 s1->pack_stack[0] = 0;
6226 s1->pack_stack_ptr = s1->pack_stack;
6229 /* compile the C file opened in 'file'. Return non zero if errors. */
6230 static int tcc_compile(TCCState *s1)
6232 Sym *define_start;
6233 char buf[512];
6234 volatile int section_sym;
6236 #ifdef INC_DEBUG
6237 printf("%s: **** new file\n", file->filename);
6238 #endif
6239 preprocess_init(s1);
6241 cur_text_section = NULL;
6242 funcname = "";
6243 anon_sym = SYM_FIRST_ANOM;
6245 /* file info: full path + filename */
6246 section_sym = 0; /* avoid warning */
6247 if (do_debug) {
6248 section_sym = put_elf_sym(symtab_section, 0, 0,
6249 ELFW(ST_INFO)(STB_LOCAL, STT_SECTION), 0,
6250 text_section->sh_num, NULL);
6251 getcwd(buf, sizeof(buf));
6252 #ifdef _WIN32
6253 normalize_slashes(buf);
6254 #endif
6255 pstrcat(buf, sizeof(buf), "/");
6256 put_stabs_r(buf, N_SO, 0, 0,
6257 text_section->data_offset, text_section, section_sym);
6258 put_stabs_r(file->filename, N_SO, 0, 0,
6259 text_section->data_offset, text_section, section_sym);
6261 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
6262 symbols can be safely used */
6263 put_elf_sym(symtab_section, 0, 0,
6264 ELFW(ST_INFO)(STB_LOCAL, STT_FILE), 0,
6265 SHN_ABS, file->filename);
6267 /* define some often used types */
6268 int_type.t = VT_INT;
6270 char_pointer_type.t = VT_BYTE;
6271 mk_pointer(&char_pointer_type);
6273 func_old_type.t = VT_FUNC;
6274 func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD);
6276 #if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)
6277 float_type.t = VT_FLOAT;
6278 double_type.t = VT_DOUBLE;
6280 func_float_type.t = VT_FUNC;
6281 func_float_type.ref = sym_push(SYM_FIELD, &float_type, FUNC_CDECL, FUNC_OLD);
6282 func_double_type.t = VT_FUNC;
6283 func_double_type.ref = sym_push(SYM_FIELD, &double_type, FUNC_CDECL, FUNC_OLD);
6284 #endif
6286 #if 0
6287 /* define 'void *alloca(unsigned int)' builtin function */
6289 Sym *s1;
6291 p = anon_sym++;
6292 sym = sym_push(p, mk_pointer(VT_VOID), FUNC_CDECL, FUNC_NEW);
6293 s1 = sym_push(SYM_FIELD, VT_UNSIGNED | VT_INT, 0, 0);
6294 s1->next = NULL;
6295 sym->next = s1;
6296 sym_push(TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0);
6298 #endif
6300 define_start = define_stack;
6301 nocode_wanted = 1;
6303 if (setjmp(s1->error_jmp_buf) == 0) {
6304 s1->nb_errors = 0;
6305 s1->error_set_jmp_enabled = 1;
6307 ch = file->buf_ptr[0];
6308 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
6309 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM;
6310 next();
6311 decl(VT_CONST);
6312 if (tok != TOK_EOF)
6313 expect("declaration");
6315 /* end of translation unit info */
6316 if (do_debug) {
6317 put_stabs_r(NULL, N_SO, 0, 0,
6318 text_section->data_offset, text_section, section_sym);
6321 s1->error_set_jmp_enabled = 0;
6323 /* reset define stack, but leave -Dsymbols (may be incorrect if
6324 they are undefined) */
6325 free_defines(define_start);
6327 gen_inline_functions();
6329 sym_pop(&global_stack, NULL);
6330 sym_pop(&local_stack, NULL);
6332 return s1->nb_errors != 0 ? -1 : 0;
6335 /* Preprocess the current file */
6336 static int tcc_preprocess(TCCState *s1)
6338 Sym *define_start;
6339 BufferedFile *file_ref;
6340 int token_seen, line_ref;
6342 preprocess_init(s1);
6343 define_start = define_stack;
6344 ch = file->buf_ptr[0];
6345 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
6346 parse_flags = PARSE_FLAG_ASM_COMMENTS | PARSE_FLAG_PREPROCESS |
6347 PARSE_FLAG_LINEFEED | PARSE_FLAG_SPACES;
6348 token_seen = 0;
6349 line_ref = 0;
6350 file_ref = NULL;
6352 for (;;) {
6353 next();
6354 if (tok == TOK_EOF) {
6355 break;
6356 } else if (tok == TOK_LINEFEED) {
6357 if (!token_seen)
6358 continue;
6359 ++line_ref;
6360 token_seen = 0;
6361 } else if (!token_seen) {
6362 int d = file->line_num - line_ref;
6363 if (file != file_ref || d < 0 || d >= 8)
6364 fprintf(s1->outfile, "# %d \"%s\"\n", file->line_num, file->filename);
6365 else
6366 while (d)
6367 fputs("\n", s1->outfile), --d;
6368 line_ref = (file_ref = file)->line_num;
6369 token_seen = 1;
6371 fputs(get_tok_str(tok, &tokc), s1->outfile);
6373 free_defines(define_start);
6374 return 0;
6377 #ifdef LIBTCC
6378 int tcc_compile_string(TCCState *s, const char *str)
6380 BufferedFile bf1, *bf = &bf1;
6381 int ret, len;
6382 char *buf;
6384 /* init file structure */
6385 bf->fd = -1;
6386 /* XXX: avoid copying */
6387 len = strlen(str);
6388 buf = tcc_malloc(len + 1);
6389 if (!buf)
6390 return -1;
6391 memcpy(buf, str, len);
6392 buf[len] = CH_EOB;
6393 bf->buf_ptr = buf;
6394 bf->buf_end = buf + len;
6395 pstrcpy(bf->filename, sizeof(bf->filename), "<string>");
6396 bf->line_num = 1;
6397 file = bf;
6398 ret = tcc_compile(s);
6399 file = NULL;
6400 tcc_free(buf);
6402 /* currently, no need to close */
6403 return ret;
6405 #endif
6407 /* define a preprocessor symbol. A value can also be provided with the '=' operator */
6408 void tcc_define_symbol(TCCState *s1, const char *sym, const char *value)
6410 BufferedFile bf1, *bf = &bf1;
6412 pstrcpy(bf->buffer, IO_BUF_SIZE, sym);
6413 pstrcat(bf->buffer, IO_BUF_SIZE, " ");
6414 /* default value */
6415 if (!value)
6416 value = "1";
6417 pstrcat(bf->buffer, IO_BUF_SIZE, value);
6419 /* init file structure */
6420 bf->fd = -1;
6421 bf->buf_ptr = bf->buffer;
6422 bf->buf_end = bf->buffer + strlen(bf->buffer);
6423 *bf->buf_end = CH_EOB;
6424 bf->filename[0] = '\0';
6425 bf->line_num = 1;
6426 file = bf;
6428 s1->include_stack_ptr = s1->include_stack;
6430 /* parse with define parser */
6431 ch = file->buf_ptr[0];
6432 next_nomacro();
6433 parse_define();
6434 file = NULL;
6437 /* undefine a preprocessor symbol */
6438 void tcc_undefine_symbol(TCCState *s1, const char *sym)
6440 TokenSym *ts;
6441 Sym *s;
6442 ts = tok_alloc(sym, strlen(sym));
6443 s = define_find(ts->tok);
6444 /* undefine symbol by putting an invalid name */
6445 if (s)
6446 define_undef(s);
6449 #ifdef CONFIG_TCC_ASM
6451 #ifdef TCC_TARGET_I386
6452 #include "i386-asm.c"
6453 #endif
6454 #include "tccasm.c"
6456 #else
6457 static void asm_instr(void)
6459 error("inline asm() not supported");
6461 static void asm_global_instr(void)
6463 error("inline asm() not supported");
6465 #endif
6467 #include "tccelf.c"
6469 #ifdef TCC_TARGET_COFF
6470 #include "tcccoff.c"
6471 #endif
6473 #ifdef TCC_TARGET_PE
6474 #include "tccpe.c"
6475 #endif
6477 #ifdef CONFIG_TCC_BACKTRACE
6478 /* print the position in the source file of PC value 'pc' by reading
6479 the stabs debug information */
6480 static void rt_printline(unsigned long wanted_pc)
6482 Stab_Sym *sym, *sym_end;
6483 char func_name[128], last_func_name[128];
6484 unsigned long func_addr, last_pc, pc;
6485 const char *incl_files[INCLUDE_STACK_SIZE];
6486 int incl_index, len, last_line_num, i;
6487 const char *str, *p;
6489 fprintf(stderr, "0x%08lx:", wanted_pc);
6491 func_name[0] = '\0';
6492 func_addr = 0;
6493 incl_index = 0;
6494 last_func_name[0] = '\0';
6495 last_pc = 0xffffffff;
6496 last_line_num = 1;
6497 sym = (Stab_Sym *)stab_section->data + 1;
6498 sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
6499 while (sym < sym_end) {
6500 switch(sym->n_type) {
6501 /* function start or end */
6502 case N_FUN:
6503 if (sym->n_strx == 0) {
6504 /* we test if between last line and end of function */
6505 pc = sym->n_value + func_addr;
6506 if (wanted_pc >= last_pc && wanted_pc < pc)
6507 goto found;
6508 func_name[0] = '\0';
6509 func_addr = 0;
6510 } else {
6511 str = stabstr_section->data + sym->n_strx;
6512 p = strchr(str, ':');
6513 if (!p) {
6514 pstrcpy(func_name, sizeof(func_name), str);
6515 } else {
6516 len = p - str;
6517 if (len > sizeof(func_name) - 1)
6518 len = sizeof(func_name) - 1;
6519 memcpy(func_name, str, len);
6520 func_name[len] = '\0';
6522 func_addr = sym->n_value;
6524 break;
6525 /* line number info */
6526 case N_SLINE:
6527 pc = sym->n_value + func_addr;
6528 if (wanted_pc >= last_pc && wanted_pc < pc)
6529 goto found;
6530 last_pc = pc;
6531 last_line_num = sym->n_desc;
6532 /* XXX: slow! */
6533 strcpy(last_func_name, func_name);
6534 break;
6535 /* include files */
6536 case N_BINCL:
6537 str = stabstr_section->data + sym->n_strx;
6538 add_incl:
6539 if (incl_index < INCLUDE_STACK_SIZE) {
6540 incl_files[incl_index++] = str;
6542 break;
6543 case N_EINCL:
6544 if (incl_index > 1)
6545 incl_index--;
6546 break;
6547 case N_SO:
6548 if (sym->n_strx == 0) {
6549 incl_index = 0; /* end of translation unit */
6550 } else {
6551 str = stabstr_section->data + sym->n_strx;
6552 /* do not add path */
6553 len = strlen(str);
6554 if (len > 0 && str[len - 1] != '/')
6555 goto add_incl;
6557 break;
6559 sym++;
6562 /* second pass: we try symtab symbols (no line number info) */
6563 incl_index = 0;
6565 ElfW(Sym) *sym, *sym_end;
6566 int type;
6568 sym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
6569 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
6570 sym < sym_end;
6571 sym++) {
6572 type = ELFW(ST_TYPE)(sym->st_info);
6573 if (type == STT_FUNC) {
6574 if (wanted_pc >= sym->st_value &&
6575 wanted_pc < sym->st_value + sym->st_size) {
6576 pstrcpy(last_func_name, sizeof(last_func_name),
6577 strtab_section->data + sym->st_name);
6578 goto found;
6583 /* did not find any info: */
6584 fprintf(stderr, " ???\n");
6585 return;
6586 found:
6587 if (last_func_name[0] != '\0') {
6588 fprintf(stderr, " %s()", last_func_name);
6590 if (incl_index > 0) {
6591 fprintf(stderr, " (%s:%d",
6592 incl_files[incl_index - 1], last_line_num);
6593 for(i = incl_index - 2; i >= 0; i--)
6594 fprintf(stderr, ", included from %s", incl_files[i]);
6595 fprintf(stderr, ")");
6597 fprintf(stderr, "\n");
6600 #ifdef __i386__
6601 /* fix for glibc 2.1 */
6602 #ifndef REG_EIP
6603 #define REG_EIP EIP
6604 #define REG_EBP EBP
6605 #endif
6607 /* return the PC at frame level 'level'. Return non zero if not found */
6608 static int rt_get_caller_pc(unsigned long *paddr,
6609 ucontext_t *uc, int level)
6611 unsigned long fp;
6612 int i;
6614 if (level == 0) {
6615 #if defined(__FreeBSD__)
6616 *paddr = uc->uc_mcontext.mc_eip;
6617 #elif defined(__dietlibc__)
6618 *paddr = uc->uc_mcontext.eip;
6619 #else
6620 *paddr = uc->uc_mcontext.gregs[REG_EIP];
6621 #endif
6622 return 0;
6623 } else {
6624 #if defined(__FreeBSD__)
6625 fp = uc->uc_mcontext.mc_ebp;
6626 #elif defined(__dietlibc__)
6627 fp = uc->uc_mcontext.ebp;
6628 #else
6629 fp = uc->uc_mcontext.gregs[REG_EBP];
6630 #endif
6631 for(i=1;i<level;i++) {
6632 /* XXX: check address validity with program info */
6633 if (fp <= 0x1000 || fp >= 0xc0000000)
6634 return -1;
6635 fp = ((unsigned long *)fp)[0];
6637 *paddr = ((unsigned long *)fp)[1];
6638 return 0;
6641 #elif defined(__x86_64__)
6642 /* return the PC at frame level 'level'. Return non zero if not found */
6643 static int rt_get_caller_pc(unsigned long *paddr,
6644 ucontext_t *uc, int level)
6646 unsigned long fp;
6647 int i;
6649 if (level == 0) {
6650 /* XXX: only support linux */
6651 *paddr = uc->uc_mcontext.gregs[REG_RIP];
6652 return 0;
6653 } else {
6654 fp = uc->uc_mcontext.gregs[REG_RBP];
6655 for(i=1;i<level;i++) {
6656 /* XXX: check address validity with program info */
6657 if (fp <= 0x1000)
6658 return -1;
6659 fp = ((unsigned long *)fp)[0];
6661 *paddr = ((unsigned long *)fp)[1];
6662 return 0;
6665 #else
6666 #warning add arch specific rt_get_caller_pc()
6667 static int rt_get_caller_pc(unsigned long *paddr,
6668 ucontext_t *uc, int level)
6670 return -1;
6672 #endif
6674 /* emit a run time error at position 'pc' */
6675 void rt_error(ucontext_t *uc, const char *fmt, ...)
6677 va_list ap;
6678 unsigned long pc;
6679 int i;
6681 va_start(ap, fmt);
6682 fprintf(stderr, "Runtime error: ");
6683 vfprintf(stderr, fmt, ap);
6684 fprintf(stderr, "\n");
6685 for(i=0;i<num_callers;i++) {
6686 if (rt_get_caller_pc(&pc, uc, i) < 0)
6687 break;
6688 if (i == 0)
6689 fprintf(stderr, "at ");
6690 else
6691 fprintf(stderr, "by ");
6692 rt_printline(pc);
6694 exit(255);
6695 va_end(ap);
6698 /* signal handler for fatal errors */
6699 static void sig_error(int signum, siginfo_t *siginf, void *puc)
6701 ucontext_t *uc = puc;
6703 switch(signum) {
6704 case SIGFPE:
6705 switch(siginf->si_code) {
6706 case FPE_INTDIV:
6707 case FPE_FLTDIV:
6708 rt_error(uc, "division by zero");
6709 break;
6710 default:
6711 rt_error(uc, "floating point exception");
6712 break;
6714 break;
6715 case SIGBUS:
6716 case SIGSEGV:
6717 if (rt_bound_error_msg && *rt_bound_error_msg)
6718 rt_error(uc, *rt_bound_error_msg);
6719 else
6720 rt_error(uc, "dereferencing invalid pointer");
6721 break;
6722 case SIGILL:
6723 rt_error(uc, "illegal instruction");
6724 break;
6725 case SIGABRT:
6726 rt_error(uc, "abort() called");
6727 break;
6728 default:
6729 rt_error(uc, "caught signal %d", signum);
6730 break;
6732 exit(255);
6735 #endif
6737 /* copy code into memory passed in by the caller and do all relocations
6738 (needed before using tcc_get_symbol()).
6739 returns -1 on error and required size if ptr is NULL */
6740 int tcc_relocate(TCCState *s1, void *ptr)
6742 Section *s;
6743 unsigned long offset, length, mem;
6744 int i;
6746 if (0 == s1->runtime_added) {
6747 s1->runtime_added = 1;
6748 s1->nb_errors = 0;
6749 #ifdef TCC_TARGET_PE
6750 pe_add_runtime(s1);
6751 relocate_common_syms();
6752 tcc_add_linker_symbols(s1);
6753 #else
6754 tcc_add_runtime(s1);
6755 relocate_common_syms();
6756 tcc_add_linker_symbols(s1);
6757 build_got_entries(s1);
6758 #endif
6761 offset = 0, mem = (unsigned long)ptr;
6762 for(i = 1; i < s1->nb_sections; i++) {
6763 s = s1->sections[i];
6764 if (0 == (s->sh_flags & SHF_ALLOC))
6765 continue;
6766 length = s->data_offset;
6767 s->sh_addr = mem ? (mem + offset + 15) & ~15 : 0;
6768 offset = (offset + length + 15) & ~15;
6771 /* relocate symbols */
6772 relocate_syms(s1, 1);
6773 if (s1->nb_errors)
6774 return -1;
6776 #ifdef TCC_TARGET_X86_64
6777 s1->runtime_plt_and_got_offset = 0;
6778 s1->runtime_plt_and_got = (char *)(mem + offset);
6779 /* double the size of the buffer for got and plt entries
6780 XXX: calculate exact size for them? */
6781 offset *= 2;
6782 #endif
6784 if (0 == mem)
6785 return offset + 15;
6787 /* relocate each section */
6788 for(i = 1; i < s1->nb_sections; i++) {
6789 s = s1->sections[i];
6790 if (s->reloc)
6791 relocate_section(s1, s);
6794 for(i = 1; i < s1->nb_sections; i++) {
6795 s = s1->sections[i];
6796 if (0 == (s->sh_flags & SHF_ALLOC))
6797 continue;
6798 length = s->data_offset;
6799 // printf("%-12s %08x %04x\n", s->name, s->sh_addr, length);
6800 ptr = (void*)s->sh_addr;
6801 if (NULL == s->data || s->sh_type == SHT_NOBITS)
6802 memset(ptr, 0, length);
6803 else
6804 memcpy(ptr, s->data, length);
6805 /* mark executable sections as executable in memory */
6806 if (s->sh_flags & SHF_EXECINSTR)
6807 set_pages_executable(ptr, length);
6809 #ifdef TCC_TARGET_X86_64
6810 set_pages_executable(s1->runtime_plt_and_got,
6811 s1->runtime_plt_and_got_offset);
6812 #endif
6813 return 0;
6816 /* launch the compiled program with the given arguments */
6817 int tcc_run(TCCState *s1, int argc, char **argv)
6819 int (*prog_main)(int, char **);
6820 void *ptr;
6821 int ret;
6823 ret = tcc_relocate(s1, NULL);
6824 if (ret < 0)
6825 return -1;
6826 ptr = tcc_malloc(ret);
6827 tcc_relocate(s1, ptr);
6829 prog_main = tcc_get_symbol_err(s1, "main");
6831 if (do_debug) {
6832 #ifdef CONFIG_TCC_BACKTRACE
6833 struct sigaction sigact;
6834 /* install TCC signal handlers to print debug info on fatal
6835 runtime errors */
6836 sigact.sa_flags = SA_SIGINFO | SA_RESETHAND;
6837 sigact.sa_sigaction = sig_error;
6838 sigemptyset(&sigact.sa_mask);
6839 sigaction(SIGFPE, &sigact, NULL);
6840 sigaction(SIGILL, &sigact, NULL);
6841 sigaction(SIGSEGV, &sigact, NULL);
6842 sigaction(SIGBUS, &sigact, NULL);
6843 sigaction(SIGABRT, &sigact, NULL);
6844 #else
6845 error("debug mode not available");
6846 #endif
6849 #ifdef CONFIG_TCC_BCHECK
6850 if (do_bounds_check) {
6851 void (*bound_init)(void);
6853 /* set error function */
6854 rt_bound_error_msg = tcc_get_symbol_err(s1, "__bound_error_msg");
6856 /* XXX: use .init section so that it also work in binary ? */
6857 bound_init = (void *)tcc_get_symbol_err(s1, "__bound_init");
6858 bound_init();
6860 #endif
6861 ret = (*prog_main)(argc, argv);
6862 tcc_free(ptr);
6863 return ret;
6866 void tcc_memstats(void)
6868 #ifdef MEM_DEBUG
6869 printf("memory in use: %d\n", mem_cur_size);
6870 #endif
6873 static void tcc_cleanup(void)
6875 int i, n;
6877 if (NULL == tcc_state)
6878 return;
6879 tcc_state = NULL;
6881 /* free -D defines */
6882 free_defines(NULL);
6884 /* free tokens */
6885 n = tok_ident - TOK_IDENT;
6886 for(i = 0; i < n; i++)
6887 tcc_free(table_ident[i]);
6888 tcc_free(table_ident);
6890 /* free sym_pools */
6891 dynarray_reset(&sym_pools, &nb_sym_pools);
6892 /* string buffer */
6893 cstr_free(&tokcstr);
6894 /* reset symbol stack */
6895 sym_free_first = NULL;
6896 /* cleanup from error/setjmp */
6897 macro_ptr = NULL;
6900 TCCState *tcc_new(void)
6902 const char *p, *r;
6903 TCCState *s;
6904 TokenSym *ts;
6905 int i, c;
6907 tcc_cleanup();
6909 s = tcc_mallocz(sizeof(TCCState));
6910 if (!s)
6911 return NULL;
6912 tcc_state = s;
6913 s->output_type = TCC_OUTPUT_MEMORY;
6915 /* init isid table */
6916 for(i=CH_EOF;i<256;i++)
6917 isidnum_table[i-CH_EOF] = isid(i) || isnum(i);
6919 /* add all tokens */
6920 table_ident = NULL;
6921 memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *));
6923 tok_ident = TOK_IDENT;
6924 p = tcc_keywords;
6925 while (*p) {
6926 r = p;
6927 for(;;) {
6928 c = *r++;
6929 if (c == '\0')
6930 break;
6932 ts = tok_alloc(p, r - p - 1);
6933 p = r;
6936 /* we add dummy defines for some special macros to speed up tests
6937 and to have working defined() */
6938 define_push(TOK___LINE__, MACRO_OBJ, NULL, NULL);
6939 define_push(TOK___FILE__, MACRO_OBJ, NULL, NULL);
6940 define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL);
6941 define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL);
6943 /* standard defines */
6944 tcc_define_symbol(s, "__STDC__", NULL);
6945 tcc_define_symbol(s, "__STDC_VERSION__", "199901L");
6946 #if defined(TCC_TARGET_I386)
6947 tcc_define_symbol(s, "__i386__", NULL);
6948 #endif
6949 #if defined(TCC_TARGET_X86_64)
6950 tcc_define_symbol(s, "__x86_64__", NULL);
6951 #endif
6952 #if defined(TCC_TARGET_ARM)
6953 tcc_define_symbol(s, "__ARM_ARCH_4__", NULL);
6954 tcc_define_symbol(s, "__arm_elf__", NULL);
6955 tcc_define_symbol(s, "__arm_elf", NULL);
6956 tcc_define_symbol(s, "arm_elf", NULL);
6957 tcc_define_symbol(s, "__arm__", NULL);
6958 tcc_define_symbol(s, "__arm", NULL);
6959 tcc_define_symbol(s, "arm", NULL);
6960 tcc_define_symbol(s, "__APCS_32__", NULL);
6961 #endif
6962 #ifdef TCC_TARGET_PE
6963 tcc_define_symbol(s, "_WIN32", NULL);
6964 #else
6965 tcc_define_symbol(s, "__unix__", NULL);
6966 tcc_define_symbol(s, "__unix", NULL);
6967 #if defined(__linux)
6968 tcc_define_symbol(s, "__linux__", NULL);
6969 tcc_define_symbol(s, "__linux", NULL);
6970 #endif
6971 #endif
6972 /* tiny C specific defines */
6973 tcc_define_symbol(s, "__TINYC__", NULL);
6975 /* tiny C & gcc defines */
6976 tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned int");
6977 tcc_define_symbol(s, "__PTRDIFF_TYPE__", "int");
6978 #ifdef TCC_TARGET_PE
6979 tcc_define_symbol(s, "__WCHAR_TYPE__", "unsigned short");
6980 #else
6981 tcc_define_symbol(s, "__WCHAR_TYPE__", "int");
6982 #endif
6984 #ifndef TCC_TARGET_PE
6985 /* default library paths */
6986 tcc_add_library_path(s, CONFIG_SYSROOT "/usr/local/lib");
6987 tcc_add_library_path(s, CONFIG_SYSROOT "/usr/lib");
6988 tcc_add_library_path(s, CONFIG_SYSROOT "/lib");
6989 #endif
6991 /* no section zero */
6992 dynarray_add((void ***)&s->sections, &s->nb_sections, NULL);
6994 /* create standard sections */
6995 text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
6996 data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
6997 bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
6999 /* symbols are always generated for linking stage */
7000 symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
7001 ".strtab",
7002 ".hashtab", SHF_PRIVATE);
7003 strtab_section = symtab_section->link;
7005 /* private symbol table for dynamic symbols */
7006 s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE,
7007 ".dynstrtab",
7008 ".dynhashtab", SHF_PRIVATE);
7009 s->alacarte_link = 1;
7011 #ifdef CHAR_IS_UNSIGNED
7012 s->char_is_unsigned = 1;
7013 #endif
7014 #if defined(TCC_TARGET_PE) && 0
7015 /* XXX: currently the PE linker is not ready to support that */
7016 s->leading_underscore = 1;
7017 #endif
7018 return s;
7021 void tcc_delete(TCCState *s1)
7023 int i;
7025 tcc_cleanup();
7027 /* free all sections */
7028 for(i = 1; i < s1->nb_sections; i++)
7029 free_section(s1->sections[i]);
7030 dynarray_reset(&s1->sections, &s1->nb_sections);
7032 for(i = 0; i < s1->nb_priv_sections; i++)
7033 free_section(s1->priv_sections[i]);
7034 dynarray_reset(&s1->priv_sections, &s1->nb_priv_sections);
7036 /* free any loaded DLLs */
7037 for ( i = 0; i < s1->nb_loaded_dlls; i++) {
7038 DLLReference *ref = s1->loaded_dlls[i];
7039 if ( ref->handle )
7040 dlclose(ref->handle);
7043 /* free loaded dlls array */
7044 dynarray_reset(&s1->loaded_dlls, &s1->nb_loaded_dlls);
7046 /* free library paths */
7047 dynarray_reset(&s1->library_paths, &s1->nb_library_paths);
7049 /* free include paths */
7050 dynarray_reset(&s1->cached_includes, &s1->nb_cached_includes);
7051 dynarray_reset(&s1->include_paths, &s1->nb_include_paths);
7052 dynarray_reset(&s1->sysinclude_paths, &s1->nb_sysinclude_paths);
7054 tcc_free(s1);
7057 int tcc_add_include_path(TCCState *s1, const char *pathname)
7059 char *pathname1;
7061 pathname1 = tcc_strdup(pathname);
7062 dynarray_add((void ***)&s1->include_paths, &s1->nb_include_paths, pathname1);
7063 return 0;
7066 int tcc_add_sysinclude_path(TCCState *s1, const char *pathname)
7068 char *pathname1;
7070 pathname1 = tcc_strdup(pathname);
7071 dynarray_add((void ***)&s1->sysinclude_paths, &s1->nb_sysinclude_paths, pathname1);
7072 return 0;
7075 static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
7077 const char *ext;
7078 ElfW(Ehdr) ehdr;
7079 int fd, ret;
7080 BufferedFile *saved_file;
7082 /* find source file type with extension */
7083 ext = tcc_fileextension(filename);
7084 if (ext[0])
7085 ext++;
7087 /* open the file */
7088 saved_file = file;
7089 file = tcc_open(s1, filename);
7090 if (!file) {
7091 if (flags & AFF_PRINT_ERROR) {
7092 error_noabort("file '%s' not found", filename);
7094 ret = -1;
7095 goto fail1;
7098 if (flags & AFF_PREPROCESS) {
7099 ret = tcc_preprocess(s1);
7100 } else if (!ext[0] || !PATHCMP(ext, "c")) {
7101 /* C file assumed */
7102 ret = tcc_compile(s1);
7103 } else
7104 #ifdef CONFIG_TCC_ASM
7105 if (!strcmp(ext, "S")) {
7106 /* preprocessed assembler */
7107 ret = tcc_assemble(s1, 1);
7108 } else if (!strcmp(ext, "s")) {
7109 /* non preprocessed assembler */
7110 ret = tcc_assemble(s1, 0);
7111 } else
7112 #endif
7113 #ifdef TCC_TARGET_PE
7114 if (!PATHCMP(ext, "def")) {
7115 ret = pe_load_def_file(s1, file->fd);
7116 } else
7117 #endif
7119 fd = file->fd;
7120 /* assume executable format: auto guess file type */
7121 ret = read(fd, &ehdr, sizeof(ehdr));
7122 lseek(fd, 0, SEEK_SET);
7123 if (ret <= 0) {
7124 error_noabort("could not read header");
7125 goto fail;
7126 } else if (ret != sizeof(ehdr)) {
7127 goto try_load_script;
7130 if (ehdr.e_ident[0] == ELFMAG0 &&
7131 ehdr.e_ident[1] == ELFMAG1 &&
7132 ehdr.e_ident[2] == ELFMAG2 &&
7133 ehdr.e_ident[3] == ELFMAG3) {
7134 file->line_num = 0; /* do not display line number if error */
7135 if (ehdr.e_type == ET_REL) {
7136 ret = tcc_load_object_file(s1, fd, 0);
7137 } else if (ehdr.e_type == ET_DYN) {
7138 if (s1->output_type == TCC_OUTPUT_MEMORY) {
7139 #ifdef TCC_TARGET_PE
7140 ret = -1;
7141 #else
7142 void *h;
7143 h = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY);
7144 if (h)
7145 ret = 0;
7146 else
7147 ret = -1;
7148 #endif
7149 } else {
7150 ret = tcc_load_dll(s1, fd, filename,
7151 (flags & AFF_REFERENCED_DLL) != 0);
7153 } else {
7154 error_noabort("unrecognized ELF file");
7155 goto fail;
7157 } else if (memcmp((char *)&ehdr, ARMAG, 8) == 0) {
7158 file->line_num = 0; /* do not display line number if error */
7159 ret = tcc_load_archive(s1, fd);
7160 } else
7161 #ifdef TCC_TARGET_COFF
7162 if (*(uint16_t *)(&ehdr) == COFF_C67_MAGIC) {
7163 ret = tcc_load_coff(s1, fd);
7164 } else
7165 #endif
7166 #ifdef TCC_TARGET_PE
7167 if (pe_test_res_file(&ehdr, ret)) {
7168 ret = pe_load_res_file(s1, fd);
7169 } else
7170 #endif
7172 /* as GNU ld, consider it is an ld script if not recognized */
7173 try_load_script:
7174 ret = tcc_load_ldscript(s1);
7175 if (ret < 0) {
7176 error_noabort("unrecognized file type");
7177 goto fail;
7181 the_end:
7182 tcc_close(file);
7183 fail1:
7184 file = saved_file;
7185 return ret;
7186 fail:
7187 ret = -1;
7188 goto the_end;
7191 int tcc_add_file(TCCState *s, const char *filename)
7193 return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR);
7196 int tcc_add_library_path(TCCState *s, const char *pathname)
7198 char *pathname1;
7200 pathname1 = tcc_strdup(pathname);
7201 dynarray_add((void ***)&s->library_paths, &s->nb_library_paths, pathname1);
7202 return 0;
7205 /* find and load a dll. Return non zero if not found */
7206 /* XXX: add '-rpath' option support ? */
7207 static int tcc_add_dll(TCCState *s, const char *filename, int flags)
7209 char buf[1024];
7210 int i;
7212 for(i = 0; i < s->nb_library_paths; i++) {
7213 snprintf(buf, sizeof(buf), "%s/%s",
7214 s->library_paths[i], filename);
7215 if (tcc_add_file_internal(s, buf, flags) == 0)
7216 return 0;
7218 return -1;
7221 /* the library name is the same as the argument of the '-l' option */
7222 int tcc_add_library(TCCState *s, const char *libraryname)
7224 char buf[1024];
7225 int i;
7227 /* first we look for the dynamic library if not static linking */
7228 if (!s->static_link) {
7229 #ifdef TCC_TARGET_PE
7230 snprintf(buf, sizeof(buf), "%s.def", libraryname);
7231 #else
7232 snprintf(buf, sizeof(buf), "lib%s.so", libraryname);
7233 #endif
7234 if (tcc_add_dll(s, buf, 0) == 0)
7235 return 0;
7238 /* then we look for the static library */
7239 for(i = 0; i < s->nb_library_paths; i++) {
7240 snprintf(buf, sizeof(buf), "%s/lib%s.a",
7241 s->library_paths[i], libraryname);
7242 if (tcc_add_file_internal(s, buf, 0) == 0)
7243 return 0;
7245 return -1;
7248 int tcc_add_symbol(TCCState *s, const char *name, void *val)
7250 add_elf_sym(symtab_section, (unsigned long)val, 0,
7251 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
7252 SHN_ABS, name);
7253 return 0;
7256 int tcc_set_output_type(TCCState *s, int output_type)
7258 char buf[1024];
7260 s->output_type = output_type;
7262 if (!s->nostdinc) {
7263 /* default include paths */
7264 /* XXX: reverse order needed if -isystem support */
7265 #ifndef TCC_TARGET_PE
7266 tcc_add_sysinclude_path(s, CONFIG_SYSROOT "/usr/local/include");
7267 tcc_add_sysinclude_path(s, CONFIG_SYSROOT "/usr/include");
7268 #endif
7269 snprintf(buf, sizeof(buf), "%s/include", tcc_lib_path);
7270 tcc_add_sysinclude_path(s, buf);
7271 #ifdef TCC_TARGET_PE
7272 snprintf(buf, sizeof(buf), "%s/include/winapi", tcc_lib_path);
7273 tcc_add_sysinclude_path(s, buf);
7274 #endif
7277 /* if bound checking, then add corresponding sections */
7278 #ifdef CONFIG_TCC_BCHECK
7279 if (do_bounds_check) {
7280 /* define symbol */
7281 tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
7282 /* create bounds sections */
7283 bounds_section = new_section(s, ".bounds",
7284 SHT_PROGBITS, SHF_ALLOC);
7285 lbounds_section = new_section(s, ".lbounds",
7286 SHT_PROGBITS, SHF_ALLOC);
7288 #endif
7290 if (s->char_is_unsigned) {
7291 tcc_define_symbol(s, "__CHAR_UNSIGNED__", NULL);
7294 /* add debug sections */
7295 if (do_debug) {
7296 /* stab symbols */
7297 stab_section = new_section(s, ".stab", SHT_PROGBITS, 0);
7298 stab_section->sh_entsize = sizeof(Stab_Sym);
7299 stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0);
7300 put_elf_str(stabstr_section, "");
7301 stab_section->link = stabstr_section;
7302 /* put first entry */
7303 put_stabs("", 0, 0, 0, 0);
7306 /* add libc crt1/crti objects */
7307 #ifndef TCC_TARGET_PE
7308 if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) &&
7309 !s->nostdlib) {
7310 if (output_type != TCC_OUTPUT_DLL)
7311 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crt1.o");
7312 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crti.o");
7314 #endif
7316 #ifdef TCC_TARGET_PE
7317 snprintf(buf, sizeof(buf), "%s/lib", tcc_lib_path);
7318 tcc_add_library_path(s, buf);
7319 #endif
7321 return 0;
7324 #define WD_ALL 0x0001 /* warning is activated when using -Wall */
7325 #define FD_INVERT 0x0002 /* invert value before storing */
7327 typedef struct FlagDef {
7328 uint16_t offset;
7329 uint16_t flags;
7330 const char *name;
7331 } FlagDef;
7333 static const FlagDef warning_defs[] = {
7334 { offsetof(TCCState, warn_unsupported), 0, "unsupported" },
7335 { offsetof(TCCState, warn_write_strings), 0, "write-strings" },
7336 { offsetof(TCCState, warn_error), 0, "error" },
7337 { offsetof(TCCState, warn_implicit_function_declaration), WD_ALL,
7338 "implicit-function-declaration" },
7341 static int set_flag(TCCState *s, const FlagDef *flags, int nb_flags,
7342 const char *name, int value)
7344 int i;
7345 const FlagDef *p;
7346 const char *r;
7348 r = name;
7349 if (r[0] == 'n' && r[1] == 'o' && r[2] == '-') {
7350 r += 3;
7351 value = !value;
7353 for(i = 0, p = flags; i < nb_flags; i++, p++) {
7354 if (!strcmp(r, p->name))
7355 goto found;
7357 return -1;
7358 found:
7359 if (p->flags & FD_INVERT)
7360 value = !value;
7361 *(int *)((uint8_t *)s + p->offset) = value;
7362 return 0;
7366 /* set/reset a warning */
7367 int tcc_set_warning(TCCState *s, const char *warning_name, int value)
7369 int i;
7370 const FlagDef *p;
7372 if (!strcmp(warning_name, "all")) {
7373 for(i = 0, p = warning_defs; i < countof(warning_defs); i++, p++) {
7374 if (p->flags & WD_ALL)
7375 *(int *)((uint8_t *)s + p->offset) = 1;
7377 return 0;
7378 } else {
7379 return set_flag(s, warning_defs, countof(warning_defs),
7380 warning_name, value);
7384 static const FlagDef flag_defs[] = {
7385 { offsetof(TCCState, char_is_unsigned), 0, "unsigned-char" },
7386 { offsetof(TCCState, char_is_unsigned), FD_INVERT, "signed-char" },
7387 { offsetof(TCCState, nocommon), FD_INVERT, "common" },
7388 { offsetof(TCCState, leading_underscore), 0, "leading-underscore" },
7391 /* set/reset a flag */
7392 int tcc_set_flag(TCCState *s, const char *flag_name, int value)
7394 return set_flag(s, flag_defs, countof(flag_defs),
7395 flag_name, value);
7398 /* set CONFIG_TCCDIR at runtime */
7399 void tcc_set_lib_path(TCCState *s, const char *path)
7401 tcc_lib_path = tcc_strdup(path);
7404 #if !defined(LIBTCC)
7406 static int64_t getclock_us(void)
7408 #ifdef _WIN32
7409 struct _timeb tb;
7410 _ftime(&tb);
7411 return (tb.time * 1000LL + tb.millitm) * 1000LL;
7412 #else
7413 struct timeval tv;
7414 gettimeofday(&tv, NULL);
7415 return tv.tv_sec * 1000000LL + tv.tv_usec;
7416 #endif
7419 void help(void)
7421 printf("tcc version " TCC_VERSION " - Tiny C Compiler - Copyright (C) 2001-2006 Fabrice Bellard\n"
7422 "usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
7423 " [-Wwarn] [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-soname name]\n"
7424 " [-static] [infile1 infile2...] [-run infile args...]\n"
7425 "\n"
7426 "General options:\n"
7427 " -v display current version, increase verbosity\n"
7428 " -c compile only - generate an object file\n"
7429 " -o outfile set output filename\n"
7430 " -Bdir set tcc internal library path\n"
7431 " -bench output compilation statistics\n"
7432 " -run run compiled source\n"
7433 " -fflag set or reset (with 'no-' prefix) 'flag' (see man page)\n"
7434 " -Wwarning set or reset (with 'no-' prefix) 'warning' (see man page)\n"
7435 " -w disable all warnings\n"
7436 "Preprocessor options:\n"
7437 " -E preprocess only\n"
7438 " -Idir add include path 'dir'\n"
7439 " -Dsym[=val] define 'sym' with value 'val'\n"
7440 " -Usym undefine 'sym'\n"
7441 "Linker options:\n"
7442 " -Ldir add library path 'dir'\n"
7443 " -llib link with dynamic or static library 'lib'\n"
7444 " -shared generate a shared library\n"
7445 " -soname set name for shared library to be used at runtime\n"
7446 " -static static linking\n"
7447 " -rdynamic export all global symbols to dynamic linker\n"
7448 " -r generate (relocatable) object file\n"
7449 "Debugger options:\n"
7450 " -g generate runtime debug info\n"
7451 #ifdef CONFIG_TCC_BCHECK
7452 " -b compile with built-in memory and bounds checker (implies -g)\n"
7453 #endif
7454 #ifdef CONFIG_TCC_BACKTRACE
7455 " -bt N show N callers in stack traces\n"
7456 #endif
7460 #define TCC_OPTION_HAS_ARG 0x0001
7461 #define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
7463 typedef struct TCCOption {
7464 const char *name;
7465 uint16_t index;
7466 uint16_t flags;
7467 } TCCOption;
7469 enum {
7470 TCC_OPTION_HELP,
7471 TCC_OPTION_I,
7472 TCC_OPTION_D,
7473 TCC_OPTION_U,
7474 TCC_OPTION_L,
7475 TCC_OPTION_B,
7476 TCC_OPTION_l,
7477 TCC_OPTION_bench,
7478 TCC_OPTION_bt,
7479 TCC_OPTION_b,
7480 TCC_OPTION_g,
7481 TCC_OPTION_c,
7482 TCC_OPTION_static,
7483 TCC_OPTION_shared,
7484 TCC_OPTION_soname,
7485 TCC_OPTION_o,
7486 TCC_OPTION_r,
7487 TCC_OPTION_Wl,
7488 TCC_OPTION_W,
7489 TCC_OPTION_O,
7490 TCC_OPTION_m,
7491 TCC_OPTION_f,
7492 TCC_OPTION_nostdinc,
7493 TCC_OPTION_nostdlib,
7494 TCC_OPTION_print_search_dirs,
7495 TCC_OPTION_rdynamic,
7496 TCC_OPTION_run,
7497 TCC_OPTION_v,
7498 TCC_OPTION_w,
7499 TCC_OPTION_pipe,
7500 TCC_OPTION_E,
7503 static const TCCOption tcc_options[] = {
7504 { "h", TCC_OPTION_HELP, 0 },
7505 { "?", TCC_OPTION_HELP, 0 },
7506 { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
7507 { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
7508 { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
7509 { "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG },
7510 { "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
7511 { "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
7512 { "bench", TCC_OPTION_bench, 0 },
7513 { "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG },
7514 #ifdef CONFIG_TCC_BCHECK
7515 { "b", TCC_OPTION_b, 0 },
7516 #endif
7517 { "g", TCC_OPTION_g, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
7518 { "c", TCC_OPTION_c, 0 },
7519 { "static", TCC_OPTION_static, 0 },
7520 { "shared", TCC_OPTION_shared, 0 },
7521 { "soname", TCC_OPTION_soname, TCC_OPTION_HAS_ARG },
7522 { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
7523 { "run", TCC_OPTION_run, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
7524 { "rdynamic", TCC_OPTION_rdynamic, 0 },
7525 { "r", TCC_OPTION_r, 0 },
7526 { "Wl,", TCC_OPTION_Wl, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
7527 { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
7528 { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
7529 { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG },
7530 { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
7531 { "nostdinc", TCC_OPTION_nostdinc, 0 },
7532 { "nostdlib", TCC_OPTION_nostdlib, 0 },
7533 { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 },
7534 { "v", TCC_OPTION_v, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
7535 { "w", TCC_OPTION_w, 0 },
7536 { "pipe", TCC_OPTION_pipe, 0},
7537 { "E", TCC_OPTION_E, 0},
7538 { NULL },
7541 /* convert 'str' into an array of space separated strings */
7542 static int expand_args(char ***pargv, const char *str)
7544 const char *s1;
7545 char **argv, *arg;
7546 int argc, len;
7548 argc = 0;
7549 argv = NULL;
7550 for(;;) {
7551 while (is_space(*str))
7552 str++;
7553 if (*str == '\0')
7554 break;
7555 s1 = str;
7556 while (*str != '\0' && !is_space(*str))
7557 str++;
7558 len = str - s1;
7559 arg = tcc_malloc(len + 1);
7560 memcpy(arg, s1, len);
7561 arg[len] = '\0';
7562 dynarray_add((void ***)&argv, &argc, arg);
7564 *pargv = argv;
7565 return argc;
7568 static char **files;
7569 static int nb_files, nb_libraries;
7570 static int multiple_files;
7571 static int print_search_dirs;
7572 static int output_type;
7573 static int reloc_output;
7574 static const char *outfile;
7576 int parse_args(TCCState *s, int argc, char **argv)
7578 int optind;
7579 const TCCOption *popt;
7580 const char *optarg, *p1, *r1;
7581 char *r;
7583 optind = 0;
7584 while (optind < argc) {
7586 r = argv[optind++];
7587 if (r[0] != '-' || r[1] == '\0') {
7588 /* add a new file */
7589 dynarray_add((void ***)&files, &nb_files, r);
7590 if (!multiple_files) {
7591 optind--;
7592 /* argv[0] will be this file */
7593 break;
7595 } else {
7596 /* find option in table (match only the first chars */
7597 popt = tcc_options;
7598 for(;;) {
7599 p1 = popt->name;
7600 if (p1 == NULL)
7601 error("invalid option -- '%s'", r);
7602 r1 = r + 1;
7603 for(;;) {
7604 if (*p1 == '\0')
7605 goto option_found;
7606 if (*r1 != *p1)
7607 break;
7608 p1++;
7609 r1++;
7611 popt++;
7613 option_found:
7614 if (popt->flags & TCC_OPTION_HAS_ARG) {
7615 if (*r1 != '\0' || (popt->flags & TCC_OPTION_NOSEP)) {
7616 optarg = r1;
7617 } else {
7618 if (optind >= argc)
7619 error("argument to '%s' is missing", r);
7620 optarg = argv[optind++];
7622 } else {
7623 if (*r1 != '\0')
7624 return 0;
7625 optarg = NULL;
7628 switch(popt->index) {
7629 case TCC_OPTION_HELP:
7630 return 0;
7632 case TCC_OPTION_I:
7633 if (tcc_add_include_path(s, optarg) < 0)
7634 error("too many include paths");
7635 break;
7636 case TCC_OPTION_D:
7638 char *sym, *value;
7639 sym = (char *)optarg;
7640 value = strchr(sym, '=');
7641 if (value) {
7642 *value = '\0';
7643 value++;
7645 tcc_define_symbol(s, sym, value);
7647 break;
7648 case TCC_OPTION_U:
7649 tcc_undefine_symbol(s, optarg);
7650 break;
7651 case TCC_OPTION_L:
7652 tcc_add_library_path(s, optarg);
7653 break;
7654 case TCC_OPTION_B:
7655 /* set tcc utilities path (mainly for tcc development) */
7656 tcc_set_lib_path(s, optarg);
7657 break;
7658 case TCC_OPTION_l:
7659 dynarray_add((void ***)&files, &nb_files, r);
7660 nb_libraries++;
7661 break;
7662 case TCC_OPTION_bench:
7663 do_bench = 1;
7664 break;
7665 #ifdef CONFIG_TCC_BACKTRACE
7666 case TCC_OPTION_bt:
7667 num_callers = atoi(optarg);
7668 break;
7669 #endif
7670 #ifdef CONFIG_TCC_BCHECK
7671 case TCC_OPTION_b:
7672 do_bounds_check = 1;
7673 do_debug = 1;
7674 break;
7675 #endif
7676 case TCC_OPTION_g:
7677 do_debug = 1;
7678 break;
7679 case TCC_OPTION_c:
7680 multiple_files = 1;
7681 output_type = TCC_OUTPUT_OBJ;
7682 break;
7683 case TCC_OPTION_static:
7684 s->static_link = 1;
7685 break;
7686 case TCC_OPTION_shared:
7687 output_type = TCC_OUTPUT_DLL;
7688 break;
7689 case TCC_OPTION_soname:
7690 s->soname = optarg;
7691 break;
7692 case TCC_OPTION_o:
7693 multiple_files = 1;
7694 outfile = optarg;
7695 break;
7696 case TCC_OPTION_r:
7697 /* generate a .o merging several output files */
7698 reloc_output = 1;
7699 output_type = TCC_OUTPUT_OBJ;
7700 break;
7701 case TCC_OPTION_nostdinc:
7702 s->nostdinc = 1;
7703 break;
7704 case TCC_OPTION_nostdlib:
7705 s->nostdlib = 1;
7706 break;
7707 case TCC_OPTION_print_search_dirs:
7708 print_search_dirs = 1;
7709 break;
7710 case TCC_OPTION_run:
7712 int argc1;
7713 char **argv1;
7714 argc1 = expand_args(&argv1, optarg);
7715 if (argc1 > 0) {
7716 parse_args(s, argc1, argv1);
7718 multiple_files = 0;
7719 output_type = TCC_OUTPUT_MEMORY;
7721 break;
7722 case TCC_OPTION_v:
7723 do {
7724 if (0 == verbose++)
7725 printf("tcc version %s\n", TCC_VERSION);
7726 } while (*optarg++ == 'v');
7727 break;
7728 case TCC_OPTION_f:
7729 if (tcc_set_flag(s, optarg, 1) < 0 && s->warn_unsupported)
7730 goto unsupported_option;
7731 break;
7732 case TCC_OPTION_W:
7733 if (tcc_set_warning(s, optarg, 1) < 0 &&
7734 s->warn_unsupported)
7735 goto unsupported_option;
7736 break;
7737 case TCC_OPTION_w:
7738 s->warn_none = 1;
7739 break;
7740 case TCC_OPTION_rdynamic:
7741 s->rdynamic = 1;
7742 break;
7743 case TCC_OPTION_Wl:
7745 const char *p;
7746 if (strstart(optarg, "-Ttext,", &p)) {
7747 s->text_addr = strtoul(p, NULL, 16);
7748 s->has_text_addr = 1;
7749 } else if (strstart(optarg, "--oformat,", &p)) {
7750 if (strstart(p, "elf32-", NULL)) {
7751 s->output_format = TCC_OUTPUT_FORMAT_ELF;
7752 } else if (!strcmp(p, "binary")) {
7753 s->output_format = TCC_OUTPUT_FORMAT_BINARY;
7754 } else
7755 #ifdef TCC_TARGET_COFF
7756 if (!strcmp(p, "coff")) {
7757 s->output_format = TCC_OUTPUT_FORMAT_COFF;
7758 } else
7759 #endif
7761 error("target %s not found", p);
7763 } else {
7764 error("unsupported linker option '%s'", optarg);
7767 break;
7768 case TCC_OPTION_E:
7769 output_type = TCC_OUTPUT_PREPROCESS;
7770 break;
7771 default:
7772 if (s->warn_unsupported) {
7773 unsupported_option:
7774 warning("unsupported option '%s'", r);
7776 break;
7780 return optind + 1;
7783 int main(int argc, char **argv)
7785 int i;
7786 TCCState *s;
7787 int nb_objfiles, ret, optind;
7788 char objfilename[1024];
7789 int64_t start_time = 0;
7791 s = tcc_new();
7792 #ifdef _WIN32
7793 tcc_set_lib_path_w32(s);
7794 #endif
7795 output_type = TCC_OUTPUT_EXE;
7796 outfile = NULL;
7797 multiple_files = 1;
7798 files = NULL;
7799 nb_files = 0;
7800 nb_libraries = 0;
7801 reloc_output = 0;
7802 print_search_dirs = 0;
7803 ret = 0;
7805 optind = parse_args(s, argc - 1, argv + 1);
7806 if (print_search_dirs) {
7807 /* enough for Linux kernel */
7808 printf("install: %s/\n", tcc_lib_path);
7809 return 0;
7811 if (optind == 0 || nb_files == 0) {
7812 if (optind && verbose)
7813 return 0;
7814 help();
7815 return 1;
7818 nb_objfiles = nb_files - nb_libraries;
7820 /* if outfile provided without other options, we output an
7821 executable */
7822 if (outfile && output_type == TCC_OUTPUT_MEMORY)
7823 output_type = TCC_OUTPUT_EXE;
7825 /* check -c consistency : only single file handled. XXX: checks file type */
7826 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
7827 /* accepts only a single input file */
7828 if (nb_objfiles != 1)
7829 error("cannot specify multiple files with -c");
7830 if (nb_libraries != 0)
7831 error("cannot specify libraries with -c");
7835 if (output_type == TCC_OUTPUT_PREPROCESS) {
7836 if (!outfile) {
7837 s->outfile = stdout;
7838 } else {
7839 s->outfile = fopen(outfile, "w");
7840 if (!s->outfile)
7841 error("could not open '%s", outfile);
7843 } else if (output_type != TCC_OUTPUT_MEMORY) {
7844 if (!outfile) {
7845 /* compute default outfile name */
7846 char *ext;
7847 const char *name =
7848 strcmp(files[0], "-") == 0 ? "a" : tcc_basename(files[0]);
7849 pstrcpy(objfilename, sizeof(objfilename), name);
7850 ext = tcc_fileextension(objfilename);
7851 #ifdef TCC_TARGET_PE
7852 if (output_type == TCC_OUTPUT_DLL)
7853 strcpy(ext, ".dll");
7854 else
7855 if (output_type == TCC_OUTPUT_EXE)
7856 strcpy(ext, ".exe");
7857 else
7858 #endif
7859 if (output_type == TCC_OUTPUT_OBJ && !reloc_output && *ext)
7860 strcpy(ext, ".o");
7861 else
7862 pstrcpy(objfilename, sizeof(objfilename), "a.out");
7863 outfile = objfilename;
7867 if (do_bench) {
7868 start_time = getclock_us();
7871 tcc_set_output_type(s, output_type);
7873 /* compile or add each files or library */
7874 for(i = 0; i < nb_files && ret == 0; i++) {
7875 const char *filename;
7877 filename = files[i];
7878 if (output_type == TCC_OUTPUT_PREPROCESS) {
7879 if (tcc_add_file_internal(s, filename,
7880 AFF_PRINT_ERROR | AFF_PREPROCESS) < 0)
7881 ret = 1;
7882 } else if (filename[0] == '-' && filename[1]) {
7883 if (tcc_add_library(s, filename + 2) < 0)
7884 error("cannot find %s", filename);
7885 } else {
7886 if (1 == verbose)
7887 printf("-> %s\n", filename);
7888 if (tcc_add_file(s, filename) < 0)
7889 ret = 1;
7893 /* free all files */
7894 tcc_free(files);
7896 if (ret)
7897 goto the_end;
7899 if (do_bench) {
7900 double total_time;
7901 total_time = (double)(getclock_us() - start_time) / 1000000.0;
7902 if (total_time < 0.001)
7903 total_time = 0.001;
7904 if (total_bytes < 1)
7905 total_bytes = 1;
7906 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
7907 tok_ident - TOK_IDENT, total_lines, total_bytes,
7908 total_time, (int)(total_lines / total_time),
7909 total_bytes / total_time / 1000000.0);
7912 if (s->output_type == TCC_OUTPUT_PREPROCESS) {
7913 if (outfile)
7914 fclose(s->outfile);
7915 } else if (s->output_type == TCC_OUTPUT_MEMORY) {
7916 ret = tcc_run(s, argc - optind, argv + optind);
7917 } else
7918 ret = tcc_output_file(s, outfile) ? 1 : 0;
7919 the_end:
7920 /* XXX: cannot do it with bound checking because of the malloc hooks */
7921 if (!do_bounds_check)
7922 tcc_delete(s);
7924 #ifdef MEM_DEBUG
7925 if (do_bench) {
7926 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size);
7928 #endif
7929 return ret;
7932 #endif