2 * TCC - Tiny C Compiler
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
23 #ifdef TCC_TARGET_I386
35 #ifdef TCC_TARGET_X86_64
36 #include "x86_64-gen.c"
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
)
56 const char *dlerror(void)
61 typedef struct 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)
79 void *resolve_sym(TCCState
*s1
, const char *symbol
, int type
)
83 while (p
->str
!= NULL
) {
84 if (!strcmp(p
->str
, symbol
))
91 #elif !defined(_WIN32)
95 void *resolve_sym(TCCState
*s1
, const char *sym
, int type
)
97 return dlsym(RTLD_DEFAULT
, sym
);
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
)
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
)
121 q_end
= buf
+ buf_size
- 1;
133 /* strcat and truncate. */
134 static char *pstrcat(char *buf
, int buf_size
, const char *s
)
139 pstrcpy(buf
+ len
, buf_size
- len
, s
);
144 static int strstart(const char *str
, const char *val
, const char **ptr
)
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
166 #define IS_PATHSEP(c) (c == '/')
167 #define IS_ABSPATH(p) IS_PATHSEP(p[0])
168 #define PATHCMP strcmp
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]))
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);
188 char *normalize_slashes(char *path
)
191 for (p
= path
; *p
; ++p
)
197 void tcc_set_lib_path_w32(TCCState
*s
)
199 /* on win32, we suppose the lib and includes are at the location
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))
209 tcc_set_lib_path(s
, path
);
213 void set_pages_executable(void *ptr
, unsigned long length
)
216 unsigned long old_protect
;
217 VirtualProtect(ptr
, length
, PAGE_EXECUTE_READWRITE
, &old_protect
);
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
);
227 /* memory management */
231 unsigned malloc_usable_size(void*);
234 static inline void tcc_free(void *ptr
)
237 mem_cur_size
-= malloc_usable_size(ptr
);
242 static void *tcc_malloc(unsigned long size
)
247 error("memory full");
249 mem_cur_size
+= malloc_usable_size(ptr
);
250 if (mem_cur_size
> mem_max_size
)
251 mem_max_size
= mem_cur_size
;
256 static void *tcc_mallocz(unsigned long size
)
259 ptr
= tcc_malloc(size
);
260 memset(ptr
, 0, size
);
264 static inline void *tcc_realloc(void *ptr
, unsigned long size
)
268 mem_cur_size
-= malloc_usable_size(ptr
);
270 ptr1
= realloc(ptr
, size
);
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
;
280 static char *tcc_strdup(const char *str
)
283 ptr
= tcc_malloc(strlen(str
) + 1);
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
)
299 /* every power of two we double array size */
300 if ((nb
& (nb
- 1)) == 0) {
305 pp
= tcc_realloc(pp
, nb_alloc
* sizeof(void *));
307 error("memory full");
314 static void dynarray_reset(void *pp
, int *n
)
317 for (p
= *(void***)pp
; *n
; ++p
, --*n
)
320 tcc_free(*(void**)pp
);
324 /* symbol allocator */
325 static Sym
*__sym_malloc(void)
327 Sym
*sym_pool
, *sym
, *last_sym
;
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
;
335 for(i
= 0; i
< SYM_POOL_NB
; i
++) {
336 sym
->next
= last_sym
;
340 sym_free_first
= last_sym
;
344 static inline Sym
*sym_malloc(void)
347 sym
= sym_free_first
;
349 sym
= __sym_malloc();
350 sym_free_first
= sym
->next
;
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
)
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
;
375 sec
->sh_addralign
= 4;
378 sec
->sh_addralign
= 1;
381 sec
->sh_addralign
= 32; /* default conservative alignment */
385 if (sh_flags
& SHF_PRIVATE
) {
386 dynarray_add((void ***)&s1
->priv_sections
, &s1
->nb_priv_sections
, sec
);
388 sec
->sh_num
= s1
->nb_sections
;
389 dynarray_add((void ***)&s1
->sections
, &s1
->nb_sections
, sec
);
395 static void free_section(Section
*s
)
400 /* realloc section and set its content to zero */
401 static void section_realloc(Section
*sec
, unsigned long new_size
)
406 size
= sec
->data_allocated
;
409 while (size
< new_size
)
411 data
= tcc_realloc(sec
->data
, size
);
413 error("memory full");
414 memset(data
+ sec
->data_allocated
, 0, size
- sec
->data_allocated
);
416 sec
->data_allocated
= size
;
419 /* reserve at least 'size' bytes in section 'sec' from
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
435 Section
*find_section(TCCState
*s1
, const char *name
)
439 for(i
= 1; i
< s1
->nb_sections
; i
++) {
440 sec
= s1
->sections
[i
];
441 if (!strcmp(name
, sec
->name
))
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
;
463 else if (section
== SECTION_ABS
)
466 sh_num
= section
->sh_num
;
470 if ((sym
->type
.t
& VT_BTYPE
) == VT_FUNC
) {
474 attr
= sym
->type
.ref
->r
;
475 if (FUNC_EXPORT(attr
))
477 if (FUNC_CALL(attr
) == FUNC_STDCALL
)
481 sym_type
= STT_OBJECT
;
484 if (sym
->type
.t
& VT_STATIC
)
485 sym_bind
= STB_LOCAL
;
487 sym_bind
= STB_GLOBAL
;
490 name
= get_tok_str(sym
->v
, NULL
);
491 #ifdef CONFIG_TCC_BCHECK
492 if (do_bounds_check
) {
495 /* XXX: avoid doing that for statics ? */
496 /* if bound checking is activated, we change some function
497 names by adding the "__bound" prefix */
500 /* XXX: we rely only on malloc hooks */
513 strcpy(buf
, "__bound_");
522 if ((other
& 2) && can_add_underscore
) {
523 sprintf(buf1
, "_%s@%d", name
, FUNC_ARGS(attr
));
527 if (tcc_state
->leading_underscore
&& can_add_underscore
) {
529 pstrcpy(buf1
+ 1, sizeof(buf1
) - 1, name
);
532 info
= ELFW(ST_INFO
)(sym_bind
, sym_type
);
533 sym
->c
= add_elf_sym(symtab_section
, value
, size
, info
, other
, sh_num
, name
);
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
)
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') ||
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';
583 static void strcat_vprintf(char *buf
, int buf_size
, const char *fmt
, va_list ap
)
587 vsnprintf(buf
+ len
, buf_size
- len
, fmt
, ap
);
590 static void strcat_printf(char *buf
, int buf_size
, const char *fmt
, ...)
594 strcat_vprintf(buf
, buf_size
, fmt
, ap
);
598 void error1(TCCState
*s1
, int is_warning
, const char *fmt
, va_list ap
)
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
);
612 strcat_printf(buf
, sizeof(buf
),
613 "%s: ", file
->filename
);
616 strcat_printf(buf
, sizeof(buf
),
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
);
627 s1
->error_func(s1
->error_opaque
, buf
);
629 if (!is_warning
|| s1
->warn_error
)
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
;
642 /* error without aborting current compilation */
643 void error_noabort(const char *fmt
, ...)
645 TCCState
*s1
= tcc_state
;
649 error1(s1
, 0, fmt
, ap
);
653 void error(const char *fmt
, ...)
655 TCCState
*s1
= tcc_state
;
659 error1(s1
, 0, fmt
, 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);
665 /* XXX: eliminate this someday */
670 void expect(const char *msg
)
672 error("%s expected", msg
);
675 void warning(const char *fmt
, ...)
677 TCCState
*s1
= tcc_state
;
684 error1(s1
, 1, fmt
, ap
);
691 error("'%c' expected", c
);
695 static void test_lvalue(void)
697 if (!(vtop
->r
& VT_LVAL
))
701 /* allocate a new token */
702 static TokenSym
*tok_alloc_new(TokenSym
**pts
, const char *str
, int len
)
704 TokenSym
*ts
, **ptable
;
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
*));
715 error("memory full");
716 table_ident
= ptable
;
719 ts
= tcc_malloc(sizeof(TokenSym
) + len
);
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
;
727 ts
->hash_next
= NULL
;
728 memcpy(ts
->str
, str
, len
);
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
)
746 h
= TOK_HASH_FUNC(h
, ((unsigned char *)str
)[i
]);
747 h
&= (TOK_HASH_SIZE
- 1);
749 pts
= &hash_ident
[h
];
754 if (ts
->len
== len
&& !memcmp(ts
->str
, str
, len
))
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
)
768 size
= cstr
->size_allocated
;
770 size
= 8; /* no need to allocate a too small first string */
771 while (size
< new_size
)
773 data
= tcc_realloc(cstr
->data_allocated
, size
);
775 error("memory full");
776 cstr
->data_allocated
= data
;
777 cstr
->size_allocated
= size
;
782 static inline void cstr_ccat(CString
*cstr
, int ch
)
785 size
= cstr
->size
+ 1;
786 if (size
> cstr
->size_allocated
)
787 cstr_realloc(cstr
, size
);
788 ((unsigned char *)cstr
->data
)[size
- 1] = ch
;
792 static void cstr_cat(CString
*cstr
, const char *str
)
804 /* add a wide char */
805 static void cstr_wccat(CString
*cstr
, int ch
)
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
;
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
);
827 #define cstr_reset(cstr) cstr_free(cstr)
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) {
839 cstr_ccat(cstr
, '\\');
841 cstr_ccat(cstr
, 'n');
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
;
861 /* NOTE: to go faster, we give a fixed buffer for small strings */
862 cstr_reset(&cstr_buf
);
864 cstr_buf
.size_allocated
= sizeof(buf
);
870 /* XXX: not quite exact, but only useful for testing */
871 sprintf(p
, "%u", cv
->ui
);
875 /* XXX: not quite exact, but only useful for testing */
876 sprintf(p
, "%Lu", cv
->ull
);
879 cstr_ccat(&cstr_buf
, 'L');
881 cstr_ccat(&cstr_buf
, '\'');
882 add_char(&cstr_buf
, cv
->i
);
883 cstr_ccat(&cstr_buf
, '\'');
884 cstr_ccat(&cstr_buf
, '\0');
888 len
= cstr
->size
- 1;
890 add_char(&cstr_buf
, ((unsigned char *)cstr
->data
)[i
]);
891 cstr_ccat(&cstr_buf
, '\0');
894 cstr_ccat(&cstr_buf
, 'L');
897 cstr_ccat(&cstr_buf
, '\"');
899 len
= cstr
->size
- 1;
901 add_char(&cstr_buf
, ((unsigned char *)cstr
->data
)[i
]);
903 len
= (cstr
->size
/ sizeof(nwchar_t
)) - 1;
905 add_char(&cstr_buf
, ((nwchar_t
*)cstr
->data
)[i
]);
907 cstr_ccat(&cstr_buf
, '\"');
908 cstr_ccat(&cstr_buf
, '\0');
917 return strcpy(p
, "...");
919 return strcpy(p
, "<<=");
921 return strcpy(p
, ">>=");
924 /* search in two bytes table */
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
);
944 /* should never happen */
949 return cstr_buf
.data
;
952 /* push, without hashing */
953 static Sym
*sym_push2(Sym
**ps
, int v
, int t
, long c
)
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
)
979 /* structure lookup */
980 static inline Sym
*struct_find(int v
)
983 if ((unsigned)v
>= (unsigned)(tok_ident
- TOK_IDENT
))
985 return table_ident
[v
]->sym_struct
;
988 /* find an identifier */
989 static inline Sym
*sym_find(int v
)
992 if ((unsigned)v
>= (unsigned)(tok_ident
- TOK_IDENT
))
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
)
1007 s
= sym_push2(ps
, v
, type
->t
, c
);
1008 s
->type
.ref
= type
->ref
;
1010 /* don't record fields or anonymous symbols */
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
];
1016 ps
= &ts
->sym_struct
;
1018 ps
= &ts
->sym_identifier
;
1025 /* push a global identifier */
1026 static Sym
*global_identifier_push(int v
, int t
, int c
)
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 */
1036 ps
= &(*ps
)->prev_tok
;
1043 /* pop symbols until top reaches 'b' */
1044 static void sym_pop(Sym
**ptop
, Sym
*b
)
1054 /* remove symbol in token array */
1056 if (!(v
& SYM_FIELD
) && (v
& ~SYM_STRUCT
) < SYM_FIRST_ANOM
) {
1057 ts
= table_ident
[(v
& ~SYM_STRUCT
) - TOK_IDENT
];
1059 ps
= &ts
->sym_struct
;
1061 ps
= &ts
->sym_identifier
;
1072 BufferedFile
*tcc_open(TCCState
*s1
, const char *filename
)
1077 if (strcmp(filename
, "-") == 0)
1078 fd
= 0, filename
= "stdin";
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
);
1086 bf
= tcc_malloc(sizeof(BufferedFile
));
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
);
1093 normalize_slashes(bf
->filename
);
1096 bf
->ifndef_macro
= 0;
1097 bf
->ifdef_stack_ptr
= s1
->ifdef_stack_ptr
;
1098 // printf("opening '%s'\n", filename);
1102 void tcc_close(BufferedFile
*bf
)
1104 total_lines
+= bf
->line_num
;
1111 void swap(int *p
, int *q
)
1119 void vsetc(CType
*type
, int r
, CValue
*vc
)
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
)
1136 vtop
->r2
= VT_CONST
;
1140 /* push integer constant */
1145 vsetc(&int_type
, VT_CONST
, &cval
);
1148 /* push long long constant */
1149 void vpushll(long long 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
)
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
);
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
)
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
)
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
;
1198 /* define a new external reference to a symbol 'v' of type 'u' */
1199 static Sym
*external_sym(int v
, CType
*type
, int r
)
1205 /* push forward reference */
1206 s
= sym_push(v
, type
, r
| VT_CONST
| VT_SYM
, 0);
1207 s
->type
.t
|= VT_EXTERN
;
1209 if (!is_compatible_types(&s
->type
, type
))
1210 error("incompatible types for redefinition of '%s'",
1211 get_tok_str(v
, NULL
));
1216 /* push a reference to global symbol v */
1217 static void vpush_global_sym(CType
*type
, int v
)
1222 sym
= external_global_sym(v
, type
, 0);
1224 vsetc(type
, VT_CONST
| VT_SYM
, &cval
);
1228 void vset(CType
*type
, int r
, int v
)
1233 vsetc(type
, r
, &cval
);
1236 void vseti(int r
, int v
)
1252 void vpushv(SValue
*v
)
1254 if (vtop
>= vstack
+ (VSTACK_SIZE
- 1))
1255 error("memory full");
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
;
1272 /* modify all stack values */
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 */
1280 /* NOTE: must reload 'r' because r might be equal to r2 */
1281 r
= p
->r
& VT_VALMASK
;
1282 /* store register in the stack */
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
;
1291 size
= type_size(type
, &align
);
1292 loc
= (loc
- size
) & -align
;
1293 sv
.type
.t
= type
->t
;
1294 sv
.r
= VT_LOCAL
| VT_LVAL
;
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) */
1303 #ifndef TCC_TARGET_X86_64
1304 /* special long long case */
1305 if ((type
->t
& VT_BTYPE
) == VT_LLONG
) {
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
1318 p
->r
= (p
->r
& ~(VT_VALMASK
| VT_BOUNDED
)) | VT_LLOCAL
;
1320 p
->r
= lvalue_type(p
->type
.t
) | VT_LOCAL
;
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
)
1335 for(r
=0;r
<NB_REGS
;r
++) {
1336 if (reg_classes
[r
] & rc2
) {
1339 for(p
= vstack
; p
<= vtop
; p
++) {
1340 if ((p
->r
& VT_VALMASK
) == r
||
1341 (p
->r2
& VT_VALMASK
) == r
)
1351 /* find a free register of class 'rc'. If none, save one register */
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
)
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
))
1377 /* also look at second register (if long long) */
1378 r
= p
->r2
& VT_VALMASK
;
1379 if (r
< VT_CONST
&& (reg_classes
[r
] & rc
)) {
1385 /* Should never comes here */
1389 /* save registers up to (vtop - n) stack entry */
1390 void save_regs(int n
)
1395 for(p
= vstack
;p
<= p1
; p
++) {
1396 r
= p
->r
& VT_VALMASK
;
1403 /* move register 's' to 'r', and flush previous value of r to memory
1405 void move_reg(int r
, int s
)
1418 /* get address of vtop (vtop MUST BE an lvalue) */
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 */
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 */
1442 vtop
->type
.t
= VT_INT
;
1445 gen_bounded_ptr_add();
1446 vtop
->r
|= lval_type
;
1449 /* then check for dereferencing */
1450 gen_bounded_ptr_deref();
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). */
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
) {
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
) {
1476 if((vtop
->type
.t
& VT_UNSIGNED
) ||
1477 (vtop
->type
.t
& VT_BTYPE
) == VT_BOOL
)
1478 type
.t
|= VT_UNSIGNED
;
1480 /* generate shifts */
1481 vpushi(bits
- (bit_pos
+ bit_size
));
1483 vpushi(bits
- bit_size
);
1484 /* NOTE: transformed to SHR if unsigned */
1488 if (is_float(vtop
->type
.t
) &&
1489 (vtop
->r
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
) {
1492 unsigned long offset
;
1493 #if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP)
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;
1509 ptr
= section_ptr_add(data_section
, size
);
1511 #if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP)
1515 ptr
[i
] = vtop
->c
.tab
[size
-1-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
;
1525 #ifdef CONFIG_TCC_BCHECK
1526 if (vtop
->r
& VT_MUSTBOUND
)
1530 r
= vtop
->r
& VT_VALMASK
;
1534 /* need to reload if:
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
))) {
1544 #ifndef TCC_TARGET_X86_64
1545 if ((vtop
->type
.t
& VT_BTYPE
) == VT_LLONG
) {
1547 unsigned long long ll
;
1548 /* two register type load : expand to two words
1550 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
) {
1553 vtop
->c
.ui
= ll
; /* first word */
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. */
1564 /* load from memory */
1567 vtop
[-1].r
= r
; /* save register value */
1568 /* increment pointer to get second word */
1569 vtop
->type
.t
= VT_INT
;
1575 /* move registers */
1578 vtop
[-1].r
= r
; /* save register value */
1579 vtop
->r
= vtop
[-1].r2
;
1581 /* allocate second register */
1585 /* write second register */
1589 if ((vtop
->r
& VT_LVAL
) && !is_float(vtop
->type
.t
)) {
1591 /* lvalue of scalar type : need to use lvalue type
1592 because of possible cast */
1595 /* compute memory access type */
1596 if (vtop
->r
& VT_LVAL_BYTE
)
1598 else if (vtop
->r
& VT_LVAL_SHORT
)
1600 if (vtop
->r
& VT_LVAL_UNSIGNED
)
1604 /* restore wanted type */
1607 /* one register type load */
1612 #ifdef TCC_TARGET_C67
1613 /* uses register pairs for doubles */
1614 if ((vtop
->type
.t
& VT_BTYPE
) == VT_DOUBLE
)
1621 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
1622 void gv2(int rc1
, int rc2
)
1626 /* generate more generic register first. But VT_JMP or VT_CMP
1627 values must be generated first in all cases to avoid possible
1629 v
= vtop
[0].r
& VT_VALMASK
;
1630 if (v
!= VT_CMP
&& (v
& ~1) != VT_JMP
&& rc1
<= rc2
) {
1635 /* test if reload is needed for first register */
1636 if ((vtop
[-1].r
& VT_VALMASK
) >= VT_CONST
) {
1646 /* test if reload is needed for first register */
1647 if ((vtop
[0].r
& VT_VALMASK
) >= VT_CONST
) {
1653 /* wrapper around RC_FRET to return a register by type */
1656 #ifdef TCC_TARGET_X86_64
1657 if (t
== VT_LDOUBLE
) {
1664 /* wrapper around REG_FRET to return a register by type */
1667 #ifdef TCC_TARGET_X86_64
1668 if (t
== VT_LDOUBLE
) {
1675 /* expand long long on stack in two int registers */
1680 u
= vtop
->type
.t
& VT_UNSIGNED
;
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)
1696 u
= vtop
->type
.t
& VT_UNSIGNED
;
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;
1705 } else if (v
== (VT_LVAL
|VT_CONST
) || v
== (VT_LVAL
|VT_LOCAL
)) {
1707 vtop
->r
= vtop
[-1].r
;
1708 } else if (v
> VT_CONST
) {
1712 vtop
->r
= vtop
[-1].r2
;
1713 vtop
[-1].r2
= VT_CONST
;
1714 vtop
[-1].type
.t
= VT_INT
| u
;
1718 /* build a long long from two ints */
1721 gv2(RC_INT
, RC_INT
);
1722 vtop
[-1].r2
= vtop
[0].r
;
1723 vtop
[-1].type
.t
= t
;
1727 /* rotate n first stack elements to the bottom
1728 I1 ... In -> I2 ... In I1 [top is right]
1736 for(i
=-n
+1;i
!=0;i
++)
1737 vtop
[i
] = vtop
[i
+1];
1741 /* rotate n first stack elements to the top
1742 I1 ... In -> In I1 ... I(n-1) [top is right]
1750 for(i
= 0;i
< n
- 1; i
++)
1751 vtop
[-i
] = vtop
[-i
- 1];
1755 #ifdef TCC_TARGET_ARM
1756 /* like vrott but in other direction
1757 In ... I1 -> I(n-1) ... I1 In [top is right]
1765 for(i
= n
- 1; i
> 0; i
--)
1766 vtop
[-i
] = vtop
[-i
+ 1];
1771 /* pop stack value */
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) */
1782 if (v
== VT_JMP
|| v
== VT_JMPI
) {
1783 /* need to put correct jump if && or || without test */
1789 /* convert stack entry to register and duplicate its value in another
1797 if ((t
& VT_BTYPE
) == VT_LLONG
) {
1804 /* stack: H L L1 H1 */
1812 /* duplicate value */
1817 #ifdef TCC_TARGET_X86_64
1818 if ((t
& VT_BTYPE
) == VT_LDOUBLE
) {
1828 load(r1
, &sv
); /* move r to r1 */
1830 /* duplicates value */
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
;
1841 unsigned short reg_iret
= REG_IRET
;
1842 unsigned short reg_lret
= REG_LRET
;
1848 func
= TOK___divdi3
;
1851 func
= TOK___udivdi3
;
1854 func
= TOK___moddi3
;
1857 func
= TOK___umoddi3
;
1864 /* call generic long long function */
1865 vpush_global_sym(&func_old_type
, func
);
1870 vtop
->r2
= reg_lret
;
1883 /* stack: L1 H1 L2 H2 */
1888 vtop
[-2] = vtop
[-3];
1891 /* stack: H1 H2 L1 L2 */
1897 /* stack: H1 H2 L1 L2 ML MH */
1900 /* stack: ML MH H1 H2 L1 L2 */
1904 /* stack: ML MH H1 L2 H2 L1 */
1909 /* stack: ML MH M1 M2 */
1912 } else if (op
== '+' || op
== '-') {
1913 /* XXX: add non carry method too (for MIPS or alpha) */
1919 /* stack: H1 H2 (L1 op L2) */
1922 gen_op(op1
+ 1); /* TOK_xxxC2 */
1925 /* stack: H1 H2 (L1 op L2) */
1928 /* stack: (L1 op L2) H1 H2 */
1930 /* stack: (L1 op L2) (H1 op H2) */
1938 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
) {
1939 t
= vtop
[-1].type
.t
;
1943 /* stack: L H shift */
1945 /* constant: simpler */
1946 /* NOTE: all comments are for SHL. the other cases are
1947 done by swaping words */
1958 if (op
!= TOK_SAR
) {
1991 /* XXX: should provide a faster fallback on x86 ? */
1994 func
= TOK___ashrdi3
;
1997 func
= TOK___lshrdi3
;
2000 func
= TOK___ashldi3
;
2006 /* compare operations */
2012 /* stack: L1 H1 L2 H2 */
2014 vtop
[-1] = vtop
[-2];
2016 /* stack: L1 L2 H1 H2 */
2019 /* when values are equal, we need to compare low words. since
2020 the jump is inverted, we invert the test too. */
2023 else if (op1
== TOK_GT
)
2025 else if (op1
== TOK_ULT
)
2027 else if (op1
== TOK_UGT
)
2032 if (op1
!= TOK_NE
) {
2036 /* generate non equal test */
2037 /* XXX: NOT PORTABLE yet */
2041 #if defined(TCC_TARGET_I386)
2042 b
= psym(0x850f, 0);
2043 #elif defined(TCC_TARGET_ARM)
2045 o(0x1A000000 | encbranch(ind
, 0, 1));
2046 #elif defined(TCC_TARGET_C67)
2047 error("not implemented");
2049 #error not supported
2053 /* compare low. Always unsigned */
2057 else if (op1
== TOK_LE
)
2059 else if (op1
== TOK_GT
)
2061 else if (op1
== TOK_GE
)
2072 /* handle integer constant optimizations and various machine
2074 void gen_opic(int op
)
2076 int c1
, c2
, t1
, t2
, n
;
2079 typedef unsigned long long U
;
2083 t1
= v1
->type
.t
& VT_BTYPE
;
2084 t2
= v2
->type
.t
& VT_BTYPE
;
2088 else if (v1
->type
.t
& VT_UNSIGNED
)
2095 else if (v2
->type
.t
& VT_UNSIGNED
)
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
;
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;
2117 /* if division by zero, generate explicit division */
2120 error("division by zero in constant");
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;
2130 case TOK_SHL
: l1
<<= l2
; break;
2131 case TOK_SHR
: l1
= (U
)l1
>> l2
; break;
2132 case TOK_SAR
: l1
>>= l2
; break;
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;
2145 case TOK_LAND
: l1
= l1
&& l2
; break;
2146 case TOK_LOR
: l1
= l1
|| l2
; break;
2153 /* if commutative ops, put c2 as constant */
2154 if (c1
&& (op
== '+' || op
== '&' || op
== '^' ||
2155 op
== '|' || op
== '*')) {
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
||
2164 ((op
== '+' || op
== '-' || op
== '|' || op
== '^' ||
2165 op
== TOK_SHL
|| op
== TOK_SHR
|| op
== TOK_SAR
) &&
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) {
2182 else if (op
== TOK_PDIV
)
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 */
2199 if (!nocode_wanted
) {
2200 /* call low level op generator */
2201 if (t1
== VT_LLONG
|| t2
== VT_LLONG
)
2212 /* generate a floating point operation with constant propagation */
2213 void gen_opif(int op
)
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
;
2225 if (v1
->type
.t
== VT_FLOAT
) {
2228 } else if (v1
->type
.t
== VT_DOUBLE
) {
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
))
2242 case '+': f1
+= f2
; break;
2243 case '-': f1
-= f2
; break;
2244 case '*': f1
*= f2
; break;
2248 error("division by zero in constant");
2253 /* XXX: also handles tests ? */
2257 /* XXX: overflow test ? */
2258 if (v1
->type
.t
== VT_FLOAT
) {
2260 } else if (v1
->type
.t
== VT_DOUBLE
) {
2268 if (!nocode_wanted
) {
2276 static int pointed_size(CType
*type
)
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
)
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
;
2302 /* null pointers are accepted for all comparisons as gcc */
2303 if (is_null_pointer(p1
) || is_null_pointer(p2
))
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");
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
) {
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
)
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 */
2338 goto invalid_operands
;
2340 warning("comparison of distinct pointer types lacks a cast");
2344 /* generic gen_op: handles types problems */
2347 int u
, t1
, t2
, bt1
, bt2
, t
;
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
;
2364 t
= VT_INT
| VT_UNSIGNED
;
2368 /* if both pointers, then it must be the '-' op */
2369 if (bt1
== VT_PTR
&& bt2
== VT_PTR
) {
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
);
2376 /* set to integer type */
2377 #ifdef TCC_TARGET_X86_64
2378 vtop
->type
.t
= VT_LLONG
;
2380 vtop
->type
.t
= VT_INT
;
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
) {
2393 type1
= vtop
[-1].type
;
2394 #ifdef TCC_TARGET_X86_64
2395 vpushll(pointed_size(&vtop
[-1].type
));
2397 /* XXX: cast to int ? (long long case) */
2398 vpushi(pointed_size(&vtop
[-1].type
));
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
2412 gen_bounded_ptr_add();
2418 /* put again type if gen_opic() swaped operands */
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
) {
2425 } else if (bt1
== VT_DOUBLE
|| bt2
== VT_DOUBLE
) {
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");
2435 } else if (bt1
== VT_LLONG
|| bt2
== VT_LLONG
) {
2436 /* cast to biggest op */
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
))
2444 /* integer operations */
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
))
2451 /* XXX: currently, some unsigned operations are explicit, so
2452 we modify them here */
2453 if (t
& VT_UNSIGNED
) {
2460 else if (op
== TOK_LT
)
2462 else if (op
== TOK_GT
)
2464 else if (op
== TOK_LE
)
2466 else if (op
== TOK_GE
)
2473 /* special case for shifts and long long: we keep the shift as
2475 if (op
== TOK_SHR
|| op
== TOK_SAR
|| op
== TOK_SHL
)
2482 if (op
>= TOK_ULT
&& op
<= TOK_GT
) {
2483 /* relationnal op: the result is an int */
2484 vtop
->type
.t
= VT_INT
;
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
)) {
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
);
2505 vpush_global_sym(&func_old_type
, TOK___floatundidf
);
2509 vtop
->r
= reg_fret(t
);
2516 /* generic ftoi for unsigned long long case */
2517 void gen_cvt_ftoi1(int t
)
2521 if (t
== (VT_LLONG
| VT_UNSIGNED
)) {
2522 /* not handled natively */
2523 st
= vtop
->type
.t
& VT_BTYPE
;
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
);
2531 vpush_global_sym(&func_old_type
, TOK___fixunsdfdi
);
2536 vtop
->r2
= REG_LRET
;
2542 /* force char or short cast */
2543 void force_charshort_cast(int t
)
2547 /* XXX: add optimization if lvalue : just change type and offset */
2552 if (t
& VT_UNSIGNED
) {
2553 vpushi((1 << bits
) - 1);
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
;
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
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
) {
2586 dbt
= type
->t
& (VT_BTYPE
| VT_UNSIGNED
);
2587 sbt
= vtop
->type
.t
& (VT_BTYPE
| VT_UNSIGNED
);
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
);
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
;
2603 if ((sbt
& VT_BTYPE
) == VT_LLONG
) {
2604 if (sbt
& VT_UNSIGNED
)
2605 vtop
->c
.ld
= vtop
->c
.ull
;
2607 vtop
->c
.ld
= vtop
->c
.ll
;
2609 if (sbt
& VT_UNSIGNED
)
2610 vtop
->c
.ld
= vtop
->c
.ui
;
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);
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
) {
2639 if ((dbt
& VT_BTYPE
) == VT_BYTE
)
2641 else if ((dbt
& VT_BTYPE
) == VT_SHORT
)
2644 if(dbt
& VT_UNSIGNED
)
2645 vtop
->c
.ui
= ((unsigned int)vtop
->c
.ll
<< s
) >> s
;
2647 vtop
->c
.i
= ((int)vtop
->c
.ll
<< s
) >> s
;
2650 } else if (p
&& dbt
== VT_BOOL
) {
2653 } else if (!nocode_wanted
) {
2654 /* non constant case: generate code */
2656 /* convert from fp to fp */
2659 /* convert int to fp */
2662 /* convert fp to int */
2663 if (dbt
== VT_BOOL
) {
2667 /* we handle char/short/etc... with generic code */
2668 if (dbt
!= (VT_INT
| VT_UNSIGNED
) &&
2669 dbt
!= (VT_LLONG
| VT_UNSIGNED
) &&
2673 if (dbt
== VT_INT
&& (type
->t
& (VT_BTYPE
| VT_UNSIGNED
)) != dbt
) {
2674 /* additional cast for char/short... */
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 */
2685 /* generate high word */
2686 if (sbt
== (VT_INT
| VT_UNSIGNED
)) {
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
);
2699 /* patch second register */
2700 vtop
[-1].r2
= vtop
->r
;
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
) {
2709 if (sbt
!= (VT_INT
| VT_UNSIGNED
) &&
2710 sbt
!= VT_PTR
&& sbt
!= VT_FUNC
) {
2711 /* x86_64 specific: movslq */
2713 o(0xc0 + (REG_VALUE(r
) << 3) + REG_VALUE(r
));
2717 } else if (dbt
== VT_BOOL
) {
2718 /* scalar to bool */
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
) {
2730 if (sbt
== VT_LLONG
) {
2731 /* from long long: just take low order word */
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
);
2749 /* return type size. Put alignment at 'a' */
2750 static int type_size(CType
*type
, int *a
)
2755 bt
= type
->t
& VT_BTYPE
;
2756 if (bt
== VT_STRUCT
) {
2761 } else if (bt
== VT_PTR
) {
2762 if (type
->t
& VT_ARRAY
) {
2766 ts
= type_size(&s
->type
, a
);
2768 if (ts
< 0 && s
->c
< 0)
2776 } else if (bt
== VT_LDOUBLE
) {
2778 return LDOUBLE_SIZE
;
2779 } else if (bt
== VT_DOUBLE
|| bt
== VT_LLONG
) {
2780 #ifdef TCC_TARGET_I386
2781 #ifdef TCC_TARGET_PE
2786 #elif defined(TCC_TARGET_ARM)
2796 } else if (bt
== VT_INT
|| bt
== VT_ENUM
|| bt
== VT_FLOAT
) {
2799 } else if (bt
== VT_SHORT
) {
2803 /* char, void, function, _Bool */
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
)
2819 s
= sym_push(SYM_FIELD
, type
, 0, -1);
2820 type
->t
= VT_PTR
| (type
->t
& ~VT_TYPE
);
2824 /* compare function types. OLD functions match any new functions */
2825 static int is_compatible_func(CType
*type1
, CType
*type2
)
2831 if (!is_compatible_types(&s1
->type
, &s2
->type
))
2833 /* check func_call */
2834 if (FUNC_CALL(s1
->r
) != FUNC_CALL(s2
->r
))
2836 /* XXX: not complete */
2837 if (s1
->c
== FUNC_OLD
|| s2
->c
== FUNC_OLD
)
2841 while (s1
!= NULL
) {
2844 if (!is_compatible_parameter_types(&s1
->type
, &s2
->type
))
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
)
2863 t1
= type1
->t
& VT_TYPE
;
2864 t2
= type2
->t
& VT_TYPE
;
2866 /* strip qualifiers before comparing */
2867 t1
&= ~(VT_CONSTANT
| VT_VOLATILE
);
2868 t2
&= ~(VT_CONSTANT
| VT_VOLATILE
);
2870 /* XXX: bitfields ? */
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
);
2888 /* return true if type1 and type2 are exactly the same (including
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 */
2906 /* XXX: add array and function pointers */
2907 void type_to_str(char *buf
, int buf_size
,
2908 CType
*type
, const char *varstr
)
2915 t
= type
->t
& VT_TYPE
;
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 ");
2953 tstr
= "long double";
2955 pstrcat(buf
, buf_size
, tstr
);
2959 if (bt
== VT_STRUCT
)
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>");
2968 pstrcat(buf
, buf_size
, get_tok_str(v
, NULL
));
2972 type_to_str(buf
, buf_size
, &s
->type
, varstr
);
2973 pstrcat(buf
, buf_size
, "(");
2975 while (sa
!= NULL
) {
2976 type_to_str(buf1
, sizeof(buf1
), &sa
->type
, NULL
);
2977 pstrcat(buf
, buf_size
, buf1
);
2980 pstrcat(buf
, buf_size
, ", ");
2982 pstrcat(buf
, buf_size
, ")");
2986 pstrcpy(buf1
, sizeof(buf1
), "*");
2988 pstrcat(buf1
, sizeof(buf1
), varstr
);
2989 type_to_str(buf
, buf_size
, &s
->type
, buf1
);
2993 pstrcat(buf
, buf_size
, " ");
2994 pstrcat(buf
, buf_size
, varstr
);
2999 /* verify type compatibility to store vtop in 'dt' type, and generate
3001 static void gen_assign_cast(CType
*dt
)
3003 CType
*st
, *type1
, *type2
, tmp_type1
, tmp_type2
;
3004 char buf1
[256], buf2
[256];
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");
3014 /* special cases for pointers */
3015 /* '0' can also be a pointer */
3016 if (is_null_pointer(vtop
))
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");
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
))
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 */
3039 /* exact type match, except for unsigned */
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");
3056 if (sbt
== VT_PTR
|| sbt
== VT_FUNC
) {
3057 warning("assignment makes integer from pointer without a cast");
3059 /* XXX: more tests */
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
)) {
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
);
3078 /* store vtop in lvalue pushed on stack */
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");
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
);
3109 vpush_global_sym(&func_old_type
, TOK_memcpy8
);
3110 else if(!(align
& 3))
3111 vpush_global_sym(&func_old_type
, TOK_memcpy4
);
3114 vpush_global_sym(&func_old_type
, TOK_memcpy
);
3118 vtop
->type
.t
= VT_PTR
;
3122 vtop
->type
.t
= VT_PTR
;
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 */
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 */
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);
3161 vpushi((1 << bit_size
) - 1);
3167 /* load destination, mask and or with source */
3169 if((ft
& VT_BTYPE
) == VT_LLONG
) {
3170 vpushll(~(((1ULL << bit_size
) - 1ULL) << bit_pos
));
3172 vpushi(~(((1 << bit_size
) - 1) << bit_pos
));
3179 /* pop off shifted source from "duplicate source..." above */
3183 #ifdef CONFIG_TCC_BCHECK
3184 /* bound check case */
3185 if (vtop
[-1].r
& VT_MUSTBOUND
) {
3191 if (!nocode_wanted
) {
3195 #ifdef TCC_TARGET_X86_64
3196 if ((ft
& VT_BTYPE
) == VT_LDOUBLE
) {
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
) {
3205 t
= get_reg(RC_INT
);
3206 #ifdef TCC_TARGET_X86_64
3211 sv
.r
= VT_LOCAL
| VT_LVAL
;
3212 sv
.c
.ul
= vtop
[-1].c
.ul
;
3214 vtop
[-1].r
= t
| VT_LVAL
;
3217 #ifndef TCC_TARGET_X86_64
3218 /* two word case handling : store second register at word + 4 */
3219 if ((ft
& VT_BTYPE
) == VT_LLONG
) {
3221 /* convert to int to increment easily */
3222 vtop
->type
.t
= VT_INT
;
3228 /* XXX: it works because r2 is spilled last ! */
3229 store(vtop
->r2
, vtop
- 1);
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
)
3243 vdup(); /* save lvalue */
3245 gv_dup(); /* duplicate value */
3250 vpushi(c
- TOK_MID
);
3252 vstore(); /* store value */
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
)
3269 while (tok
== TOK_ATTRIBUTE1
|| tok
== TOK_ATTRIBUTE2
) {
3273 while (tok
!= ')') {
3274 if (tok
< TOK_IDENT
)
3275 expect("attribute name");
3283 expect("section name");
3284 ad
->section
= find_section(tcc_state
, (char *)tokc
.cstr
->data
);
3293 if (n
<= 0 || (n
& (n
- 1)) != 0)
3294 error("alignment must be a positive power of two");
3307 /* currently, no need to handle it because tcc does not
3308 track unused objects */
3312 /* currently, no need to handle it because tcc does not
3313 track unused objects */
3318 FUNC_CALL(ad
->func_attr
) = FUNC_CDECL
;
3323 FUNC_CALL(ad
->func_attr
) = FUNC_STDCALL
;
3325 #ifdef TCC_TARGET_I386
3335 FUNC_CALL(ad
->func_attr
) = FUNC_FASTCALL1
+ n
- 1;
3341 FUNC_CALL(ad
->func_attr
) = FUNC_FASTCALLW
;
3345 FUNC_EXPORT(ad
->func_attr
) = 1;
3348 if (tcc_state
->warn_unsupported
)
3349 warning("'%s' attribute ignored", get_tok_str(t
, NULL
));
3350 /* skip parameters */
3352 int parenthesis
= 0;
3356 else if (tok
== ')')
3359 } while (parenthesis
&& tok
!= -1);
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
;
3381 a
= tok
; /* save decl type */
3386 /* struct already defined ? return it */
3388 expect("struct/union/enum name");
3392 error("invalid type");
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 */
3410 error("struct/union/enum already defined");
3411 /* cannot be empty */
3413 /* non empty enums are not allowed */
3414 if (a
== TOK_ENUM
) {
3418 expect("identifier");
3424 /* enum symbols have static storage */
3425 ss
= sym_push(v
, &int_type
, VT_CONST
, c
);
3426 ss
->type
.t
|= VT_STATIC
;
3431 /* NOTE: we accept a trailing comma */
3442 while (tok
!= '}') {
3443 parse_btype(&btype
, &ad
);
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
));
3459 bit_size
= expr_const();
3460 /* XXX: handle v = 0 case for messages */
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
);
3470 if (align
< ad
.aligned
)
3472 } else if (ad
.packed
) {
3474 } else if (*tcc_state
->pack_stack_ptr
) {
3475 if (align
> *tcc_state
->pack_stack_ptr
)
3476 align
= *tcc_state
->pack_stack_ptr
;
3479 if (bit_size
>= 0) {
3480 bt
= type1
.t
& VT_BTYPE
;
3487 error("bitfields must have scalar type");
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 */
3495 } else if (bit_size
== 0) {
3496 /* XXX: what to do if only padding in a
3498 /* zero size: means to pad */
3501 /* we do not have enough room ?
3502 did the type change?
3504 if ((bit_pos
+ bit_size
) > bsize
||
3505 bt
!= prevbt
|| a
== TOK_UNION
)
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
;
3518 if (v
!= 0 || (type1
.t
& VT_BTYPE
) == VT_STRUCT
) {
3519 /* add new memory data only if starting
3521 if (lbit_pos
== 0) {
3522 if (a
== TOK_STRUCT
) {
3523 c
= (c
+ align
- 1) & -align
;
3532 if (align
> maxalign
)
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);
3546 if (v
== 0 && (type1
.t
& VT_BTYPE
) == VT_STRUCT
) {
3548 while ((ass
= ass
->next
) != NULL
) {
3549 ss
= sym_push(ass
->v
, &ass
->type
, 0, offset
+ ass
->c
);
3554 ss
= sym_push(v
| SYM_FIELD
, &type1
, 0, offset
);
3558 if (tok
== ';' || tok
== TOK_EOF
)
3565 /* store size and alignment */
3566 s
->c
= (c
+ maxalign
- 1) & -maxalign
;
3572 /* return 0 if no type declaration. otherwise, return the basic type
3575 static int parse_btype(CType
*type
, AttributeDef
*ad
)
3577 int t
, u
, type_found
, typespec_found
, typedef_found
;
3581 memset(ad
, 0, sizeof(AttributeDef
));
3589 /* currently, we really ignore extension */
3599 if ((t
& VT_BTYPE
) != 0)
3600 error("too many basic types");
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
;
3633 if ((t
& VT_BTYPE
) == VT_LONG
) {
3634 t
= (t
& ~VT_BTYPE
) | VT_LDOUBLE
;
3641 struct_decl(&type1
, VT_ENUM
);
3644 type
->ref
= type1
.ref
;
3648 struct_decl(&type1
, VT_STRUCT
);
3651 /* type modifiers */
3704 /* GNUC attribute */
3705 case TOK_ATTRIBUTE1
:
3706 case TOK_ATTRIBUTE2
:
3707 parse_attribute(ad
);
3714 parse_expr_type(&type1
);
3717 if (typespec_found
|| typedef_found
)
3720 if (!s
|| !(s
->type
.t
& VT_TYPEDEF
))
3723 t
|= (s
->type
.t
& ~VT_TYPEDEF
);
3724 type
->ref
= s
->type
.ref
;
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
)
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
;
3745 t
= (t
& ~VT_BTYPE
) | VT_LLONG
;
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 */
3760 if ((pt
->t
& VT_BTYPE
) == VT_FUNC
) {
3765 static void post_type(CType
*type
, AttributeDef
*ad
)
3767 int n
, l
, t1
, arg_size
, align
;
3768 Sym
**plast
, *s
, *first
;
3773 /* function declaration */
3781 /* read param name and compute offset */
3782 if (l
!= FUNC_OLD
) {
3783 if (!parse_btype(&pt
, &ad1
)) {
3785 error("invalid type");
3792 if ((pt
.t
& VT_BTYPE
) == VT_VOID
&& tok
== ')')
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;
3802 expect("identifier");
3806 convert_parameter_type(&pt
);
3807 s
= sym_push(n
| SYM_FIELD
, &pt
, 0, 0);
3813 if (l
== FUNC_NEW
&& tok
== TOK_DOTS
) {
3820 /* if no parameters, then old type prototype */
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
);
3833 type
->t
= t1
| VT_FUNC
;
3835 } else if (tok
== '[') {
3836 /* array definition */
3838 if (tok
== TOK_RESTRICT1
)
3844 error("invalid array size");
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
3854 s
= sym_push(SYM_FIELD
, type
, 0, n
);
3855 type
->t
= t1
| VT_ARRAY
| VT_PTR
;
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
3866 static void type_decl(CType
*type
, AttributeDef
*ad
, int *v
, int td
)
3869 CType type1
, *type2
;
3872 while (tok
== '*') {
3880 qualifiers
|= VT_CONSTANT
;
3885 qualifiers
|= VT_VOLATILE
;
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 */
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
);
3912 /* type identifier */
3913 if (tok
>= TOK_IDENT
&& (td
& TYPE_DIRECT
)) {
3917 if (!(td
& TYPE_ABSTRACT
))
3918 expect("identifier");
3922 post_type(type
, ad
);
3923 if (tok
== TOK_ATTRIBUTE1
|| tok
== TOK_ATTRIBUTE2
)
3924 parse_attribute(ad
);
3927 /* append type at the end of type1 */
3940 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
3941 static int lvalue_type(int t
)
3946 if (bt
== VT_BYTE
|| bt
== VT_BOOL
)
3948 else if (bt
== VT_SHORT
)
3952 if (t
& VT_UNSIGNED
)
3953 r
|= VT_LVAL_UNSIGNED
;
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
)
3965 if ((vtop
->r
& VT_LVAL
) && !nocode_wanted
)
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
)
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
) {
3992 } else if (arg
== NULL
) {
3993 error("too many arguments to function");
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
4003 static void parse_expr_type(CType
*type
)
4009 if (parse_btype(type
, &ad
)) {
4010 type_decl(type
, &ad
, &n
, TYPE_ABSTRACT
);
4017 static void parse_type(CType
*type
)
4022 if (!parse_btype(type
, &ad
)) {
4025 type_decl(type
, &ad
, &n
, TYPE_ABSTRACT
);
4028 static void vpush_tokc(int t
)
4032 vsetc(&type
, VT_CONST
, &tokc
);
4035 static void unary(void)
4037 int n
, t
, align
, size
, r
;
4042 /* XXX: GCC 2.95.3 does not generate a table although it should be
4056 vpush_tokc(VT_INT
| VT_UNSIGNED
);
4060 vpush_tokc(VT_LLONG
);
4064 vpush_tokc(VT_LLONG
| VT_UNSIGNED
);
4068 vpush_tokc(VT_FLOAT
);
4072 vpush_tokc(VT_DOUBLE
);
4076 vpush_tokc(VT_LDOUBLE
);
4079 case TOK___FUNCTION__
:
4081 goto tok_identifier
;
4087 /* special function name identifier */
4088 len
= strlen(funcname
) + 1;
4089 /* generate char[len] type */
4094 vpush_ref(&type
, data_section
, data_section
->data_offset
, len
);
4095 ptr
= section_ptr_add(data_section
, len
);
4096 memcpy(ptr
, funcname
, len
);
4101 #ifdef TCC_TARGET_PE
4102 t
= VT_SHORT
| VT_UNSIGNED
;
4108 /* string parsing */
4111 if (tcc_state
->warn_write_strings
)
4116 memset(&ad
, 0, sizeof(AttributeDef
));
4117 decl_initializer_alloc(&type
, &ad
, VT_CONST
, 2, 0, 0);
4122 if (parse_btype(&type
, &ad
)) {
4123 type_decl(&type
, &ad
, &n
, TYPE_ABSTRACT
);
4125 /* check ISOC99 compound literal */
4127 /* data is allocated locally by default */
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);
4141 } else if (tok
== '{') {
4142 /* save all registers */
4144 /* statement expression : we do not accept break/continue
4145 inside as GCC does */
4146 block(NULL
, NULL
, NULL
, NULL
, 0, 1);
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
))
4169 mk_pointer(&vtop
->type
);
4175 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
) {
4177 boolean
.t
= VT_BOOL
;
4179 vtop
->c
.i
= !vtop
->c
.i
;
4180 } else if ((vtop
->r
& VT_VALMASK
) == VT_CMP
)
4181 vtop
->c
.i
= vtop
->c
.i
^ 1;
4184 vseti(VT_JMP
, gtst(1, 0));
4195 /* in order to force cast, we add zero */
4197 if ((vtop
->type
.t
& VT_BTYPE
) == VT_PTR
)
4198 error("pointer not accepted for unary plus");
4208 parse_expr_type(&type
);
4212 size
= type_size(&type
, &align
);
4213 if (t
== TOK_SIZEOF
) {
4215 error("sizeof applied to an incomplete type");
4220 vtop
->type
.t
|= VT_UNSIGNED
;
4223 case TOK_builtin_types_compatible_p
:
4232 type1
.t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
4233 type2
.t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
4234 vpushi(is_compatible_types(&type1
, &type2
));
4237 case TOK_builtin_constant_p
:
4239 int saved_nocode_wanted
, res
;
4242 saved_nocode_wanted
= nocode_wanted
;
4245 res
= (vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
4247 nocode_wanted
= saved_nocode_wanted
;
4252 case TOK_builtin_frame_address
:
4257 if (tok
!= TOK_CINT
) {
4258 error("__builtin_frame_address only takes integers");
4261 error("TCC only supports __builtin_frame_address(0)");
4267 vset(&type
, VT_LOCAL
, 0);
4270 #ifdef TCC_TARGET_X86_64
4271 case TOK_builtin_malloc
:
4273 goto tok_identifier
;
4274 case TOK_builtin_free
:
4276 goto tok_identifier
;
4293 goto tok_identifier
;
4295 /* allow to take the address of a label */
4296 if (tok
< TOK_UIDENT
)
4297 expect("label identifier");
4298 s
= label_find(tok
);
4300 s
= label_push(&global_label_stack
, tok
, LABEL_FORWARD
);
4302 if (s
->r
== LABEL_DECLARED
)
4303 s
->r
= LABEL_FORWARD
;
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);
4319 expect("identifier");
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. */
4339 put_extern_sym(s
, text_section
, 0, 0);
4340 r
= VT_SYM
| VT_CONST
;
4344 vset(&s
->type
, r
, s
->c
);
4345 /* if forward reference, we must point to s */
4346 if (vtop
->r
& VT_SYM
) {
4353 /* post operations */
4355 if (tok
== TOK_INC
|| tok
== TOK_DEC
) {
4358 } else if (tok
== '.' || tok
== TOK_ARROW
) {
4360 if (tok
== TOK_ARROW
)
4365 /* expect pointer on structure */
4366 if ((vtop
->type
.t
& VT_BTYPE
) != VT_STRUCT
)
4367 expect("struct or union");
4371 while ((s
= s
->next
) != NULL
) {
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 *' */
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
;
4391 } else if (tok
== '[') {
4397 } else if (tok
== '(') {
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
)
4411 expect("function pointer");
4414 vtop
->r
&= ~VT_LVAL
; /* no lvalue */
4416 /* get return type */
4419 sa
= s
->next
; /* first parameter */
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
;
4428 ret
.r
= VT_LOCAL
| VT_LVAL
;
4429 /* pass it as 'int' to avoid structure arg passing
4431 vseti(VT_LOCAL
, loc
);
4436 /* return in register */
4437 if (is_float(ret
.type
.t
)) {
4438 ret
.r
= reg_fret(ret
.type
.t
);
4440 if ((ret
.type
.t
& VT_BTYPE
) == VT_LLONG
)
4449 gfunc_param_typed(s
, sa
);
4459 error("too few arguments to function");
4461 if (!nocode_wanted
) {
4462 gfunc_call(nb_args
);
4464 vtop
-= (nb_args
+ 1);
4467 vsetc(&ret
.type
, ret
.r
, &ret
.c
);
4475 static void uneq(void)
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
) {
4498 static void expr_prod(void)
4503 while (tok
== '*' || tok
== '/' || tok
== '%') {
4511 static void expr_sum(void)
4516 while (tok
== '+' || tok
== '-') {
4524 static void expr_shift(void)
4529 while (tok
== TOK_SHL
|| tok
== TOK_SAR
) {
4537 static void expr_cmp(void)
4542 while ((tok
>= TOK_ULE
&& tok
<= TOK_GT
) ||
4543 tok
== TOK_ULT
|| tok
== TOK_UGE
) {
4551 static void expr_cmpeq(void)
4556 while (tok
== TOK_EQ
|| tok
== TOK_NE
) {
4564 static void expr_and(void)
4567 while (tok
== '&') {
4574 static void expr_xor(void)
4577 while (tok
== '^') {
4584 static void expr_or(void)
4587 while (tok
== '|') {
4594 /* XXX: fix this mess */
4595 static void expr_land_const(void)
4598 while (tok
== TOK_LAND
) {
4605 /* XXX: fix this mess */
4606 static void expr_lor_const(void)
4609 while (tok
== TOK_LOR
) {
4616 /* only used if non constant */
4617 static void expr_land(void)
4622 if (tok
== TOK_LAND
) {
4627 if (tok
!= TOK_LAND
) {
4637 static void expr_lor(void)
4642 if (tok
== TOK_LOR
) {
4647 if (tok
!= TOK_LOR
) {
4657 /* XXX: better constant handling */
4658 static void expr_eq(void)
4660 int tt
, u
, r1
, r2
, rc
, t1
, t2
, bt1
, bt2
;
4662 CType type
, type1
, type2
;
4669 boolean
.t
= VT_BOOL
;
4675 if (tok
!= ':' || !gnu_ext
) {
4690 if (vtop
!= vstack
) {
4691 /* needed to avoid having different registers saved in
4693 if (is_float(vtop
->type
.t
)) {
4695 #ifdef TCC_TARGET_X86_64
4696 if ((vtop
->type
.t
& VT_BTYPE
) == VT_LDOUBLE
) {
4706 if (tok
== ':' && gnu_ext
) {
4714 sv
= *vtop
; /* save value to handle it later */
4715 vtop
--; /* no vpop so that FP stack is not flushed */
4723 bt1
= t1
& VT_BTYPE
;
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
) {
4735 } else if (bt1
== VT_LLONG
|| bt2
== VT_LLONG
) {
4736 /* cast to biggest op */
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 */
4745 } else if (bt1
== VT_FUNC
|| bt2
== VT_FUNC
) {
4746 /* XXX: test function pointer compatibility */
4748 } else if (bt1
== VT_STRUCT
|| bt2
== VT_STRUCT
) {
4749 /* XXX: test structure compatibility */
4751 } else if (bt1
== VT_VOID
|| bt2
== VT_VOID
) {
4752 /* NOTE: as an extension, we accept void on only one side */
4755 /* integer operations */
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 */
4765 if (VT_STRUCT
== (vtop
->type
.t
& VT_BTYPE
))
4768 if (is_float(type
.t
)) {
4770 #ifdef TCC_TARGET_X86_64
4771 if ((type
.t
& VT_BTYPE
) == VT_LDOUBLE
) {
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 */
4782 /* this is horrible, but we must also convert first
4786 /* put again first value and cast it */
4789 if (VT_STRUCT
== (vtop
->type
.t
& VT_BTYPE
))
4799 static void gexpr(void)
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
;
4820 nocode_wanted
= saved_nocode_wanted
;
4823 /* parse a unary expression and return its type without any side
4825 static void unary_type(CType
*type
)
4837 /* parse a constant expression and return value in vtop. */
4838 static void expr_const1(void)
4847 /* parse an integer constant and return its value. */
4848 static int expr_const(void)
4852 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) != VT_CONST
)
4853 expect("constant expression");
4859 /* return the label token if current token is a label, otherwise
4861 static int is_label(void)
4865 /* fast test first */
4866 if (tok
< TOK_UIDENT
)
4868 /* no need to save tokc because tok is an identifier */
4875 unget_tok(last_tok
);
4880 static void block(int *bsym
, int *csym
, int *case_sym
, int *def_sym
,
4881 int case_reg
, int is_expr
)
4886 /* generate line number info */
4888 (last_line_num
!= file
->line_num
|| last_ind
!= ind
)) {
4889 put_stabn(N_SLINE
, 0, file
->line_num
, ind
- func_ind
);
4891 last_line_num
= file
->line_num
;
4895 /* default return value is (void) */
4897 vtop
->type
.t
= VT_VOID
;
4900 if (tok
== TOK_IF
) {
4907 block(bsym
, csym
, case_sym
, def_sym
, case_reg
, 0);
4909 if (c
== TOK_ELSE
) {
4913 block(bsym
, csym
, case_sym
, def_sym
, case_reg
, 0);
4914 gsym(d
); /* patch else jmp */
4917 } else if (tok
== TOK_WHILE
) {
4925 block(&a
, &b
, case_sym
, def_sym
, case_reg
, 0);
4929 } else if (tok
== '{') {
4933 /* record local declaration stack position */
4935 llabel
= local_label_stack
;
4936 /* handle local labels declarations */
4937 if (tok
== TOK_LABEL
) {
4940 if (tok
< TOK_UIDENT
)
4941 expect("label identifier");
4942 label_push(&local_label_stack
, tok
, LABEL_DECLARED
);
4952 while (tok
!= '}') {
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 */
4964 /* XXX: this solution makes only valgrind happy...
4965 triggered by gcc.c-torture/execute/20000917-1.c */
4967 switch(vtop
->type
.t
& VT_BTYPE
) {
4972 for(p
=vtop
->type
.ref
;p
;p
=p
->prev
)
4974 error("unsupported expression type");
4977 sym_pop(&local_stack
, s
);
4979 } else if (tok
== TOK_RETURN
) {
4983 gen_assign_cast(&func_vt
);
4984 if ((func_vt
.t
& VT_BTYPE
) == VT_STRUCT
) {
4986 /* if returning structure, must copy it to implicit
4987 first pointer arg location */
4990 size
= type_size(&func_vt
,&align
);
4993 if((vtop
->r
!= (VT_LOCAL
| VT_LVAL
) || (vtop
->c
.i
& 3))
4997 loc
= (loc
- size
) & -4;
5000 vset(&type
, VT_LOCAL
| VT_LVAL
, addr
);
5003 vset(&int_type
, VT_LOCAL
| VT_LVAL
, addr
);
5005 vtop
->type
= int_type
;
5011 vset(&type
, VT_LOCAL
| VT_LVAL
, func_vc
);
5014 /* copy structure value to pointer */
5019 } else if (is_float(func_vt
.t
)) {
5020 gv(rc_fret(func_vt
.t
));
5024 vtop
--; /* NOT vpop() because on x86 it would flush the fp stack */
5027 rsym
= gjmp(rsym
); /* jmp */
5028 } else if (tok
== TOK_BREAK
) {
5031 error("cannot break");
5032 *bsym
= gjmp(*bsym
);
5035 } else if (tok
== TOK_CONTINUE
) {
5038 error("cannot continue");
5039 *csym
= gjmp(*csym
);
5042 } else if (tok
== TOK_FOR
) {
5069 block(&a
, &b
, case_sym
, def_sym
, case_reg
, 0);
5074 if (tok
== TOK_DO
) {
5079 block(&a
, &b
, case_sym
, def_sym
, case_reg
, 0);
5090 if (tok
== TOK_SWITCH
) {
5094 /* XXX: other types than integer */
5095 case_reg
= gv(RC_INT
);
5099 b
= gjmp(0); /* jump to first case */
5101 block(&a
, csym
, &b
, &c
, case_reg
, 0);
5102 /* if no default, jmp after switch */
5110 if (tok
== TOK_CASE
) {
5117 if (gnu_ext
&& tok
== TOK_DOTS
) {
5121 warning("empty case range");
5123 /* since a case is like a label, we must skip it with a jmp */
5130 *case_sym
= gtst(1, 0);
5133 *case_sym
= gtst(1, 0);
5137 *case_sym
= gtst(1, *case_sym
);
5142 goto block_after_label
;
5144 if (tok
== TOK_DEFAULT
) {
5150 error("too many 'default'");
5153 goto block_after_label
;
5155 if (tok
== TOK_GOTO
) {
5157 if (tok
== '*' && gnu_ext
) {
5161 if ((vtop
->type
.t
& VT_BTYPE
) != VT_PTR
)
5164 } else if (tok
>= TOK_UIDENT
) {
5165 s
= label_find(tok
);
5166 /* put forward definition if needed */
5168 s
= label_push(&global_label_stack
, tok
, LABEL_FORWARD
);
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
);
5177 gjmp_addr((long)s
->next
);
5180 expect("label identifier");
5183 } else if (tok
== TOK_ASM1
|| tok
== TOK_ASM2
|| tok
== TOK_ASM3
) {
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
;
5196 s
= label_push(&global_label_stack
, b
, LABEL_DEFINED
);
5198 s
->next
= (void *)ind
;
5199 /* we accept this, but it is a mistake */
5202 warning("deprecated use of label at end of compound statement");
5206 block(bsym
, csym
, case_sym
, def_sym
, case_reg
, is_expr
);
5209 /* expression case */
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
5228 static void decl_designator(CType
*type
, Section
*sec
, unsigned long c
,
5229 int *cur_index
, Sym
**cur_field
,
5233 int notfirst
, index
, index_last
, align
, l
, nb_elems
, elem_size
;
5239 if (gnu_ext
&& (l
= is_label()) != 0)
5241 while (tok
== '[' || tok
== '.') {
5243 if (!(type
->t
& VT_ARRAY
))
5244 expect("array type");
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
) {
5252 index_last
= expr_const();
5253 if (index_last
< 0 ||
5254 (s
->c
>= 0 && index_last
>= s
->c
) ||
5256 expect("invalid index");
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) {
5277 if ((type
->t
& VT_BTYPE
) != VT_STRUCT
)
5278 expect("struct/union type");
5291 /* XXX: fix this mess by using explicit storage field */
5293 type1
.t
|= (type
->t
& ~VT_TYPE
);
5307 if (type
->t
& VT_ARRAY
) {
5309 type
= pointed_type(type
);
5310 c
+= index
* type_size(type
, &align
);
5314 error("too many field init");
5315 /* XXX: fix this mess by using explicit storage field */
5317 type1
.t
|= (type
->t
& ~VT_TYPE
);
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
;
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
;
5337 for(i
= 1; i
< nb_elems
; i
++) {
5339 memcpy(dst
, src
, elem_size
);
5345 #define EXPR_CONST 1
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
;
5354 unsigned long long bit_mask
;
5362 /* compound literals must be allocated globally in this case */
5363 saved_global_expr
= global_expr
;
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");
5377 dtype
.t
&= ~VT_CONSTANT
; /* need to do that to avoid false warning */
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
)) {
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
) &&
5405 (bt
== VT_INT
&& bit_size
!= 32)))
5406 error("initializer element is not computable at load time");
5409 vtop
->c
.i
= (vtop
->c
.i
!= 0);
5411 *(char *)ptr
|= (vtop
->c
.i
& bit_mask
) << bit_pos
;
5414 *(short *)ptr
|= (vtop
->c
.i
& bit_mask
) << bit_pos
;
5417 *(double *)ptr
= vtop
->c
.d
;
5420 *(long double *)ptr
= vtop
->c
.ld
;
5423 *(long long *)ptr
|= (vtop
->c
.ll
& bit_mask
) << bit_pos
;
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
;
5434 vset(&dtype
, VT_LOCAL
|VT_LVAL
, c
);
5441 /* put zeros for variable based init */
5442 static void init_putz(CType
*t
, Section
*sec
, unsigned long c
, int size
)
5445 /* nothing to do because globals are already set to zero */
5447 vpush_global_sym(&func_old_type
, TOK_memset
);
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
;
5468 if (type
->t
& VT_ARRAY
) {
5472 t1
= pointed_type(type
);
5473 size1
= type_size(t1
, &align1
);
5476 if ((first
&& tok
!= TOK_LSTR
&& tok
!= TOK_STR
) ||
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
)
5488 (t1
->t
& VT_BTYPE
) == VT_INT
5490 ) || (tok
== TOK_STR
&& (t1
->t
& VT_BTYPE
) == VT_BYTE
)) {
5491 while (tok
== TOK_STR
|| tok
== TOK_LSTR
) {
5496 /* compute maximum number of chars wanted */
5498 cstr_len
= cstr
->size
;
5500 cstr_len
= cstr
->size
/ sizeof(nwchar_t
);
5503 if (n
>= 0 && nb
> (n
- array_length
))
5504 nb
= n
- array_length
;
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
5511 if (sec
&& tok
== TOK_STR
&& size1
== 1) {
5512 memcpy(sec
->data
+ c
+ array_length
, cstr
->data
, nb
);
5516 ch
= ((unsigned char *)cstr
->data
)[i
];
5518 ch
= ((nwchar_t
*)cstr
->data
)[i
];
5519 init_putv(t1
, sec
, c
+ (array_length
+ i
) * size1
,
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
) {
5531 init_putv(t1
, sec
, c
+ (array_length
* size1
), 0, EXPR_VAL
);
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
);
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
5553 if (index
>= n
&& no_oblock
)
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 */
5569 s
->c
= array_length
;
5570 } else if ((type
->t
& VT_BTYPE
) == VT_STRUCT
&&
5571 (sec
|| !first
|| tok
== '{')) {
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) */
5587 while (tok
== '(') {
5591 if (!parse_btype(&type1
, &ad1
))
5593 type_decl(&type1
, &ad1
, &n
, TYPE_ABSTRACT
);
5595 if (!is_assignable_types(type
, &type1
))
5596 error("invalid type for cast");
5601 if (first
|| tok
== '{') {
5610 while (tok
!= '}') {
5611 decl_designator(type
, sec
, c
, NULL
, &f
, size_only
);
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
;
5621 if (no_oblock
&& f
== NULL
)
5627 /* put zeros at the end */
5628 if (!size_only
&& array_length
< n
) {
5629 init_putz(type
, sec
, c
+ array_length
,
5638 } else if (tok
== '{') {
5640 decl_initializer(type
, sec
, c
, first
, size_only
);
5642 } else if (size_only
) {
5643 /* just skip expression */
5645 while ((parlevel
> 0 || (tok
!= '}' && tok
!= ',')) &&
5649 else if (tok
== ')')
5654 /* currently, we always use constant expression for globals
5655 (may change for scripting case) */
5656 expr_type
= EXPR_CONST
;
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
;
5675 ParseState saved_parse_state
= {0};
5676 TokenString init_str
;
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
);
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
);
5699 while (level
> 0 || (tok
!= ',' && tok
!= ';')) {
5701 error("unexpected end of file in initializer");
5702 tok_str_add_tok(&init_str
);
5705 else if (tok
== '}') {
5715 tok_str_add(&init_str
, -1);
5716 tok_str_add(&init_str
, 0);
5719 save_parse_state(&saved_parse_state
);
5721 macro_ptr
= init_str
.str
;
5723 decl_initializer(type
, NULL
, 0, 1, 1);
5724 /* prepare second initializer parsing */
5725 macro_ptr
= init_str
.str
;
5728 /* if still unknown size, error */
5729 size
= type_size(type
, &align
);
5731 error("unknown type size");
5733 /* take into account specified alignment if bigger */
5735 if (ad
->aligned
> align
)
5736 align
= ad
->aligned
;
5737 } else if (ad
->packed
) {
5740 if ((r
& VT_VALMASK
) == VT_LOCAL
) {
5742 if (do_bounds_check
&& (type
->t
& VT_ARRAY
))
5744 loc
= (loc
- size
) & -align
;
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 */
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
;
5759 /* local variable */
5760 sym_push(v
, type
, r
, addr
);
5762 /* push local reference */
5763 vset(type
, r
, addr
);
5769 if (v
&& scope
== VT_CONST
) {
5770 /* see if the symbol was already defined */
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
5781 if ((sym
->type
.t
& VT_ARRAY
) &&
5782 sym
->type
.ref
->c
< 0 &&
5784 sym
->type
.ref
->c
= type
->ref
->c
;
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
5792 /* no init data, we won't add more to the symbol */
5799 /* allocate symbol in corresponding section */
5804 else if (tcc_state
->nocommon
)
5808 data_offset
= sec
->data_offset
;
5809 data_offset
= (data_offset
+ align
- 1) & -align
;
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
)
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
;
5826 addr
= 0; /* avoid warning */
5830 if (scope
!= VT_CONST
|| !sym
) {
5831 sym
= sym_push(v
, type
, r
| VT_SYM
, 0);
5833 /* update symbol definition */
5835 put_extern_sym(sym
, sec
, addr
, size
);
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
;
5847 /* push global reference */
5848 sym
= get_sym_ref(type
, sec
, addr
, size
);
5850 vsetc(type
, VT_CONST
| VT_SYM
, &cval
);
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
;
5867 decl_initializer(type
, sec
, addr
, 1, 0);
5868 /* restore parse state if needed */
5870 tok_str_free(init_str
.str
);
5871 restore_parse_state(&saved_parse_state
);
5877 void put_func_debug(Sym
*sym
)
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);
5893 /* parse an old style function declaration list */
5894 /* XXX: check multiple parameter */
5895 static void func_decl_list(Sym
*func_sym
)
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
) &&
5909 /* we accept no variable after */
5913 type_decl(&type
, &ad
, &v
, TYPE_DIRECT
);
5914 /* find parameter in function parameter list */
5917 if ((s
->v
& ~SYM_FIELD
) == v
)
5921 error("declaration for parameter '%s' but no such parameter",
5922 get_tok_str(v
, NULL
));
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) */
5930 /* accept other parameters */
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
;
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
);
5952 /* put debug symbol */
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
);
5959 block(NULL
, NULL
, NULL
, NULL
, 0, 0);
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
=
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)
5984 int *str
, inline_generated
;
5986 /* iterate while inline function are referenced */
5988 inline_generated
= 0;
5989 for(sym
= global_stack
; sym
!= NULL
; sym
= sym
->prev
) {
5991 if (((type
->t
& VT_BTYPE
) == VT_FUNC
) &&
5992 (type
->t
& (VT_STATIC
| VT_INLINE
)) ==
5993 (VT_STATIC
| VT_INLINE
) &&
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
;
6003 cur_text_section
= text_section
;
6005 macro_ptr
= NULL
; /* fail safe */
6008 inline_generated
= 1;
6011 if (!inline_generated
)
6015 /* free all remaining inline function tokens */
6016 for(sym
= global_stack
; sym
!= NULL
; sym
= sym
->prev
) {
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!
6024 str
= INLINE_DEF(sym
->r
);
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
)
6040 if (!parse_btype(&btype
, &ad
)) {
6041 /* skip redundant ';' */
6042 /* XXX: find more elegant solution */
6047 if (l
== VT_CONST
&&
6048 (tok
== TOK_ASM1
|| tok
== TOK_ASM2
|| tok
== TOK_ASM3
)) {
6049 /* global asm block */
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
)
6059 if (((btype
.t
& VT_BTYPE
) == VT_ENUM
||
6060 (btype
.t
& VT_BTYPE
) == VT_STRUCT
) &&
6062 /* we accept no variable after */
6066 while (1) { /* iterate thru each declaration */
6068 type_decl(&type
, &ad
, &v
, TYPE_DIRECT
);
6072 type_to_str(buf
, sizeof(buf
), t
, get_tok_str(v
, NULL
));
6073 printf("type = '%s'\n", buf
);
6076 if ((type
.t
& VT_BTYPE
) == VT_FUNC
) {
6077 /* if old style function prototype, we accept a
6080 if (sym
->c
== FUNC_OLD
)
6081 func_decl_list(sym
);
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 */
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
;
6102 if ((sym
->type
.t
& VT_BTYPE
) != VT_FUNC
)
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
);
6112 FUNC_EXPORT(type
.ref
->r
) = 1;
6114 if (!is_compatible_types(&sym
->type
, &type
)) {
6116 error("incompatible types for redefinition of '%s'",
6117 get_tok_str(v
, NULL
));
6119 /* if symbol is already defined, then put complete type */
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
;
6135 tok_str_new(&func_str
);
6141 error("unexpected end of file");
6142 tok_str_add_tok(&func_str
);
6147 } else if (t
== '}') {
6149 if (block_level
== 0)
6153 tok_str_add(&func_str
, -1);
6154 tok_str_add(&func_str
, 0);
6155 INLINE_DEF(sym
->r
) = func_str
.str
;
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
;
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 */
6175 type
.ref
->r
= ad
.func_attr
;
6176 external_sym(v
, &type
, 0);
6178 /* not lvalue if array */
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
6190 external_sym(v
, &type
, r
);
6192 type
.t
|= (btype
.t
& VT_STATIC
); /* Retain "static". */
6193 if (type
.t
& VT_STATIC
)
6199 decl_initializer_alloc(&type
, &ad
, r
,
6213 /* better than nothing, but needs extension to handle '-E' option
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 */
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
)
6234 volatile int section_sym
;
6237 printf("%s: **** new file\n", file
->filename
);
6239 preprocess_init(s1
);
6241 cur_text_section
= NULL
;
6243 anon_sym
= SYM_FIRST_ANOM
;
6245 /* file info: full path + filename */
6246 section_sym
= 0; /* avoid warning */
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
));
6253 normalize_slashes(buf
);
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
);
6287 /* define 'void *alloca(unsigned int)' builtin function */
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);
6296 sym_push(TOK_alloca
, VT_FUNC
| (p
<< VT_STRUCT_SHIFT
), VT_CONST
, 0);
6300 define_start
= define_stack
;
6303 if (setjmp(s1
->error_jmp_buf
) == 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
;
6313 expect("declaration");
6315 /* end of translation unit info */
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
)
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
;
6354 if (tok
== TOK_EOF
) {
6356 } else if (tok
== TOK_LINEFEED
) {
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
);
6367 fputs("\n", s1
->outfile
), --d
;
6368 line_ref
= (file_ref
= file
)->line_num
;
6371 fputs(get_tok_str(tok
, &tokc
), s1
->outfile
);
6373 free_defines(define_start
);
6378 int tcc_compile_string(TCCState
*s
, const char *str
)
6380 BufferedFile bf1
, *bf
= &bf1
;
6384 /* init file structure */
6386 /* XXX: avoid copying */
6388 buf
= tcc_malloc(len
+ 1);
6391 memcpy(buf
, str
, len
);
6394 bf
->buf_end
= buf
+ len
;
6395 pstrcpy(bf
->filename
, sizeof(bf
->filename
), "<string>");
6398 ret
= tcc_compile(s
);
6402 /* currently, no need to close */
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
, " ");
6417 pstrcat(bf
->buffer
, IO_BUF_SIZE
, value
);
6419 /* init file structure */
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';
6428 s1
->include_stack_ptr
= s1
->include_stack
;
6430 /* parse with define parser */
6431 ch
= file
->buf_ptr
[0];
6437 /* undefine a preprocessor symbol */
6438 void tcc_undefine_symbol(TCCState
*s1
, const char *sym
)
6442 ts
= tok_alloc(sym
, strlen(sym
));
6443 s
= define_find(ts
->tok
);
6444 /* undefine symbol by putting an invalid name */
6449 #ifdef CONFIG_TCC_ASM
6451 #ifdef TCC_TARGET_I386
6452 #include "i386-asm.c"
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");
6469 #ifdef TCC_TARGET_COFF
6470 #include "tcccoff.c"
6473 #ifdef TCC_TARGET_PE
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';
6494 last_func_name
[0] = '\0';
6495 last_pc
= 0xffffffff;
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 */
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
)
6508 func_name
[0] = '\0';
6511 str
= stabstr_section
->data
+ sym
->n_strx
;
6512 p
= strchr(str
, ':');
6514 pstrcpy(func_name
, sizeof(func_name
), 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
;
6525 /* line number info */
6527 pc
= sym
->n_value
+ func_addr
;
6528 if (wanted_pc
>= last_pc
&& wanted_pc
< pc
)
6531 last_line_num
= sym
->n_desc
;
6533 strcpy(last_func_name
, func_name
);
6537 str
= stabstr_section
->data
+ sym
->n_strx
;
6539 if (incl_index
< INCLUDE_STACK_SIZE
) {
6540 incl_files
[incl_index
++] = str
;
6548 if (sym
->n_strx
== 0) {
6549 incl_index
= 0; /* end of translation unit */
6551 str
= stabstr_section
->data
+ sym
->n_strx
;
6552 /* do not add path */
6554 if (len
> 0 && str
[len
- 1] != '/')
6562 /* second pass: we try symtab symbols (no line number info) */
6565 ElfW(Sym
) *sym
, *sym_end
;
6568 sym_end
= (ElfW(Sym
) *)(symtab_section
->data
+ symtab_section
->data_offset
);
6569 for(sym
= (ElfW(Sym
) *)symtab_section
->data
+ 1;
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
);
6583 /* did not find any info: */
6584 fprintf(stderr
, " ???\n");
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");
6601 /* fix for glibc 2.1 */
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
)
6615 #if defined(__FreeBSD__)
6616 *paddr
= uc
->uc_mcontext
.mc_eip
;
6617 #elif defined(__dietlibc__)
6618 *paddr
= uc
->uc_mcontext
.eip
;
6620 *paddr
= uc
->uc_mcontext
.gregs
[REG_EIP
];
6624 #if defined(__FreeBSD__)
6625 fp
= uc
->uc_mcontext
.mc_ebp
;
6626 #elif defined(__dietlibc__)
6627 fp
= uc
->uc_mcontext
.ebp
;
6629 fp
= uc
->uc_mcontext
.gregs
[REG_EBP
];
6631 for(i
=1;i
<level
;i
++) {
6632 /* XXX: check address validity with program info */
6633 if (fp
<= 0x1000 || fp
>= 0xc0000000)
6635 fp
= ((unsigned long *)fp
)[0];
6637 *paddr
= ((unsigned long *)fp
)[1];
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
)
6650 /* XXX: only support linux */
6651 *paddr
= uc
->uc_mcontext
.gregs
[REG_RIP
];
6654 fp
= uc
->uc_mcontext
.gregs
[REG_RBP
];
6655 for(i
=1;i
<level
;i
++) {
6656 /* XXX: check address validity with program info */
6659 fp
= ((unsigned long *)fp
)[0];
6661 *paddr
= ((unsigned long *)fp
)[1];
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
)
6674 /* emit a run time error at position 'pc' */
6675 void rt_error(ucontext_t
*uc
, const char *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)
6689 fprintf(stderr
, "at ");
6691 fprintf(stderr
, "by ");
6698 /* signal handler for fatal errors */
6699 static void sig_error(int signum
, siginfo_t
*siginf
, void *puc
)
6701 ucontext_t
*uc
= puc
;
6705 switch(siginf
->si_code
) {
6708 rt_error(uc
, "division by zero");
6711 rt_error(uc
, "floating point exception");
6717 if (rt_bound_error_msg
&& *rt_bound_error_msg
)
6718 rt_error(uc
, *rt_bound_error_msg
);
6720 rt_error(uc
, "dereferencing invalid pointer");
6723 rt_error(uc
, "illegal instruction");
6726 rt_error(uc
, "abort() called");
6729 rt_error(uc
, "caught signal %d", signum
);
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
)
6743 unsigned long offset
, length
, mem
;
6746 if (0 == s1
->runtime_added
) {
6747 s1
->runtime_added
= 1;
6749 #ifdef TCC_TARGET_PE
6751 relocate_common_syms();
6752 tcc_add_linker_symbols(s1
);
6754 tcc_add_runtime(s1
);
6755 relocate_common_syms();
6756 tcc_add_linker_symbols(s1
);
6757 build_got_entries(s1
);
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
))
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);
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? */
6787 /* relocate each section */
6788 for(i
= 1; i
< s1
->nb_sections
; i
++) {
6789 s
= s1
->sections
[i
];
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
))
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
);
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
);
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 **);
6823 ret
= tcc_relocate(s1
, NULL
);
6826 ptr
= tcc_malloc(ret
);
6827 tcc_relocate(s1
, ptr
);
6829 prog_main
= tcc_get_symbol_err(s1
, "main");
6832 #ifdef CONFIG_TCC_BACKTRACE
6833 struct sigaction sigact
;
6834 /* install TCC signal handlers to print debug info on fatal
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
);
6845 error("debug mode not available");
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");
6861 ret
= (*prog_main
)(argc
, argv
);
6866 void tcc_memstats(void)
6869 printf("memory in use: %d\n", mem_cur_size
);
6873 static void tcc_cleanup(void)
6877 if (NULL
== tcc_state
)
6881 /* free -D defines */
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
);
6893 cstr_free(&tokcstr
);
6894 /* reset symbol stack */
6895 sym_free_first
= NULL
;
6896 /* cleanup from error/setjmp */
6900 TCCState
*tcc_new(void)
6909 s
= tcc_mallocz(sizeof(TCCState
));
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 */
6921 memset(hash_ident
, 0, TOK_HASH_SIZE
* sizeof(TokenSym
*));
6923 tok_ident
= TOK_IDENT
;
6932 ts
= tok_alloc(p
, r
- p
- 1);
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
);
6949 #if defined(TCC_TARGET_X86_64)
6950 tcc_define_symbol(s
, "__x86_64__", NULL
);
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
);
6962 #ifdef TCC_TARGET_PE
6963 tcc_define_symbol(s
, "_WIN32", NULL
);
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
);
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");
6981 tcc_define_symbol(s
, "__WCHAR_TYPE__", "int");
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");
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,
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
,
7008 ".dynhashtab", SHF_PRIVATE
);
7009 s
->alacarte_link
= 1;
7011 #ifdef CHAR_IS_UNSIGNED
7012 s
->char_is_unsigned
= 1;
7014 #if defined(TCC_TARGET_PE) && 0
7015 /* XXX: currently the PE linker is not ready to support that */
7016 s
->leading_underscore
= 1;
7021 void tcc_delete(TCCState
*s1
)
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
];
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
);
7057 int tcc_add_include_path(TCCState
*s1
, const char *pathname
)
7061 pathname1
= tcc_strdup(pathname
);
7062 dynarray_add((void ***)&s1
->include_paths
, &s1
->nb_include_paths
, pathname1
);
7066 int tcc_add_sysinclude_path(TCCState
*s1
, const char *pathname
)
7070 pathname1
= tcc_strdup(pathname
);
7071 dynarray_add((void ***)&s1
->sysinclude_paths
, &s1
->nb_sysinclude_paths
, pathname1
);
7075 static int tcc_add_file_internal(TCCState
*s1
, const char *filename
, int flags
)
7080 BufferedFile
*saved_file
;
7082 /* find source file type with extension */
7083 ext
= tcc_fileextension(filename
);
7089 file
= tcc_open(s1
, filename
);
7091 if (flags
& AFF_PRINT_ERROR
) {
7092 error_noabort("file '%s' not found", filename
);
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
);
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);
7113 #ifdef TCC_TARGET_PE
7114 if (!PATHCMP(ext
, "def")) {
7115 ret
= pe_load_def_file(s1
, file
->fd
);
7120 /* assume executable format: auto guess file type */
7121 ret
= read(fd
, &ehdr
, sizeof(ehdr
));
7122 lseek(fd
, 0, SEEK_SET
);
7124 error_noabort("could not read header");
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
7143 h
= dlopen(filename
, RTLD_GLOBAL
| RTLD_LAZY
);
7150 ret
= tcc_load_dll(s1
, fd
, filename
,
7151 (flags
& AFF_REFERENCED_DLL
) != 0);
7154 error_noabort("unrecognized ELF file");
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
);
7161 #ifdef TCC_TARGET_COFF
7162 if (*(uint16_t *)(&ehdr
) == COFF_C67_MAGIC
) {
7163 ret
= tcc_load_coff(s1
, fd
);
7166 #ifdef TCC_TARGET_PE
7167 if (pe_test_res_file(&ehdr
, ret
)) {
7168 ret
= pe_load_res_file(s1
, fd
);
7172 /* as GNU ld, consider it is an ld script if not recognized */
7174 ret
= tcc_load_ldscript(s1
);
7176 error_noabort("unrecognized file type");
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
)
7200 pathname1
= tcc_strdup(pathname
);
7201 dynarray_add((void ***)&s
->library_paths
, &s
->nb_library_paths
, pathname1
);
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
)
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)
7221 /* the library name is the same as the argument of the '-l' option */
7222 int tcc_add_library(TCCState
*s
, const char *libraryname
)
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
);
7232 snprintf(buf
, sizeof(buf
), "lib%s.so", libraryname
);
7234 if (tcc_add_dll(s
, buf
, 0) == 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)
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,
7256 int tcc_set_output_type(TCCState
*s
, int output_type
)
7260 s
->output_type
= output_type
;
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");
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
);
7277 /* if bound checking, then add corresponding sections */
7278 #ifdef CONFIG_TCC_BCHECK
7279 if (do_bounds_check
) {
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
);
7290 if (s
->char_is_unsigned
) {
7291 tcc_define_symbol(s
, "__CHAR_UNSIGNED__", NULL
);
7294 /* add debug sections */
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
) &&
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");
7316 #ifdef TCC_TARGET_PE
7317 snprintf(buf
, sizeof(buf
), "%s/lib", tcc_lib_path
);
7318 tcc_add_library_path(s
, buf
);
7324 #define WD_ALL 0x0001 /* warning is activated when using -Wall */
7325 #define FD_INVERT 0x0002 /* invert value before storing */
7327 typedef struct 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
)
7349 if (r
[0] == 'n' && r
[1] == 'o' && r
[2] == '-') {
7353 for(i
= 0, p
= flags
; i
< nb_flags
; i
++, p
++) {
7354 if (!strcmp(r
, p
->name
))
7359 if (p
->flags
& FD_INVERT
)
7361 *(int *)((uint8_t *)s
+ p
->offset
) = value
;
7366 /* set/reset a warning */
7367 int tcc_set_warning(TCCState
*s
, const char *warning_name
, int value
)
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;
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
),
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)
7411 return (tb
.time
* 1000LL + tb
.millitm
) * 1000LL;
7414 gettimeofday(&tv
, NULL
);
7415 return tv
.tv_sec
* 1000000LL + tv
.tv_usec
;
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"
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"
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"
7454 #ifdef CONFIG_TCC_BACKTRACE
7455 " -bt N show N callers in stack traces\n"
7460 #define TCC_OPTION_HAS_ARG 0x0001
7461 #define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
7463 typedef struct TCCOption
{
7492 TCC_OPTION_nostdinc
,
7493 TCC_OPTION_nostdlib
,
7494 TCC_OPTION_print_search_dirs
,
7495 TCC_OPTION_rdynamic
,
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 },
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},
7541 /* convert 'str' into an array of space separated strings */
7542 static int expand_args(char ***pargv
, const char *str
)
7551 while (is_space(*str
))
7556 while (*str
!= '\0' && !is_space(*str
))
7559 arg
= tcc_malloc(len
+ 1);
7560 memcpy(arg
, s1
, len
);
7562 dynarray_add((void ***)&argv
, &argc
, arg
);
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
)
7579 const TCCOption
*popt
;
7580 const char *optarg
, *p1
, *r1
;
7584 while (optind
< argc
) {
7587 if (r
[0] != '-' || r
[1] == '\0') {
7588 /* add a new file */
7589 dynarray_add((void ***)&files
, &nb_files
, r
);
7590 if (!multiple_files
) {
7592 /* argv[0] will be this file */
7596 /* find option in table (match only the first chars */
7601 error("invalid option -- '%s'", r
);
7614 if (popt
->flags
& TCC_OPTION_HAS_ARG
) {
7615 if (*r1
!= '\0' || (popt
->flags
& TCC_OPTION_NOSEP
)) {
7619 error("argument to '%s' is missing", r
);
7620 optarg
= argv
[optind
++];
7628 switch(popt
->index
) {
7629 case TCC_OPTION_HELP
:
7633 if (tcc_add_include_path(s
, optarg
) < 0)
7634 error("too many include paths");
7639 sym
= (char *)optarg
;
7640 value
= strchr(sym
, '=');
7645 tcc_define_symbol(s
, sym
, value
);
7649 tcc_undefine_symbol(s
, optarg
);
7652 tcc_add_library_path(s
, optarg
);
7655 /* set tcc utilities path (mainly for tcc development) */
7656 tcc_set_lib_path(s
, optarg
);
7659 dynarray_add((void ***)&files
, &nb_files
, r
);
7662 case TCC_OPTION_bench
:
7665 #ifdef CONFIG_TCC_BACKTRACE
7667 num_callers
= atoi(optarg
);
7670 #ifdef CONFIG_TCC_BCHECK
7672 do_bounds_check
= 1;
7681 output_type
= TCC_OUTPUT_OBJ
;
7683 case TCC_OPTION_static
:
7686 case TCC_OPTION_shared
:
7687 output_type
= TCC_OUTPUT_DLL
;
7689 case TCC_OPTION_soname
:
7697 /* generate a .o merging several output files */
7699 output_type
= TCC_OUTPUT_OBJ
;
7701 case TCC_OPTION_nostdinc
:
7704 case TCC_OPTION_nostdlib
:
7707 case TCC_OPTION_print_search_dirs
:
7708 print_search_dirs
= 1;
7710 case TCC_OPTION_run
:
7714 argc1
= expand_args(&argv1
, optarg
);
7716 parse_args(s
, argc1
, argv1
);
7719 output_type
= TCC_OUTPUT_MEMORY
;
7725 printf("tcc version %s\n", TCC_VERSION
);
7726 } while (*optarg
++ == 'v');
7729 if (tcc_set_flag(s
, optarg
, 1) < 0 && s
->warn_unsupported
)
7730 goto unsupported_option
;
7733 if (tcc_set_warning(s
, optarg
, 1) < 0 &&
7734 s
->warn_unsupported
)
7735 goto unsupported_option
;
7740 case TCC_OPTION_rdynamic
:
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
;
7755 #ifdef TCC_TARGET_COFF
7756 if (!strcmp(p
, "coff")) {
7757 s
->output_format
= TCC_OUTPUT_FORMAT_COFF
;
7761 error("target %s not found", p
);
7764 error("unsupported linker option '%s'", optarg
);
7769 output_type
= TCC_OUTPUT_PREPROCESS
;
7772 if (s
->warn_unsupported
) {
7774 warning("unsupported option '%s'", r
);
7783 int main(int argc
, char **argv
)
7787 int nb_objfiles
, ret
, optind
;
7788 char objfilename
[1024];
7789 int64_t start_time
= 0;
7793 tcc_set_lib_path_w32(s
);
7795 output_type
= TCC_OUTPUT_EXE
;
7802 print_search_dirs
= 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
);
7811 if (optind
== 0 || nb_files
== 0) {
7812 if (optind
&& verbose
)
7818 nb_objfiles
= nb_files
- nb_libraries
;
7820 /* if outfile provided without other options, we output an
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
) {
7837 s
->outfile
= stdout
;
7839 s
->outfile
= fopen(outfile
, "w");
7841 error("could not open '%s", outfile
);
7843 } else if (output_type
!= TCC_OUTPUT_MEMORY
) {
7845 /* compute default outfile 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");
7855 if (output_type
== TCC_OUTPUT_EXE
)
7856 strcpy(ext
, ".exe");
7859 if (output_type
== TCC_OUTPUT_OBJ
&& !reloc_output
&& *ext
)
7862 pstrcpy(objfilename
, sizeof(objfilename
), "a.out");
7863 outfile
= objfilename
;
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)
7882 } else if (filename
[0] == '-' && filename
[1]) {
7883 if (tcc_add_library(s
, filename
+ 2) < 0)
7884 error("cannot find %s", filename
);
7887 printf("-> %s\n", filename
);
7888 if (tcc_add_file(s
, filename
) < 0)
7893 /* free all files */
7901 total_time
= (double)(getclock_us() - start_time
) / 1000000.0;
7902 if (total_time
< 0.001)
7904 if (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
) {
7915 } else if (s
->output_type
== TCC_OUTPUT_MEMORY
) {
7916 ret
= tcc_run(s
, argc
- optind
, argv
+ optind
);
7918 ret
= tcc_output_file(s
, outfile
) ? 1 : 0;
7920 /* XXX: cannot do it with bound checking because of the malloc hooks */
7921 if (!do_bounds_check
)
7926 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size
, mem_max_size
);