diff options
Diffstat (limited to 'utils/benchmark/inputs/tccgen.c.pp')
-rw-r--r-- | utils/benchmark/inputs/tccgen.c.pp | 9993 |
1 files changed, 9993 insertions, 0 deletions
diff --git a/utils/benchmark/inputs/tccgen.c.pp b/utils/benchmark/inputs/tccgen.c.pp new file mode 100644 index 0000000..b007f19 --- /dev/null +++ b/utils/benchmark/inputs/tccgen.c.pp @@ -0,0 +1,9993 @@ +# 1 "tccgen.c" +# 1 "<built-in>" +# 1 "<command-line>" +# 1 "tccgen.c" +# 21 "tccgen.c" +# 1 "tcc.h" 1 +# 25 "tcc.h" +# 1 "config.h" 1 +# 26 "tcc.h" 2 + +# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stdlib.h" 1 +# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1 +# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stdlib.h" 2 +# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_typedefs.h" 1 + + + +typedef int size_t; +typedef int __builtin_va_list; +typedef int __gnuc_va_list; +typedef int va_list; +typedef int __int8_t; +typedef int __uint8_t; +typedef int __int16_t; +typedef int __uint16_t; +typedef int __int_least16_t; +typedef int __uint_least16_t; +typedef int __int32_t; +typedef int __uint32_t; +typedef int __int64_t; +typedef int __uint64_t; +typedef int __int_least32_t; +typedef int __uint_least32_t; +typedef int __s8; +typedef int __u8; +typedef int __s16; +typedef int __u16; +typedef int __s32; +typedef int __u32; +typedef int __s64; +typedef int __u64; +typedef int _LOCK_T; +typedef int _LOCK_RECURSIVE_T; +typedef int _off_t; +typedef int __dev_t; +typedef int __uid_t; +typedef int __gid_t; +typedef int _off64_t; +typedef int _fpos_t; +typedef int _ssize_t; +typedef int wint_t; +typedef int _mbstate_t; +typedef int _flock_t; +typedef int _iconv_t; +typedef int __ULong; +typedef int __FILE; +typedef int ptrdiff_t; +typedef int wchar_t; +typedef int __off_t; +typedef int __pid_t; +typedef int __loff_t; +typedef int u_char; +typedef int u_short; +typedef int u_int; +typedef int u_long; +typedef int ushort; +typedef int uint; +typedef int clock_t; +typedef int time_t; +typedef int daddr_t; +typedef int caddr_t; +typedef int ino_t; +typedef int off_t; +typedef int dev_t; +typedef int uid_t; +typedef int gid_t; +typedef int pid_t; +typedef int key_t; +typedef int ssize_t; +typedef int mode_t; +typedef int nlink_t; +typedef int fd_mask; +typedef int _types_fd_set; +typedef int clockid_t; +typedef int timer_t; +typedef int useconds_t; +typedef int suseconds_t; +typedef int FILE; +typedef int fpos_t; +typedef int cookie_read_function_t; +typedef int cookie_write_function_t; +typedef int cookie_seek_function_t; +typedef int cookie_close_function_t; +typedef int cookie_io_functions_t; +typedef int div_t; +typedef int ldiv_t; +typedef int lldiv_t; +typedef int sigset_t; +typedef int __sigset_t; +typedef int _sig_func_ptr; +typedef int sig_atomic_t; +typedef int __tzrule_type; +typedef int __tzinfo_type; +typedef int mbstate_t; +typedef int sem_t; +typedef int pthread_t; +typedef int pthread_attr_t; +typedef int pthread_mutex_t; +typedef int pthread_mutexattr_t; +typedef int pthread_cond_t; +typedef int pthread_condattr_t; +typedef int pthread_key_t; +typedef int pthread_once_t; +typedef int pthread_rwlock_t; +typedef int pthread_rwlockattr_t; +typedef int pthread_spinlock_t; +typedef int pthread_barrier_t; +typedef int pthread_barrierattr_t; +typedef int jmp_buf; +typedef int rlim_t; +typedef int sa_family_t; +typedef int sigjmp_buf; +typedef int stack_t; +typedef int siginfo_t; +typedef int z_stream; + + +typedef int int8_t; +typedef int uint8_t; +typedef int int16_t; +typedef int uint16_t; +typedef int int32_t; +typedef int uint32_t; +typedef int int64_t; +typedef int uint64_t; + + +typedef int int_least8_t; +typedef int uint_least8_t; +typedef int int_least16_t; +typedef int uint_least16_t; +typedef int int_least32_t; +typedef int uint_least32_t; +typedef int int_least64_t; +typedef int uint_least64_t; + + +typedef int int_fast8_t; +typedef int uint_fast8_t; +typedef int int_fast16_t; +typedef int uint_fast16_t; +typedef int int_fast32_t; +typedef int uint_fast32_t; +typedef int int_fast64_t; +typedef int uint_fast64_t; + + +typedef int intptr_t; +typedef int uintptr_t; + + +typedef int intmax_t; +typedef int uintmax_t; + + +typedef _Bool bool; + + +typedef void* MirEGLNativeWindowType; +typedef void* MirEGLNativeDisplayType; +typedef struct MirConnection MirConnection; +typedef struct MirSurface MirSurface; +typedef struct MirSurfaceSpec MirSurfaceSpec; +typedef struct MirScreencast MirScreencast; +typedef struct MirPromptSession MirPromptSession; +typedef struct MirBufferStream MirBufferStream; +typedef struct MirPersistentId MirPersistentId; +typedef struct MirBlob MirBlob; +typedef struct MirDisplayConfig MirDisplayConfig; + + +typedef struct xcb_connection_t xcb_connection_t; +typedef uint32_t xcb_window_t; +typedef uint32_t xcb_visualid_t; +# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stdlib.h" 2 +# 28 "tcc.h" 2 +# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stdio.h" 1 +# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1 +# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stdio.h" 2 +# 29 "tcc.h" 2 +# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stdarg.h" 1 +# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1 +# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stdarg.h" 2 +# 30 "tcc.h" 2 +# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/string.h" 1 +# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1 +# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/string.h" 2 +# 31 "tcc.h" 2 +# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/errno.h" 1 +# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1 +# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/errno.h" 2 +# 32 "tcc.h" 2 +# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/math.h" 1 +# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1 +# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/math.h" 2 +# 33 "tcc.h" 2 +# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/fcntl.h" 1 +# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1 +# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/fcntl.h" 2 +# 34 "tcc.h" 2 +# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/setjmp.h" 1 +# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1 +# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/setjmp.h" 2 +# 35 "tcc.h" 2 +# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/time.h" 1 +# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1 +# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/time.h" 2 +# 36 "tcc.h" 2 + + +# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/unistd.h" 1 +# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1 +# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/unistd.h" 2 +# 39 "tcc.h" 2 +# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/sys/time.h" 1 +# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1 +# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/sys/time.h" 2 +# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_typedefs.h" 1 +# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/sys/time.h" 2 +# 40 "tcc.h" 2 + +# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/dlfcn.h" 1 +# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1 +# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/dlfcn.h" 2 +# 42 "tcc.h" 2 + + +extern float strtof (const char *__nptr, char **__endptr); +extern long double strtold (const char *__nptr, char **__endptr); +# 283 "tcc.h" +# 1 "libtcc.h" 1 +# 12 "libtcc.h" +struct TCCState; + +typedef struct TCCState TCCState; + + + TCCState *tcc_new(void); + + + void tcc_delete(TCCState *s); + + + void tcc_set_lib_path(TCCState *s, const char *path); + + + void tcc_set_error_func(TCCState *s, void *error_opaque, + void (*error_func)(void *opaque, const char *msg)); + + + void tcc_set_options(TCCState *s, const char *str); + + + + + + int tcc_add_include_path(TCCState *s, const char *pathname); + + + int tcc_add_sysinclude_path(TCCState *s, const char *pathname); + + + void tcc_define_symbol(TCCState *s, const char *sym, const char *value); + + + void tcc_undefine_symbol(TCCState *s, const char *sym); + + + + + + int tcc_add_file(TCCState *s, const char *filename); + + + int tcc_compile_string(TCCState *s, const char *buf); + + + + + + int tcc_set_output_type(TCCState *s, int output_type); + + + + + + + + int tcc_add_library_path(TCCState *s, const char *pathname); + + + int tcc_add_library(TCCState *s, const char *libraryname); + + + int tcc_add_symbol(TCCState *s, const char *name, const void *val); + + + + int tcc_output_file(TCCState *s, const char *filename); + + + + int tcc_run(TCCState *s, int argc, char **argv); + + + int tcc_relocate(TCCState *s1, void *ptr); +# 94 "libtcc.h" + void *tcc_get_symbol(TCCState *s, const char *name); +# 284 "tcc.h" 2 +# 1 "elf.h" 1 +# 23 "elf.h" +# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/inttypes.h" 1 +# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1 +# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/inttypes.h" 2 +# 24 "elf.h" 2 +# 41 "elf.h" +typedef uint16_t Elf32_Half; +typedef uint16_t Elf64_Half; + + +typedef uint32_t Elf32_Word; +typedef int32_t Elf32_Sword; +typedef uint32_t Elf64_Word; +typedef int32_t Elf64_Sword; + + +typedef uint64_t Elf32_Xword; +typedef int64_t Elf32_Sxword; +typedef uint64_t Elf64_Xword; +typedef int64_t Elf64_Sxword; + + +typedef uint32_t Elf32_Addr; +typedef uint64_t Elf64_Addr; + + +typedef uint32_t Elf32_Off; +typedef uint64_t Elf64_Off; + + +typedef uint16_t Elf32_Section; +typedef uint16_t Elf64_Section; + + +typedef Elf32_Half Elf32_Versym; +typedef Elf64_Half Elf64_Versym; + + + + + + +typedef struct +{ + unsigned char e_ident[(16)]; + Elf32_Half e_type; + Elf32_Half e_machine; + Elf32_Word e_version; + Elf32_Addr e_entry; + Elf32_Off e_phoff; + Elf32_Off e_shoff; + Elf32_Word e_flags; + Elf32_Half e_ehsize; + Elf32_Half e_phentsize; + Elf32_Half e_phnum; + Elf32_Half e_shentsize; + Elf32_Half e_shnum; + Elf32_Half e_shstrndx; +} Elf32_Ehdr; + +typedef struct +{ + unsigned char e_ident[(16)]; + Elf64_Half e_type; + Elf64_Half e_machine; + Elf64_Word e_version; + Elf64_Addr e_entry; + Elf64_Off e_phoff; + Elf64_Off e_shoff; + Elf64_Word e_flags; + Elf64_Half e_ehsize; + Elf64_Half e_phentsize; + Elf64_Half e_phnum; + Elf64_Half e_shentsize; + Elf64_Half e_shnum; + Elf64_Half e_shstrndx; +} Elf64_Ehdr; +# 282 "elf.h" +typedef struct +{ + Elf32_Word sh_name; + Elf32_Word sh_type; + Elf32_Word sh_flags; + Elf32_Addr sh_addr; + Elf32_Off sh_offset; + Elf32_Word sh_size; + Elf32_Word sh_link; + Elf32_Word sh_info; + Elf32_Word sh_addralign; + Elf32_Word sh_entsize; +} Elf32_Shdr; + +typedef struct +{ + Elf64_Word sh_name; + Elf64_Word sh_type; + Elf64_Xword sh_flags; + Elf64_Addr sh_addr; + Elf64_Off sh_offset; + Elf64_Xword sh_size; + Elf64_Word sh_link; + Elf64_Word sh_info; + Elf64_Xword sh_addralign; + Elf64_Xword sh_entsize; +} Elf64_Shdr; +# 392 "elf.h" +typedef struct +{ + Elf32_Word st_name; + Elf32_Addr st_value; + Elf32_Word st_size; + unsigned char st_info; + unsigned char st_other; + Elf32_Section st_shndx; +} Elf32_Sym; + +typedef struct +{ + Elf64_Word st_name; + unsigned char st_info; + unsigned char st_other; + Elf64_Section st_shndx; + Elf64_Addr st_value; + Elf64_Xword st_size; +} Elf64_Sym; + + + + +typedef struct +{ + Elf32_Half si_boundto; + Elf32_Half si_flags; +} Elf32_Syminfo; + +typedef struct +{ + Elf64_Half si_boundto; + Elf64_Half si_flags; +} Elf64_Syminfo; +# 507 "elf.h" +typedef struct +{ + Elf32_Addr r_offset; + Elf32_Word r_info; +} Elf32_Rel; + + + + + + +typedef struct +{ + Elf64_Addr r_offset; + Elf64_Xword r_info; +} Elf64_Rel; + + + +typedef struct +{ + Elf32_Addr r_offset; + Elf32_Word r_info; + Elf32_Sword r_addend; +} Elf32_Rela; + +typedef struct +{ + Elf64_Addr r_offset; + Elf64_Xword r_info; + Elf64_Sxword r_addend; +} Elf64_Rela; +# 552 "elf.h" +typedef struct +{ + Elf32_Word p_type; + Elf32_Off p_offset; + Elf32_Addr p_vaddr; + Elf32_Addr p_paddr; + Elf32_Word p_filesz; + Elf32_Word p_memsz; + Elf32_Word p_flags; + Elf32_Word p_align; +} Elf32_Phdr; + +typedef struct +{ + Elf64_Word p_type; + Elf64_Word p_flags; + Elf64_Off p_offset; + Elf64_Addr p_vaddr; + Elf64_Addr p_paddr; + Elf64_Xword p_filesz; + Elf64_Xword p_memsz; + Elf64_Xword p_align; +} Elf64_Phdr; +# 658 "elf.h" +typedef struct +{ + Elf32_Sword d_tag; + union + { + Elf32_Word d_val; + Elf32_Addr d_ptr; + } d_un; +} Elf32_Dyn; + +typedef struct +{ + Elf64_Sxword d_tag; + union + { + Elf64_Xword d_val; + Elf64_Addr d_ptr; + } d_un; +} Elf64_Dyn; +# 834 "elf.h" +typedef struct +{ + Elf32_Half vd_version; + Elf32_Half vd_flags; + Elf32_Half vd_ndx; + Elf32_Half vd_cnt; + Elf32_Word vd_hash; + Elf32_Word vd_aux; + Elf32_Word vd_next; + +} Elf32_Verdef; + +typedef struct +{ + Elf64_Half vd_version; + Elf64_Half vd_flags; + Elf64_Half vd_ndx; + Elf64_Half vd_cnt; + Elf64_Word vd_hash; + Elf64_Word vd_aux; + Elf64_Word vd_next; + +} Elf64_Verdef; +# 876 "elf.h" +typedef struct +{ + Elf32_Word vda_name; + Elf32_Word vda_next; + +} Elf32_Verdaux; + +typedef struct +{ + Elf64_Word vda_name; + Elf64_Word vda_next; + +} Elf64_Verdaux; + + + + +typedef struct +{ + Elf32_Half vn_version; + Elf32_Half vn_cnt; + Elf32_Word vn_file; + + Elf32_Word vn_aux; + Elf32_Word vn_next; + +} Elf32_Verneed; + +typedef struct +{ + Elf64_Half vn_version; + Elf64_Half vn_cnt; + Elf64_Word vn_file; + + Elf64_Word vn_aux; + Elf64_Word vn_next; + +} Elf64_Verneed; +# 923 "elf.h" +typedef struct +{ + Elf32_Word vna_hash; + Elf32_Half vna_flags; + Elf32_Half vna_other; + Elf32_Word vna_name; + Elf32_Word vna_next; + +} Elf32_Vernaux; + +typedef struct +{ + Elf64_Word vna_hash; + Elf64_Half vna_flags; + Elf64_Half vna_other; + Elf64_Word vna_name; + Elf64_Word vna_next; + +} Elf64_Vernaux; +# 957 "elf.h" +typedef struct +{ + uint32_t a_type; + union + { + uint32_t a_val; + + + + } a_un; +} Elf32_auxv_t; + +typedef struct +{ + uint64_t a_type; + union + { + uint64_t a_val; + + + + } a_un; +} Elf64_auxv_t; +# 1041 "elf.h" +typedef struct +{ + Elf32_Word n_namesz; + Elf32_Word n_descsz; + Elf32_Word n_type; +} Elf32_Nhdr; + +typedef struct +{ + Elf64_Word n_namesz; + Elf64_Word n_descsz; + Elf64_Word n_type; +} Elf64_Nhdr; +# 1105 "elf.h" +typedef struct +{ + Elf32_Xword m_value; + Elf32_Word m_info; + Elf32_Word m_poffset; + Elf32_Half m_repeat; + Elf32_Half m_stride; +} Elf32_Move; + +typedef struct +{ + Elf64_Xword m_value; + Elf64_Xword m_info; + Elf64_Xword m_poffset; + Elf64_Half m_repeat; + Elf64_Half m_stride; +} Elf64_Move; +# 1489 "elf.h" +typedef union +{ + struct + { + Elf32_Word gt_current_g_value; + Elf32_Word gt_unused; + } gt_header; + struct + { + Elf32_Word gt_g_value; + Elf32_Word gt_bytes; + } gt_entry; +} Elf32_gptab; + + + +typedef struct +{ + Elf32_Word ri_gprmask; + Elf32_Word ri_cprmask[4]; + Elf32_Sword ri_gp_value; +} Elf32_RegInfo; + + + +typedef struct +{ + unsigned char kind; + + unsigned char size; + Elf32_Section section; + + Elf32_Word info; +} Elf_Options; +# 1565 "elf.h" +typedef struct +{ + Elf32_Word hwp_flags1; + Elf32_Word hwp_flags2; +} Elf_Options_Hw; +# 1726 "elf.h" +typedef struct +{ + Elf32_Word l_name; + Elf32_Word l_time_stamp; + Elf32_Word l_checksum; + Elf32_Word l_version; + Elf32_Word l_flags; +} Elf32_Lib; + +typedef struct +{ + Elf64_Word l_name; + Elf64_Word l_time_stamp; + Elf64_Word l_checksum; + Elf64_Word l_version; + Elf64_Word l_flags; +} Elf64_Lib; +# 1757 "elf.h" +typedef Elf32_Addr Elf32_Conflict; +# 285 "tcc.h" 2 +# 1 "stab.h" 1 +# 9 "stab.h" +enum __stab_debug_code +{ +# 1 "stab.def" 1 +# 24 "stab.def" +N_GSYM=0x20, + + + +N_FNAME=0x22, + + + + +N_FUN=0x24, + + + +N_STSYM=0x26, + + +N_LCSYM=0x28, + + + +N_MAIN=0x2a, + + + +N_PC=0x30, + + +N_NSYMS=0x32, + + +N_NOMAP=0x34, + + + +N_OBJ=0x38, + + + + +N_OPT=0x3c, + + +N_RSYM=0x40, + + +N_M2C=0x42, + + + +N_SLINE=0x44, + + +N_DSLINE=0x46, + + +N_BSLINE=0x48, + + + + +N_BROWS=0x48, + + + + + +N_DEFD=0x4a, + + + + +N_EHDECL=0x50, + +N_MOD2=0x50, + + + + + + +N_CATCH=0x54, + + +N_SSYM=0x60, + + + +N_SO=0x64, + + + +N_LSYM=0x80, + + + + +N_BINCL=0x82, + + + +N_SOL=0x84, + + + +N_PSYM=0xa0, + + + + + +N_EINCL=0xa2, + + +N_ENTRY=0xa4, + + + + + +N_LBRAC=0xc0, + + + + + +N_EXCL=0xc2, + + +N_SCOPE=0xc4, + + + +N_RBRAC=0xe0, + + +N_BCOMM=0xe2, + + + +N_ECOMM=0xe4, + + + +N_ECOML=0xe8, + + + + +N_NBTEXT=0xF0, +N_NBDATA=0xF2, +N_NBBSS=0xF4, +N_NBSTS=0xF6, +N_NBLCS=0xF8, + + + +N_LENG=0xfe, +# 12 "stab.h" 2 +LAST_UNUSED_STAB_CODE +}; +# 286 "tcc.h" 2 +# 320 "tcc.h" +# 1 "x86_64-gen.c" 1 +# 57 "x86_64-gen.c" +enum { + TREG_RAX = 0, + TREG_RCX = 1, + TREG_RDX = 2, + TREG_RSP = 4, + TREG_RSI = 6, + TREG_RDI = 7, + + TREG_R8 = 8, + TREG_R9 = 9, + TREG_R10 = 10, + TREG_R11 = 11, + + TREG_XMM0 = 16, + TREG_XMM1 = 17, + TREG_XMM2 = 18, + TREG_XMM3 = 19, + TREG_XMM4 = 20, + TREG_XMM5 = 21, + TREG_XMM6 = 22, + TREG_XMM7 = 23, + + TREG_ST0 = 24, + + TREG_MEM = 0x20 +}; +# 321 "tcc.h" 2 +# 1 "x86_64-link.c" 1 +# 322 "tcc.h" 2 +# 381 "tcc.h" +typedef struct TokenSym { + struct TokenSym *hash_next; + struct Sym *sym_define; + struct Sym *sym_label; + struct Sym *sym_struct; + struct Sym *sym_identifier; + int tok; + int len; + char str[1]; +} TokenSym; + + + + +typedef int nwchar_t; + + +typedef struct CString { + int size; + void *data; + int size_allocated; +} CString; + + +typedef struct CType { + int t; + struct Sym *ref; +} CType; + + +typedef union CValue { + long double ld; + double d; + float f; + uint64_t i; + struct { + int size; + const void *data; + } str; + int tab[16/4]; +} CValue; + + +typedef struct SValue { + CType type; + unsigned short r; + unsigned short r2; + + CValue c; + struct Sym *sym; + +} SValue; + + +struct SymAttr { + unsigned short + aligned : 5, + packed : 1, + weak : 1, + visibility : 2, + dllexport : 1, + dllimport : 1, + unused : 5; +}; + + +struct FuncAttr { + unsigned + func_call : 3, + func_type : 2, + func_args : 8; +}; + + +typedef struct AttributeDef { + struct SymAttr a; + struct FuncAttr f; + struct Section *section; + int alias_target; + int asm_label; + char attr_mode; +} AttributeDef; + + +typedef struct Sym { + int v; + unsigned short r; + struct SymAttr a; + union { + struct { + int c; + union { + int sym_scope; + int jnext; + struct FuncAttr f; + int auxtype; + }; + }; + long long enum_val; + int *d; + }; + CType type; + union { + struct Sym *next; + int asm_label; + }; + struct Sym *prev; + struct Sym *prev_tok; +} Sym; + + +typedef struct Section { + unsigned long data_offset; + unsigned char *data; + unsigned long data_allocated; + int sh_name; + int sh_num; + int sh_type; + int sh_flags; + int sh_info; + int sh_addralign; + int sh_entsize; + unsigned long sh_size; + Elf64_Addr sh_addr; + unsigned long sh_offset; + int nb_hashed_syms; + struct Section *link; + struct Section *reloc; + struct Section *hash; + struct Section *prev; + char name[1]; +} Section; + +typedef struct DLLReference { + int level; + void *handle; + char name[1]; +} DLLReference; +# 554 "tcc.h" +typedef struct BufferedFile { + uint8_t *buf_ptr; + uint8_t *buf_end; + int fd; + struct BufferedFile *prev; + int line_num; + int line_ref; + int ifndef_macro; + int ifndef_macro_saved; + int *ifdef_stack_ptr; + int include_next_index; + char filename[1024]; + char *true_filename; + unsigned char unget[4]; + unsigned char buffer[1]; +} BufferedFile; + + + + + +typedef struct TokenString { + int *str; + int len; + int lastlen; + int allocated_len; + int last_line_num; + int save_line_num; + + struct TokenString *prev; + const int *prev_ptr; + char alloc; +} TokenString; + + +typedef struct InlineFunc { + TokenString *func_str; + Sym *sym; + char filename[1]; +} InlineFunc; + + + +typedef struct CachedInclude { + int ifndef_macro; + int once; + int hash_next; + char filename[1]; +} CachedInclude; + + + + +typedef struct ExprValue { + uint64_t v; + Sym *sym; + int pcrel; +} ExprValue; + + +typedef struct ASMOperand { + int id; + char *constraint; + char asm_str[16]; + SValue *vt; + int ref_index; + int input_index; + int priority; + int reg; + int is_llong; + int is_memory; + int is_rw; +} ASMOperand; + + + +struct sym_attr { + unsigned got_offset; + unsigned plt_offset; + int plt_sym; + int dyn_index; + + + +}; + +struct TCCState { + + int verbose; + int nostdinc; + int nostdlib; + int nocommon; + int static_link; + int rdynamic; + int symbolic; + int alacarte_link; + + char *tcc_lib_path; + char *soname; + char *rpath; + int enable_new_dtags; + + + int output_type; + + int output_format; + + + int char_is_unsigned; + int leading_underscore; + int ms_extensions; + int dollars_in_identifiers; + int ms_bitfields; + + + int warn_write_strings; + int warn_unsupported; + int warn_error; + int warn_none; + int warn_implicit_function_declaration; + int warn_gcc_compat; + + + int do_debug; + + + int do_bounds_check; + + + + + int run_test; + + Elf64_Addr text_addr; + int has_text_addr; + + unsigned section_align; + + char *init_symbol; + char *fini_symbol; + + + + + + int nosse; + + + + DLLReference **loaded_dlls; + int nb_loaded_dlls; + + + char **include_paths; + int nb_include_paths; + + char **sysinclude_paths; + int nb_sysinclude_paths; + + + char **library_paths; + int nb_library_paths; + + + char **crt_paths; + int nb_crt_paths; + + + char **cmd_include_files; + int nb_cmd_include_files; + + + void *error_opaque; + void (*error_func)(void *opaque, const char *msg); + int error_set_jmp_enabled; + jmp_buf error_jmp_buf; + int nb_errors; + + + FILE *ppfp; + enum { + LINE_MACRO_OUTPUT_FORMAT_GCC, + LINE_MACRO_OUTPUT_FORMAT_NONE, + LINE_MACRO_OUTPUT_FORMAT_STD, + LINE_MACRO_OUTPUT_FORMAT_P10 = 11 + } Pflag; + char dflag; + + + char **target_deps; + int nb_target_deps; + + + BufferedFile *include_stack[32]; + BufferedFile **include_stack_ptr; + + int ifdef_stack[64]; + int *ifdef_stack_ptr; + + + int cached_includes_hash[32]; + CachedInclude **cached_includes; + int nb_cached_includes; + + + int pack_stack[8]; + int *pack_stack_ptr; + char **pragma_libs; + int nb_pragma_libs; + + + + struct InlineFunc **inline_fns; + int nb_inline_fns; + + + Section **sections; + int nb_sections; + + Section **priv_sections; + int nb_priv_sections; + + + Section *got; + Section *plt; + + + Section *dynsymtab_section; + + Section *dynsym; + + Section *symtab; + + struct sym_attr *sym_attrs; + int nb_sym_attrs; +# 805 "tcc.h" + const char *runtime_main; + void **runtime_mem; + int nb_runtime_mem; + + + + struct filespec **files; + int nb_files; + int nb_libraries; + int filetype; + char *outfile; + int option_r; + int do_bench; + int gen_deps; + char *deps_outfile; + int option_pthread; + int argc; + char **argv; +}; + +struct filespec { + char type; + char alacarte; + char name[1]; +}; +# 1070 "tcc.h" +enum tcc_token { + TOK_LAST = 256 - 1 + +# 1 "tcctok.h" 1 + + ,TOK_INT + ,TOK_VOID + ,TOK_CHAR + ,TOK_IF + ,TOK_ELSE + ,TOK_WHILE + ,TOK_BREAK + ,TOK_RETURN + ,TOK_FOR + ,TOK_EXTERN + ,TOK_STATIC + ,TOK_UNSIGNED + ,TOK_GOTO + ,TOK_DO + ,TOK_CONTINUE + ,TOK_SWITCH + ,TOK_CASE + + ,TOK_CONST1 + ,TOK_CONST2 + ,TOK_CONST3 + ,TOK_VOLATILE1 + ,TOK_VOLATILE2 + ,TOK_VOLATILE3 + ,TOK_LONG + ,TOK_REGISTER + ,TOK_SIGNED1 + ,TOK_SIGNED2 + ,TOK_SIGNED3 + ,TOK_AUTO + ,TOK_INLINE1 + ,TOK_INLINE2 + ,TOK_INLINE3 + ,TOK_RESTRICT1 + ,TOK_RESTRICT2 + ,TOK_RESTRICT3 + ,TOK_EXTENSION + + ,TOK_GENERIC + + ,TOK_FLOAT + ,TOK_DOUBLE + ,TOK_BOOL + ,TOK_SHORT + ,TOK_STRUCT + ,TOK_UNION + ,TOK_TYPEDEF + ,TOK_DEFAULT + ,TOK_ENUM + ,TOK_SIZEOF + ,TOK_ATTRIBUTE1 + ,TOK_ATTRIBUTE2 + ,TOK_ALIGNOF1 + ,TOK_ALIGNOF2 + ,TOK_TYPEOF1 + ,TOK_TYPEOF2 + ,TOK_TYPEOF3 + ,TOK_LABEL + ,TOK_ASM1 + ,TOK_ASM2 + ,TOK_ASM3 +# 71 "tcctok.h" + ,TOK_DEFINE + ,TOK_INCLUDE + ,TOK_INCLUDE_NEXT + ,TOK_IFDEF + ,TOK_IFNDEF + ,TOK_ELIF + ,TOK_ENDIF + ,TOK_DEFINED + ,TOK_UNDEF + ,TOK_ERROR + ,TOK_WARNING + ,TOK_LINE + ,TOK_PRAGMA + ,TOK___LINE__ + ,TOK___FILE__ + ,TOK___DATE__ + ,TOK___TIME__ + ,TOK___FUNCTION__ + ,TOK___VA_ARGS__ + ,TOK___COUNTER__ + + + ,TOK___FUNC__ + + + ,TOK___NAN__ + ,TOK___SNAN__ + ,TOK___INF__ + + + + ,TOK_SECTION1 + ,TOK_SECTION2 + ,TOK_ALIGNED1 + ,TOK_ALIGNED2 + ,TOK_PACKED1 + ,TOK_PACKED2 + ,TOK_WEAK1 + ,TOK_WEAK2 + ,TOK_ALIAS1 + ,TOK_ALIAS2 + ,TOK_UNUSED1 + ,TOK_UNUSED2 + ,TOK_CDECL1 + ,TOK_CDECL2 + ,TOK_CDECL3 + ,TOK_STDCALL1 + ,TOK_STDCALL2 + ,TOK_STDCALL3 + ,TOK_FASTCALL1 + ,TOK_FASTCALL2 + ,TOK_FASTCALL3 + ,TOK_REGPARM1 + ,TOK_REGPARM2 + + ,TOK_MODE + ,TOK_MODE_QI + ,TOK_MODE_DI + ,TOK_MODE_HI + ,TOK_MODE_SI + ,TOK_MODE_word + + ,TOK_DLLEXPORT + ,TOK_DLLIMPORT + ,TOK_NORETURN1 + ,TOK_NORETURN2 + ,TOK_VISIBILITY1 + ,TOK_VISIBILITY2 + + ,TOK_builtin_types_compatible_p + ,TOK_builtin_choose_expr + ,TOK_builtin_constant_p + ,TOK_builtin_frame_address + ,TOK_builtin_return_address + ,TOK_builtin_expect + + + + + ,TOK_builtin_va_arg_types + + + + + + + ,TOK_pack + + + + + + ,TOK_comment + ,TOK_lib + ,TOK_push_macro + ,TOK_pop_macro + ,TOK_once + ,TOK_option + + + + ,TOK_memcpy + ,TOK_memmove + ,TOK_memset + ,TOK___divdi3 + ,TOK___moddi3 + ,TOK___udivdi3 + ,TOK___umoddi3 + ,TOK___ashrdi3 + ,TOK___lshrdi3 + ,TOK___ashldi3 + ,TOK___floatundisf + ,TOK___floatundidf + + ,TOK___floatundixf + ,TOK___fixunsxfdi + + ,TOK___fixunssfdi + ,TOK___fixunsdfdi +# 251 "tcctok.h" + ,TOK_alloca +# 285 "tcctok.h" + ,TOK___bound_ptr_add + ,TOK___bound_ptr_indir1 + ,TOK___bound_ptr_indir2 + ,TOK___bound_ptr_indir4 + ,TOK___bound_ptr_indir8 + ,TOK___bound_ptr_indir12 + ,TOK___bound_ptr_indir16 + ,TOK___bound_main_arg + ,TOK___bound_local_new + ,TOK___bound_local_delete + + + + + + + + ,TOK_strlen + ,TOK_strcpy + + + + ,TOK_ASMDIR_byte + ,TOK_ASMDIR_word + ,TOK_ASMDIR_align + ,TOK_ASMDIR_balign + ,TOK_ASMDIR_p2align + ,TOK_ASMDIR_set + ,TOK_ASMDIR_skip + ,TOK_ASMDIR_space + ,TOK_ASMDIR_string + ,TOK_ASMDIR_asciz + ,TOK_ASMDIR_ascii + ,TOK_ASMDIR_file + ,TOK_ASMDIR_globl + ,TOK_ASMDIR_global + ,TOK_ASMDIR_weak + ,TOK_ASMDIR_hidden + ,TOK_ASMDIR_ident + ,TOK_ASMDIR_size + ,TOK_ASMDIR_type + ,TOK_ASMDIR_text + ,TOK_ASMDIR_data + ,TOK_ASMDIR_bss + ,TOK_ASMDIR_previous + ,TOK_ASMDIR_pushsection + ,TOK_ASMDIR_popsection + ,TOK_ASMDIR_fill + ,TOK_ASMDIR_rept + ,TOK_ASMDIR_endr + ,TOK_ASMDIR_org + ,TOK_ASMDIR_quad + + + + + ,TOK_ASMDIR_code64 + + ,TOK_ASMDIR_short + ,TOK_ASMDIR_long + ,TOK_ASMDIR_int + ,TOK_ASMDIR_section + + +# 1 "i386-tok.h" 1 + + + + + ,TOK_ASM_al + ,TOK_ASM_cl + ,TOK_ASM_dl + ,TOK_ASM_bl + ,TOK_ASM_ah + ,TOK_ASM_ch + ,TOK_ASM_dh + ,TOK_ASM_bh + ,TOK_ASM_ax + ,TOK_ASM_cx + ,TOK_ASM_dx + ,TOK_ASM_bx + ,TOK_ASM_sp + ,TOK_ASM_bp + ,TOK_ASM_si + ,TOK_ASM_di + ,TOK_ASM_eax + ,TOK_ASM_ecx + ,TOK_ASM_edx + ,TOK_ASM_ebx + ,TOK_ASM_esp + ,TOK_ASM_ebp + ,TOK_ASM_esi + ,TOK_ASM_edi + + ,TOK_ASM_rax + ,TOK_ASM_rcx + ,TOK_ASM_rdx + ,TOK_ASM_rbx + ,TOK_ASM_rsp + ,TOK_ASM_rbp + ,TOK_ASM_rsi + ,TOK_ASM_rdi + + ,TOK_ASM_mm0 + ,TOK_ASM_mm1 + ,TOK_ASM_mm2 + ,TOK_ASM_mm3 + ,TOK_ASM_mm4 + ,TOK_ASM_mm5 + ,TOK_ASM_mm6 + ,TOK_ASM_mm7 + ,TOK_ASM_xmm0 + ,TOK_ASM_xmm1 + ,TOK_ASM_xmm2 + ,TOK_ASM_xmm3 + ,TOK_ASM_xmm4 + ,TOK_ASM_xmm5 + ,TOK_ASM_xmm6 + ,TOK_ASM_xmm7 + ,TOK_ASM_cr0 + ,TOK_ASM_cr1 + ,TOK_ASM_cr2 + ,TOK_ASM_cr3 + ,TOK_ASM_cr4 + ,TOK_ASM_cr5 + ,TOK_ASM_cr6 + ,TOK_ASM_cr7 + ,TOK_ASM_tr0 + ,TOK_ASM_tr1 + ,TOK_ASM_tr2 + ,TOK_ASM_tr3 + ,TOK_ASM_tr4 + ,TOK_ASM_tr5 + ,TOK_ASM_tr6 + ,TOK_ASM_tr7 + ,TOK_ASM_db0 + ,TOK_ASM_db1 + ,TOK_ASM_db2 + ,TOK_ASM_db3 + ,TOK_ASM_db4 + ,TOK_ASM_db5 + ,TOK_ASM_db6 + ,TOK_ASM_db7 + ,TOK_ASM_dr0 + ,TOK_ASM_dr1 + ,TOK_ASM_dr2 + ,TOK_ASM_dr3 + ,TOK_ASM_dr4 + ,TOK_ASM_dr5 + ,TOK_ASM_dr6 + ,TOK_ASM_dr7 + ,TOK_ASM_es + ,TOK_ASM_cs + ,TOK_ASM_ss + ,TOK_ASM_ds + ,TOK_ASM_fs + ,TOK_ASM_gs + ,TOK_ASM_st + ,TOK_ASM_rip + + + + + ,TOK_ASM_spl + ,TOK_ASM_bpl + ,TOK_ASM_sil + ,TOK_ASM_dil + + + ,TOK_ASM_movb ,TOK_ASM_movw ,TOK_ASM_movl ,TOK_ASM_movq ,TOK_ASM_mov + + ,TOK_ASM_addb ,TOK_ASM_addw ,TOK_ASM_addl ,TOK_ASM_addq ,TOK_ASM_add + ,TOK_ASM_orb ,TOK_ASM_orw ,TOK_ASM_orl ,TOK_ASM_orq ,TOK_ASM_or + ,TOK_ASM_adcb ,TOK_ASM_adcw ,TOK_ASM_adcl ,TOK_ASM_adcq ,TOK_ASM_adc + ,TOK_ASM_sbbb ,TOK_ASM_sbbw ,TOK_ASM_sbbl ,TOK_ASM_sbbq ,TOK_ASM_sbb + ,TOK_ASM_andb ,TOK_ASM_andw ,TOK_ASM_andl ,TOK_ASM_andq ,TOK_ASM_and + ,TOK_ASM_subb ,TOK_ASM_subw ,TOK_ASM_subl ,TOK_ASM_subq ,TOK_ASM_sub + ,TOK_ASM_xorb ,TOK_ASM_xorw ,TOK_ASM_xorl ,TOK_ASM_xorq ,TOK_ASM_xor + ,TOK_ASM_cmpb ,TOK_ASM_cmpw ,TOK_ASM_cmpl ,TOK_ASM_cmpq ,TOK_ASM_cmp + + + ,TOK_ASM_incb ,TOK_ASM_incw ,TOK_ASM_incl ,TOK_ASM_incq ,TOK_ASM_inc + ,TOK_ASM_decb ,TOK_ASM_decw ,TOK_ASM_decl ,TOK_ASM_decq ,TOK_ASM_dec + ,TOK_ASM_notb ,TOK_ASM_notw ,TOK_ASM_notl ,TOK_ASM_notq ,TOK_ASM_not + ,TOK_ASM_negb ,TOK_ASM_negw ,TOK_ASM_negl ,TOK_ASM_negq ,TOK_ASM_neg + ,TOK_ASM_mulb ,TOK_ASM_mulw ,TOK_ASM_mull ,TOK_ASM_mulq ,TOK_ASM_mul + ,TOK_ASM_imulb ,TOK_ASM_imulw ,TOK_ASM_imull ,TOK_ASM_imulq ,TOK_ASM_imul + ,TOK_ASM_divb ,TOK_ASM_divw ,TOK_ASM_divl ,TOK_ASM_divq ,TOK_ASM_div + ,TOK_ASM_idivb ,TOK_ASM_idivw ,TOK_ASM_idivl ,TOK_ASM_idivq ,TOK_ASM_idiv + + ,TOK_ASM_xchgb ,TOK_ASM_xchgw ,TOK_ASM_xchgl ,TOK_ASM_xchgq ,TOK_ASM_xchg + ,TOK_ASM_testb ,TOK_ASM_testw ,TOK_ASM_testl ,TOK_ASM_testq ,TOK_ASM_test + + + ,TOK_ASM_rolb ,TOK_ASM_rolw ,TOK_ASM_roll ,TOK_ASM_rolq ,TOK_ASM_rol + ,TOK_ASM_rorb ,TOK_ASM_rorw ,TOK_ASM_rorl ,TOK_ASM_rorq ,TOK_ASM_ror + ,TOK_ASM_rclb ,TOK_ASM_rclw ,TOK_ASM_rcll ,TOK_ASM_rclq ,TOK_ASM_rcl + ,TOK_ASM_rcrb ,TOK_ASM_rcrw ,TOK_ASM_rcrl ,TOK_ASM_rcrq ,TOK_ASM_rcr + ,TOK_ASM_shlb ,TOK_ASM_shlw ,TOK_ASM_shll ,TOK_ASM_shlq ,TOK_ASM_shl + ,TOK_ASM_shrb ,TOK_ASM_shrw ,TOK_ASM_shrl ,TOK_ASM_shrq ,TOK_ASM_shr + ,TOK_ASM_sarb ,TOK_ASM_sarw ,TOK_ASM_sarl ,TOK_ASM_sarq ,TOK_ASM_sar + + ,TOK_ASM_shldw ,TOK_ASM_shldl ,TOK_ASM_shldq ,TOK_ASM_shld + ,TOK_ASM_shrdw ,TOK_ASM_shrdl ,TOK_ASM_shrdq ,TOK_ASM_shrd + + ,TOK_ASM_pushw + ,TOK_ASM_pushl + + ,TOK_ASM_pushq + + ,TOK_ASM_push + + ,TOK_ASM_popw + ,TOK_ASM_popl + + ,TOK_ASM_popq + + ,TOK_ASM_pop + + ,TOK_ASM_inb ,TOK_ASM_inw ,TOK_ASM_inl ,TOK_ASM_in + ,TOK_ASM_outb ,TOK_ASM_outw ,TOK_ASM_outl ,TOK_ASM_out + + ,TOK_ASM_movzbw ,TOK_ASM_movzbl ,TOK_ASM_movzbq ,TOK_ASM_movzb + ,TOK_ASM_movzwl + ,TOK_ASM_movsbw + ,TOK_ASM_movsbl + ,TOK_ASM_movswl + + ,TOK_ASM_movsbq + ,TOK_ASM_movswq + ,TOK_ASM_movzwq + ,TOK_ASM_movslq + + + ,TOK_ASM_leaw ,TOK_ASM_leal ,TOK_ASM_leaq ,TOK_ASM_lea + + ,TOK_ASM_les + ,TOK_ASM_lds + ,TOK_ASM_lss + ,TOK_ASM_lfs + ,TOK_ASM_lgs + + ,TOK_ASM_call + ,TOK_ASM_jmp + ,TOK_ASM_lcall + ,TOK_ASM_ljmp + + ,TOK_ASM_jo ,TOK_ASM_jno ,TOK_ASM_jb ,TOK_ASM_jc ,TOK_ASM_jnae ,TOK_ASM_jnb ,TOK_ASM_jnc ,TOK_ASM_jae ,TOK_ASM_je ,TOK_ASM_jz ,TOK_ASM_jne ,TOK_ASM_jnz ,TOK_ASM_jbe ,TOK_ASM_jna ,TOK_ASM_jnbe ,TOK_ASM_ja ,TOK_ASM_js ,TOK_ASM_jns ,TOK_ASM_jp ,TOK_ASM_jpe ,TOK_ASM_jnp ,TOK_ASM_jpo ,TOK_ASM_jl ,TOK_ASM_jnge ,TOK_ASM_jnl ,TOK_ASM_jge ,TOK_ASM_jle ,TOK_ASM_jng ,TOK_ASM_jnle ,TOK_ASM_jg + + ,TOK_ASM_seto ,TOK_ASM_setno ,TOK_ASM_setb ,TOK_ASM_setc ,TOK_ASM_setnae ,TOK_ASM_setnb ,TOK_ASM_setnc ,TOK_ASM_setae ,TOK_ASM_sete ,TOK_ASM_setz ,TOK_ASM_setne ,TOK_ASM_setnz ,TOK_ASM_setbe ,TOK_ASM_setna ,TOK_ASM_setnbe ,TOK_ASM_seta ,TOK_ASM_sets ,TOK_ASM_setns ,TOK_ASM_setp ,TOK_ASM_setpe ,TOK_ASM_setnp ,TOK_ASM_setpo ,TOK_ASM_setl ,TOK_ASM_setnge ,TOK_ASM_setnl ,TOK_ASM_setge ,TOK_ASM_setle ,TOK_ASM_setng ,TOK_ASM_setnle ,TOK_ASM_setg + ,TOK_ASM_setob ,TOK_ASM_setnob ,TOK_ASM_setbb ,TOK_ASM_setcb ,TOK_ASM_setnaeb ,TOK_ASM_setnbb ,TOK_ASM_setncb ,TOK_ASM_setaeb ,TOK_ASM_seteb ,TOK_ASM_setzb ,TOK_ASM_setneb ,TOK_ASM_setnzb ,TOK_ASM_setbeb ,TOK_ASM_setnab ,TOK_ASM_setnbeb ,TOK_ASM_setab ,TOK_ASM_setsb ,TOK_ASM_setnsb ,TOK_ASM_setpb ,TOK_ASM_setpeb ,TOK_ASM_setnpb ,TOK_ASM_setpob ,TOK_ASM_setlb ,TOK_ASM_setngeb ,TOK_ASM_setnlb ,TOK_ASM_setgeb ,TOK_ASM_setleb ,TOK_ASM_setngb ,TOK_ASM_setnleb ,TOK_ASM_setgb + ,TOK_ASM_cmovo ,TOK_ASM_cmovno ,TOK_ASM_cmovb ,TOK_ASM_cmovc ,TOK_ASM_cmovnae ,TOK_ASM_cmovnb ,TOK_ASM_cmovnc ,TOK_ASM_cmovae ,TOK_ASM_cmove ,TOK_ASM_cmovz ,TOK_ASM_cmovne ,TOK_ASM_cmovnz ,TOK_ASM_cmovbe ,TOK_ASM_cmovna ,TOK_ASM_cmovnbe ,TOK_ASM_cmova ,TOK_ASM_cmovs ,TOK_ASM_cmovns ,TOK_ASM_cmovp ,TOK_ASM_cmovpe ,TOK_ASM_cmovnp ,TOK_ASM_cmovpo ,TOK_ASM_cmovl ,TOK_ASM_cmovnge ,TOK_ASM_cmovnl ,TOK_ASM_cmovge ,TOK_ASM_cmovle ,TOK_ASM_cmovng ,TOK_ASM_cmovnle ,TOK_ASM_cmovg + + ,TOK_ASM_bsfw ,TOK_ASM_bsfl ,TOK_ASM_bsfq ,TOK_ASM_bsf + ,TOK_ASM_bsrw ,TOK_ASM_bsrl ,TOK_ASM_bsrq ,TOK_ASM_bsr + ,TOK_ASM_btw ,TOK_ASM_btl ,TOK_ASM_btq ,TOK_ASM_bt + ,TOK_ASM_btsw ,TOK_ASM_btsl ,TOK_ASM_btsq ,TOK_ASM_bts + ,TOK_ASM_btrw ,TOK_ASM_btrl ,TOK_ASM_btrq ,TOK_ASM_btr + ,TOK_ASM_btcw ,TOK_ASM_btcl ,TOK_ASM_btcq ,TOK_ASM_btc + + ,TOK_ASM_larw ,TOK_ASM_larl ,TOK_ASM_larq ,TOK_ASM_lar + ,TOK_ASM_lslw ,TOK_ASM_lsll ,TOK_ASM_lslq ,TOK_ASM_lsl + + + ,TOK_ASM_fadd ,TOK_ASM_faddp ,TOK_ASM_fadds ,TOK_ASM_fiaddl ,TOK_ASM_faddl ,TOK_ASM_fiadds + ,TOK_ASM_fmul ,TOK_ASM_fmulp ,TOK_ASM_fmuls ,TOK_ASM_fimull ,TOK_ASM_fmull ,TOK_ASM_fimuls + + ,TOK_ASM_fcom + ,TOK_ASM_fcom_1 + ,TOK_ASM_fcoms ,TOK_ASM_ficoml ,TOK_ASM_fcoml ,TOK_ASM_ficoms + + ,TOK_ASM_fcomp ,TOK_ASM_fcompp ,TOK_ASM_fcomps ,TOK_ASM_ficompl ,TOK_ASM_fcompl ,TOK_ASM_ficomps + ,TOK_ASM_fsub ,TOK_ASM_fsubp ,TOK_ASM_fsubs ,TOK_ASM_fisubl ,TOK_ASM_fsubl ,TOK_ASM_fisubs + ,TOK_ASM_fsubr ,TOK_ASM_fsubrp ,TOK_ASM_fsubrs ,TOK_ASM_fisubrl ,TOK_ASM_fsubrl ,TOK_ASM_fisubrs + ,TOK_ASM_fdiv ,TOK_ASM_fdivp ,TOK_ASM_fdivs ,TOK_ASM_fidivl ,TOK_ASM_fdivl ,TOK_ASM_fidivs + ,TOK_ASM_fdivr ,TOK_ASM_fdivrp ,TOK_ASM_fdivrs ,TOK_ASM_fidivrl ,TOK_ASM_fdivrl ,TOK_ASM_fidivrs + + ,TOK_ASM_xaddb ,TOK_ASM_xaddw ,TOK_ASM_xaddl ,TOK_ASM_xaddq ,TOK_ASM_xadd + ,TOK_ASM_cmpxchgb ,TOK_ASM_cmpxchgw ,TOK_ASM_cmpxchgl ,TOK_ASM_cmpxchgq ,TOK_ASM_cmpxchg + + + ,TOK_ASM_cmpsb ,TOK_ASM_cmpsw ,TOK_ASM_cmpsl ,TOK_ASM_cmpsq ,TOK_ASM_cmps + ,TOK_ASM_scmpb ,TOK_ASM_scmpw ,TOK_ASM_scmpl ,TOK_ASM_scmpq ,TOK_ASM_scmp + ,TOK_ASM_insb ,TOK_ASM_insw ,TOK_ASM_insl ,TOK_ASM_ins + ,TOK_ASM_outsb ,TOK_ASM_outsw ,TOK_ASM_outsl ,TOK_ASM_outs + ,TOK_ASM_lodsb ,TOK_ASM_lodsw ,TOK_ASM_lodsl ,TOK_ASM_lodsq ,TOK_ASM_lods + ,TOK_ASM_slodb ,TOK_ASM_slodw ,TOK_ASM_slodl ,TOK_ASM_slodq ,TOK_ASM_slod + ,TOK_ASM_movsb ,TOK_ASM_movsw ,TOK_ASM_movsl ,TOK_ASM_movsq ,TOK_ASM_movs + ,TOK_ASM_smovb ,TOK_ASM_smovw ,TOK_ASM_smovl ,TOK_ASM_smovq ,TOK_ASM_smov + ,TOK_ASM_scasb ,TOK_ASM_scasw ,TOK_ASM_scasl ,TOK_ASM_scasq ,TOK_ASM_scas + ,TOK_ASM_sscab ,TOK_ASM_sscaw ,TOK_ASM_sscal ,TOK_ASM_sscaq ,TOK_ASM_ssca + ,TOK_ASM_stosb ,TOK_ASM_stosw ,TOK_ASM_stosl ,TOK_ASM_stosq ,TOK_ASM_stos + ,TOK_ASM_sstob ,TOK_ASM_sstow ,TOK_ASM_sstol ,TOK_ASM_sstoq ,TOK_ASM_ssto +# 238 "i386-tok.h" +# 1 "x86_64-asm.h" 1 + ,TOK_ASM_clc + ,TOK_ASM_cld + ,TOK_ASM_cli + ,TOK_ASM_clts + ,TOK_ASM_cmc + ,TOK_ASM_lahf + ,TOK_ASM_sahf + ,TOK_ASM_pushfq + ,TOK_ASM_popfq + ,TOK_ASM_pushf + ,TOK_ASM_popf + ,TOK_ASM_stc + ,TOK_ASM_std + ,TOK_ASM_sti + ,TOK_ASM_aaa + ,TOK_ASM_aas + ,TOK_ASM_daa + ,TOK_ASM_das + ,TOK_ASM_aad + ,TOK_ASM_aam + ,TOK_ASM_cbw + ,TOK_ASM_cwd + ,TOK_ASM_cwde + ,TOK_ASM_cdq + ,TOK_ASM_cbtw + ,TOK_ASM_cwtl + ,TOK_ASM_cwtd + ,TOK_ASM_cltd + ,TOK_ASM_cqto + ,TOK_ASM_int3 + ,TOK_ASM_into + ,TOK_ASM_iret + ,TOK_ASM_rsm + ,TOK_ASM_hlt + ,TOK_ASM_wait + ,TOK_ASM_nop + ,TOK_ASM_pause + ,TOK_ASM_xlat + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ,TOK_ASM_lock + ,TOK_ASM_rep + ,TOK_ASM_repe + ,TOK_ASM_repz + ,TOK_ASM_repne + ,TOK_ASM_repnz + + ,TOK_ASM_invd + ,TOK_ASM_wbinvd + ,TOK_ASM_cpuid + ,TOK_ASM_wrmsr + ,TOK_ASM_rdtsc + ,TOK_ASM_rdmsr + ,TOK_ASM_rdpmc + + ,TOK_ASM_syscall + ,TOK_ASM_sysret + + ,TOK_ASM_ud2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ,TOK_ASM_leave + ,TOK_ASM_ret + ,TOK_ASM_retq + + + ,TOK_ASM_lret + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ,TOK_ASM_fucompp + ,TOK_ASM_ftst + ,TOK_ASM_fxam + ,TOK_ASM_fld1 + ,TOK_ASM_fldl2t + ,TOK_ASM_fldl2e + ,TOK_ASM_fldpi + ,TOK_ASM_fldlg2 + ,TOK_ASM_fldln2 + ,TOK_ASM_fldz + + ,TOK_ASM_f2xm1 + ,TOK_ASM_fyl2x + ,TOK_ASM_fptan + ,TOK_ASM_fpatan + ,TOK_ASM_fxtract + ,TOK_ASM_fprem1 + ,TOK_ASM_fdecstp + ,TOK_ASM_fincstp + ,TOK_ASM_fprem + ,TOK_ASM_fyl2xp1 + ,TOK_ASM_fsqrt + ,TOK_ASM_fsincos + ,TOK_ASM_frndint + ,TOK_ASM_fscale + ,TOK_ASM_fsin + ,TOK_ASM_fcos + ,TOK_ASM_fchs + ,TOK_ASM_fabs + ,TOK_ASM_fninit + ,TOK_ASM_fnclex + ,TOK_ASM_fnop + ,TOK_ASM_fwait + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ,TOK_ASM_fxch + + + + + + + + + + + ,TOK_ASM_fnstsw + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ,TOK_ASM_emms + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +# 239 "i386-tok.h" 2 +# 250 "i386-tok.h" +# 1 "x86_64-asm.h" 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ,TOK_ASM_sysretq + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ,TOK_ASM_ljmpw + ,TOK_ASM_ljmpl + + + + + ,TOK_ASM_enter + + + + + + + + + + ,TOK_ASM_loopne + ,TOK_ASM_loopnz + ,TOK_ASM_loope + ,TOK_ASM_loopz + ,TOK_ASM_loop + ,TOK_ASM_jecxz + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ,TOK_ASM_fld + ,TOK_ASM_fldl + ,TOK_ASM_flds + + ,TOK_ASM_fildl + ,TOK_ASM_fildq + ,TOK_ASM_fildll + ,TOK_ASM_fldt + ,TOK_ASM_fbld + + + ,TOK_ASM_fst + ,TOK_ASM_fstl + ,TOK_ASM_fsts + ,TOK_ASM_fstps + + ,TOK_ASM_fstpl + ,TOK_ASM_fist + ,TOK_ASM_fistp + ,TOK_ASM_fistl + ,TOK_ASM_fistpl + + ,TOK_ASM_fstp + ,TOK_ASM_fistpq + ,TOK_ASM_fistpll + ,TOK_ASM_fstpt + ,TOK_ASM_fbstp + + + + + + + ,TOK_ASM_fucom + ,TOK_ASM_fucomp + + ,TOK_ASM_finit + ,TOK_ASM_fldcw + ,TOK_ASM_fnstcw + ,TOK_ASM_fstcw + + + + ,TOK_ASM_fstsw + + + ,TOK_ASM_fclex + ,TOK_ASM_fnstenv + ,TOK_ASM_fstenv + ,TOK_ASM_fldenv + ,TOK_ASM_fnsave + ,TOK_ASM_fsave + ,TOK_ASM_frstor + ,TOK_ASM_ffree + ,TOK_ASM_ffreep + ,TOK_ASM_fxsave + ,TOK_ASM_fxrstor + + + + + ,TOK_ASM_fxsaveq + ,TOK_ASM_fxrstorq + + + ,TOK_ASM_arpl + + ,TOK_ASM_lgdt + ,TOK_ASM_lgdtq + ,TOK_ASM_lidt + ,TOK_ASM_lidtq + ,TOK_ASM_lldt + ,TOK_ASM_lmsw + + ,TOK_ASM_ltr + ,TOK_ASM_sgdt + ,TOK_ASM_sgdtq + ,TOK_ASM_sidt + ,TOK_ASM_sidtq + ,TOK_ASM_sldt + ,TOK_ASM_smsw + ,TOK_ASM_str + + + ,TOK_ASM_verr + ,TOK_ASM_verw + ,TOK_ASM_swapgs + + + + ,TOK_ASM_bswap + ,TOK_ASM_bswapl + ,TOK_ASM_bswapq + + + + ,TOK_ASM_invlpg + + + ,TOK_ASM_cmpxchg8b + + + ,TOK_ASM_cmpxchg16b + + + + + ,TOK_ASM_fcmovb + ,TOK_ASM_fcmove + ,TOK_ASM_fcmovbe + ,TOK_ASM_fcmovu + ,TOK_ASM_fcmovnb + ,TOK_ASM_fcmovne + ,TOK_ASM_fcmovnbe + ,TOK_ASM_fcmovnu + + ,TOK_ASM_fucomi + ,TOK_ASM_fcomi + ,TOK_ASM_fucomip + ,TOK_ASM_fcomip + + + + ,TOK_ASM_movd + + + + + + + + + + + + + ,TOK_ASM_packssdw + ,TOK_ASM_packsswb + ,TOK_ASM_packuswb + ,TOK_ASM_paddb + ,TOK_ASM_paddw + ,TOK_ASM_paddd + ,TOK_ASM_paddsb + ,TOK_ASM_paddsw + ,TOK_ASM_paddusb + ,TOK_ASM_paddusw + ,TOK_ASM_pand + ,TOK_ASM_pandn + ,TOK_ASM_pcmpeqb + ,TOK_ASM_pcmpeqw + ,TOK_ASM_pcmpeqd + ,TOK_ASM_pcmpgtb + ,TOK_ASM_pcmpgtw + ,TOK_ASM_pcmpgtd + ,TOK_ASM_pmaddwd + ,TOK_ASM_pmulhw + ,TOK_ASM_pmullw + ,TOK_ASM_por + ,TOK_ASM_psllw + + ,TOK_ASM_pslld + + ,TOK_ASM_psllq + + ,TOK_ASM_psraw + + ,TOK_ASM_psrad + + ,TOK_ASM_psrlw + + ,TOK_ASM_psrld + + ,TOK_ASM_psrlq + + ,TOK_ASM_psubb + ,TOK_ASM_psubw + ,TOK_ASM_psubd + ,TOK_ASM_psubsb + ,TOK_ASM_psubsw + ,TOK_ASM_psubusb + ,TOK_ASM_psubusw + ,TOK_ASM_punpckhbw + ,TOK_ASM_punpckhwd + ,TOK_ASM_punpckhdq + ,TOK_ASM_punpcklbw + ,TOK_ASM_punpcklwd + ,TOK_ASM_punpckldq + ,TOK_ASM_pxor + + + ,TOK_ASM_movups + + ,TOK_ASM_movaps + + ,TOK_ASM_movhps + + ,TOK_ASM_addps + ,TOK_ASM_cvtpi2ps + ,TOK_ASM_cvtps2pi + ,TOK_ASM_cvttps2pi + ,TOK_ASM_divps + ,TOK_ASM_maxps + ,TOK_ASM_minps + ,TOK_ASM_mulps + ,TOK_ASM_pavgb + ,TOK_ASM_pavgw + ,TOK_ASM_pmaxsw + ,TOK_ASM_pmaxub + ,TOK_ASM_pminsw + ,TOK_ASM_pminub + ,TOK_ASM_rcpss + ,TOK_ASM_rsqrtps + ,TOK_ASM_sqrtps + ,TOK_ASM_subps + + ,TOK_ASM_prefetchnta + ,TOK_ASM_prefetcht0 + ,TOK_ASM_prefetcht1 + ,TOK_ASM_prefetcht2 + ,TOK_ASM_prefetchw + ,TOK_ASM_lfence + ,TOK_ASM_mfence + ,TOK_ASM_sfence + ,TOK_ASM_clflush +# 251 "i386-tok.h" 2 +# 350 "tcctok.h" 2 +# 1074 "tcc.h" 2 + +}; + + + + + + + +static int gnu_ext; + +static int tcc_ext; + +static struct TCCState *tcc_state; + + +static char *pstrcpy(char *buf, int buf_size, const char *s); +static char *pstrcat(char *buf, int buf_size, const char *s); +static char *pstrncpy(char *out, const char *in, size_t num); + char *tcc_basename(const char *name); + char *tcc_fileextension (const char *name); + + + void tcc_free(void *ptr); + void *tcc_malloc(unsigned long size); + void *tcc_mallocz(unsigned long size); + void *tcc_realloc(void *ptr, unsigned long size); + char *tcc_strdup(const char *str); +# 1120 "tcc.h" + void tcc_memcheck(void); + void tcc_error_noabort(const char *fmt, ...); + void tcc_error(const char *fmt, ...); + void tcc_warning(const char *fmt, ...); + + +static void dynarray_add(void *ptab, int *nb_ptr, void *data); +static void dynarray_reset(void *pp, int *n); +static inline void cstr_ccat(CString *cstr, int ch); +static void cstr_cat(CString *cstr, const char *str, int len); +static void cstr_wccat(CString *cstr, int ch); +static void cstr_new(CString *cstr); +static void cstr_free(CString *cstr); +static void cstr_reset(CString *cstr); + +static inline void sym_free(Sym *sym); +static Sym *sym_push2(Sym **ps, int v, int t, int c); +static Sym *sym_find2(Sym *s, int v); +static Sym *sym_push(int v, CType *type, int r, int c); +static void sym_pop(Sym **ptop, Sym *b, int keep); +static inline Sym *struct_find(int v); +static inline Sym *sym_find(int v); +static Sym *global_identifier_push(int v, int t, int c); + +static void tcc_open_bf(TCCState *s1, const char *filename, int initlen); +static int tcc_open(TCCState *s1, const char *filename); +static void tcc_close(void); + +static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags); +# 1166 "tcc.h" +static int tcc_add_crt(TCCState *s, const char *filename); +static int tcc_add_dll(TCCState *s, const char *filename, int flags); +static void tcc_add_pragma_libs(TCCState *s1); + int tcc_add_library_err(TCCState *s, const char *f); + void tcc_print_stats(TCCState *s, unsigned total_time); + int tcc_parse_args(TCCState *s, int *argc, char ***argv, int optind); +# 1188 "tcc.h" +static struct BufferedFile *file; +static int ch, tok; +static CValue tokc; +static const int *macro_ptr; +static int parse_flags; +static int tok_flags; +static CString tokcstr; + + +static int total_lines; +static int total_bytes; +static int tok_ident; +static TokenSym **table_ident; +# 1222 "tcc.h" +static TokenSym *tok_alloc(const char *str, int len); +static const char *get_tok_str(int v, CValue *cv); +static void begin_macro(TokenString *str, int alloc); +static void end_macro(void); +static int set_idnum(int c, int val); +static inline void tok_str_new(TokenString *s); +static TokenString *tok_str_alloc(void); +static void tok_str_free(TokenString *s); +static void tok_str_free_str(int *str); +static void tok_str_add(TokenString *s, int t); +static void tok_str_add_tok(TokenString *s); +static inline void define_push(int v, int macro_type, int *str, Sym *first_arg); +static void define_undef(Sym *s); +static inline Sym *define_find(int v); +static void free_defines(Sym *b); +static Sym *label_find(int v); +static Sym *label_push(Sym **ptop, int v, int flags); +static void label_pop(Sym **ptop, Sym *slast, int keep); +static void parse_define(void); +static void preprocess(int is_bof); +static void next_nomacro(void); +static void next(void); +static inline void unget_tok(int last_tok); +static void preprocess_start(TCCState *s1, int is_asm); +static void preprocess_end(TCCState *s1); +static void tccpp_new(TCCState *s); +static void tccpp_delete(TCCState *s); +static int tcc_preprocess(TCCState *s1); +static void skip(int c); +static void expect(const char *msg); + + +static inline int is_space(int ch) { + return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r'; +} +static inline int isid(int c) { + return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_'; +} +static inline int isnum(int c) { + return c >= '0' && c <= '9'; +} +static inline int isoct(int c) { + return c >= '0' && c <= '7'; +} +static inline int toup(int c) { + return (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c; +} + + + + +static Sym *sym_free_first; +static void **sym_pools; +static int nb_sym_pools; + +static Sym *global_stack; +static Sym *local_stack; +static Sym *local_label_stack; +static Sym *global_label_stack; +static Sym *define_stack; +static CType char_pointer_type, func_old_type, int_type, size_type; +static SValue __vstack[1+ 256], *vtop, *pvtop; + +static int rsym, anon_sym, ind, loc; + +static int const_wanted; +static int nocode_wanted; +static int global_expr; +static CType func_vt; +static int func_var; +static int func_vc; +static int last_line_num, last_ind, func_ind; +static const char *funcname; +static int g_debug; + +static void tcc_debug_start(TCCState *s1); +static void tcc_debug_end(TCCState *s1); +static void tcc_debug_funcstart(TCCState *s1, Sym *sym); +static void tcc_debug_funcend(TCCState *s1, int size); +static void tcc_debug_line(TCCState *s1); + +static int tccgen_compile(TCCState *s1); +static void free_inline_functions(TCCState *s); +static void check_vstack(void); + +static inline int is_float(int t); +static int ieee_finite(double d); +static void test_lvalue(void); +static void vpushi(int v); +static Elf64_Sym *elfsym(Sym *); +static void update_storage(Sym *sym); +static Sym *external_global_sym(int v, CType *type, int r); +static void vset(CType *type, int r, int v); +static void vswap(void); +static void vpush_global_sym(CType *type, int v); +static void vrote(SValue *e, int n); +static void vrott(int n); +static void vrotb(int n); + + + + +static void vpushv(SValue *v); +static void save_reg(int r); +static void save_reg_upstack(int r, int n); +static int get_reg(int rc); +static void save_regs(int n); +static void gaddrof(void); +static int gv(int rc); +static void gv2(int rc1, int rc2); +static void vpop(void); +static void gen_op(int op); +static int type_size(CType *type, int *a); +static void mk_pointer(CType *type); +static void vstore(void); +static void inc(int post, int c); +static void parse_mult_str (CString *astr, const char *msg); +static void parse_asm_str(CString *astr); +static int lvalue_type(int t); +static void indir(void); +static void unary(void); +static void expr_prod(void); +static void expr_sum(void); +static void gexpr(void); +static int expr_const(void); + +static Sym *get_sym_ref(CType *type, Section *sec, unsigned long offset, unsigned long size); + + +static int classify_x86_64_va_arg(CType *ty); +# 1362 "tcc.h" +typedef struct { + unsigned int n_strx; + unsigned char n_type; + unsigned char n_other; + unsigned short n_desc; + unsigned int n_value; +} Stab_Sym; + +static Section *text_section, *data_section, *bss_section; +static Section *common_section; +static Section *cur_text_section; + +static Section *last_text_section; + + + +static Section *bounds_section; +static Section *lbounds_section; +static void tccelf_bounds_new(TCCState *s); + + +static Section *symtab_section; + +static Section *stab_section, *stabstr_section; + +static void tccelf_new(TCCState *s); +static void tccelf_delete(TCCState *s); +static void tccelf_stab_new(TCCState *s); +static void tccelf_begin_file(TCCState *s1); +static void tccelf_end_file(TCCState *s1); + +static Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags); +static void section_realloc(Section *sec, unsigned long new_size); +static size_t section_add(Section *sec, Elf64_Addr size, int align); +static void *section_ptr_add(Section *sec, Elf64_Addr size); +static void section_reserve(Section *sec, unsigned long size); +static Section *find_section(TCCState *s1, const char *name); +static Section *new_symtab(TCCState *s1, const char *symtab_name, int sh_type, int sh_flags, const char *strtab_name, const char *hash_name, int hash_sh_flags); + +static void put_extern_sym2(Sym *sym, int sh_num, Elf64_Addr value, unsigned long size, int can_add_underscore); +static void put_extern_sym(Sym *sym, Section *section, Elf64_Addr value, unsigned long size); + + + +static void greloca(Section *s, Sym *sym, unsigned long offset, int type, Elf64_Addr addend); + +static int put_elf_str(Section *s, const char *sym); +static int put_elf_sym(Section *s, Elf64_Addr value, unsigned long size, int info, int other, int shndx, const char *name); +static int set_elf_sym(Section *s, Elf64_Addr value, unsigned long size, int info, int other, int shndx, const char *name); +static int find_elf_sym(Section *s, const char *name); +static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset, int type, int symbol); +static void put_elf_reloca(Section *symtab, Section *s, unsigned long offset, int type, int symbol, Elf64_Addr addend); + +static void put_stabs(const char *str, int type, int other, int desc, unsigned long value); +static void put_stabs_r(const char *str, int type, int other, int desc, unsigned long value, Section *sec, int sym_index); +static void put_stabn(int type, int other, int desc, int value); +static void put_stabd(int type, int other, int desc); + +static void resolve_common_syms(TCCState *s1); +static void relocate_syms(TCCState *s1, Section *symtab, int do_resolve); +static void relocate_section(TCCState *s1, Section *s); + +static int tcc_object_type(int fd, Elf64_Ehdr *h); +static int tcc_load_object_file(TCCState *s1, int fd, unsigned long file_offset); +static int tcc_load_archive(TCCState *s1, int fd); +static void tcc_add_bcheck(TCCState *s1); +static void tcc_add_runtime(TCCState *s1); + +static void build_got_entries(TCCState *s1); +static struct sym_attr *get_sym_attr(TCCState *s1, int index, int alloc); +static void squeeze_multi_relocs(Section *sec, size_t oldrelocoffset); + +static Elf64_Addr get_elf_sym_addr(TCCState *s, const char *name, int err); + +static void *tcc_get_symbol_err(TCCState *s, const char *name); + + + +static int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level); +static int tcc_load_ldscript(TCCState *s1); +static uint8_t *parse_comment(uint8_t *p); +static void minp(void); +static inline void inp(void); +static int handle_eob(void); + + + + + + +enum gotplt_entry { + NO_GOTPLT_ENTRY, + BUILD_GOT_ONLY, + AUTO_GOTPLT_ENTRY, + ALWAYS_GOTPLT_ENTRY +}; + +static int code_reloc (int reloc_type); +static int gotplt_entry_type (int reloc_type); +static unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr); +static void relocate_init(Section *sr); +static void relocate(TCCState *s1, Elf64_Rela *rel, int type, unsigned char *ptr, Elf64_Addr addr, Elf64_Addr val); +static void relocate_plt(TCCState *s1); + + + +static const int reg_classes[25]; + +static void gsym_addr(int t, int a); +static void gsym(int t); +static void load(int r, SValue *sv); +static void store(int r, SValue *v); +static int gfunc_sret(CType *vt, int variadic, CType *ret, int *align, int *regsize); +static void gfunc_call(int nb_args); +static void gfunc_prolog(CType *func_type); +static void gfunc_epilog(void); +static int gjmp(int t); +static void gjmp_addr(int a); +static int gtst(int inv, int t); + +static void gtst_addr(int inv, int a); + + + +static void gen_opi(int op); +static void gen_opf(int op); +static void gen_cvt_ftoi(int t); +static void gen_cvt_ftof(int t); +static void ggoto(void); + +static void o(unsigned int c); + + +static void gen_cvt_itof(int t); + +static void gen_vla_sp_save(int addr); +static void gen_vla_sp_restore(int addr); +static void gen_vla_alloc(CType *type, int align); + +static inline uint16_t read16le(unsigned char *p) { + return p[0] | (uint16_t)p[1] << 8; +} +static inline void write16le(unsigned char *p, uint16_t x) { + p[0] = x & 255; p[1] = x >> 8 & 255; +} +static inline uint32_t read32le(unsigned char *p) { + return read16le(p) | (uint32_t)read16le(p + 2) << 16; +} +static inline void write32le(unsigned char *p, uint32_t x) { + write16le(p, x); write16le(p + 2, x >> 16); +} +static inline void add32le(unsigned char *p, int32_t x) { + write32le(p, read32le(p) + x); +} +static inline uint64_t read64le(unsigned char *p) { + return read32le(p) | (uint64_t)read32le(p + 4) << 32; +} +static inline void write64le(unsigned char *p, uint64_t x) { + write32le(p, x); write32le(p + 4, x >> 32); +} +static inline void add64le(unsigned char *p, int64_t x) { + write64le(p, read64le(p) + x); +} + + + +static void g(int c); +static void gen_le16(int c); +static void gen_le32(int c); +static void gen_addr32(int r, Sym *sym, int c); +static void gen_addrpc32(int r, Sym *sym, int c); + + + +static void gen_bounded_ptr_add(void); +static void gen_bounded_ptr_deref(void); + + + + +static void gen_addr64(int r, Sym *sym, int64_t c); +static void gen_opl(int op); +# 1580 "tcc.h" +static void asm_instr(void); +static void asm_global_instr(void); + +static int find_constraint(ASMOperand *operands, int nb_operands, const char *name, const char **pp); +static Sym* get_asm_sym(int name, Sym *csym); +static void asm_expr(TCCState *s1, ExprValue *pe); +static int asm_int_expr(TCCState *s1); +static int tcc_assemble(TCCState *s1, int do_preprocess); + +static void gen_expr32(ExprValue *pe); + +static void gen_expr64(ExprValue *pe); + +static void asm_opcode(TCCState *s1, int opcode); +static int asm_parse_regvar(int t); +static void asm_compute_constraints(ASMOperand *operands, int nb_operands, int nb_outputs, const uint8_t *clobber_regs, int *pout_reg); +static void subst_asm_operand(CString *add_str, SValue *sv, int modifier); +static void asm_gen_code(ASMOperand *operands, int nb_operands, int nb_outputs, int is_output, uint8_t *clobber_regs, int out_reg); +static void asm_clobber(uint8_t *clobber_regs, const char *str); +# 1634 "tcc.h" +static int rt_num_callers; +static const char **rt_bound_error_msg; +static void *rt_prog_main; +static void tcc_set_num_callers(int n); + +static void tcc_run_free(TCCState *s1); +# 22 "tccgen.c" 2 +# 31 "tccgen.c" +static int rsym, anon_sym, ind, loc; + +static Sym *sym_free_first; +static void **sym_pools; +static int nb_sym_pools; + +static Sym *global_stack; +static Sym *local_stack; +static Sym *define_stack; +static Sym *global_label_stack; +static Sym *local_label_stack; +static int local_scope; +static int in_sizeof; +static int section_sym; + +static int vlas_in_scope; +static int vla_sp_root_loc; +static int vla_sp_loc; + +static SValue __vstack[1+256], *vtop, *pvtop; + +static int const_wanted; +static int nocode_wanted; + + +static int global_expr; +static CType func_vt; +static int func_var; +static int func_vc; +static int last_line_num, last_ind, func_ind; +static const char *funcname; +static int g_debug; + +static CType char_pointer_type, func_old_type, int_type, size_type, ptrdiff_type; + +static struct switch_t { + struct case_t { + int64_t v1, v2; + int sym; + } **p; int n; + int def_sym; +} *cur_switch; + + + +static void gen_cast(CType *type); +static void gen_cast_s(int t); +static inline CType *pointed_type(CType *type); +static int is_compatible_types(CType *type1, CType *type2); +static int parse_btype(CType *type, AttributeDef *ad); +static CType *type_decl(CType *type, AttributeDef *ad, int *v, int td); +static void parse_expr_type(CType *type); +static void init_putv(CType *type, Section *sec, unsigned long c); +static void decl_initializer(CType *type, Section *sec, unsigned long c, int first, int size_only); +static void block(int *bsym, int *csym, int is_expr); +static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, int has_init, int v, int scope); +static void decl(int l); +static int decl0(int l, int is_for_loop_init, Sym *); +static void expr_eq(void); +static void vla_runtime_type_size(CType *type, int *a); +static void vla_sp_restore(void); +static void vla_sp_restore_root(void); +static int is_compatible_unqualified_types(CType *type1, CType *type2); +static inline int64_t expr_const64(void); +static void vpush64(int ty, unsigned long long v); +static void vpush(CType *type); +static int gvtst(int inv, int t); +static void gen_inline_functions(TCCState *s); +static void skip_or_save_block(TokenString **str); +static void gv_dup(void); + +static inline int is_float(int t) +{ + int bt; + bt = t & 0x000f; + return bt == 10 || bt == 9 || bt == 8 || bt == 14; +} + + + + +static int ieee_finite(double d) +{ + int p[4]; + memcpy(p, &d, sizeof(double)); + return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31; +} + + + + + + + +static void test_lvalue(void) +{ + if (!(vtop->r & 0x0100)) + expect("lvalue"); +} + +static void check_vstack(void) +{ + if (pvtop != vtop) + tcc_error("internal compiler error: vstack leak (%d)", vtop - pvtop); +} +# 154 "tccgen.c" +static void tcc_debug_start(TCCState *s1) +{ + if (s1->do_debug) { + char buf[512]; + + + section_sym = put_elf_sym(symtab_section, 0, 0, + ((((0)) << 4) + (((3)) & 0xf)), 0, + text_section->sh_num, 0); + getcwd(buf, sizeof(buf)); + + + + pstrcat(buf, sizeof(buf), "/"); + put_stabs_r(buf, N_SO, 0, 0, + text_section->data_offset, text_section, section_sym); + put_stabs_r(file->filename, N_SO, 0, 0, + text_section->data_offset, text_section, section_sym); + last_ind = 0; + last_line_num = 0; + } + + + + put_elf_sym(symtab_section, 0, 0, + ((((0)) << 4) + (((4)) & 0xf)), 0, + 0xfff1, file->filename); +} + + +static void tcc_debug_end(TCCState *s1) +{ + if (!s1->do_debug) + return; + put_stabs_r(0, N_SO, 0, 0, + text_section->data_offset, text_section, section_sym); + +} + + +static void tcc_debug_line(TCCState *s1) +{ + if (!s1->do_debug) + return; + if ((last_line_num != file->line_num || last_ind != ind)) { + put_stabn(N_SLINE, 0, file->line_num, ind - func_ind); + last_ind = ind; + last_line_num = file->line_num; + } +} + + +static void tcc_debug_funcstart(TCCState *s1, Sym *sym) +{ + char buf[512]; + + if (!s1->do_debug) + return; + + + + snprintf(buf, sizeof(buf), "%s:%c1", + funcname, sym->type.t & 0x00002000 ? 'f' : 'F'); + put_stabs_r(buf, N_FUN, 0, file->line_num, 0, + cur_text_section, sym->c); + + put_stabn(N_SLINE, 0, file->line_num, 0); + + last_ind = 0; + last_line_num = 0; +} + + +static void tcc_debug_funcend(TCCState *s1, int size) +{ + if (!s1->do_debug) + return; + put_stabn(N_FUN, 0, 0, size); +} + + +static int tccgen_compile(TCCState *s1) +{ + cur_text_section = 0; + funcname = ""; + anon_sym = 0x10000000; + section_sym = 0; + const_wanted = 0; + nocode_wanted = 0x80000000; + + + int_type.t = 3; + char_pointer_type.t = 1; + mk_pointer(&char_pointer_type); + + + + + + + + size_type.t = 0x0800 | 4 | 0x0010; + ptrdiff_type.t = 0x0800 | 4; + + func_old_type.t = 6; + func_old_type.ref = sym_push(0x20000000, &int_type, 0, 0); + func_old_type.ref->f.func_call = 0; + func_old_type.ref->f.func_type = 2; + + tcc_debug_start(s1); +# 273 "tccgen.c" + parse_flags = 0x0001 | 0x0002 | 0x0040; + next(); + decl(0x0030); + gen_inline_functions(s1); + check_vstack(); + + tcc_debug_end(s1); + return 0; +} + + +static Elf64_Sym *elfsym(Sym *s) +{ + if (!s || !s->c) + return 0; + return &((Elf64_Sym *)symtab_section->data)[s->c]; +} + + +static void update_storage(Sym *sym) +{ + Elf64_Sym *esym; + int sym_bind, old_sym_bind; + + esym = elfsym(sym); + if (!esym) + return; + + if (sym->a.visibility) + esym->st_other = (esym->st_other & ~((-1) & 0x03)) + | sym->a.visibility; + + if (sym->type.t & 0x00002000) + sym_bind = 0; + else if (sym->a.weak) + sym_bind = 2; + else + sym_bind = 1; + old_sym_bind = (((unsigned char) (esym->st_info)) >> 4); + if (sym_bind != old_sym_bind) { + esym->st_info = ((((sym_bind)) << 4) + (((((esym->st_info) & 0xf))) & 0xf)); + } +# 332 "tccgen.c" +} + + + + + +static void put_extern_sym2(Sym *sym, int sh_num, + Elf64_Addr value, unsigned long size, + int can_add_underscore) +{ + int sym_type, sym_bind, info, other, t; + Elf64_Sym *esym; + const char *name; + char buf1[256]; + + char buf[32]; + + + if (!sym->c) { + name = get_tok_str(sym->v, 0); + + if (tcc_state->do_bounds_check) { + + + + switch(sym->v) { +# 366 "tccgen.c" + case TOK_memcpy: + case TOK_memmove: + case TOK_memset: + case TOK_strlen: + case TOK_strcpy: + case TOK_alloca: + strcpy(buf, "__bound_"); + strcat(buf, name); + name = buf; + break; + } + } + + t = sym->type.t; + if ((t & 0x000f) == 6) { + sym_type = 2; + } else if ((t & 0x000f) == 0) { + sym_type = 0; + } else { + sym_type = 1; + } + if (t & 0x00002000) + sym_bind = 0; + else + sym_bind = 1; + other = 0; +# 403 "tccgen.c" + if (tcc_state->leading_underscore && can_add_underscore) { + buf1[0] = '_'; + pstrcpy(buf1 + 1, sizeof(buf1) - 1, name); + name = buf1; + } + if (sym->asm_label) + name = get_tok_str(sym->asm_label, 0); + info = ((((sym_bind)) << 4) + (((sym_type)) & 0xf)); + sym->c = put_elf_sym(symtab_section, value, size, info, other, sh_num, name); + } else { + esym = elfsym(sym); + esym->st_value = value; + esym->st_size = size; + esym->st_shndx = sh_num; + } + update_storage(sym); +} + +static void put_extern_sym(Sym *sym, Section *section, + Elf64_Addr value, unsigned long size) +{ + int sh_num = section ? section->sh_num : 0; + put_extern_sym2(sym, sh_num, value, size, 1); +} + + +static void greloca(Section *s, Sym *sym, unsigned long offset, int type, + Elf64_Addr addend) +{ + int c = 0; + + if (nocode_wanted && s == cur_text_section) + return; + + if (sym) { + if (0 == sym->c) + put_extern_sym(sym, 0, 0, 0); + c = sym->c; + } + + + put_elf_reloca(symtab_section, s, offset, type, c, addend); +} +# 456 "tccgen.c" +static Sym *__sym_malloc(void) +{ + Sym *sym_pool, *sym, *last_sym; + int i; + + sym_pool = tcc_malloc((8192 / sizeof(Sym)) * sizeof(Sym)); + dynarray_add(&sym_pools, &nb_sym_pools, sym_pool); + + last_sym = sym_free_first; + sym = sym_pool; + for(i = 0; i < (8192 / sizeof(Sym)); i++) { + sym->next = last_sym; + last_sym = sym; + sym++; + } + sym_free_first = last_sym; + return last_sym; +} + +static inline Sym *sym_malloc(void) +{ + Sym *sym; + + sym = sym_free_first; + if (!sym) + sym = __sym_malloc(); + sym_free_first = sym->next; + return sym; + + + + +} + +static inline void sym_free(Sym *sym) +{ + + sym->next = sym_free_first; + sym_free_first = sym; + + + +} + + +static Sym *sym_push2(Sym **ps, int v, int t, int c) +{ + Sym *s; + + s = sym_malloc(); + memset(s, 0, sizeof *s); + s->v = v; + s->type.t = t; + s->c = c; + + s->prev = *ps; + *ps = s; + return s; +} + + + +static Sym *sym_find2(Sym *s, int v) +{ + while (s) { + if (s->v == v) + return s; + else if (s->v == -1) + return 0; + s = s->prev; + } + return 0; +} + + +static inline Sym *struct_find(int v) +{ + v -= 256; + if ((unsigned)v >= (unsigned)(tok_ident - 256)) + return 0; + return table_ident[v]->sym_struct; +} + + +static inline Sym *sym_find(int v) +{ + v -= 256; + if ((unsigned)v >= (unsigned)(tok_ident - 256)) + return 0; + return table_ident[v]->sym_identifier; +} + + +static Sym *sym_push(int v, CType *type, int r, int c) +{ + Sym *s, **ps; + TokenSym *ts; + + if (local_stack) + ps = &local_stack; + else + ps = &global_stack; + s = sym_push2(ps, v, type->t, c); + s->type.ref = type->ref; + s->r = r; + + + if (!(v & 0x20000000) && (v & ~0x40000000) < 0x10000000) { + + ts = table_ident[(v & ~0x40000000) - 256]; + if (v & 0x40000000) + ps = &ts->sym_struct; + else + ps = &ts->sym_identifier; + s->prev_tok = *ps; + *ps = s; + s->sym_scope = local_scope; + if (s->prev_tok && s->prev_tok->sym_scope == s->sym_scope) + tcc_error("redeclaration of '%s'", + get_tok_str(v & ~0x40000000, 0)); + } + return s; +} + + +static Sym *global_identifier_push(int v, int t, int c) +{ + Sym *s, **ps; + s = sym_push2(&global_stack, v, t, c); + + if (v < 0x10000000) { + ps = &table_ident[v - 256]->sym_identifier; + + + while (*ps != 0 && (*ps)->sym_scope) + ps = &(*ps)->prev_tok; + s->prev_tok = *ps; + *ps = s; + } + return s; +} + + + +static void sym_pop(Sym **ptop, Sym *b, int keep) +{ + Sym *s, *ss, **ps; + TokenSym *ts; + int v; + + s = *ptop; + while(s != b) { + ss = s->prev; + v = s->v; + + + if (!(v & 0x20000000) && (v & ~0x40000000) < 0x10000000) { + ts = table_ident[(v & ~0x40000000) - 256]; + if (v & 0x40000000) + ps = &ts->sym_struct; + else + ps = &ts->sym_identifier; + *ps = s->prev_tok; + } + if (!keep) + sym_free(s); + s = ss; + } + if (!keep) + *ptop = b; +} + + + +static void vsetc(CType *type, int r, CValue *vc) +{ + int v; + + if (vtop >= (__vstack + 1) + (256 - 1)) + tcc_error("memory full (vstack)"); +# 649 "tccgen.c" + if (vtop >= (__vstack + 1) && !nocode_wanted) { + v = vtop->r & 0x003f; + if (v == 0x0033 || (v & ~1) == 0x0034) + gv(0x0001); + } + + vtop++; + vtop->type = *type; + vtop->r = r; + vtop->r2 = 0x0030; + vtop->c = *vc; + vtop->sym = 0; +} + +static void vswap(void) +{ + SValue tmp; + + if (vtop >= (__vstack + 1) && !nocode_wanted) { + int v = vtop->r & 0x003f; + if (v == 0x0033 || (v & ~1) == 0x0034) + gv(0x0001); + } + tmp = vtop[0]; + vtop[0] = vtop[-1]; + vtop[-1] = tmp; +} + + +static void vpop(void) +{ + int v; + v = vtop->r & 0x003f; + + + if (v == TREG_ST0) { + o(0xd8dd); + } else + + if (v == 0x0034 || v == 0x0035) { + + gsym(vtop->c.i); + } + vtop--; +} + + +static void vpush(CType *type) +{ + vset(type, 0x0030, 0); +} + + +static void vpushi(int v) +{ + CValue cval; + cval.i = v; + vsetc(&int_type, 0x0030, &cval); +} + + +static void vpushs(Elf64_Addr v) +{ + CValue cval; + cval.i = v; + vsetc(&size_type, 0x0030, &cval); +} + + +static void vpush64(int ty, unsigned long long v) +{ + CValue cval; + CType ctype; + ctype.t = ty; + ctype.ref = 0; + cval.i = v; + vsetc(&ctype, 0x0030, &cval); +} + + +static inline void vpushll(long long v) +{ + vpush64(4, v); +} + +static void vset(CType *type, int r, int v) +{ + CValue cval; + + cval.i = v; + vsetc(type, r, &cval); +} + +static void vseti(int r, int v) +{ + CType type; + type.t = 3; + type.ref = 0; + vset(&type, r, v); +} + +static void vpushv(SValue *v) +{ + if (vtop >= (__vstack + 1) + (256 - 1)) + tcc_error("memory full (vstack)"); + vtop++; + *vtop = *v; +} + +static void vdup(void) +{ + vpushv(vtop); +} + + + + +static void vrotb(int n) +{ + int i; + SValue tmp; + + tmp = vtop[-n + 1]; + for(i=-n+1;i!=0;i++) + vtop[i] = vtop[i+1]; + vtop[0] = tmp; +} + + + + +static void vrote(SValue *e, int n) +{ + int i; + SValue tmp; + + tmp = *e; + for(i = 0;i < n - 1; i++) + e[-i] = e[-i - 1]; + e[-n + 1] = tmp; +} + + + + +static void vrott(int n) +{ + vrote(vtop, n); +} + + +static inline void vpushsym(CType *type, Sym *sym) +{ + CValue cval; + cval.i = 0; + vsetc(type, 0x0030 | 0x0200, &cval); + vtop->sym = sym; +} + + +static Sym *get_sym_ref(CType *type, Section *sec, unsigned long offset, unsigned long size) +{ + int v; + Sym *sym; + + v = anon_sym++; + sym = global_identifier_push(v, type->t | 0x00002000, 0); + sym->type.ref = type->ref; + sym->r = 0x0030 | 0x0200; + put_extern_sym(sym, sec, offset, size); + return sym; +} + + +static void vpush_ref(CType *type, Section *sec, unsigned long offset, unsigned long size) +{ + vpushsym(type, get_sym_ref(type, sec, offset, size)); +} + + +static Sym *external_global_sym(int v, CType *type, int r) +{ + Sym *s; + + s = sym_find(v); + if (!s) { + + s = global_identifier_push(v, type->t | 0x00001000, 0); + s->type.ref = type->ref; + s->r = r | 0x0030 | 0x0200; + } else if ((((s)->type.t & (0x000f | (0 | 0x0010))) == (0 | 0x0010))) { + s->type.t = type->t | (s->type.t & 0x00001000); + s->type.ref = type->ref; + update_storage(s); + } + return s; +} + + +static void patch_type(Sym *sym, CType *type) +{ + if (!(type->t & 0x00001000)) { + if (!(sym->type.t & 0x00001000)) + tcc_error("redefinition of '%s'", get_tok_str(sym->v, 0)); + sym->type.t &= ~0x00001000; + } + + if ((((sym)->type.t & (0x000f | (0 | 0x0010))) == (0 | 0x0010))) { + + sym->type.t = type->t & (sym->type.t | ~0x00002000); + sym->type.ref = type->ref; + } + + if (!is_compatible_types(&sym->type, type)) { + tcc_error("incompatible types for redefinition of '%s'", + get_tok_str(sym->v, 0)); + + } else if ((sym->type.t & 0x000f) == 6) { + int static_proto = sym->type.t & 0x00002000; + + if ((type->t & 0x00002000) && !static_proto && !(type->t & 0x00008000)) + tcc_warning("static storage ignored for redefinition of '%s'", + get_tok_str(sym->v, 0)); + + if (0 == (type->t & 0x00001000)) { + + sym->type.t = (type->t & ~0x00002000) | static_proto; + if (type->t & 0x00008000) + sym->type.t = type->t; + sym->type.ref = type->ref; + } + + } else { + if ((sym->type.t & 0x0040) && type->ref->c >= 0) { + + if (sym->type.ref->c < 0) + sym->type.ref->c = type->ref->c; + else if (sym->type.ref->c != type->ref->c) + tcc_error("conflicting type for '%s'", get_tok_str(sym->v, 0)); + } + if ((type->t ^ sym->type.t) & 0x00002000) + tcc_warning("storage mismatch for redefinition of '%s'", + get_tok_str(sym->v, 0)); + } +} + + + +static void patch_storage(Sym *sym, AttributeDef *ad, CType *type) +{ + if (type) + patch_type(sym, type); + + + + + + + + sym->a.weak |= ad->a.weak; + if (ad->a.visibility) { + int vis = sym->a.visibility; + int vis2 = ad->a.visibility; + if (vis == 0) + vis = vis2; + else if (vis2 != 0) + vis = (vis < vis2) ? vis : vis2; + sym->a.visibility = vis; + } + if (ad->a.aligned) + sym->a.aligned = ad->a.aligned; + if (ad->asm_label) + sym->asm_label = ad->asm_label; + update_storage(sym); +} + + +static Sym *external_sym(int v, CType *type, int r, AttributeDef *ad) +{ + Sym *s; + s = sym_find(v); + if (!s) { + + s = sym_push(v, type, r | 0x0030 | 0x0200, 0); + s->type.t |= 0x00001000; + s->a = ad->a; + s->sym_scope = 0; + } else { + if (s->type.ref == func_old_type.ref) { + s->type.ref = type->ref; + s->r = r | 0x0030 | 0x0200; + s->type.t |= 0x00001000; + } + patch_storage(s, ad, type); + } + return s; +} + + +static void vpush_global_sym(CType *type, int v) +{ + vpushsym(type, external_global_sym(v, type, 0)); +} + + +static void save_regs(int n) +{ + SValue *p, *p1; + for(p = (__vstack + 1), p1 = vtop - n; p <= p1; p++) + save_reg(p->r); +} + + +static void save_reg(int r) +{ + save_reg_upstack(r, 0); +} + + + +static void save_reg_upstack(int r, int n) +{ + int l, saved, size, align; + SValue *p, *p1, sv; + CType *type; + + if ((r &= 0x003f) >= 0x0030) + return; + if (nocode_wanted) + return; + + + saved = 0; + l = 0; + for(p = (__vstack + 1), p1 = vtop - n; p <= p1; p++) { + if ((p->r & 0x003f) == r || + ((p->type.t & 0x000f) == 4 && (p->r2 & 0x003f) == r)) { + + if (!saved) { + + r = p->r & 0x003f; + + type = &p->type; + if ((p->r & 0x0100) || + (!is_float(type->t) && (type->t & 0x000f) != 4)) + + type = &char_pointer_type; + + + + size = type_size(type, &align); + loc = (loc - size) & -align; + sv.type.t = type->t; + sv.r = 0x0032 | 0x0100; + sv.c.i = loc; + store(r, &sv); + + + if (r == TREG_ST0) { + o(0xd8dd); + } +# 1018 "tccgen.c" + l = loc; + saved = 1; + } + + if (p->r & 0x0100) { + + + + p->r = (p->r & ~(0x003f | 0x8000)) | 0x0031; + } else { + p->r = lvalue_type(p->type.t) | 0x0032; + } + p->r2 = 0x0030; + p->c.i = l; + } + } +} +# 1062 "tccgen.c" +static int get_reg(int rc) +{ + int r; + SValue *p; + + + for(r=0;r<25;r++) { + if (reg_classes[r] & rc) { + if (nocode_wanted) + return r; + for(p=(__vstack + 1);p<=vtop;p++) { + if ((p->r & 0x003f) == r || + (p->r2 & 0x003f) == r) + goto notfound; + } + return r; + } + notfound: ; + } + + + + + for(p=(__vstack + 1);p<=vtop;p++) { + + r = p->r2 & 0x003f; + if (r < 0x0030 && (reg_classes[r] & rc)) + goto save_found; + r = p->r & 0x003f; + if (r < 0x0030 && (reg_classes[r] & rc)) { + save_found: + save_reg(r); + return r; + } + } + + return -1; +} + + + +static void move_reg(int r, int s, int t) +{ + SValue sv; + + if (r != s) { + save_reg(r); + sv.type.t = t; + sv.type.ref = 0; + sv.r = s; + sv.c.i = 0; + load(r, &sv); + } +} + + +static void gaddrof(void) +{ + vtop->r &= ~0x0100; + + if ((vtop->r & 0x003f) == 0x0031) + vtop->r = (vtop->r & ~(0x003f | (0x1000 | 0x2000 | 0x4000))) | 0x0032 | 0x0100; + + +} + + + +static void gbound(void) +{ + int lval_type; + CType type1; + + vtop->r &= ~0x0800; + + if (vtop->r & 0x0100) { + + if (!(vtop->r & 0x8000)) { + lval_type = vtop->r & ((0x1000 | 0x2000 | 0x4000) | 0x0100); + + type1 = vtop->type; + vtop->type.t = 5; + gaddrof(); + vpushi(0); + gen_bounded_ptr_add(); + vtop->r |= lval_type; + vtop->type = type1; + } + + gen_bounded_ptr_deref(); + } +} + + +static void incr_bf_adr(int o) +{ + vtop->type = char_pointer_type; + gaddrof(); + vpushi(o); + gen_op('+'); + vtop->type.t = (vtop->type.t & ~(0x000f|0x0020)) + | (1|0x0010); + vtop->r = (vtop->r & ~(0x1000 | 0x2000 | 0x4000)) + | (0x1000|0x4000|0x0100); +} + + +static void load_packed_bf(CType *type, int bit_pos, int bit_size) +{ + int n, o, bits; + save_reg_upstack(vtop->r, 1); + vpush64(type->t & 0x000f, 0); + bits = 0, o = bit_pos >> 3, bit_pos &= 7; + do { + vswap(); + incr_bf_adr(o); + vdup(); + n = 8 - bit_pos; + if (n > bit_size) + n = bit_size; + if (bit_pos) + vpushi(bit_pos), gen_op(0xc9), bit_pos = 0; + if (n < 8) + vpushi((1 << n) - 1), gen_op('&'); + gen_cast(type); + if (bits) + vpushi(bits), gen_op(0x01); + vrotb(3); + gen_op('|'); + bits += n, bit_size -= n, o = 1; + } while (bit_size); + vswap(), vpop(); + if (!(type->t & 0x0010)) { + n = ((type->t & 0x000f) == 4 ? 64 : 32) - bits; + vpushi(n), gen_op(0x01); + vpushi(n), gen_op(0x02); + } +} + + +static void store_packed_bf(int bit_pos, int bit_size) +{ + int bits, n, o, m, c; + + c = (vtop->r & (0x003f | 0x0100 | 0x0200)) == 0x0030; + vswap(); + save_reg_upstack(vtop->r, 1); + bits = 0, o = bit_pos >> 3, bit_pos &= 7; + do { + incr_bf_adr(o); + vswap(); + c ? vdup() : gv_dup(); + vrott(3); + if (bits) + vpushi(bits), gen_op(0xc9); + if (bit_pos) + vpushi(bit_pos), gen_op(0x01); + n = 8 - bit_pos; + if (n > bit_size) + n = bit_size; + if (n < 8) { + m = ((1 << n) - 1) << bit_pos; + vpushi(m), gen_op('&'); + vpushv(vtop-1); + vpushi(m & 0x80 ? ~m & 0x7f : ~m); + gen_op('&'); + gen_op('|'); + } + vdup(), vtop[-1] = vtop[-2]; + vstore(), vpop(); + bits += n, bit_size -= n, bit_pos = 0, o = 1; + } while (bit_size); + vpop(), vpop(); +} + +static int adjust_bf(SValue *sv, int bit_pos, int bit_size) +{ + int t; + if (0 == sv->type.ref) + return 0; + t = sv->type.ref->auxtype; + if (t != -1 && t != 7) { + sv->type.t = (sv->type.t & ~0x000f) | t; + sv->r = (sv->r & ~(0x1000 | 0x2000 | 0x4000)) | lvalue_type(sv->type.t); + } + return t; +} + + + + +static int gv(int rc) +{ + int r, bit_pos, bit_size, size, align, rc2; + + + if (vtop->type.t & 0x0080) { + CType type; + + bit_pos = (((vtop->type.t) >> 20) & 0x3f); + bit_size = (((vtop->type.t) >> (20 + 6)) & 0x3f); + + vtop->type.t &= ~(((1 << (6+6)) - 1) << 20 | 0x0080); + + type.ref = 0; + type.t = vtop->type.t & 0x0010; + if ((vtop->type.t & 0x000f) == 11) + type.t |= 0x0010; + + r = adjust_bf(vtop, bit_pos, bit_size); + + if ((vtop->type.t & 0x000f) == 4) + type.t |= 4; + else + type.t |= 3; + + if (r == 7) { + load_packed_bf(&type, bit_pos, bit_size); + } else { + int bits = (type.t & 0x000f) == 4 ? 64 : 32; + + gen_cast(&type); + + vpushi(bits - (bit_pos + bit_size)); + gen_op(0x01); + vpushi(bits - bit_size); + + gen_op(0x02); + } + r = gv(rc); + } else { + if (is_float(vtop->type.t) && + (vtop->r & (0x003f | 0x0100)) == 0x0030) { + unsigned long offset; + + + size = type_size(&vtop->type, &align); + if ((nocode_wanted > 0)) + size = 0, align = 1; + offset = section_add(data_section, size, align); + vpush_ref(&vtop->type, data_section, offset, size); + vswap(); + init_putv(&vtop->type, data_section, offset); + vtop->r |= 0x0100; + } + + if (vtop->r & 0x0800) + gbound(); + + + r = vtop->r & 0x003f; + rc2 = (rc & 0x0002) ? 0x0002 : 0x0001; + + if (rc == 0x0004) + rc2 = 0x0010; + + else if (rc == 0x1000) + rc2 = 0x2000; + + + + + + + if (r >= 0x0030 + || (vtop->r & 0x0100) + || !(reg_classes[r] & rc) + + || ((vtop->type.t & 0x000f) == 13 && !(reg_classes[vtop->r2] & rc2)) + || ((vtop->type.t & 0x000f) == 14 && !(reg_classes[vtop->r2] & rc2)) + + + + ) + { + r = get_reg(rc); + + if (((vtop->type.t & 0x000f) == 13) || ((vtop->type.t & 0x000f) == 14)) { + int addr_type = 4, load_size = 8, load_type = ((vtop->type.t & 0x000f) == 13) ? 4 : 9; + + + + + + int r2, original_type; + original_type = vtop->type.t; +# 1360 "tccgen.c" + if (vtop->r & 0x0100) { +# 1369 "tccgen.c" + save_reg_upstack(vtop->r, 1); + + + vtop->type.t = load_type; + load(r, vtop); + vdup(); + vtop[-1].r = r; + + vtop->type.t = addr_type; + gaddrof(); + vpushi(load_size); + gen_op('+'); + vtop->r |= 0x0100; + vtop->type.t = load_type; + } else { + + load(r, vtop); + vdup(); + vtop[-1].r = r; + vtop->r = vtop[-1].r2; + } + + + r2 = get_reg(rc2); + load(r2, vtop); + vpop(); + + vtop->r2 = r2; + vtop->type.t = original_type; + } else if ((vtop->r & 0x0100) && !is_float(vtop->type.t)) { + int t1, t; + + + t = vtop->type.t; + t1 = t; + + if (vtop->r & 0x1000) + t = 1; + else if (vtop->r & 0x2000) + t = 2; + if (vtop->r & 0x4000) + t |= 0x0010; + vtop->type.t = t; + load(r, vtop); + + vtop->type.t = t1; + } else { + + load(r, vtop); + } + } + vtop->r = r; + + + + + + } + return r; +} + + +static void gv2(int rc1, int rc2) +{ + int v; + + + + + v = vtop[0].r & 0x003f; + if (v != 0x0033 && (v & ~1) != 0x0034 && rc1 <= rc2) { + vswap(); + gv(rc1); + vswap(); + gv(rc2); + + if ((vtop[-1].r & 0x003f) >= 0x0030) { + vswap(); + gv(rc1); + vswap(); + } + } else { + gv(rc2); + vswap(); + gv(rc1); + vswap(); + + if ((vtop[0].r & 0x003f) >= 0x0030) { + gv(rc2); + } + } +} + + + +static int rc_fret(int t) +{ + + if (t == 10) { + return 0x0080; + } + + return 0x1000; +} + + + +static int reg_fret(int t) +{ + + if (t == 10) { + return TREG_ST0; + } + + return TREG_XMM0; +} +# 1550 "tccgen.c" +static void gv_dup(void) +{ + int rc, t, r, r1; + SValue sv; + + t = vtop->type.t; +# 1577 "tccgen.c" + { + + rc = 0x0001; + sv.type.t = 3; + if (is_float(t)) { + rc = 0x0002; + + if ((t & 0x000f) == 10) { + rc = 0x0080; + } + + sv.type.t = t; + } + r = gv(rc); + r1 = get_reg(rc); + sv.r = r; + sv.c.i = 0; + load(r1, &sv); + vdup(); + + if (r != r1) + vtop->r = r1; + } +} + + + + +static int gvtst(int inv, int t) +{ + int v = vtop->r & 0x003f; + if (v != 0x0033 && v != 0x0034 && v != 0x0035) { + vpushi(0); + gen_op(0x95); + } + if ((vtop->r & (0x003f | 0x0100 | 0x0200)) == 0x0030) { + + if ((vtop->c.i != 0) != inv) + t = gjmp(t); + vtop--; + return t; + } + return gtst(inv, t); +} +# 1851 "tccgen.c" +static uint64_t gen_opic_sdiv(uint64_t a, uint64_t b) +{ + uint64_t x = (a >> 63 ? -a : a) / (b >> 63 ? -b : b); + return (a ^ b) >> 63 ? -x : x; +} + +static int gen_opic_lt(uint64_t a, uint64_t b) +{ + return (a ^ (uint64_t)1 << 63) < (b ^ (uint64_t)1 << 63); +} + + + +static void gen_opic(int op) +{ + SValue *v1 = vtop - 1; + SValue *v2 = vtop; + int t1 = v1->type.t & 0x000f; + int t2 = v2->type.t & 0x000f; + int c1 = (v1->r & (0x003f | 0x0100 | 0x0200)) == 0x0030; + int c2 = (v2->r & (0x003f | 0x0100 | 0x0200)) == 0x0030; + uint64_t l1 = c1 ? v1->c.i : 0; + uint64_t l2 = c2 ? v2->c.i : 0; + int shm = (t1 == 4) ? 63 : 31; + + if (t1 != 4 && (8 != 8 || t1 != 5)) + l1 = ((uint32_t)l1 | + (v1->type.t & 0x0010 ? 0 : -(l1 & 0x80000000))); + if (t2 != 4 && (8 != 8 || t2 != 5)) + l2 = ((uint32_t)l2 | + (v2->type.t & 0x0010 ? 0 : -(l2 & 0x80000000))); + + if (c1 && c2) { + switch(op) { + case '+': l1 += l2; break; + case '-': l1 -= l2; break; + case '&': l1 &= l2; break; + case '^': l1 ^= l2; break; + case '|': l1 |= l2; break; + case '*': l1 *= l2; break; + + case 0xb2: + case '/': + case '%': + case 0xb0: + case 0xb1: + + if (l2 == 0) { + if (const_wanted) + tcc_error("division by zero in constant"); + goto general_case; + } + switch(op) { + default: l1 = gen_opic_sdiv(l1, l2); break; + case '%': l1 = l1 - l2 * gen_opic_sdiv(l1, l2); break; + case 0xb0: l1 = l1 / l2; break; + case 0xb1: l1 = l1 % l2; break; + } + break; + case 0x01: l1 <<= (l2 & shm); break; + case 0xc9: l1 >>= (l2 & shm); break; + case 0x02: + l1 = (l1 >> 63) ? ~(~l1 >> (l2 & shm)) : l1 >> (l2 & shm); + break; + + case 0x92: l1 = l1 < l2; break; + case 0x93: l1 = l1 >= l2; break; + case 0x94: l1 = l1 == l2; break; + case 0x95: l1 = l1 != l2; break; + case 0x96: l1 = l1 <= l2; break; + case 0x97: l1 = l1 > l2; break; + case 0x9c: l1 = gen_opic_lt(l1, l2); break; + case 0x9d: l1 = !gen_opic_lt(l1, l2); break; + case 0x9e: l1 = !gen_opic_lt(l2, l1); break; + case 0x9f: l1 = gen_opic_lt(l2, l1); break; + + case 0xa0: l1 = l1 && l2; break; + case 0xa1: l1 = l1 || l2; break; + default: + goto general_case; + } + if (t1 != 4 && (8 != 8 || t1 != 5)) + l1 = ((uint32_t)l1 | + (v1->type.t & 0x0010 ? 0 : -(l1 & 0x80000000))); + v1->c.i = l1; + vtop--; + } else { + + if (c1 && (op == '+' || op == '&' || op == '^' || + op == '|' || op == '*')) { + vswap(); + c2 = c1; + l2 = l1; + } + if (!const_wanted && + c1 && ((l1 == 0 && + (op == 0x01 || op == 0xc9 || op == 0x02)) || + (l1 == -1 && op == 0x02))) { + + vtop--; + } else if (!const_wanted && + c2 && ((l2 == 0 && (op == '&' || op == '*')) || + (op == '|' && + (l2 == -1 || (l2 == 0xFFFFFFFF && t2 != 4))) || + (l2 == 1 && (op == '%' || op == 0xb1)))) { + + if (l2 == 1) + vtop->c.i = 0; + vswap(); + vtop--; + } else if (c2 && (((op == '*' || op == '/' || op == 0xb0 || + op == 0xb2) && + l2 == 1) || + ((op == '+' || op == '-' || op == '|' || op == '^' || + op == 0x01 || op == 0xc9 || op == 0x02) && + l2 == 0) || + (op == '&' && + (l2 == -1 || (l2 == 0xFFFFFFFF && t2 != 4))))) { + + vtop--; + } else if (c2 && (op == '*' || op == 0xb2 || op == 0xb0)) { + + if (l2 > 0 && (l2 & (l2 - 1)) == 0) { + int n = -1; + while (l2) { + l2 >>= 1; + n++; + } + vtop->c.i = n; + if (op == '*') + op = 0x01; + else if (op == 0xb2) + op = 0x02; + else + op = 0xc9; + } + goto general_case; + } else if (c2 && (op == '+' || op == '-') && + (((vtop[-1].r & (0x003f | 0x0100 | 0x0200)) == (0x0030 | 0x0200)) + || (vtop[-1].r & (0x003f | 0x0100)) == 0x0032)) { + + if (op == '-') + l2 = -l2; + l2 += vtop[-1].c.i; + + + if ((int)l2 != l2) + goto general_case; + vtop--; + vtop->c.i = l2; + } else { + general_case: + + if (t1 == 4 || t2 == 4 || + (8 == 8 && (t1 == 5 || t2 == 5))) + gen_opl(op); + else + gen_opi(op); + } + } +} + + +static void gen_opif(int op) +{ + int c1, c2; + SValue *v1, *v2; + + + + + long double f1, f2; + + v1 = vtop - 1; + v2 = vtop; + + c1 = (v1->r & (0x003f | 0x0100 | 0x0200)) == 0x0030; + c2 = (v2->r & (0x003f | 0x0100 | 0x0200)) == 0x0030; + if (c1 && c2) { + if (v1->type.t == 8) { + f1 = v1->c.f; + f2 = v2->c.f; + } else if (v1->type.t == 9) { + f1 = v1->c.d; + f2 = v2->c.d; + } else { + f1 = v1->c.ld; + f2 = v2->c.ld; + } + + + + if (!ieee_finite(f1) || !ieee_finite(f2)) + goto general_case; + + switch(op) { + case '+': f1 += f2; break; + case '-': f1 -= f2; break; + case '*': f1 *= f2; break; + case '/': + if (f2 == 0.0) { + if (const_wanted) + tcc_error("division by zero in constant"); + goto general_case; + } + f1 /= f2; + break; + + default: + goto general_case; + } + + if (v1->type.t == 8) { + v1->c.f = f1; + } else if (v1->type.t == 9) { + v1->c.d = f1; + } else { + v1->c.ld = f1; + } + vtop--; + } else { + general_case: + gen_opf(op); + } +} + +static int pointed_size(CType *type) +{ + int align; + return type_size(pointed_type(type), &align); +} + +static void vla_runtime_pointed_size(CType *type) +{ + int align; + vla_runtime_type_size(pointed_type(type), &align); +} + +static inline int is_null_pointer(SValue *p) +{ + if ((p->r & (0x003f | 0x0100 | 0x0200)) != 0x0030) + return 0; + return ((p->type.t & 0x000f) == 3 && (uint32_t)p->c.i == 0) || + ((p->type.t & 0x000f) == 4 && p->c.i == 0) || + ((p->type.t & 0x000f) == 5 && + (8 == 4 ? (uint32_t)p->c.i == 0 : p->c.i == 0)); +} + +static inline int is_integer_btype(int bt) +{ + return (bt == 1 || bt == 2 || + bt == 3 || bt == 4); +} + + +static void check_comparison_pointer_types(SValue *p1, SValue *p2, int op) +{ + CType *type1, *type2, tmp_type1, tmp_type2; + int bt1, bt2; + + + if (is_null_pointer(p1) || is_null_pointer(p2)) + return; + type1 = &p1->type; + type2 = &p2->type; + bt1 = type1->t & 0x000f; + bt2 = type2->t & 0x000f; + + if ((is_integer_btype(bt1) || is_integer_btype(bt2)) && op != '-') { + if (op != 0xa1 && op != 0xa0 ) + tcc_warning("comparison between pointer and integer"); + return; + } + + + if (bt1 == 5) { + type1 = pointed_type(type1); + } else if (bt1 != 6) + goto invalid_operands; + + if (bt2 == 5) { + type2 = pointed_type(type2); + } else if (bt2 != 6) { + invalid_operands: + tcc_error("invalid operands to binary %s", get_tok_str(op, 0)); + } + if ((type1->t & 0x000f) == 0 || + (type2->t & 0x000f) == 0) + return; + tmp_type1 = *type1; + tmp_type2 = *type2; + tmp_type1.t &= ~(0x0020 | 0x0010 | 0x0100 | 0x0200); + tmp_type2.t &= ~(0x0020 | 0x0010 | 0x0100 | 0x0200); + if (!is_compatible_types(&tmp_type1, &tmp_type2)) { + + if (op == '-') + goto invalid_operands; + else + tcc_warning("comparison of distinct pointer types lacks a cast"); + } +} + + +static void gen_op(int op) +{ + int u, t1, t2, bt1, bt2, t; + CType type1; + +redo: + t1 = vtop[-1].type.t; + t2 = vtop[0].type.t; + bt1 = t1 & 0x000f; + bt2 = t2 & 0x000f; + + if (bt1 == 7 || bt2 == 7) { + tcc_error("operation on a struct"); + } else if (bt1 == 6 || bt2 == 6) { + if (bt2 == 6) { + mk_pointer(&vtop->type); + gaddrof(); + } + if (bt1 == 6) { + vswap(); + mk_pointer(&vtop->type); + gaddrof(); + vswap(); + } + goto redo; + } else if (bt1 == 5 || bt2 == 5) { + + + if (op >= 0x92 && op <= 0xa1) { + check_comparison_pointer_types(vtop - 1, vtop, op); + + + t = 4 | 0x0010; + + + + goto std_op; + } + + if (bt1 == 5 && bt2 == 5) { + if (op != '-') + tcc_error("cannot use pointers here"); + check_comparison_pointer_types(vtop - 1, vtop, op); + + if (vtop[-1].type.t & 0x0400) { + vla_runtime_pointed_size(&vtop[-1].type); + } else { + vpushi(pointed_size(&vtop[-1].type)); + } + vrott(3); + gen_opic(op); + vtop->type.t = ptrdiff_type.t; + vswap(); + gen_op(0xb2); + } else { + + if (op != '-' && op != '+') + tcc_error("cannot use pointers here"); + + if (bt2 == 5) { + vswap(); + t = t1, t1 = t2, t2 = t; + } + + + + + + type1 = vtop[-1].type; + type1.t &= ~0x0040; + if (vtop[-1].type.t & 0x0400) + vla_runtime_pointed_size(&vtop[-1].type); + else { + u = pointed_size(&vtop[-1].type); + if (u < 0) + tcc_error("unknown array element size"); + + vpushll(u); + + + + + } + gen_op('*'); +# 2267 "tccgen.c" + { + gen_opic(op); + } + + vtop->type = type1; + } + } else if (is_float(bt1) || is_float(bt2)) { + + if (bt1 == 10 || bt2 == 10) { + t = 10; + } else if (bt1 == 9 || bt2 == 9) { + t = 9; + } else { + t = 8; + } + + if (op != '+' && op != '-' && op != '*' && op != '/' && + (op < 0x92 || op > 0x9f)) + tcc_error("invalid operands for binary operation"); + goto std_op; + } else if (op == 0xc9 || op == 0x02 || op == 0x01) { + t = bt1 == 4 ? 4 : 3; + if ((t1 & (0x000f | 0x0010 | 0x0080)) == (t | 0x0010)) + t |= 0x0010; + t |= (0x0800 & t1); + goto std_op; + } else if (bt1 == 4 || bt2 == 4) { + + t = 4 | 0x0800; + if (bt1 == 4) + t &= t1; + if (bt2 == 4) + t &= t2; + + if ((t1 & (0x000f | 0x0010 | 0x0080)) == (4 | 0x0010) || + (t2 & (0x000f | 0x0010 | 0x0080)) == (4 | 0x0010)) + t |= 0x0010; + goto std_op; + } else { + + t = 3 | (0x0800 & (t1 | t2)); + + if ((t1 & (0x000f | 0x0010 | 0x0080)) == (3 | 0x0010) || + (t2 & (0x000f | 0x0010 | 0x0080)) == (3 | 0x0010)) + t |= 0x0010; + std_op: + + + if (t & 0x0010) { + if (op == 0x02) + op = 0xc9; + else if (op == '/') + op = 0xb0; + else if (op == '%') + op = 0xb1; + else if (op == 0x9c) + op = 0x92; + else if (op == 0x9f) + op = 0x97; + else if (op == 0x9e) + op = 0x96; + else if (op == 0x9d) + op = 0x93; + } + vswap(); + type1.t = t; + type1.ref = 0; + gen_cast(&type1); + vswap(); + + + if (op == 0xc9 || op == 0x02 || op == 0x01) + type1.t = 3; + gen_cast(&type1); + if (is_float(t)) + gen_opif(op); + else + gen_opic(op); + if (op >= 0x92 && op <= 0x9f) { + + vtop->type.t = 3; + } else { + vtop->type.t = t; + } + } + + if (vtop->r & 0x0100) + gv(is_float(vtop->type.t & 0x000f) ? 0x0002 : 0x0001); +} + + + +static void gen_cvt_itof1(int t) +{ + + + + if ((vtop->type.t & (0x000f | 0x0010)) == + (4 | 0x0010)) { + + if (t == 8) + vpush_global_sym(&func_old_type, TOK___floatundisf); + + else if (t == 10) + vpush_global_sym(&func_old_type, TOK___floatundixf); + + else + vpush_global_sym(&func_old_type, TOK___floatundidf); + vrott(2); + gfunc_call(1); + vpushi(0); + vtop->r = reg_fret(t); + } else { + gen_cvt_itof(t); + } + +} + + + +static void gen_cvt_ftoi1(int t) +{ + + + + int st; + + if (t == (4 | 0x0010)) { + + st = vtop->type.t & 0x000f; + if (st == 8) + vpush_global_sym(&func_old_type, TOK___fixunssfdi); + + else if (st == 10) + vpush_global_sym(&func_old_type, TOK___fixunsxfdi); + + else + vpush_global_sym(&func_old_type, TOK___fixunsdfdi); + vrott(2); + gfunc_call(1); + vpushi(0); + vtop->r = TREG_RAX; + vtop->r2 = TREG_RDX; + } else { + gen_cvt_ftoi(t); + } + +} + + +static void force_charshort_cast(int t) +{ + int bits, dbt; + + + if ((nocode_wanted & 0xC0000000)) + return; + + dbt = t & 0x000f; + + if (dbt == 1) + bits = 8; + else + bits = 16; + if (t & 0x0010) { + vpushi((1 << bits) - 1); + gen_op('&'); + } else { + if ((vtop->type.t & 0x000f) == 4) + bits = 64 - bits; + else + bits = 32 - bits; + vpushi(bits); + gen_op(0x01); + + + + vtop->type.t &= ~0x0010; + vpushi(bits); + gen_op(0x02); + } +} + + +static void gen_cast_s(int t) +{ + CType type; + type.t = t; + type.ref = 0; + gen_cast(&type); +} + +static void gen_cast(CType *type) +{ + int sbt, dbt, sf, df, c, p; + + + + + if (vtop->r & 0x0400) { + vtop->r &= ~0x0400; + force_charshort_cast(vtop->type.t); + } + + + if (vtop->type.t & 0x0080) { + gv(0x0001); + } + + dbt = type->t & (0x000f | 0x0010); + sbt = vtop->type.t & (0x000f | 0x0010); + + if (sbt != dbt) { + sf = is_float(sbt); + df = is_float(dbt); + c = (vtop->r & (0x003f | 0x0100 | 0x0200)) == 0x0030; + p = (vtop->r & (0x003f | 0x0100 | 0x0200)) == (0x0030 | 0x0200); + + + + if (c) { + + + if (sbt == 8) + vtop->c.ld = vtop->c.f; + else if (sbt == 9) + vtop->c.ld = vtop->c.d; + + if (df) { + if ((sbt & 0x000f) == 4) { + if ((sbt & 0x0010) || !(vtop->c.i >> 63)) + vtop->c.ld = vtop->c.i; + else + vtop->c.ld = -(long double)-vtop->c.i; + } else if(!sf) { + if ((sbt & 0x0010) || !(vtop->c.i >> 31)) + vtop->c.ld = (uint32_t)vtop->c.i; + else + vtop->c.ld = -(long double)-(uint32_t)vtop->c.i; + } + + if (dbt == 8) + vtop->c.f = (float)vtop->c.ld; + else if (dbt == 9) + vtop->c.d = (double)vtop->c.ld; + } else if (sf && dbt == (4|0x0010)) { + vtop->c.i = vtop->c.ld; + } else if (sf && dbt == 11) { + vtop->c.i = (vtop->c.ld != 0); + } else { + if(sf) + vtop->c.i = vtop->c.ld; + else if (sbt == (4|0x0010)) + ; + else if (sbt & 0x0010) + vtop->c.i = (uint32_t)vtop->c.i; + + else if (sbt == 5) + ; + + else if (sbt != 4) + vtop->c.i = ((uint32_t)vtop->c.i | + -(vtop->c.i & 0x80000000)); + + if (dbt == (4|0x0010)) + ; + else if (dbt == 11) + vtop->c.i = (vtop->c.i != 0); + + else if (dbt == 5) + ; + + else if (dbt != 4) { + uint32_t m = ((dbt & 0x000f) == 1 ? 0xff : + (dbt & 0x000f) == 2 ? 0xffff : + 0xffffffff); + vtop->c.i &= m; + if (!(dbt & 0x0010)) + vtop->c.i |= -(vtop->c.i & ((m >> 1) + 1)); + } + } + } else if (p && dbt == 11) { + vtop->r = 0x0030; + vtop->c.i = 1; + } else { + + if (sf && df) { + + gen_cvt_ftof(dbt); + } else if (df) { + + gen_cvt_itof1(dbt); + } else if (sf) { + + if (dbt == 11) { + vpushi(0); + gen_op(0x95); + } else { + + if (dbt != (3 | 0x0010) && + dbt != (4 | 0x0010) && + dbt != 4) + dbt = 3; + gen_cvt_ftoi1(dbt); + if (dbt == 3 && (type->t & (0x000f | 0x0010)) != dbt) { + + vtop->type.t = dbt; + gen_cast(type); + } + } +# 2602 "tccgen.c" + } else if ((dbt & 0x000f) == 4 || + (dbt & 0x000f) == 5 || + (dbt & 0x000f) == 6) { + if ((sbt & 0x000f) != 4 && + (sbt & 0x000f) != 5 && + (sbt & 0x000f) != 6) { + + gv(0x0001); + if (sbt != (3 | 0x0010)) { + + + + int r = gv(0x0001); + + o(0x6348); + o(0xc0 + (((r) & 7) << 3) + ((r) & 7)); + + + + } + } + + } else if (dbt == 11) { + + vpushi(0); + gen_op(0x95); + } else if ((dbt & 0x000f) == 1 || + (dbt & 0x000f) == 2) { + if (sbt == 5) { + vtop->type.t = 3; + tcc_warning("nonportable conversion from pointer to char/short"); + } + force_charshort_cast(dbt); +# 2647 "tccgen.c" + } + } + } else if ((dbt & 0x000f) == 5 && !(vtop->r & 0x0100)) { + + + vtop->r = (vtop->r & ~(0x1000 | 0x2000 | 0x4000)) + | (lvalue_type(type->ref->type.t) & (0x1000 | 0x2000 | 0x4000)); + } + vtop->type = *type; +} + + +static int type_size(CType *type, int *a) +{ + Sym *s; + int bt; + + bt = type->t & 0x000f; + if (bt == 7) { + + s = type->ref; + *a = s->r; + return s->c; + } else if (bt == 5) { + if (type->t & 0x0040) { + int ts; + + s = type->ref; + ts = type_size(&s->type, a); + + if (ts < 0 && s->c < 0) + ts = -ts; + + return ts * s->c; + } else { + *a = 8; + return 8; + } + } else if (((type->t & (((1 << (6+6)) - 1) << 20 | 0x0080)) == (2 << 20)) && type->ref->c == -1) { + return -1; + } else if (bt == 10) { + *a = 16; + return 16; + } else if (bt == 9 || bt == 4) { +# 2704 "tccgen.c" + *a = 8; + + return 8; + } else if (bt == 3 || bt == 8) { + *a = 4; + return 4; + } else if (bt == 2) { + *a = 2; + return 2; + } else if (bt == 13 || bt == 14) { + *a = 8; + return 16; + } else { + + *a = 1; + return 1; + } +} + + + +static void vla_runtime_type_size(CType *type, int *a) +{ + if (type->t & 0x0400) { + type_size(&type->ref->type, a); + vset(&int_type, 0x0032|0x0100, type->ref->c); + } else { + vpushi(type_size(type, a)); + } +} + +static void vla_sp_restore(void) { + if (vlas_in_scope) { + gen_vla_sp_restore(vla_sp_loc); + } +} + +static void vla_sp_restore_root(void) { + if (vlas_in_scope) { + gen_vla_sp_restore(vla_sp_root_loc); + } +} + + +static inline CType *pointed_type(CType *type) +{ + return &type->ref->type; +} + + +static void mk_pointer(CType *type) +{ + Sym *s; + s = sym_push(0x20000000, type, 0, -1); + type->t = 5 | (type->t & (0x00001000 | 0x00002000 | 0x00004000 | 0x00008000)); + type->ref = s; +} + + +static int is_compatible_func(CType *type1, CType *type2) +{ + Sym *s1, *s2; + + s1 = type1->ref; + s2 = type2->ref; + if (!is_compatible_types(&s1->type, &s2->type)) + return 0; + + if (s1->f.func_call != s2->f.func_call) + return 0; + + if (s1->f.func_type == 2 || s2->f.func_type == 2) + return 1; + if (s1->f.func_type != s2->f.func_type) + return 0; + while (s1 != 0) { + if (s2 == 0) + return 0; + if (!is_compatible_unqualified_types(&s1->type, &s2->type)) + return 0; + s1 = s1->next; + s2 = s2->next; + } + if (s2) + return 0; + return 1; +} + + + + + + +static int compare_types(CType *type1, CType *type2, int unqualified) +{ + int bt1, t1, t2; + + t1 = type1->t & (~((0x00001000 | 0x00002000 | 0x00004000 | 0x00008000)|(((1 << (6+6)) - 1) << 20 | 0x0080))); + t2 = type2->t & (~((0x00001000 | 0x00002000 | 0x00004000 | 0x00008000)|(((1 << (6+6)) - 1) << 20 | 0x0080))); + if (unqualified) { + + t1 &= ~(0x0100 | 0x0200); + t2 &= ~(0x0100 | 0x0200); + } + + + if ((t1 & 0x000f) != 1) { + t1 &= ~0x0020; + t2 &= ~0x0020; + } + + if (t1 != t2) + return 0; + + bt1 = t1 & 0x000f; + if (bt1 == 5) { + type1 = pointed_type(type1); + type2 = pointed_type(type2); + return is_compatible_types(type1, type2); + } else if (bt1 == 7) { + return (type1->ref == type2->ref); + } else if (bt1 == 6) { + return is_compatible_func(type1, type2); + } else { + return 1; + } +} + + + + +static int is_compatible_types(CType *type1, CType *type2) +{ + return compare_types(type1,type2,0); +} + + + +static int is_compatible_unqualified_types(CType *type1, CType *type2) +{ + return compare_types(type1,type2,1); +} + + + + + +static void type_to_str(char *buf, int buf_size, + CType *type, const char *varstr) +{ + int bt, v, t; + Sym *s, *sa; + char buf1[256]; + const char *tstr; + + t = type->t; + bt = t & 0x000f; + buf[0] = '\0'; + + if (t & 0x00001000) + pstrcat(buf, buf_size, "extern "); + if (t & 0x00002000) + pstrcat(buf, buf_size, "static "); + if (t & 0x00004000) + pstrcat(buf, buf_size, "typedef "); + if (t & 0x00008000) + pstrcat(buf, buf_size, "inline "); + if (t & 0x0200) + pstrcat(buf, buf_size, "volatile "); + if (t & 0x0100) + pstrcat(buf, buf_size, "const "); + + if (((t & 0x0020) && bt == 1) + || ((t & 0x0010) + && (bt == 2 || bt == 3 || bt == 4) + && !((t & (((1 << (6+6)) - 1) << 20 | 0x0080)) == (2 << 20)) + )) + pstrcat(buf, buf_size, (t & 0x0010) ? "unsigned " : "signed "); + + buf_size -= strlen(buf); + buf += strlen(buf); + + switch(bt) { + case 0: + tstr = "void"; + goto add_tstr; + case 11: + tstr = "_Bool"; + goto add_tstr; + case 1: + tstr = "char"; + goto add_tstr; + case 2: + tstr = "short"; + goto add_tstr; + case 3: + tstr = "int"; + goto maybe_long; + case 4: + tstr = "long long"; + maybe_long: + if (t & 0x0800) + tstr = "long"; + if (!((t & (((1 << (6+6)) - 1) << 20 | 0x0080)) == (2 << 20))) + goto add_tstr; + tstr = "enum "; + goto tstruct; + case 8: + tstr = "float"; + goto add_tstr; + case 9: + tstr = "double"; + goto add_tstr; + case 10: + tstr = "long double"; + add_tstr: + pstrcat(buf, buf_size, tstr); + break; + case 7: + tstr = "struct "; + if (((t & ((((1 << (6+6)) - 1) << 20 | 0x0080)|0x000f)) == (1 << 20 | 7))) + tstr = "union "; + tstruct: + pstrcat(buf, buf_size, tstr); + v = type->ref->v & ~0x40000000; + if (v >= 0x10000000) + pstrcat(buf, buf_size, "<anonymous>"); + else + pstrcat(buf, buf_size, get_tok_str(v, 0)); + break; + case 6: + s = type->ref; + type_to_str(buf, buf_size, &s->type, varstr); + pstrcat(buf, buf_size, "("); + sa = s->next; + while (sa != 0) { + type_to_str(buf1, sizeof(buf1), &sa->type, 0); + pstrcat(buf, buf_size, buf1); + sa = sa->next; + if (sa) + pstrcat(buf, buf_size, ", "); + } + pstrcat(buf, buf_size, ")"); + goto no_var; + case 5: + s = type->ref; + if (t & 0x0040) { + snprintf(buf1, sizeof(buf1), "%s[%d]", varstr ? varstr : "", s->c); + type_to_str(buf, buf_size, &s->type, buf1); + goto no_var; + } + pstrcpy(buf1, sizeof(buf1), "*"); + if (t & 0x0100) + pstrcat(buf1, buf_size, "const "); + if (t & 0x0200) + pstrcat(buf1, buf_size, "volatile "); + if (varstr) + pstrcat(buf1, sizeof(buf1), varstr); + type_to_str(buf, buf_size, &s->type, buf1); + goto no_var; + } + if (varstr) { + pstrcat(buf, buf_size, " "); + pstrcat(buf, buf_size, varstr); + } + no_var: ; +} + + + +static void gen_assign_cast(CType *dt) +{ + CType *st, *type1, *type2; + char buf1[256], buf2[256]; + int dbt, sbt; + + st = &vtop->type; + dbt = dt->t & 0x000f; + sbt = st->t & 0x000f; + if (sbt == 0 || dbt == 0) { + if (sbt == 0 && dbt == 0) + ; +# 2994 "tccgen.c" + else + tcc_error("cannot cast from/to void"); + } + if (dt->t & 0x0100) + tcc_warning("assignment of read-only location"); + switch(dbt) { + case 5: + + + if (is_null_pointer(vtop)) + goto type_ok; + + if (is_integer_btype(sbt)) { + tcc_warning("assignment makes pointer from integer without a cast"); + goto type_ok; + } + type1 = pointed_type(dt); + + if (sbt == 6) { + if ((type1->t & 0x000f) != 0 && + !is_compatible_types(pointed_type(dt), st)) + tcc_warning("assignment from incompatible pointer type"); + goto type_ok; + } + if (sbt != 5) + goto error; + type2 = pointed_type(st); + if ((type1->t & 0x000f) == 0 || + (type2->t & 0x000f) == 0) { + + } else { + + + if (!is_compatible_unqualified_types(type1, type2)) { + + + + + if ((type1->t & (0x000f|0x0800)) != (type2->t & (0x000f|0x0800)) + || ((type1->t & (((1 << (6+6)) - 1) << 20 | 0x0080)) == (2 << 20)) || ((type2->t & (((1 << (6+6)) - 1) << 20 | 0x0080)) == (2 << 20)) + ) + tcc_warning("assignment from incompatible pointer type"); + } + } + + if ((!(type1->t & 0x0100) && (type2->t & 0x0100)) || + (!(type1->t & 0x0200) && (type2->t & 0x0200))) + tcc_warning("assignment discards qualifiers from pointer target type"); + break; + case 1: + case 2: + case 3: + case 4: + if (sbt == 5 || sbt == 6) { + tcc_warning("assignment makes integer from pointer without a cast"); + } else if (sbt == 7) { + goto case_VT_STRUCT; + } + + break; + case 7: + case_VT_STRUCT: + if (!is_compatible_unqualified_types(dt, st)) { + error: + type_to_str(buf1, sizeof(buf1), st, 0); + type_to_str(buf2, sizeof(buf2), dt, 0); + tcc_error("cannot cast '%s' to '%s'", buf1, buf2); + } + break; + } + type_ok: + gen_cast(dt); +} + + +static void vstore(void) +{ + int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast; + + ft = vtop[-1].type.t; + sbt = vtop->type.t & 0x000f; + dbt = ft & 0x000f; + if ((((sbt == 3 || sbt == 2) && dbt == 1) || + (sbt == 3 && dbt == 2)) + && !(vtop->type.t & 0x0080)) { + + delayed_cast = 0x0400; + vtop->type.t = ft & (~((0x00001000 | 0x00002000 | 0x00004000 | 0x00008000)|(((1 << (6+6)) - 1) << 20 | 0x0080))); + + if (ft & 0x0100) + tcc_warning("assignment of read-only location"); + } else { + delayed_cast = 0; + if (!(ft & 0x0080)) + gen_assign_cast(&vtop[-1].type); + } + + if (sbt == 7) { + + + + size = type_size(&vtop->type, &align); + + + vswap(); + vtop->type.t = 5; + gaddrof(); +# 3111 "tccgen.c" + vpush_global_sym(&func_old_type, TOK_memmove); + + vswap(); + + vpushv(vtop - 2); + vtop->type.t = 5; + gaddrof(); + + vpushi(size); + gfunc_call(3); + + + } else if (ft & 0x0080) { + + + + vdup(), vtop[-1] = vtop[-2]; + + bit_pos = (((ft) >> 20) & 0x3f); + bit_size = (((ft) >> (20 + 6)) & 0x3f); + + vtop[-1].type.t = ft & ~(((1 << (6+6)) - 1) << 20 | 0x0080); + + if ((ft & 0x000f) == 11) { + gen_cast(&vtop[-1].type); + vtop[-1].type.t = (vtop[-1].type.t & ~0x000f) | (1 | 0x0010); + } + + r = adjust_bf(vtop - 1, bit_pos, bit_size); + if (r == 7) { + gen_cast_s((ft & 0x000f) == 4 ? 4 : 3); + store_packed_bf(bit_pos, bit_size); + } else { + unsigned long long mask = (1ULL << bit_size) - 1; + if ((ft & 0x000f) != 11) { + + if ((vtop[-1].type.t & 0x000f) == 4) + vpushll(mask); + else + vpushi((unsigned)mask); + gen_op('&'); + } + + vpushi(bit_pos); + gen_op(0x01); + vswap(); + + vdup(); + vrott(3); + + if ((vtop->type.t & 0x000f) == 4) + vpushll(~(mask << bit_pos)); + else + vpushi(~((unsigned)mask << bit_pos)); + gen_op('&'); + gen_op('|'); + + vstore(); + + vpop(); + } + } else if (dbt == 0) { + --vtop; + } else { + + + if (vtop[-1].r & 0x0800) { + vswap(); + gbound(); + vswap(); + } + + rc = 0x0001; + if (is_float(ft)) { + rc = 0x0002; + + if ((ft & 0x000f) == 10) { + rc = 0x0080; + } else if ((ft & 0x000f) == 14) { + rc = 0x1000; + } + + } + r = gv(rc); + + if ((vtop[-1].r & 0x003f) == 0x0031) { + SValue sv; + t = get_reg(0x0001); + + sv.type.t = 5; + + + + sv.r = 0x0032 | 0x0100; + sv.c.i = vtop[-1].c.i; + load(t, &sv); + vtop[-1].r = t | 0x0100; + } + + + if (((ft & 0x000f) == 13) || ((ft & 0x000f) == 14)) { + int addr_type = 4, load_size = 8, load_type = ((vtop->type.t & 0x000f) == 13) ? 4 : 9; + + + + + vtop[-1].type.t = load_type; + store(r, vtop - 1); + vswap(); + + vtop->type.t = addr_type; + gaddrof(); + vpushi(load_size); + gen_op('+'); + vtop->r |= 0x0100; + vswap(); + vtop[-1].type.t = load_type; + + store(vtop->r2, vtop - 1); + } else { + store(r, vtop - 1); + } + + vswap(); + vtop--; + vtop->r |= delayed_cast; + } +} + + +static void inc(int post, int c) +{ + test_lvalue(); + vdup(); + if (post) { + gv_dup(); + vrotb(3); + vrotb(3); + } + + vpushi(c - 0xa3); + gen_op('+'); + vstore(); + if (post) + vpop(); +} + +static void parse_mult_str (CString *astr, const char *msg) +{ + + if (tok != 0xb9) + expect(msg); + cstr_new(astr); + while (tok == 0xb9) { + + cstr_cat(astr, tokc.str.data, -1); + next(); + } + cstr_ccat(astr, '\0'); +} + + + +static int exact_log2p1(int i) +{ + int ret; + if (!i) + return 0; + for (ret = 1; i >= 1 << 8; ret += 8) + i >>= 8; + if (i >= 1 << 4) + ret += 4, i >>= 4; + if (i >= 1 << 2) + ret += 2, i >>= 2; + if (i >= 1 << 1) + ret++; + return ret; +} + + +static void parse_attribute(AttributeDef *ad) +{ + int t, n; + CString astr; + +redo: + if (tok != TOK_ATTRIBUTE1 && tok != TOK_ATTRIBUTE2) + return; + next(); + skip('('); + skip('('); + while (tok != ')') { + if (tok < 256) + expect("attribute name"); + t = tok; + next(); + switch(t) { + case TOK_SECTION1: + case TOK_SECTION2: + skip('('); + parse_mult_str(&astr, "section name"); + ad->section = find_section(tcc_state, (char *)astr.data); + skip(')'); + cstr_free(&astr); + break; + case TOK_ALIAS1: + case TOK_ALIAS2: + skip('('); + parse_mult_str(&astr, "alias(\"target\")"); + ad->alias_target = + tok_alloc((char*)astr.data, astr.size-1)->tok; + skip(')'); + cstr_free(&astr); + break; + case TOK_VISIBILITY1: + case TOK_VISIBILITY2: + skip('('); + parse_mult_str(&astr, + "visibility(\"default|hidden|internal|protected\")"); + if (!strcmp (astr.data, "default")) + ad->a.visibility = 0; + else if (!strcmp (astr.data, "hidden")) + ad->a.visibility = 2; + else if (!strcmp (astr.data, "internal")) + ad->a.visibility = 1; + else if (!strcmp (astr.data, "protected")) + ad->a.visibility = 3; + else + expect("visibility(\"default|hidden|internal|protected\")"); + skip(')'); + cstr_free(&astr); + break; + case TOK_ALIGNED1: + case TOK_ALIGNED2: + if (tok == '(') { + next(); + n = expr_const(); + if (n <= 0 || (n & (n - 1)) != 0) + tcc_error("alignment must be a positive power of two"); + skip(')'); + } else { + n = 16; + } + ad->a.aligned = exact_log2p1(n); + if (n != 1 << (ad->a.aligned - 1)) + tcc_error("alignment of %d is larger than implemented", n); + break; + case TOK_PACKED1: + case TOK_PACKED2: + ad->a.packed = 1; + break; + case TOK_WEAK1: + case TOK_WEAK2: + ad->a.weak = 1; + break; + case TOK_UNUSED1: + case TOK_UNUSED2: + + + break; + case TOK_NORETURN1: + case TOK_NORETURN2: + + + break; + case TOK_CDECL1: + case TOK_CDECL2: + case TOK_CDECL3: + ad->f.func_call = 0; + break; + case TOK_STDCALL1: + case TOK_STDCALL2: + case TOK_STDCALL3: + ad->f.func_call = 1; + break; +# 3405 "tccgen.c" + case TOK_MODE: + skip('('); + switch(tok) { + case TOK_MODE_DI: + ad->attr_mode = 4 + 1; + break; + case TOK_MODE_QI: + ad->attr_mode = 1 + 1; + break; + case TOK_MODE_HI: + ad->attr_mode = 2 + 1; + break; + case TOK_MODE_SI: + case TOK_MODE_word: + ad->attr_mode = 3 + 1; + break; + default: + tcc_warning("__mode__(%s) not supported\n", get_tok_str(tok, 0)); + break; + } + next(); + skip(')'); + break; + case TOK_DLLEXPORT: + ad->a.dllexport = 1; + break; + case TOK_DLLIMPORT: + ad->a.dllimport = 1; + break; + default: + if (tcc_state->warn_unsupported) + tcc_warning("'%s' attribute ignored", get_tok_str(t, 0)); + + if (tok == '(') { + int parenthesis = 0; + do { + if (tok == '(') + parenthesis++; + else if (tok == ')') + parenthesis--; + next(); + } while (parenthesis && tok != -1); + } + break; + } + if (tok != ',') + break; + next(); + } + skip(')'); + skip(')'); + goto redo; +} + +static Sym * find_field (CType *type, int v) +{ + Sym *s = type->ref; + v |= 0x20000000; + while ((s = s->next) != 0) { + if ((s->v & 0x20000000) && + (s->type.t & 0x000f) == 7 && + (s->v & ~0x20000000) >= 0x10000000) { + Sym *ret = find_field (&s->type, v); + if (ret) + return ret; + } + if (s->v == v) + break; + } + return s; +} + +static void struct_add_offset (Sym *s, int offset) +{ + while ((s = s->next) != 0) { + if ((s->v & 0x20000000) && + (s->type.t & 0x000f) == 7 && + (s->v & ~0x20000000) >= 0x10000000) { + struct_add_offset(s->type.ref, offset); + } else + s->c += offset; + } +} + +static void struct_layout(CType *type, AttributeDef *ad) +{ + int size, align, maxalign, offset, c, bit_pos, bit_size; + int packed, a, bt, prevbt, prev_bit_size; + int pcc = !tcc_state->ms_bitfields; + int pragma_pack = *tcc_state->pack_stack_ptr; + Sym *f; + + maxalign = 1; + offset = 0; + c = 0; + bit_pos = 0; + prevbt = 7; + prev_bit_size = 0; + + + + for (f = type->ref->next; f; f = f->next) { + if (f->type.t & 0x0080) + bit_size = (((f->type.t) >> (20 + 6)) & 0x3f); + else + bit_size = -1; + size = type_size(&f->type, &align); + a = f->a.aligned ? 1 << (f->a.aligned - 1) : 0; + packed = 0; + + if (pcc && bit_size == 0) { + + + } else { + + if (pcc && (f->a.packed || ad->a.packed)) + align = packed = 1; + + + if (pragma_pack) { + packed = 1; + if (pragma_pack < align) + align = pragma_pack; + + if (pcc && pragma_pack < a) + a = 0; + } + } + + if (a) + align = a; + + if (type->ref->type.t == (1 << 20 | 7)) { + if (pcc && bit_size >= 0) + size = (bit_size + 7) >> 3; + offset = 0; + if (size > c) + c = size; + + } else if (bit_size < 0) { + if (pcc) + c += (bit_pos + 7) >> 3; + c = (c + align - 1) & -align; + offset = c; + if (size > 0) + c += size; + bit_pos = 0; + prevbt = 7; + prev_bit_size = 0; + + } else { + + + if (pcc) { + + + + + + + if (bit_size == 0) { + new_field: + c = (c + ((bit_pos + 7) >> 3) + align - 1) & -align; + bit_pos = 0; + } else if (f->a.aligned) { + goto new_field; + } else if (!packed) { + int a8 = align * 8; + int ofs = ((c * 8 + bit_pos) % a8 + bit_size + a8 - 1) / a8; + if (ofs > size / align) + goto new_field; + } + + + if (size == 8 && bit_size <= 32) + f->type.t = (f->type.t & ~0x000f) | 3, size = 4; + + while (bit_pos >= align * 8) + c += align, bit_pos -= align * 8; + offset = c; + + + + + if (f->v & 0x10000000 + + ) + align = 1; + + } else { + bt = f->type.t & 0x000f; + if ((bit_pos + bit_size > size * 8) + || (bit_size > 0) == (bt != prevbt) + ) { + c = (c + align - 1) & -align; + offset = c; + bit_pos = 0; + + + + + if (bit_size || prev_bit_size) + c += size; + } + + + + + if (bit_size == 0 && prevbt != bt) + align = 1; + prevbt = bt; + prev_bit_size = bit_size; + } + + f->type.t = (f->type.t & ~(0x3f << 20)) + | (bit_pos << 20); + bit_pos += bit_size; + } + if (align > maxalign) + maxalign = align; +# 3638 "tccgen.c" + if (f->v & 0x10000000 && (f->type.t & 0x000f) == 7) { + Sym *ass; + + + + + + + + int v2 = f->type.ref->v; + if (!(v2 & 0x20000000) && + (v2 & ~0x40000000) < 0x10000000) { + Sym **pps; + + + + + + ass = f->type.ref; + f->type.ref = sym_push(anon_sym++ | 0x20000000, + &f->type.ref->type, 0, + f->type.ref->c); + pps = &f->type.ref->next; + while ((ass = ass->next) != 0) { + *pps = sym_push(ass->v, &ass->type, 0, ass->c); + pps = &((*pps)->next); + } + *pps = 0; + } + struct_add_offset(f->type.ref, offset); + f->c = 0; + } else { + f->c = offset; + } + + f->r = 0; + } + + if (pcc) + c += (bit_pos + 7) >> 3; + + + a = bt = ad->a.aligned ? 1 << (ad->a.aligned - 1) : 1; + if (a < maxalign) + a = maxalign; + type->ref->r = a; + if (pragma_pack && pragma_pack < maxalign && 0 == pcc) { + + + a = pragma_pack; + if (a < bt) + a = bt; + } + c = (c + a - 1) & -a; + type->ref->c = c; + + + + + + + for (f = type->ref->next; f; f = f->next) { + int s, px, cx, c0; + CType t; + + if (0 == (f->type.t & 0x0080)) + continue; + f->type.ref = f; + f->auxtype = -1; + bit_size = (((f->type.t) >> (20 + 6)) & 0x3f); + if (bit_size == 0) + continue; + bit_pos = (((f->type.t) >> 20) & 0x3f); + size = type_size(&f->type, &align); + if (bit_pos + bit_size <= size * 8 && f->c + size <= c) + continue; + + + c0 = -1, s = align = 1; + for (;;) { + px = f->c * 8 + bit_pos; + cx = (px >> 3) & -align; + px = px - (cx << 3); + if (c0 == cx) + break; + s = (px + bit_size + 7) >> 3; + if (s > 4) { + t.t = 4; + } else if (s > 2) { + t.t = 3; + } else if (s > 1) { + t.t = 2; + } else { + t.t = 1; + } + s = type_size(&t, &align); + c0 = cx; + } + + if (px + bit_size <= s * 8 && cx + s <= c) { + + f->c = cx; + bit_pos = px; + f->type.t = (f->type.t & ~(0x3f << 20)) + | (bit_pos << 20); + if (s != size) + f->auxtype = t.t; + + + + + + + } else { + + f->auxtype = 7; + + + + + } + } +} + + +static void struct_decl(CType *type, int u) +{ + int v, c, size, align, flexible; + int bit_size, bsize, bt; + Sym *s, *ss, **ps; + AttributeDef ad, ad1; + CType type1, btype; + + memset(&ad, 0, sizeof ad); + next(); + parse_attribute(&ad); + if (tok != '{') { + v = tok; + next(); + + if (v < 256) + expect("struct/union/enum name"); + s = struct_find(v); + if (s && (s->sym_scope == local_scope || tok != '{')) { + if (u == s->type.t) + goto do_decl; + if (u == (2 << 20) && ((s->type.t & (((1 << (6+6)) - 1) << 20 | 0x0080)) == (2 << 20))) + goto do_decl; + tcc_error("redefinition of '%s'", get_tok_str(v, 0)); + } + } else { + v = anon_sym++; + } + + type1.t = u == (2 << 20) ? u | 3 | 0x0010 : u; + type1.ref = 0; + + s = sym_push(v | 0x40000000, &type1, 0, -1); + s->r = 0; +do_decl: + type->t = s->type.t; + type->ref = s; + + if (tok == '{') { + next(); + if (s->c != -1) + tcc_error("struct/union/enum already defined"); + + + ps = &s->next; + if (u == (2 << 20)) { + long long ll = 0, pl = 0, nl = 0; + CType t; + t.ref = s; + + t.t = 3|0x00002000|(3 << 20); + for(;;) { + v = tok; + if (v < TOK_DEFINE) + expect("identifier"); + ss = sym_find(v); + if (ss && !local_stack) + tcc_error("redefinition of enumerator '%s'", + get_tok_str(v, 0)); + next(); + if (tok == '=') { + next(); + ll = expr_const64(); + } + ss = sym_push(v, &t, 0x0030, 0); + ss->enum_val = ll; + *ps = ss, ps = &ss->next; + if (ll < nl) + nl = ll; + if (ll > pl) + pl = ll; + if (tok != ',') + break; + next(); + ll++; + + if (tok == '}') + break; + } + skip('}'); + + t.t = 3; + if (nl >= 0) { + if (pl != (unsigned)pl) + t.t = (8==8 ? 4|0x0800 : 4); + t.t |= 0x0010; + } else if (pl != (int)pl || nl != (int)nl) + t.t = (8==8 ? 4|0x0800 : 4); + s->type.t = type->t = t.t | (2 << 20); + s->c = 0; + + for (ss = s->next; ss; ss = ss->next) { + ll = ss->enum_val; + if (ll == (int)ll) + continue; + if (t.t & 0x0010) { + ss->type.t |= 0x0010; + if (ll == (unsigned)ll) + continue; + } + ss->type.t = (ss->type.t & ~0x000f) + | (8==8 ? 4|0x0800 : 4); + } + } else { + c = 0; + flexible = 0; + while (tok != '}') { + if (!parse_btype(&btype, &ad1)) { + skip(';'); + continue; + } + while (1) { + if (flexible) + tcc_error("flexible array member '%s' not at the end of struct", + get_tok_str(v, 0)); + bit_size = -1; + v = 0; + type1 = btype; + if (tok != ':') { + if (tok != ';') + type_decl(&type1, &ad1, &v, 2); + if (v == 0) { + if ((type1.t & 0x000f) != 7) + expect("identifier"); + else { + int v = btype.ref->v; + if (!(v & 0x20000000) && (v & ~0x40000000) < 0x10000000) { + if (tcc_state->ms_extensions == 0) + expect("identifier"); + } + } + } + if (type_size(&type1, &align) < 0) { + if ((u == 7) && (type1.t & 0x0040) && c) + flexible = 1; + else + tcc_error("field '%s' has incomplete type", + get_tok_str(v, 0)); + } + if ((type1.t & 0x000f) == 6 || + (type1.t & (0x00001000 | 0x00002000 | 0x00004000 | 0x00008000))) + tcc_error("invalid type for '%s'", + get_tok_str(v, 0)); + } + if (tok == ':') { + next(); + bit_size = expr_const(); + + if (bit_size < 0) + tcc_error("negative width in bit-field '%s'", + get_tok_str(v, 0)); + if (v && bit_size == 0) + tcc_error("zero width for bit-field '%s'", + get_tok_str(v, 0)); + parse_attribute(&ad1); + } + size = type_size(&type1, &align); + if (bit_size >= 0) { + bt = type1.t & 0x000f; + if (bt != 3 && + bt != 1 && + bt != 2 && + bt != 11 && + bt != 4) + tcc_error("bitfields must have scalar type"); + bsize = size * 8; + if (bit_size > bsize) { + tcc_error("width of '%s' exceeds its type", + get_tok_str(v, 0)); + } else if (bit_size == bsize + && !ad.a.packed && !ad1.a.packed) { + + ; + } else if (bit_size == 64) { + tcc_error("field width 64 not implemented"); + } else { + type1.t = (type1.t & ~(((1 << (6+6)) - 1) << 20 | 0x0080)) + | 0x0080 + | (bit_size << (20 + 6)); + } + } + if (v != 0 || (type1.t & 0x000f) == 7) { + + + c = 1; + } + + + if (v == 0 && + ((type1.t & 0x000f) == 7 || + bit_size >= 0)) { + v = anon_sym++; + } + if (v) { + ss = sym_push(v | 0x20000000, &type1, 0, 0); + ss->a = ad1.a; + *ps = ss; + ps = &ss->next; + } + if (tok == ';' || tok == (-1)) + break; + skip(','); + } + skip(';'); + } + skip('}'); + parse_attribute(&ad); + struct_layout(type, &ad); + } + } +} + +static void sym_to_attr(AttributeDef *ad, Sym *s) +{ + if (s->a.aligned && 0 == ad->a.aligned) + ad->a.aligned = s->a.aligned; + if (s->f.func_call && 0 == ad->f.func_call) + ad->f.func_call = s->f.func_call; + if (s->f.func_type && 0 == ad->f.func_type) + ad->f.func_type = s->f.func_type; + if (s->a.packed) + ad->a.packed = 1; +} + + + +static void parse_btype_qualify(CType *type, int qualifiers) +{ + while (type->t & 0x0040) { + type->ref = sym_push(0x20000000, &type->ref->type, 0, type->ref->c); + type = &type->ref->type; + } + type->t |= qualifiers; +} + + + + +static int parse_btype(CType *type, AttributeDef *ad) +{ + int t, u, bt, st, type_found, typespec_found, g; + Sym *s; + CType type1; + + memset(ad, 0, sizeof(AttributeDef)); + type_found = 0; + typespec_found = 0; + t = 3; + bt = st = -1; + type->ref = 0; + + while(1) { + switch(tok) { + case TOK_EXTENSION: + + next(); + continue; + + + case TOK_CHAR: + u = 1; + basic_type: + next(); + basic_type1: + if (u == 2 || u == 0x0800) { + if (st != -1 || (bt != -1 && bt != 3)) + tmbt: tcc_error("too many basic types"); + st = u; + } else { + if (bt != -1 || (st != -1 && u != 3)) + goto tmbt; + bt = u; + } + if (u != 3) + t = (t & ~(0x000f|0x0800)) | u; + typespec_found = 1; + break; + case TOK_VOID: + u = 0; + goto basic_type; + case TOK_SHORT: + u = 2; + goto basic_type; + case TOK_INT: + u = 3; + goto basic_type; + case TOK_LONG: + if ((t & 0x000f) == 9) { + t = (t & ~(0x000f|0x0800)) | 10; + } else if ((t & (0x000f|0x0800)) == 0x0800) { + t = (t & ~(0x000f|0x0800)) | 4; + } else { + u = 0x0800; + goto basic_type; + } + next(); + break; + + + + + + + + case TOK_BOOL: + u = 11; + goto basic_type; + case TOK_FLOAT: + u = 8; + goto basic_type; + case TOK_DOUBLE: + if ((t & (0x000f|0x0800)) == 0x0800) { + t = (t & ~(0x000f|0x0800)) | 10; + } else { + u = 9; + goto basic_type; + } + next(); + break; + case TOK_ENUM: + struct_decl(&type1, (2 << 20)); + basic_type2: + u = type1.t; + type->ref = type1.ref; + goto basic_type1; + case TOK_STRUCT: + struct_decl(&type1, 7); + goto basic_type2; + case TOK_UNION: + struct_decl(&type1, (1 << 20 | 7)); + goto basic_type2; + + + case TOK_CONST1: + case TOK_CONST2: + case TOK_CONST3: + type->t = t; + parse_btype_qualify(type, 0x0100); + t = type->t; + next(); + break; + case TOK_VOLATILE1: + case TOK_VOLATILE2: + case TOK_VOLATILE3: + type->t = t; + parse_btype_qualify(type, 0x0200); + t = type->t; + next(); + break; + case TOK_SIGNED1: + case TOK_SIGNED2: + case TOK_SIGNED3: + if ((t & (0x0020|0x0010)) == (0x0020|0x0010)) + tcc_error("signed and unsigned modifier"); + t |= 0x0020; + next(); + typespec_found = 1; + break; + case TOK_REGISTER: + case TOK_AUTO: + case TOK_RESTRICT1: + case TOK_RESTRICT2: + case TOK_RESTRICT3: + next(); + break; + case TOK_UNSIGNED: + if ((t & (0x0020|0x0010)) == 0x0020) + tcc_error("signed and unsigned modifier"); + t |= 0x0020 | 0x0010; + next(); + typespec_found = 1; + break; + + + case TOK_EXTERN: + g = 0x00001000; + goto storage; + case TOK_STATIC: + g = 0x00002000; + goto storage; + case TOK_TYPEDEF: + g = 0x00004000; + goto storage; + storage: + if (t & (0x00001000|0x00002000|0x00004000) & ~g) + tcc_error("multiple storage classes"); + t |= g; + next(); + break; + case TOK_INLINE1: + case TOK_INLINE2: + case TOK_INLINE3: + t |= 0x00008000; + next(); + break; + + + case TOK_ATTRIBUTE1: + case TOK_ATTRIBUTE2: + parse_attribute(ad); + if (ad->attr_mode) { + u = ad->attr_mode -1; + t = (t & ~(0x000f|0x0800)) | u; + } + break; + + case TOK_TYPEOF1: + case TOK_TYPEOF2: + case TOK_TYPEOF3: + next(); + parse_expr_type(&type1); + + type1.t &= ~((0x00001000 | 0x00002000 | 0x00004000 | 0x00008000)&~0x00004000); + if (type1.ref) + sym_to_attr(ad, type1.ref); + goto basic_type2; + default: + if (typespec_found) + goto the_end; + s = sym_find(tok); + if (!s || !(s->type.t & 0x00004000)) + goto the_end; + t &= ~(0x000f|0x0800); + u = t & ~(0x0100 | 0x0200), t ^= u; + type->t = (s->type.t & ~0x00004000) | u; + type->ref = s->type.ref; + if (t) + parse_btype_qualify(type, t); + t = type->t; + + sym_to_attr(ad, s); + next(); + typespec_found = 1; + st = bt = -2; + break; + } + type_found = 1; + } +the_end: + if (tcc_state->char_is_unsigned) { + if ((t & (0x0020|0x000f)) == 1) + t |= 0x0010; + } + + bt = t & (0x000f|0x0800); + if (bt == 0x0800) + t |= 8 == 8 ? 4 : 3; + + + + + type->t = t; + return type_found; +} + + + +static inline void convert_parameter_type(CType *pt) +{ + + + pt->t &= ~(0x0100 | 0x0200); + + pt->t &= ~0x0040; + if ((pt->t & 0x000f) == 6) { + mk_pointer(pt); + } +} + +static void parse_asm_str(CString *astr) +{ + skip('('); + parse_mult_str(astr, "string constant"); +} + + +static int asm_label_instr(void) +{ + int v; + CString astr; + + next(); + parse_asm_str(&astr); + skip(')'); + + + + v = tok_alloc(astr.data, astr.size - 1)->tok; + cstr_free(&astr); + return v; +} + +static int post_type(CType *type, AttributeDef *ad, int storage, int td) +{ + int n, l, t1, arg_size, align; + Sym **plast, *s, *first; + AttributeDef ad1; + CType pt; + + if (tok == '(') { + + next(); + if (td && !(td & 1)) + return 0; + if (tok == ')') + l = 0; + else if (parse_btype(&pt, &ad1)) + l = 1; + else if (td) + return 0; + else + l = 2; + first = 0; + plast = &first; + arg_size = 0; + if (l) { + for(;;) { + + if (l != 2) { + if ((pt.t & 0x000f) == 0 && tok == ')') + break; + type_decl(&pt, &ad1, &n, 2 | 1); + if ((pt.t & 0x000f) == 0) + tcc_error("parameter declared as void"); + arg_size += (type_size(&pt, &align) + 8 - 1) / 8; + } else { + n = tok; + if (n < TOK_DEFINE) + expect("identifier"); + pt.t = 0; + next(); + } + convert_parameter_type(&pt); + s = sym_push(n | 0x20000000, &pt, 0, 0); + *plast = s; + plast = &s->next; + if (tok == ')') + break; + skip(','); + if (l == 1 && tok == 0xc8) { + l = 3; + next(); + break; + } + if (l == 1 && !parse_btype(&pt, &ad1)) + tcc_error("invalid type"); + } + } else + + l = 2; + skip(')'); + + + type->t &= ~0x0100; + + + + if (tok == '[') { + next(); + skip(']'); + mk_pointer(type); + } + + ad->f.func_args = arg_size; + ad->f.func_type = l; + s = sym_push(0x20000000, type, 0, 0); + s->a = ad->a; + s->f = ad->f; + s->next = first; + type->t = 6; + type->ref = s; + } else if (tok == '[') { + int saved_nocode_wanted = nocode_wanted; + + next(); + if (tok == TOK_RESTRICT1) + next(); + n = -1; + t1 = 0; + if (tok != ']') { + if (!local_stack || (storage & 0x00002000)) + vpushi(expr_const()); + else { + + + + + nocode_wanted = 0; + gexpr(); + } + if ((vtop->r & (0x003f | 0x0100 | 0x0200)) == 0x0030) { + n = vtop->c.i; + if (n < 0) + tcc_error("invalid array size"); + } else { + if (!is_integer_btype(vtop->type.t & 0x000f)) + tcc_error("size of variable length array should be an integer"); + t1 = 0x0400; + } + } + skip(']'); + + post_type(type, ad, storage, 0); + if (type->t == 6) + tcc_error("declaration of an array of functions"); + t1 |= type->t & 0x0400; + + if (t1 & 0x0400) { + loc -= type_size(&int_type, &align); + loc &= -align; + n = loc; + + vla_runtime_type_size(type, &align); + gen_op('*'); + vset(&int_type, 0x0032|0x0100, n); + vswap(); + vstore(); + } + if (n != -1) + vpop(); + nocode_wanted = saved_nocode_wanted; + + + + s = sym_push(0x20000000, type, 0, n); + type->t = (t1 ? 0x0400 : 0x0040) | 5; + type->ref = s; + } + return 1; +} +# 4401 "tccgen.c" +static CType *type_decl(CType *type, AttributeDef *ad, int *v, int td) +{ + CType *post, *ret; + int qualifiers, storage; + + + storage = type->t & (0x00001000 | 0x00002000 | 0x00004000 | 0x00008000); + type->t &= ~(0x00001000 | 0x00002000 | 0x00004000 | 0x00008000); + post = ret = type; + + while (tok == '*') { + qualifiers = 0; + redo: + next(); + switch(tok) { + case TOK_CONST1: + case TOK_CONST2: + case TOK_CONST3: + qualifiers |= 0x0100; + goto redo; + case TOK_VOLATILE1: + case TOK_VOLATILE2: + case TOK_VOLATILE3: + qualifiers |= 0x0200; + goto redo; + case TOK_RESTRICT1: + case TOK_RESTRICT2: + case TOK_RESTRICT3: + goto redo; + + case TOK_ATTRIBUTE1: + case TOK_ATTRIBUTE2: + parse_attribute(ad); + break; + } + mk_pointer(type); + type->t |= qualifiers; + if (ret == type) + + ret = pointed_type(type); + } + + if (tok == '(') { + + + if (!post_type(type, ad, 0, td)) { + + + + + parse_attribute(ad); + post = type_decl(type, ad, v, td); + skip(')'); + } + } else if (tok >= 256 && (td & 2)) { + + *v = tok; + next(); + } else { + if (!(td & 1)) + expect("identifier"); + *v = 0; + } + post_type(post, ad, storage, 0); + parse_attribute(ad); + type->t |= storage; + return ret; +} + + +static int lvalue_type(int t) +{ + int bt, r; + r = 0x0100; + bt = t & 0x000f; + if (bt == 1 || bt == 11) + r |= 0x1000; + else if (bt == 2) + r |= 0x2000; + else + return r; + if (t & 0x0010) + r |= 0x4000; + return r; +} + + +static void indir(void) +{ + if ((vtop->type.t & 0x000f) != 5) { + if ((vtop->type.t & 0x000f) == 6) + return; + expect("pointer"); + } + if (vtop->r & 0x0100) + gv(0x0001); + vtop->type = *pointed_type(&vtop->type); + + if (!(vtop->type.t & 0x0040) && !(vtop->type.t & 0x0400) + && (vtop->type.t & 0x000f) != 6) { + vtop->r |= lvalue_type(vtop->type.t); + + + if (tcc_state->do_bounds_check) + vtop->r |= 0x0800; + + } +} + + +static void gfunc_param_typed(Sym *func, Sym *arg) +{ + int func_type; + CType type; + + func_type = func->f.func_type; + if (func_type == 2 || + (func_type == 3 && arg == 0)) { + + if ((vtop->type.t & 0x000f) == 8) { + gen_cast_s(9); + } else if (vtop->type.t & 0x0080) { + type.t = vtop->type.t & (0x000f | 0x0010); + type.ref = vtop->type.ref; + gen_cast(&type); + } + } else if (arg == 0) { + tcc_error("too many arguments to function"); + } else { + type = arg->type; + type.t &= ~0x0100; + gen_assign_cast(&type); + } +} + + +static void expr_type(CType *type, void (*expr_fn)(void)) +{ + nocode_wanted++; + expr_fn(); + *type = vtop->type; + vpop(); + nocode_wanted--; +} + + + +static void parse_expr_type(CType *type) +{ + int n; + AttributeDef ad; + + skip('('); + if (parse_btype(type, &ad)) { + type_decl(type, &ad, &n, 1); + } else { + expr_type(type, gexpr); + } + skip(')'); +} + +static void parse_type(CType *type) +{ + AttributeDef ad; + int n; + + if (!parse_btype(type, &ad)) { + expect("type"); + } + type_decl(type, &ad, &n, 1); +} + +static void parse_builtin_params(int nc, const char *args) +{ + char c, sep = '('; + CType t; + if (nc) + nocode_wanted++; + next(); + while ((c = *args++)) { + skip(sep); + sep = ','; + switch (c) { + case 'e': expr_eq(); continue; + case 't': parse_type(&t); vpush(&t); continue; + default: tcc_error("internal error"); break; + } + } + skip(')'); + if (nc) + nocode_wanted--; +} + +static void unary(void) +{ + int n, t, align, size, r, sizeof_caller; + CType type; + Sym *s; + AttributeDef ad; + + sizeof_caller = in_sizeof; + in_sizeof = 0; + type.ref = 0; + + + tok_next: + switch(tok) { + case TOK_EXTENSION: + next(); + goto tok_next; + case 0xb4: + + + + + case 0xb5: + case 0xb3: + t = 3; + push_tokc: + type.t = t; + vsetc(&type, 0x0030, &tokc); + next(); + break; + case 0xb6: + t = 3 | 0x0010; + goto push_tokc; + case 0xb7: + t = 4; + goto push_tokc; + case 0xb8: + t = 4 | 0x0010; + goto push_tokc; + case 0xbb: + t = 8; + goto push_tokc; + case 0xbc: + t = 9; + goto push_tokc; + case 0xbd: + t = 10; + goto push_tokc; + case 0xce: + t = (8 == 8 ? 4 : 3) | 0x0800; + goto push_tokc; + case 0xcf: + t = (8 == 8 ? 4 : 3) | 0x0800 | 0x0010; + goto push_tokc; + case TOK___FUNCTION__: + if (!gnu_ext) + goto tok_identifier; + + case TOK___FUNC__: + { + void *ptr; + int len; + + len = strlen(funcname) + 1; + + type.t = 1; + mk_pointer(&type); + type.t |= 0x0040; + type.ref->c = len; + vpush_ref(&type, data_section, data_section->data_offset, len); + if (!(nocode_wanted > 0)) { + ptr = section_ptr_add(data_section, len); + memcpy(ptr, funcname, len); + } + next(); + } + break; + case 0xba: + + + + t = 3; + + goto str_init; + case 0xb9: + + t = 1; + if (tcc_state->char_is_unsigned) + t = 1 | 0x0010; + str_init: + if (tcc_state->warn_write_strings) + t |= 0x0100; + type.t = t; + mk_pointer(&type); + type.t |= 0x0040; + memset(&ad, 0, sizeof(AttributeDef)); + decl_initializer_alloc(&type, &ad, 0x0030, 2, 0, 0); + break; + case '(': + next(); + + if (parse_btype(&type, &ad)) { + type_decl(&type, &ad, &n, 1); + skip(')'); + + if (tok == '{') { + + if (global_expr) + r = 0x0030; + else + r = 0x0032; + + if (!(type.t & 0x0040)) + r |= lvalue_type(type.t); + memset(&ad, 0, sizeof(AttributeDef)); + decl_initializer_alloc(&type, &ad, r, 1, 0, 0); + } else { + if (sizeof_caller) { + vpush(&type); + return; + } + unary(); + gen_cast(&type); + } + } else if (tok == '{') { + int saved_nocode_wanted = nocode_wanted; + if (const_wanted) + tcc_error("expected constant"); + + save_regs(0); + + + + + + block(0, 0, 1); + nocode_wanted = saved_nocode_wanted; + skip(')'); + } else { + gexpr(); + skip(')'); + } + break; + case '*': + next(); + unary(); + indir(); + break; + case '&': + next(); + unary(); + + + + + + if ((vtop->type.t & 0x000f) != 6 && + !(vtop->type.t & 0x0040)) + test_lvalue(); + mk_pointer(&vtop->type); + gaddrof(); + break; + case '!': + next(); + unary(); + if ((vtop->r & (0x003f | 0x0100 | 0x0200)) == 0x0030) { + gen_cast_s(11); + vtop->c.i = !vtop->c.i; + } else if ((vtop->r & 0x003f) == 0x0033) + vtop->c.i ^= 1; + else { + save_regs(1); + vseti(0x0034, gvtst(1, 0)); + } + break; + case '~': + next(); + unary(); + vpushi(-1); + gen_op('^'); + break; + case '+': + next(); + unary(); + if ((vtop->type.t & 0x000f) == 5) + tcc_error("pointer not accepted for unary plus"); + + + + if (!is_float(vtop->type.t)) { + vpushi(0); + gen_op('+'); + } + break; + case TOK_SIZEOF: + case TOK_ALIGNOF1: + case TOK_ALIGNOF2: + t = tok; + next(); + in_sizeof++; + expr_type(&type, unary); + s = vtop[1].sym; + size = type_size(&type, &align); + if (s && s->a.aligned) + align = 1 << (s->a.aligned - 1); + if (t == TOK_SIZEOF) { + if (!(type.t & 0x0400)) { + if (size < 0) + tcc_error("sizeof applied to an incomplete type"); + vpushs(size); + } else { + vla_runtime_type_size(&type, &align); + } + } else { + vpushs(align); + } + vtop->type.t |= 0x0010; + break; + + case TOK_builtin_expect: + + parse_builtin_params(0, "ee"); + vpop(); + break; + case TOK_builtin_types_compatible_p: + parse_builtin_params(0, "tt"); + vtop[-1].type.t &= ~(0x0100 | 0x0200); + vtop[0].type.t &= ~(0x0100 | 0x0200); + n = is_compatible_types(&vtop[-1].type, &vtop[0].type); + vtop -= 2; + vpushi(n); + break; + case TOK_builtin_choose_expr: + { + int64_t c; + next(); + skip('('); + c = expr_const64(); + skip(','); + if (!c) { + nocode_wanted++; + } + expr_eq(); + if (!c) { + vpop(); + nocode_wanted--; + } + skip(','); + if (c) { + nocode_wanted++; + } + expr_eq(); + if (c) { + vpop(); + nocode_wanted--; + } + skip(')'); + } + break; + case TOK_builtin_constant_p: + parse_builtin_params(1, "e"); + n = (vtop->r & (0x003f | 0x0100 | 0x0200)) == 0x0030; + vtop--; + vpushi(n); + break; + case TOK_builtin_frame_address: + case TOK_builtin_return_address: + { + int tok1 = tok; + int level; + next(); + skip('('); + if (tok != 0xb5) { + tcc_error("%s only takes positive integers", + tok1 == TOK_builtin_return_address ? + "__builtin_return_address" : + "__builtin_frame_address"); + } + level = (uint32_t)tokc.i; + next(); + skip(')'); + type.t = 0; + mk_pointer(&type); + vset(&type, 0x0032, 0); + while (level--) { + mk_pointer(&vtop->type); + indir(); + } + if (tok1 == TOK_builtin_return_address) { + + vpushi(8); + gen_op('+'); + mk_pointer(&vtop->type); + indir(); + } + } + break; +# 4906 "tccgen.c" + case TOK_builtin_va_arg_types: + parse_builtin_params(0, "t"); + vpushi(classify_x86_64_va_arg(&vtop->type)); + vswap(); + vpop(); + break; +# 4942 "tccgen.c" + case 0xa4: + case 0xa2: + t = tok; + next(); + unary(); + inc(0, t); + break; + case '-': + next(); + unary(); + t = vtop->type.t & 0x000f; + if (is_float(t)) { + + + vpush(&vtop->type); + if (t == 8) + vtop->c.f = -1.0 * 0.0; + else if (t == 9) + vtop->c.d = -1.0 * 0.0; + else + vtop->c.ld = -1.0 * 0.0; + } else + vpushi(0); + vswap(); + gen_op('-'); + break; + case 0xa0: + if (!gnu_ext) + goto tok_identifier; + next(); + + if (tok < TOK_DEFINE) + expect("label identifier"); + s = label_find(tok); + if (!s) { + s = label_push(&global_label_stack, tok, 1); + } else { + if (s->r == 2) + s->r = 1; + } + if (!s->type.t) { + s->type.t = 0; + mk_pointer(&s->type); + s->type.t |= 0x00002000; + } + vpushsym(&s->type, s); + next(); + break; + + case TOK_GENERIC: + { + CType controlling_type; + int has_default = 0; + int has_match = 0; + int learn = 0; + TokenString *str = 0; + + next(); + skip('('); + expr_type(&controlling_type, expr_eq); + controlling_type.t &= ~(0x0100 | 0x0200 | 0x0040); + for (;;) { + learn = 0; + skip(','); + if (tok == TOK_DEFAULT) { + if (has_default) + tcc_error("too many 'default'"); + has_default = 1; + if (!has_match) + learn = 1; + next(); + } else { + AttributeDef ad_tmp; + int itmp; + CType cur_type; + parse_btype(&cur_type, &ad_tmp); + type_decl(&cur_type, &ad_tmp, &itmp, 1); + if (compare_types(&controlling_type, &cur_type, 0)) { + if (has_match) { + tcc_error("type match twice"); + } + has_match = 1; + learn = 1; + } + } + skip(':'); + if (learn) { + if (str) + tok_str_free(str); + skip_or_save_block(&str); + } else { + skip_or_save_block(0); + } + if (tok == ')') + break; + } + if (!str) { + char buf[60]; + type_to_str(buf, sizeof buf, &controlling_type, 0); + tcc_error("type '%s' does not match any association", buf); + } + begin_macro(str, 1); + next(); + expr_eq(); + if (tok != (-1)) + expect(","); + end_macro(); + next(); + break; + } + + case TOK___NAN__: + vpush64(9, 0x7ff8000000000000ULL); + next(); + break; + case TOK___SNAN__: + vpush64(9, 0x7ff0000000000001ULL); + next(); + break; + case TOK___INF__: + vpush64(9, 0x7ff0000000000000ULL); + next(); + break; + + default: + tok_identifier: + t = tok; + next(); + if (t < TOK_DEFINE) + expect("identifier"); + s = sym_find(t); + if (!s || (((s)->type.t & (0x000f | (0 | 0x0010))) == (0 | 0x0010))) { + const char *name = get_tok_str(t, 0); + if (tok != '(') + tcc_error("'%s' undeclared", name); + + + if (tcc_state->warn_implicit_function_declaration + + + + + + ) + tcc_warning("implicit declaration of function '%s'", name); + s = external_global_sym(t, &func_old_type, 0); + } + + r = s->r; + + + if ((r & 0x003f) < 0x0030) + r = (r & ~0x003f) | 0x0032; + + vset(&s->type, r, s->c); + + + + vtop->sym = s; + + if (r & 0x0200) { + vtop->c.i = 0; + } else if (r == 0x0030 && ((s->type.t & (((1 << (6+6)) - 1) << 20 | 0x0080)) == (3 << 20))) { + vtop->c.i = s->enum_val; + } + break; + } + + + while (1) { + if (tok == 0xa4 || tok == 0xa2) { + inc(1, tok); + next(); + } else if (tok == '.' || tok == 0xc7 || tok == 0xbc) { + int qualifiers; + + if (tok == 0xc7) + indir(); + qualifiers = vtop->type.t & (0x0100 | 0x0200); + test_lvalue(); + gaddrof(); + + if ((vtop->type.t & 0x000f) != 7) + expect("struct or union"); + if (tok == 0xbc) + expect("field name"); + next(); + if (tok == 0xb5 || tok == 0xb6) + expect("field name"); + s = find_field(&vtop->type, tok); + if (!s) + tcc_error("field not found: %s", get_tok_str(tok & ~0x20000000, &tokc)); + + vtop->type = char_pointer_type; + vpushi(s->c); + gen_op('+'); + + vtop->type = s->type; + vtop->type.t |= qualifiers; + + if (!(vtop->type.t & 0x0040)) { + vtop->r |= lvalue_type(vtop->type.t); + + + if (tcc_state->do_bounds_check && (vtop->r & 0x003f) != 0x0032) + vtop->r |= 0x0800; + + } + next(); + } else if (tok == '[') { + next(); + gexpr(); + gen_op('+'); + indir(); + skip(']'); + } else if (tok == '(') { + SValue ret; + Sym *sa; + int nb_args, ret_nregs, ret_align, regsize, variadic; + + + if ((vtop->type.t & 0x000f) != 6) { + + if ((vtop->type.t & (0x000f | 0x0040)) == 5) { + vtop->type = *pointed_type(&vtop->type); + if ((vtop->type.t & 0x000f) != 6) + goto error_func; + } else { + error_func: + expect("function pointer"); + } + } else { + vtop->r &= ~0x0100; + } + + s = vtop->type.ref; + next(); + sa = s->next; + nb_args = regsize = 0; + ret.r2 = 0x0030; + + if ((s->type.t & 0x000f) == 7) { + variadic = (s->f.func_type == 3); + ret_nregs = gfunc_sret(&s->type, variadic, &ret.type, + &ret_align, ®size); + if (!ret_nregs) { + + size = type_size(&s->type, &align); +# 5199 "tccgen.c" + loc = (loc - size) & -align; + ret.type = s->type; + ret.r = 0x0032 | 0x0100; + + + vseti(0x0032, loc); + ret.c = vtop->c; + nb_args++; + } + } else { + ret_nregs = 1; + ret.type = s->type; + } + + if (ret_nregs) { + + if (is_float(ret.type.t)) { + ret.r = reg_fret(ret.type.t); + + if ((ret.type.t & 0x000f) == 14) + ret.r2 = TREG_XMM1; + + } else { + + + if ((ret.type.t & 0x000f) == 13) + + + + ret.r2 = TREG_RDX; + + ret.r = TREG_RAX; + } + ret.c.i = 0; + } + if (tok != ')') { + for(;;) { + expr_eq(); + gfunc_param_typed(s, sa); + nb_args++; + if (sa) + sa = sa->next; + if (tok == ')') + break; + skip(','); + } + } + if (sa) + tcc_error("too few arguments to function"); + skip(')'); + gfunc_call(nb_args); + + + for (r = ret.r + ret_nregs + !ret_nregs; r-- > ret.r;) { + vsetc(&ret.type, r, &ret.c); + vtop->r2 = ret.r2; + } + + + if (((s->type.t & 0x000f) == 7) && ret_nregs) { + int addr, offset; + + size = type_size(&s->type, &align); + + + if (regsize > align) + align = regsize; + loc = (loc - size) & -align; + addr = loc; + offset = 0; + for (;;) { + vset(&ret.type, 0x0032 | 0x0100, addr + offset); + vswap(); + vstore(); + vtop--; + if (--ret_nregs == 0) + break; + offset += regsize; + } + vset(&s->type, 0x0032 | 0x0100, addr); + } + } else { + break; + } + } +} + +static void expr_prod(void) +{ + int t; + + unary(); + while (tok == '*' || tok == '/' || tok == '%') { + t = tok; + next(); + unary(); + gen_op(t); + } +} + +static void expr_sum(void) +{ + int t; + + expr_prod(); + while (tok == '+' || tok == '-') { + t = tok; + next(); + expr_prod(); + gen_op(t); + } +} + +static void expr_shift(void) +{ + int t; + + expr_sum(); + while (tok == 0x01 || tok == 0x02) { + t = tok; + next(); + expr_sum(); + gen_op(t); + } +} + +static void expr_cmp(void) +{ + int t; + + expr_shift(); + while ((tok >= 0x96 && tok <= 0x9f) || + tok == 0x92 || tok == 0x93) { + t = tok; + next(); + expr_shift(); + gen_op(t); + } +} + +static void expr_cmpeq(void) +{ + int t; + + expr_cmp(); + while (tok == 0x94 || tok == 0x95) { + t = tok; + next(); + expr_cmp(); + gen_op(t); + } +} + +static void expr_and(void) +{ + expr_cmpeq(); + while (tok == '&') { + next(); + expr_cmpeq(); + gen_op('&'); + } +} + +static void expr_xor(void) +{ + expr_and(); + while (tok == '^') { + next(); + expr_and(); + gen_op('^'); + } +} + +static void expr_or(void) +{ + expr_xor(); + while (tok == '|') { + next(); + expr_xor(); + gen_op('|'); + } +} + +static void expr_land(void) +{ + expr_or(); + if (tok == 0xa0) { + int t = 0; + for(;;) { + if ((vtop->r & (0x003f | 0x0100 | 0x0200)) == 0x0030) { + gen_cast_s(11); + if (vtop->c.i) { + vpop(); + } else { + nocode_wanted++; + while (tok == 0xa0) { + next(); + expr_or(); + vpop(); + } + nocode_wanted--; + if (t) + gsym(t); + gen_cast_s(3); + break; + } + } else { + if (!t) + save_regs(1); + t = gvtst(1, t); + } + if (tok != 0xa0) { + if (t) + vseti(0x0035, t); + else + vpushi(1); + break; + } + next(); + expr_or(); + } + } +} + +static void expr_lor(void) +{ + expr_land(); + if (tok == 0xa1) { + int t = 0; + for(;;) { + if ((vtop->r & (0x003f | 0x0100 | 0x0200)) == 0x0030) { + gen_cast_s(11); + if (!vtop->c.i) { + vpop(); + } else { + nocode_wanted++; + while (tok == 0xa1) { + next(); + expr_land(); + vpop(); + } + nocode_wanted--; + if (t) + gsym(t); + gen_cast_s(3); + break; + } + } else { + if (!t) + save_regs(1); + t = gvtst(0, t); + } + if (tok != 0xa1) { + if (t) + vseti(0x0034, t); + else + vpushi(0); + break; + } + next(); + expr_land(); + } + } +} + + + + +static int condition_3way(void) +{ + int c = -1; + if ((vtop->r & (0x003f | 0x0100)) == 0x0030 && + (!(vtop->r & 0x0200) || !vtop->sym->a.weak)) { + vdup(); + gen_cast_s(11); + c = vtop->c.i; + vpop(); + } + return c; +} + +static void expr_cond(void) +{ + int tt, u, r1, r2, rc, t1, t2, bt1, bt2, islv, c, g; + SValue sv; + CType type, type1, type2; + + expr_lor(); + if (tok == '?') { + next(); + c = condition_3way(); + g = (tok == ':' && gnu_ext); + if (c < 0) { + + + if (is_float(vtop->type.t)) { + rc = 0x0002; + + if ((vtop->type.t & 0x000f) == 10) { + rc = 0x0080; + } + + } else + rc = 0x0001; + gv(rc); + save_regs(1); + if (g) + gv_dup(); + tt = gvtst(1, 0); + + } else { + if (!g) + vpop(); + tt = 0; + } + + if (1) { + if (c == 0) + nocode_wanted++; + if (!g) + gexpr(); + + type1 = vtop->type; + sv = *vtop; + vtop--; + skip(':'); + + u = 0; + if (c < 0) + u = gjmp(0); + gsym(tt); + + if (c == 0) + nocode_wanted--; + if (c == 1) + nocode_wanted++; + expr_cond(); + if (c == 1) + nocode_wanted--; + + type2 = vtop->type; + t1 = type1.t; + bt1 = t1 & 0x000f; + t2 = type2.t; + bt2 = t2 & 0x000f; + type.ref = 0; + + + if (is_float(bt1) || is_float(bt2)) { + if (bt1 == 10 || bt2 == 10) { + type.t = 10; + + } else if (bt1 == 9 || bt2 == 9) { + type.t = 9; + } else { + type.t = 8; + } + } else if (bt1 == 4 || bt2 == 4) { + + type.t = 4 | 0x0800; + if (bt1 == 4) + type.t &= t1; + if (bt2 == 4) + type.t &= t2; + + if ((t1 & (0x000f | 0x0010 | 0x0080)) == (4 | 0x0010) || + (t2 & (0x000f | 0x0010 | 0x0080)) == (4 | 0x0010)) + type.t |= 0x0010; + } else if (bt1 == 5 || bt2 == 5) { + + + if (is_null_pointer (vtop)) + type = type1; + else if (is_null_pointer (&sv)) + type = type2; + + + else + type = type1; + } else if (bt1 == 6 || bt2 == 6) { + + type = bt1 == 6 ? type1 : type2; + } else if (bt1 == 7 || bt2 == 7) { + + type = bt1 == 7 ? type1 : type2; + } else if (bt1 == 0 || bt2 == 0) { + + type.t = 0; + } else { + + type.t = 3 | (0x0800 & (t1 | t2)); + + if ((t1 & (0x000f | 0x0010 | 0x0080)) == (3 | 0x0010) || + (t2 & (0x000f | 0x0010 | 0x0080)) == (3 | 0x0010)) + type.t |= 0x0010; + } + + + islv = (vtop->r & 0x0100) && (sv.r & 0x0100) && 7 == (type.t & 0x000f); + islv &= c < 0; + + + if (c != 1) { + gen_cast(&type); + if (islv) { + mk_pointer(&vtop->type); + gaddrof(); + } else if (7 == (vtop->type.t & 0x000f)) + gaddrof(); + } + + rc = 0x0001; + if (is_float(type.t)) { + rc = 0x0002; + + if ((type.t & 0x000f) == 10) { + rc = 0x0080; + } + + } else if ((type.t & 0x000f) == 4) { + + + rc = 0x0004; + } + + tt = r2 = 0; + if (c < 0) { + r2 = gv(rc); + tt = gjmp(0); + } + gsym(u); + + + + if (c != 0) { + *vtop = sv; + gen_cast(&type); + if (islv) { + mk_pointer(&vtop->type); + gaddrof(); + } else if (7 == (vtop->type.t & 0x000f)) + gaddrof(); + } + + if (c < 0) { + r1 = gv(rc); + move_reg(r2, r1, type.t); + vtop->r = r2; + gsym(tt); + if (islv) + indir(); + } + } + } +} + +static void expr_eq(void) +{ + int t; + + expr_cond(); + if (tok == '=' || + (tok >= 0xa5 && tok <= 0xaf) || + tok == 0xde || tok == 0xfc || + tok == 0x81 || tok == 0x82) { + test_lvalue(); + t = tok; + next(); + if (t == '=') { + expr_eq(); + } else { + vdup(); + expr_eq(); + gen_op(t & 0x7f); + } + vstore(); + } +} + +static void gexpr(void) +{ + while (1) { + expr_eq(); + if (tok != ',') + break; + vpop(); + next(); + } +} + + +static void expr_const1(void) +{ + const_wanted++; + nocode_wanted++; + expr_cond(); + nocode_wanted--; + const_wanted--; +} + + +static inline int64_t expr_const64(void) +{ + int64_t c; + expr_const1(); + if ((vtop->r & (0x003f | 0x0100 | 0x0200)) != 0x0030) + expect("constant expression"); + c = vtop->c.i; + vpop(); + return c; +} + + + +static int expr_const(void) +{ + int c; + int64_t wc = expr_const64(); + c = wc; + if (c != wc && (unsigned)c != wc) + tcc_error("constant exceeds 32 bit"); + return c; +} + + + +static int is_label(void) +{ + int last_tok; + + + if (tok < TOK_DEFINE) + return 0; + + last_tok = tok; + next(); + if (tok == ':') { + return last_tok; + } else { + unget_tok(last_tok); + return 0; + } +} + + +static void gfunc_return(CType *func_type) +{ + if ((func_type->t & 0x000f) == 7) { + CType type, ret_type; + int ret_align, ret_nregs, regsize; + ret_nregs = gfunc_sret(func_type, func_var, &ret_type, + &ret_align, ®size); + if (0 == ret_nregs) { + + + type = *func_type; + mk_pointer(&type); + vset(&type, 0x0032 | 0x0100, func_vc); + indir(); + vswap(); + + vstore(); + } else { + + int r, size, addr, align; + size = type_size(func_type,&align); + if ((vtop->r != (0x0032 | 0x0100) || + (vtop->c.i & (ret_align-1))) + && (align & (ret_align-1))) { + loc = (loc - size) & -ret_align; + addr = loc; + type = *func_type; + vset(&type, 0x0032 | 0x0100, addr); + vswap(); + vstore(); + vpop(); + vset(&ret_type, 0x0032 | 0x0100, addr); + } + vtop->type = ret_type; + if (is_float(ret_type.t)) + r = rc_fret(ret_type.t); + else + r = 0x0004; + + if (ret_nregs == 1) + gv(r); + else { + for (;;) { + vdup(); + gv(r); + vpop(); + if (--ret_nregs == 0) + break; + + + + r <<= 1; + vtop->c.i += regsize; + } + } + } + } else if (is_float(func_type->t)) { + gv(rc_fret(func_type->t)); + } else { + gv(0x0004); + } + vtop--; +} + + +static int case_cmp(const void *pa, const void *pb) +{ + int64_t a = (*(struct case_t**) pa)->v1; + int64_t b = (*(struct case_t**) pb)->v1; + return a < b ? -1 : a > b; +} + +static void gcase(struct case_t **base, int len, int *bsym) +{ + struct case_t *p; + int e; + int ll = (vtop->type.t & 0x000f) == 4; + gv(0x0001); + while (len > 4) { + + p = base[len/2]; + vdup(); + if (ll) + vpushll(p->v2); + else + vpushi(p->v2); + gen_op(0x9e); + e = gtst(1, 0); + vdup(); + if (ll) + vpushll(p->v1); + else + vpushi(p->v1); + gen_op(0x9d); + gtst_addr(0, p->sym); + + gcase(base, len/2, bsym); + if (cur_switch->def_sym) + gjmp_addr(cur_switch->def_sym); + else + *bsym = gjmp(*bsym); + + gsym(e); + e = len/2 + 1; + base += e; len -= e; + } + + while (len--) { + p = *base++; + vdup(); + if (ll) + vpushll(p->v2); + else + vpushi(p->v2); + if (p->v1 == p->v2) { + gen_op(0x94); + gtst_addr(0, p->sym); + } else { + gen_op(0x9e); + e = gtst(1, 0); + vdup(); + if (ll) + vpushll(p->v1); + else + vpushi(p->v1); + gen_op(0x9d); + gtst_addr(0, p->sym); + gsym(e); + } + } +} + +static void block(int *bsym, int *csym, int is_expr) +{ + int a, b, c, d, cond; + Sym *s; + + + if (tcc_state->do_debug) + tcc_debug_line(tcc_state); + + if (is_expr) { + + vpushi(0); + vtop->type.t = 0; + } + + if (tok == TOK_IF) { + + int saved_nocode_wanted = nocode_wanted; + next(); + skip('('); + gexpr(); + skip(')'); + cond = condition_3way(); + if (cond == 1) + a = 0, vpop(); + else + a = gvtst(1, 0); + if (cond == 0) + nocode_wanted |= 0x20000000; + block(bsym, csym, 0); + if (cond != 1) + nocode_wanted = saved_nocode_wanted; + c = tok; + if (c == TOK_ELSE) { + next(); + d = gjmp(0); + gsym(a); + if (cond == 1) + nocode_wanted |= 0x20000000; + block(bsym, csym, 0); + gsym(d); + if (cond != 0) + nocode_wanted = saved_nocode_wanted; + } else + gsym(a); + } else if (tok == TOK_WHILE) { + int saved_nocode_wanted; + nocode_wanted &= ~0x20000000; + next(); + d = ind; + vla_sp_restore(); + skip('('); + gexpr(); + skip(')'); + a = gvtst(1, 0); + b = 0; + ++local_scope; + saved_nocode_wanted = nocode_wanted; + block(&a, &b, 0); + nocode_wanted = saved_nocode_wanted; + --local_scope; + gjmp_addr(d); + gsym(a); + gsym_addr(b, d); + } else if (tok == '{') { + Sym *llabel; + int block_vla_sp_loc = vla_sp_loc, saved_vlas_in_scope = vlas_in_scope; + + next(); + + s = local_stack; + llabel = local_label_stack; + ++local_scope; + + + if (tok == TOK_LABEL) { + next(); + for(;;) { + if (tok < TOK_DEFINE) + expect("label identifier"); + label_push(&local_label_stack, tok, 2); + next(); + if (tok == ',') { + next(); + } else { + skip(';'); + break; + } + } + } + while (tok != '}') { + if ((a = is_label())) + unget_tok(a); + else + decl(0x0032); + if (tok != '}') { + if (is_expr) + vpop(); + block(bsym, csym, is_expr); + } + } + + label_pop(&local_label_stack, llabel, is_expr); + + --local_scope; + + + + + + + + sym_pop(&local_stack, s, is_expr); + + + if (vlas_in_scope > saved_vlas_in_scope) { + vla_sp_loc = saved_vlas_in_scope ? block_vla_sp_loc : vla_sp_root_loc; + vla_sp_restore(); + } + vlas_in_scope = saved_vlas_in_scope; + + next(); + } else if (tok == TOK_RETURN) { + next(); + if (tok != ';') { + gexpr(); + gen_assign_cast(&func_vt); + if ((func_vt.t & 0x000f) == 0) + vtop--; + else + gfunc_return(&func_vt); + } + skip(';'); + + if (tok != '}' || local_scope != 1) + rsym = gjmp(rsym); + nocode_wanted |= 0x20000000; + } else if (tok == TOK_BREAK) { + + if (!bsym) + tcc_error("cannot break"); + *bsym = gjmp(*bsym); + next(); + skip(';'); + nocode_wanted |= 0x20000000; + } else if (tok == TOK_CONTINUE) { + + if (!csym) + tcc_error("cannot continue"); + vla_sp_restore_root(); + *csym = gjmp(*csym); + next(); + skip(';'); + } else if (tok == TOK_FOR) { + int e; + int saved_nocode_wanted; + nocode_wanted &= ~0x20000000; + next(); + skip('('); + s = local_stack; + ++local_scope; + if (tok != ';') { + + if (!decl0(0x0032, 1, 0)) { + + gexpr(); + vpop(); + } + } + skip(';'); + d = ind; + c = ind; + vla_sp_restore(); + a = 0; + b = 0; + if (tok != ';') { + gexpr(); + a = gvtst(1, 0); + } + skip(';'); + if (tok != ')') { + e = gjmp(0); + c = ind; + vla_sp_restore(); + gexpr(); + vpop(); + gjmp_addr(d); + gsym(e); + } + skip(')'); + saved_nocode_wanted = nocode_wanted; + block(&a, &b, 0); + nocode_wanted = saved_nocode_wanted; + gjmp_addr(c); + gsym(a); + gsym_addr(b, c); + --local_scope; + sym_pop(&local_stack, s, 0); + + } else + if (tok == TOK_DO) { + int saved_nocode_wanted; + nocode_wanted &= ~0x20000000; + next(); + a = 0; + b = 0; + d = ind; + vla_sp_restore(); + saved_nocode_wanted = nocode_wanted; + block(&a, &b, 0); + skip(TOK_WHILE); + skip('('); + gsym(b); + gexpr(); + c = gvtst(0, 0); + gsym_addr(c, d); + nocode_wanted = saved_nocode_wanted; + skip(')'); + gsym(a); + skip(';'); + } else + if (tok == TOK_SWITCH) { + struct switch_t *saved, sw; + int saved_nocode_wanted = nocode_wanted; + SValue switchval; + next(); + skip('('); + gexpr(); + skip(')'); + switchval = *vtop--; + a = 0; + b = gjmp(0); + sw.p = 0; sw.n = 0; sw.def_sym = 0; + saved = cur_switch; + cur_switch = &sw; + block(&a, csym, 0); + nocode_wanted = saved_nocode_wanted; + a = gjmp(a); + + gsym(b); + qsort(sw.p, sw.n, sizeof(void*), case_cmp); + for (b = 1; b < sw.n; b++) + if (sw.p[b - 1]->v2 >= sw.p[b]->v1) + tcc_error("duplicate case value"); + + + if ((switchval.type.t & 0x000f) == 4) + switchval.type.t &= ~0x0010; + vpushv(&switchval); + gcase(sw.p, sw.n, &a); + vpop(); + if (sw.def_sym) + gjmp_addr(sw.def_sym); + dynarray_reset(&sw.p, &sw.n); + cur_switch = saved; + + gsym(a); + } else + if (tok == TOK_CASE) { + struct case_t *cr = tcc_malloc(sizeof(struct case_t)); + if (!cur_switch) + expect("switch"); + nocode_wanted &= ~0x20000000; + next(); + cr->v1 = cr->v2 = expr_const64(); + if (gnu_ext && tok == 0xc8) { + next(); + cr->v2 = expr_const64(); + if (cr->v2 < cr->v1) + tcc_warning("empty case range"); + } + cr->sym = ind; + dynarray_add(&cur_switch->p, &cur_switch->n, cr); + skip(':'); + is_expr = 0; + goto block_after_label; + } else + if (tok == TOK_DEFAULT) { + next(); + skip(':'); + if (!cur_switch) + expect("switch"); + if (cur_switch->def_sym) + tcc_error("too many 'default'"); + cur_switch->def_sym = ind; + is_expr = 0; + goto block_after_label; + } else + if (tok == TOK_GOTO) { + next(); + if (tok == '*' && gnu_ext) { + + next(); + gexpr(); + if ((vtop->type.t & 0x000f) != 5) + expect("pointer"); + ggoto(); + } else if (tok >= TOK_DEFINE) { + s = label_find(tok); + + if (!s) { + s = label_push(&global_label_stack, tok, 1); + } else { + if (s->r == 2) + s->r = 1; + } + vla_sp_restore_root(); + if (s->r & 1) + s->jnext = gjmp(s->jnext); + else + gjmp_addr(s->jnext); + next(); + } else { + expect("label identifier"); + } + skip(';'); + } else if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) { + asm_instr(); + } else { + b = is_label(); + if (b) { + + next(); + s = label_find(b); + if (s) { + if (s->r == 0) + tcc_error("duplicate label '%s'", get_tok_str(s->v, 0)); + gsym(s->jnext); + s->r = 0; + } else { + s = label_push(&global_label_stack, b, 0); + } + s->jnext = ind; + vla_sp_restore(); + + block_after_label: + nocode_wanted &= ~0x20000000; + if (tok == '}') { + tcc_warning("deprecated use of label at end of compound statement"); + } else { + if (is_expr) + vpop(); + block(bsym, csym, is_expr); + } + } else { + + if (tok != ';') { + if (is_expr) { + vpop(); + gexpr(); + } else { + gexpr(); + vpop(); + } + } + skip(';'); + } + } +} + + + + + + +static void skip_or_save_block(TokenString **str) +{ + int braces = tok == '{'; + int level = 0; + if (str) + *str = tok_str_alloc(); + + while ((level > 0 || (tok != '}' && tok != ',' && tok != ';' && tok != ')'))) { + int t; + if (tok == (-1)) { + if (str || level > 0) + tcc_error("unexpected end of file"); + else + break; + } + if (str) + tok_str_add_tok(*str); + t = tok; + next(); + if (t == '{' || t == '(') { + level++; + } else if (t == '}' || t == ')') { + level--; + if (level == 0 && braces && t == '}') + break; + } + } + if (str) { + tok_str_add(*str, -1); + tok_str_add(*str, 0); + } +} + + + + +static void parse_init_elem(int expr_type) +{ + int saved_global_expr; + switch(expr_type) { + case 1: + + saved_global_expr = global_expr; + global_expr = 1; + expr_const1(); + global_expr = saved_global_expr; + + + if (((vtop->r & (0x003f | 0x0100)) != 0x0030 + && ((vtop->r & (0x0200|0x0100)) != (0x0200|0x0100) + || vtop->sym->v < 0x10000000)) + + + + ) + tcc_error("initializer element is not constant"); + break; + case 2: + expr_eq(); + break; + } +} + + +static void init_putz(Section *sec, unsigned long c, int size) +{ + if (sec) { + + } else { + vpush_global_sym(&func_old_type, TOK_memset); + vseti(0x0032, c); + + + + + vpushi(0); + vpushs(size); + + gfunc_call(3); + } +} + + + + + + + +static int decl_designator(CType *type, Section *sec, unsigned long c, + Sym **cur_field, int size_only, int al) +{ + Sym *s, *f; + int index, index_last, align, l, nb_elems, elem_size; + unsigned long corig = c; + + elem_size = 0; + nb_elems = 1; + if (gnu_ext && (l = is_label()) != 0) + goto struct_field; + + while (nb_elems == 1 && (tok == '[' || tok == '.')) { + if (tok == '[') { + if (!(type->t & 0x0040)) + expect("array type"); + next(); + index = index_last = expr_const(); + if (tok == 0xc8 && gnu_ext) { + next(); + index_last = expr_const(); + } + skip(']'); + s = type->ref; + if (index < 0 || (s->c >= 0 && index_last >= s->c) || + index_last < index) + tcc_error("invalid index"); + if (cur_field) + (*cur_field)->c = index_last; + type = pointed_type(type); + elem_size = type_size(type, &align); + c += index * elem_size; + nb_elems = index_last - index + 1; + } else { + next(); + l = tok; + struct_field: + next(); + if ((type->t & 0x000f) != 7) + expect("struct/union type"); + f = find_field(type, l); + if (!f) + expect("field"); + if (cur_field) + *cur_field = f; + type = &f->type; + c += f->c; + } + cur_field = 0; + } + if (!cur_field) { + if (tok == '=') { + next(); + } else if (!gnu_ext) { + expect("="); + } + } else { + if (type->t & 0x0040) { + index = (*cur_field)->c; + if (type->ref->c >= 0 && index >= type->ref->c) + tcc_error("index too large"); + type = pointed_type(type); + c += index * type_size(type, &align); + } else { + f = *cur_field; + while (f && (f->v & 0x10000000) && (f->type.t & 0x0080)) + *cur_field = f = f->next; + if (!f) + tcc_error("too many field init"); + type = &f->type; + c += f->c; + } + } + + + if (!size_only && c - corig > al) + init_putz(sec, corig + al, c - corig - al); + decl_initializer(type, sec, c, 0, size_only); + + + if (!size_only && nb_elems > 1) { + unsigned long c_end; + uint8_t *src, *dst; + int i; + + if (!sec) { + vset(type, 0x0032|0x0100, c); + for (i = 1; i < nb_elems; i++) { + vset(type, 0x0032|0x0100, c + elem_size * i); + vswap(); + vstore(); + } + vpop(); + } else if (!(nocode_wanted > 0)) { + c_end = c + nb_elems * elem_size; + if (c_end > sec->data_allocated) + section_realloc(sec, c_end); + src = sec->data + c; + dst = src; + for(i = 1; i < nb_elems; i++) { + dst += elem_size; + memcpy(dst, src, elem_size); + } + } + } + c += nb_elems * type_size(type, &align); + if (c - corig > al) + al = c - corig; + return al; +} + + +static void init_putv(CType *type, Section *sec, unsigned long c) +{ + int bt; + void *ptr; + CType dtype; + + dtype = *type; + dtype.t &= ~0x0100; + + if (sec) { + int size, align; + + + gen_assign_cast(&dtype); + bt = type->t & 0x000f; + + if ((vtop->r & 0x0200) + && bt != 5 + && bt != 6 + && (bt != (8 == 8 ? 4 : 3) + || (type->t & 0x0080)) + && !((vtop->r & 0x0030) && vtop->sym->v >= 0x10000000) + ) + tcc_error("initializer element is not computable at load time"); + + if ((nocode_wanted > 0)) { + vtop--; + return; + } + + size = type_size(type, &align); + section_reserve(sec, c + size); + ptr = sec->data + c; + + + if ((vtop->r & (0x0200|0x0030)) == (0x0200|0x0030) && + vtop->sym->v >= 0x10000000 && +# 6488 "tccgen.c" + (vtop->type.t & 0x000f) != 5) { + + Section *ssec; + Elf64_Sym *esym; + Elf64_Rela *rel; + esym = elfsym(vtop->sym); + ssec = tcc_state->sections[esym->st_shndx]; + memmove (ptr, ssec->data + esym->st_value, size); + if (ssec->reloc) { + + + + + int num_relocs = ssec->reloc->data_offset / sizeof(*rel); + rel = (Elf64_Rela*)(ssec->reloc->data + ssec->reloc->data_offset); + while (num_relocs--) { + rel--; + if (rel->r_offset >= esym->st_value + size) + continue; + if (rel->r_offset < esym->st_value) + break; + + + + + + + put_elf_reloca(symtab_section, sec, + c + rel->r_offset - esym->st_value, + ((rel->r_info) & 0xffffffff), + ((rel->r_info) >> 32), + + rel->r_addend + + + + ); + } + } + } else { + if (type->t & 0x0080) { + int bit_pos, bit_size, bits, n; + unsigned char *p, v, m; + bit_pos = (((vtop->type.t) >> 20) & 0x3f); + bit_size = (((vtop->type.t) >> (20 + 6)) & 0x3f); + p = (unsigned char*)ptr + (bit_pos >> 3); + bit_pos &= 7, bits = 0; + while (bit_size) { + n = 8 - bit_pos; + if (n > bit_size) + n = bit_size; + v = vtop->c.i >> bits << bit_pos; + m = ((1 << n) - 1) << bit_pos; + *p = (*p & ~m) | (v & m); + bits += n, bit_size -= n, bit_pos = 0, ++p; + } + } else + switch(bt) { + + + + case 11: + vtop->c.i = vtop->c.i != 0; + case 1: + *(char *)ptr |= vtop->c.i; + break; + case 2: + *(short *)ptr |= vtop->c.i; + break; + case 8: + *(float*)ptr = vtop->c.f; + break; + case 9: + *(double *)ptr = vtop->c.d; + break; + case 10: + + if (sizeof (long double) >= 10) + memcpy(ptr, &vtop->c.ld, 10); + + + + + else if (vtop->c.ld == 0.0) + ; + else + + if (sizeof(long double) == 16) + *(long double*)ptr = vtop->c.ld; + else if (sizeof(double) == 16) + *(double *)ptr = (double)vtop->c.ld; + else + tcc_error("can't cross compile long double constants"); + break; + + + + + + case 4: + + case 5: + { + Elf64_Addr val = vtop->c.i; + + if (vtop->r & 0x0200) + greloca(sec, vtop->sym, c, 1, val); + else + *(Elf64_Addr *)ptr |= val; + + + + + + break; + } + default: + { + int val = vtop->c.i; + + if (vtop->r & 0x0200) + greloca(sec, vtop->sym, c, 1, val); + else + *(int *)ptr |= val; + + + + + + break; + } + } + } + vtop--; + } else { + vset(&dtype, 0x0032|0x0100, c); + vswap(); + vstore(); + vpop(); + } +} + + + + + + +static void decl_initializer(CType *type, Section *sec, unsigned long c, + int first, int size_only) +{ + int len, n, no_oblock, nb, i; + int size1, align1; + int have_elem; + Sym *s, *f; + Sym indexsym; + CType *t1; + + + + have_elem = tok == '}' || tok == ','; + if (!have_elem && tok != '{' && + + + + tok != 0xba && tok != 0xb9 && + !size_only) { + parse_init_elem(!sec ? 2 : 1); + have_elem = 1; + } + + if (have_elem && + !(type->t & 0x0040) && + + + + is_compatible_unqualified_types(type, &vtop->type)) { + init_putv(type, sec, c); + } else if (type->t & 0x0040) { + s = type->ref; + n = s->c; + t1 = pointed_type(type); + size1 = type_size(t1, &align1); + + no_oblock = 1; + if ((first && tok != 0xba && tok != 0xb9) || + tok == '{') { + if (tok != '{') + tcc_error("character array initializer must be a literal," + " optionally enclosed in braces"); + skip('{'); + no_oblock = 0; + } + + + + if ((tok == 0xba && + + + + (t1->t & 0x000f) == 3 + + ) || (tok == 0xb9 && (t1->t & 0x000f) == 1)) { + len = 0; + while (tok == 0xb9 || tok == 0xba) { + int cstr_len, ch; + + + if (tok == 0xb9) + cstr_len = tokc.str.size; + else + cstr_len = tokc.str.size / sizeof(nwchar_t); + cstr_len--; + nb = cstr_len; + if (n >= 0 && nb > (n - len)) + nb = n - len; + if (!size_only) { + if (cstr_len > nb) + tcc_warning("initializer-string for array is too long"); + + + + if (sec && tok == 0xb9 && size1 == 1) { + if (!(nocode_wanted > 0)) + memcpy(sec->data + c + len, tokc.str.data, nb); + } else { + for(i=0;i<nb;i++) { + if (tok == 0xb9) + ch = ((unsigned char *)tokc.str.data)[i]; + else + ch = ((nwchar_t *)tokc.str.data)[i]; + vpushi(ch); + init_putv(t1, sec, c + (len + i) * size1); + } + } + } + len += nb; + next(); + } + + + if (n < 0 || len < n) { + if (!size_only) { + vpushi(0); + init_putv(t1, sec, c + (len * size1)); + } + len++; + } + len *= size1; + } else { + indexsym.c = 0; + f = &indexsym; + + do_init_list: + len = 0; + while (tok != '}' || have_elem) { + len = decl_designator(type, sec, c, &f, size_only, len); + have_elem = 0; + if (type->t & 0x0040) { + ++indexsym.c; + + + + if (no_oblock && len >= n*size1) + break; + } else { + if (s->type.t == (1 << 20 | 7)) + f = 0; + else + f = f->next; + if (no_oblock && f == 0) + break; + } + + if (tok == '}') + break; + skip(','); + } + } + + if (!size_only && len < n*size1) + init_putz(sec, c + len, n*size1 - len); + if (!no_oblock) + skip('}'); + + if (n < 0) + s->c = size1 == 1 ? len : ((len + size1 - 1)/size1); + } else if ((type->t & 0x000f) == 7) { + size1 = 1; + no_oblock = 1; + if (first || tok == '{') { + skip('{'); + no_oblock = 0; + } + s = type->ref; + f = s->next; + n = s->c; + goto do_init_list; + } else if (tok == '{') { + next(); + decl_initializer(type, sec, c, first, size_only); + skip('}'); + } else if (size_only) { + + + + + + + + skip_or_save_block(0); + } else { + if (!have_elem) { + + + + if (tok != 0xb9 && tok != 0xba) + expect("string constant"); + parse_init_elem(!sec ? 2 : 1); + } + init_putv(type, sec, c); + } +} +# 6818 "tccgen.c" +static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, + int has_init, int v, int scope) +{ + int size, align, addr; + TokenString *init_str = 0; + + Section *sec; + Sym *flexible_array; + Sym *sym = 0; + int saved_nocode_wanted = nocode_wanted; + + int bcheck = tcc_state->do_bounds_check && !(nocode_wanted > 0); + + + if (type->t & 0x00002000) + nocode_wanted |= (nocode_wanted > 0) ? 0x40000000 : 0x80000000; + + flexible_array = 0; + if ((type->t & 0x000f) == 7) { + Sym *field = type->ref->next; + if (field) { + while (field->next) + field = field->next; + if (field->type.t & 0x0040 && field->type.ref->c < 0) + flexible_array = field; + } + } + + size = type_size(type, &align); + + + + + + + if (size < 0 || (flexible_array && has_init)) { + if (!has_init) + tcc_error("unknown type size"); + + if (has_init == 2) { + init_str = tok_str_alloc(); + + while (tok == 0xb9 || tok == 0xba) { + tok_str_add_tok(init_str); + next(); + } + tok_str_add(init_str, -1); + tok_str_add(init_str, 0); + } else { + skip_or_save_block(&init_str); + } + unget_tok(0); + + + begin_macro(init_str, 1); + next(); + decl_initializer(type, 0, 0, 1, 1); + + macro_ptr = init_str->str; + next(); + + + size = type_size(type, &align); + if (size < 0) + tcc_error("unknown type size"); + } + + + if (flexible_array && + flexible_array->type.ref->c > 0) + size += flexible_array->type.ref->c + * pointed_size(&flexible_array->type); + + if (ad->a.aligned) { + int speca = 1 << (ad->a.aligned - 1); + if (speca > align) + align = speca; + } else if (ad->a.packed) { + align = 1; + } + + if ((nocode_wanted > 0)) + size = 0, align = 1; + + if ((r & 0x003f) == 0x0032) { + sec = 0; + + if (bcheck && (type->t & 0x0040)) { + loc--; + } + + loc = (loc - size) & -align; + addr = loc; + + + + + if (bcheck && (type->t & 0x0040)) { + Elf64_Addr *bounds_ptr; + + loc--; + + bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(Elf64_Addr)); + bounds_ptr[0] = addr; + bounds_ptr[1] = size; + } + + if (v) { + + + if (ad->asm_label) { + int reg = asm_parse_regvar(ad->asm_label); + if (reg >= 0) + r = (r & ~0x003f) | reg; + } + + sym = sym_push(v, type, r, addr); + sym->a = ad->a; + } else { + + vset(type, r, addr); + } + } else { + if (v && scope == 0x0030) { + + sym = sym_find(v); + if (sym) { + patch_storage(sym, ad, type); + + if (!has_init && sym->c && elfsym(sym)->st_shndx != 0) + goto no_alloc; + } + } + + + sec = ad->section; + if (!sec) { + if (has_init) + sec = data_section; + else if (tcc_state->nocommon) + sec = bss_section; + } + + if (sec) { + addr = section_add(sec, size, align); + + + if (bcheck) + section_add(sec, 1, 1); + + } else { + addr = align; + sec = common_section; + } + + if (v) { + if (!sym) { + sym = sym_push(v, type, r | 0x0200, 0); + patch_storage(sym, ad, 0); + } + + + sym->sym_scope = 0; + + put_extern_sym(sym, sec, addr, size); + } else { + + sym = get_sym_ref(type, sec, addr, size); + vpushsym(type, sym); + vtop->r |= r; + } + + + + + if (bcheck) { + Elf64_Addr *bounds_ptr; + + greloca(bounds_section, sym, bounds_section->data_offset, 1, 0); + + bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(Elf64_Addr)); + bounds_ptr[0] = 0; + bounds_ptr[1] = size; + } + + } + + if (type->t & 0x0400) { + int a; + + if ((nocode_wanted > 0)) + goto no_alloc; + + + if (vlas_in_scope == 0) { + if (vla_sp_root_loc == -1) + vla_sp_root_loc = (loc -= 8); + gen_vla_sp_save(vla_sp_root_loc); + } + + vla_runtime_type_size(type, &a); + gen_vla_alloc(type, a); + + + + + + gen_vla_sp_save(addr); + vla_sp_loc = addr; + vlas_in_scope++; + + } else if (has_init) { + size_t oldreloc_offset = 0; + if (sec && sec->reloc) + oldreloc_offset = sec->reloc->data_offset; + decl_initializer(type, sec, addr, 1, 0); + if (sec && sec->reloc) + squeeze_multi_relocs(sec, oldreloc_offset); + + + if (flexible_array) + flexible_array->type.ref->c = -1; + } + + no_alloc: + + if (init_str) { + end_macro(); + next(); + } + + nocode_wanted = saved_nocode_wanted; +} + + + +static void gen_function(Sym *sym) +{ + nocode_wanted = 0; + ind = cur_text_section->data_offset; + + put_extern_sym(sym, cur_text_section, ind, 0); + funcname = get_tok_str(sym->v, 0); + func_ind = ind; + + vla_sp_loc = -1; + vla_sp_root_loc = -1; + + tcc_debug_funcstart(tcc_state, sym); + + sym_push2(&local_stack, 0x20000000, 0, 0); + local_scope = 1; + gfunc_prolog(&sym->type); + local_scope = 0; + rsym = 0; + block(0, 0, 0); + nocode_wanted = 0; + gsym(rsym); + gfunc_epilog(); + cur_text_section->data_offset = ind; + label_pop(&global_label_stack, 0, 0); + + local_scope = 0; + sym_pop(&local_stack, 0, 0); + + + elfsym(sym)->st_size = ind - func_ind; + tcc_debug_funcend(tcc_state, ind - func_ind); + + cur_text_section = 0; + funcname = ""; + func_vt.t = 0; + func_var = 0; + ind = 0; + nocode_wanted = 0x80000000; + check_vstack(); +} + +static void gen_inline_functions(TCCState *s) +{ + Sym *sym; + int inline_generated, i, ln; + struct InlineFunc *fn; + + ln = file->line_num; + + do { + inline_generated = 0; + for (i = 0; i < s->nb_inline_fns; ++i) { + fn = s->inline_fns[i]; + sym = fn->sym; + if (sym && sym->c) { + + + fn->sym = 0; + if (file) + pstrcpy(file->filename, sizeof file->filename, fn->filename); + sym->type.t &= ~0x00008000; + + begin_macro(fn->func_str, 1); + next(); + cur_text_section = text_section; + gen_function(sym); + end_macro(); + + inline_generated = 1; + } + } + } while (inline_generated); + file->line_num = ln; +} + +static void free_inline_functions(TCCState *s) +{ + int i; + + for (i = 0; i < s->nb_inline_fns; ++i) { + struct InlineFunc *fn = s->inline_fns[i]; + if (fn->sym) + tok_str_free(fn->func_str); + } + dynarray_reset(&s->inline_fns, &s->nb_inline_fns); +} + + + +static int decl0(int l, int is_for_loop_init, Sym *func_sym) +{ + int v, has_init, r; + CType type, btype; + Sym *sym; + AttributeDef ad; + + while (1) { + if (!parse_btype(&btype, &ad)) { + if (is_for_loop_init) + return 0; + + if (tok == ';' && l != 0x0033) { + next(); + continue; + } + if (l != 0x0030) + break; + if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) { + + asm_global_instr(); + continue; + } + if (tok >= TOK_DEFINE) { + + + btype.t = 3; + } else { + if (tok != (-1)) + expect("declaration"); + break; + } + } + if (tok == ';') { + if ((btype.t & 0x000f) == 7) { + int v = btype.ref->v; + if (!(v & 0x20000000) && (v & ~0x40000000) >= 0x10000000) + tcc_warning("unnamed struct/union that defines no instances"); + next(); + continue; + } + if (((btype.t & (((1 << (6+6)) - 1) << 20 | 0x0080)) == (2 << 20))) { + next(); + continue; + } + } + while (1) { + type = btype; + + + + + + if ((type.t & 0x0040) && type.ref->c < 0) { + type.ref = sym_push(0x20000000, &type.ref->type, 0, type.ref->c); + } + type_decl(&type, &ad, &v, 2); + + + + + + + + if ((type.t & 0x000f) == 6) { + if ((type.t & 0x00002000) && (l == 0x0032)) { + tcc_error("function without file scope cannot be static"); + } + + + sym = type.ref; + if (sym->f.func_type == 2 && l == 0x0030) + decl0(0x0033, 0, sym); + } + + if (gnu_ext && (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3)) { + ad.asm_label = asm_label_instr(); + + parse_attribute(&ad); + if (tok == '{') + expect(";"); + } +# 7239 "tccgen.c" + if (tok == '{') { + if (l != 0x0030) + tcc_error("cannot use local functions"); + if ((type.t & 0x000f) != 6) + expect("function definition"); + + + + sym = type.ref; + while ((sym = sym->next) != 0) { + if (!(sym->v & ~0x20000000)) + expect("identifier"); + if (sym->type.t == 0) + sym->type = int_type; + } + + + if ((type.t & (0x00001000 | 0x00008000)) == (0x00001000 | 0x00008000)) + type.t = (type.t & ~0x00001000) | 0x00002000; + + + sym = external_global_sym(v, &type, 0); + type.t &= ~0x00001000; + patch_storage(sym, &ad, &type); + + + + + if ((type.t & (0x00008000 | 0x00002000)) == + (0x00008000 | 0x00002000)) { + struct InlineFunc *fn; + const char *filename; + + filename = file ? file->filename : ""; + fn = tcc_malloc(sizeof *fn + strlen(filename)); + strcpy(fn->filename, filename); + fn->sym = sym; + skip_or_save_block(&fn->func_str); + dynarray_add(&tcc_state->inline_fns, + &tcc_state->nb_inline_fns, fn); + } else { + + cur_text_section = ad.section; + if (!cur_text_section) + cur_text_section = text_section; + gen_function(sym); + } + break; + } else { + if (l == 0x0033) { + + for (sym = func_sym->next; sym; sym = sym->next) + if ((sym->v & ~0x20000000) == v) + goto found; + tcc_error("declaration for parameter '%s' but no such parameter", + get_tok_str(v, 0)); +found: + if (type.t & (0x00001000 | 0x00002000 | 0x00004000 | 0x00008000)) + tcc_error("storage class specified for '%s'", + get_tok_str(v, 0)); + if (sym->type.t != 0) + tcc_error("redefinition of parameter '%s'", + get_tok_str(v, 0)); + convert_parameter_type(&type); + sym->type = type; + } else if (type.t & 0x00004000) { + + + sym = sym_find(v); + if (sym && sym->sym_scope == local_scope) { + if (!is_compatible_types(&sym->type, &type) + || !(sym->type.t & 0x00004000)) + tcc_error("incompatible redefinition of '%s'", + get_tok_str(v, 0)); + sym->type = type; + } else { + sym = sym_push(v, &type, 0, 0); + } + sym->a = ad.a; + sym->f = ad.f; + } else { + r = 0; + if ((type.t & 0x000f) == 6) { + + + type.ref->f = ad.f; + } else if (!(type.t & 0x0040)) { + + r |= lvalue_type(type.t); + } + has_init = (tok == '='); + if (has_init && (type.t & 0x0400)) + tcc_error("variable length array cannot be initialized"); + if (((type.t & 0x00001000) && (!has_init || l != 0x0030)) || + ((type.t & 0x000f) == 6) || + ((type.t & 0x0040) && (type.t & 0x00002000) && + !has_init && l == 0x0030 && type.ref->c < 0)) { + + + + + type.t |= 0x00001000; + sym = external_sym(v, &type, r, &ad); + if (ad.alias_target) { + Elf64_Sym *esym; + Sym *alias_target; + alias_target = sym_find(ad.alias_target); + esym = elfsym(alias_target); + if (!esym) + tcc_error("unsupported forward __alias__ attribute"); + + + sym->sym_scope = 0; + put_extern_sym2(sym, esym->st_shndx, esym->st_value, esym->st_size, 0); + } + } else { + if (type.t & 0x00002000) + r |= 0x0030; + else + r |= l; + if (has_init) + next(); + else if (l == 0x0030) + + type.t |= 0x00001000; + decl_initializer_alloc(&type, &ad, r, has_init, v, l); + } + } + if (tok != ',') { + if (is_for_loop_init) + return 1; + skip(';'); + break; + } + next(); + } + ad.a.aligned = 0; + } + } + return 0; +} + +static void decl(int l) +{ + decl0(l, 0, 0); +} |