# 1 "tccgen.c" # 1 "" # 1 "" # 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, ""); 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;it & 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); }