From 826d1afd58c2e064a9c8fdb09eda1b08469de1a8 Mon Sep 17 00:00:00 2001 From: pommicket Date: Fri, 18 Feb 2022 12:36:57 -0500 Subject: newer version of tcc almost working --- 05/tcc-0.9.25/libtcc.c | 2276 ------------------------------------------------ 1 file changed, 2276 deletions(-) delete mode 100644 05/tcc-0.9.25/libtcc.c (limited to '05/tcc-0.9.25/libtcc.c') diff --git a/05/tcc-0.9.25/libtcc.c b/05/tcc-0.9.25/libtcc.c deleted file mode 100644 index 3311357..0000000 --- a/05/tcc-0.9.25/libtcc.c +++ /dev/null @@ -1,2276 +0,0 @@ -/* - * TCC - Tiny C Compiler - * - * Copyright (c) 2001-2004 Fabrice Bellard - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "tcc.h" - -/********************************************************/ -/* global variables */ - -/* display benchmark infos */ -int total_lines; -int total_bytes; - -/* parser */ -static struct BufferedFile *file; -static int ch, tok; -static CValue tokc; -static CString tokcstr; /* current parsed string, if any */ -/* additional informations about token */ -static int tok_flags; -#define TOK_FLAG_BOL 0x0001 /* beginning of line before */ -#define TOK_FLAG_BOF 0x0002 /* beginning of file before */ -#define TOK_FLAG_ENDIF 0x0004 /* a endif was found matching starting #ifdef */ -#define TOK_FLAG_EOF 0x0008 /* end of file */ - -static int *macro_ptr, *macro_ptr_allocated; -static int *unget_saved_macro_ptr; -static int unget_saved_buffer[TOK_MAX_SIZE + 1]; -static int unget_buffer_enabled; -static int parse_flags; -#define PARSE_FLAG_PREPROCESS 0x0001 /* activate preprocessing */ -#define PARSE_FLAG_TOK_NUM 0x0002 /* return numbers instead of TOK_PPNUM */ -#define PARSE_FLAG_LINEFEED 0x0004 /* line feed is returned as a - token. line feed is also - returned at eof */ -#define PARSE_FLAG_ASM_COMMENTS 0x0008 /* '#' can be used for line comment */ -#define PARSE_FLAG_SPACES 0x0010 /* next() returns space tokens (for -E) */ - -static Section *text_section, *data_section, *bss_section; /* predefined sections */ -static Section *cur_text_section; /* current section where function code is - generated */ -#ifdef CONFIG_TCC_ASM -static Section *last_text_section; /* to handle .previous asm directive */ -#endif -/* bound check related sections */ -static Section *bounds_section; /* contains global data bound description */ -static Section *lbounds_section; /* contains local data bound description */ -/* symbol sections */ -static Section *symtab_section, *strtab_section; - -/* debug sections */ -static Section *stab_section, *stabstr_section; - -/* loc : local variable index - ind : output code index - rsym: return symbol - anon_sym: anonymous symbol index -*/ -static int rsym, anon_sym, ind, loc; -/* expression generation modifiers */ -static int const_wanted; /* true if constant wanted */ -static int nocode_wanted; /* true if no code generation wanted for an expression */ -static int global_expr; /* true if compound literals must be allocated - globally (used during initializers parsing */ -static CType func_vt; /* current function return type (used by return - instruction) */ -static int func_vc; -static int last_line_num, last_ind, func_ind; /* debug last line number and pc */ -static int tok_ident; -static TokenSym **table_ident; -static TokenSym *hash_ident[TOK_HASH_SIZE]; -static char token_buf[STRING_MAX_SIZE + 1]; -static char *funcname; -static Sym *global_stack, *local_stack; -static Sym *define_stack; -static Sym *global_label_stack, *local_label_stack; -/* symbol allocator */ -#define SYM_POOL_NB (8192 / sizeof(Sym)) -static Sym *sym_free_first; -static void **sym_pools; -static int nb_sym_pools; - -static SValue vstack[VSTACK_SIZE], *vtop; -/* some predefined types */ -static CType char_pointer_type, func_old_type, int_type; - -/* use GNU C extensions */ -static int gnu_ext = 1; - -/* use Tiny C extensions */ -static int tcc_ext = 1; - -/* max number of callers shown if error */ -#ifdef CONFIG_TCC_BACKTRACE -int num_callers = 6; -const char **rt_bound_error_msg; -#endif - -/* XXX: get rid of this ASAP */ -static struct TCCState *tcc_state; - -/********************************************************/ -/* function prototypes */ - -/* tccpp.c */ -static void next(void); -char *get_tok_str(int v, CValue *cv); - -/* tccgen.c */ -static void parse_expr_type(CType *type); -static void expr_type(CType *type); -static void unary_type(CType *type); -static void block(int *bsym, int *csym, int *case_sym, int *def_sym, - int case_reg, int is_expr); -static int expr_const(void); -static void expr_eq(void); -static void gexpr(void); -static void gen_inline_functions(void); -static void decl(int l); -static void decl_initializer(CType *type, Section *sec, unsigned long c, - int first, int size_only); -static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, - int has_init, int v, int scope); -int gv(int rc); -void gv2(int rc1, int rc2); -void move_reg(int r, int s); -void save_regs(int n); -void save_reg(int r); -void vpop(void); -void vswap(void); -void vdup(void); -int get_reg(int rc); -int get_reg_ex(int rc,int rc2); - -void gen_op(int op); -void force_charshort_cast(int t); -static void gen_cast(CType *type); -void vstore(void); -static Sym *sym_find(int v); -static Sym *sym_push(int v, CType *type, int r, int c); - -/* type handling */ -static int type_size(CType *type, int *a); -static inline CType *pointed_type(CType *type); -static int pointed_size(CType *type); -static int lvalue_type(int t); -static int parse_btype(CType *type, AttributeDef *ad); -static void type_decl(CType *type, AttributeDef *ad, int *v, int td); -static int compare_types(CType *type1, CType *type2, int unqualified); -static int is_compatible_types(CType *type1, CType *type2); -static int is_compatible_parameter_types(CType *type1, CType *type2); - -int ieee_finite(double d); -void vpushi(int v); -void vpushll(long long v); -void vrott(int n); -void vnrott(int n); -void lexpand_nr(void); -static void vpush_global_sym(CType *type, int v); -void vset(CType *type, int r, int v); -void type_to_str(char *buf, int buf_size, - CType *type, const char *varstr); -static Sym *get_sym_ref(CType *type, Section *sec, - unsigned long offset, unsigned long size); -static Sym *external_global_sym(int v, CType *type, int r); - -/* section generation */ -static void section_realloc(Section *sec, unsigned long new_size); -static void *section_ptr_add(Section *sec, unsigned long size); -static void put_extern_sym(Sym *sym, Section *section, - unsigned long value, unsigned long size); -static void greloc(Section *s, Sym *sym, unsigned long addr, int type); -static int put_elf_str(Section *s, const char *sym); -static int put_elf_sym(Section *s, - unsigned long value, unsigned long size, - int info, int other, int shndx, const char *name); -static int add_elf_sym(Section *s, unsigned long value, unsigned long size, - int info, int other, int sh_num, const char *name); -static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset, - int type, int symbol); -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 int tcc_add_dll(TCCState *s, const char *filename, int flags); - -#define AFF_PRINT_ERROR 0x0001 /* print error if file not found */ -#define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */ -#define AFF_PREPROCESS 0x0004 /* preprocess file */ -static int tcc_add_file_internal(TCCState *s, const char *filename, int flags); - -/* tcccoff.c */ -int tcc_output_coff(TCCState *s1, FILE *f); - -/* tccpe.c */ -void *resolve_sym(TCCState *s1, const char *sym, int type); -int pe_load_def_file(struct TCCState *s1, int fd); -int pe_test_res_file(void *v, int size); -int pe_load_res_file(struct TCCState *s1, int fd); -void pe_add_runtime(struct TCCState *s1); -void pe_guess_outfile(char *objfilename, int output_type); -int pe_output_file(struct TCCState *s1, const char *filename); - -/* tccasm.c */ -#ifdef CONFIG_TCC_ASM -static void asm_expr(TCCState *s1, ExprValue *pe); -static int asm_int_expr(TCCState *s1); -static int find_constraint(ASMOperand *operands, int nb_operands, - const char *name, const char **pp); - -static int tcc_assemble(TCCState *s1, int do_preprocess); -#endif - -static void asm_instr(void); -static void asm_global_instr(void); - -/********************************************************/ -/* global variables */ - -#ifdef TCC_TARGET_I386 -#include "i386-gen.c" -#endif - -#ifdef TCC_TARGET_ARM -#include "arm-gen.c" -#endif - -#ifdef TCC_TARGET_C67 -#include "c67-gen.c" -#endif - -#ifdef TCC_TARGET_X86_64 -#include "x86_64-gen.c" -#endif - -#ifdef CONFIG_TCC_STATIC - -#define RTLD_LAZY 0x001 -#define RTLD_NOW 0x002 -#define RTLD_GLOBAL 0x100 -#define RTLD_DEFAULT NULL - -/* dummy function for profiling */ -void *dlopen(const char *filename, int flag) -{ - return NULL; -} - -void dlclose(void *p) -{ -} - -const char *dlerror(void) -{ - return "error"; -} - -typedef struct TCCSyms { - char *str; - void *ptr; -} TCCSyms; - -#define TCCSYM(a) { #a, &a, }, - -/* add the symbol you want here if no dynamic linking is done */ -static TCCSyms tcc_syms[] = { - {"printf", 0}, - {"fprintf", 0}, - {"fopen", 0}, - {"fclose", 0}, - { NULL, NULL } -}; - -void _init_tcc_syms(void) { - tcc_syms[0].ptr = printf; - tcc_syms[1].ptr = fprintf; - tcc_syms[2].ptr = fopen; - tcc_syms[3].ptr = fclose; -} - -void *resolve_sym(TCCState *s1, const char *symbol, int type) -{ - TCCSyms *p; - p = tcc_syms; - while (p->str != NULL) { - if (!strcmp(p->str, symbol)) - return p->ptr; - p++; - } - return NULL; -} - -#elif !defined(_WIN32) - -#include - -void *resolve_sym(TCCState *s1, const char *sym, int type) -{ - return dlsym(RTLD_DEFAULT, sym); -} - -#endif - -/********************************************************/ - -/* we use our own 'finite' function to avoid potential problems with - non standard math libs */ -/* XXX: endianness dependent */ -int ieee_finite(double d) -{ - int *p = (int *)&d; - return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31; -} - -/* copy a string and truncate it. */ -char *pstrcpy(char *buf, int buf_size, const char *s) -{ - char *q, *q_end; - int c; - - if (buf_size > 0) { - q = buf; - q_end = buf + buf_size - 1; - while (q < q_end) { - c = *s++; - if (c == '\0') - break; - *q++ = c; - } - *q = '\0'; - } - return buf; -} - -/* strcat and truncate. */ -char *pstrcat(char *buf, int buf_size, const char *s) -{ - int len; - len = strlen(buf); - if (len < buf_size) - pstrcpy(buf + len, buf_size - len, s); - return buf; -} - -/* extract the basename of a file */ -char *tcc_basename(const char *name) -{ - char *p = strchr(name, 0); - while (p > name && !IS_PATHSEP(p[-1])) - --p; - return p; -} - -char *tcc_fileextension (const char *name) -{ - char *b = tcc_basename(name); - char *e = strrchr(b, '.'); - return e ? e : strchr(b, 0); -} - -#ifdef _WIN32 -char *normalize_slashes(char *path) -{ - char *p; - for (p = path; *p; ++p) - if (*p == '\\') - *p = '/'; - return path; -} - -void tcc_set_lib_path_w32(TCCState *s) -{ - /* on win32, we suppose the lib and includes are at the location - of 'tcc.exe' */ - char path[1024], *p; - GetModuleFileNameA(NULL, path, sizeof path); - p = tcc_basename(normalize_slashes(strlwr(path))); - if (p - 5 > path && 0 == strncmp(p - 5, "/bin/", 5)) - p -= 5; - else if (p > path) - p--; - *p = 0; - tcc_set_lib_path(s, path); -} -#endif - -void set_pages_executable(void *ptr, unsigned long length) -{ -#ifdef _WIN32 - unsigned long old_protect; - VirtualProtect(ptr, length, PAGE_EXECUTE_READWRITE, &old_protect); -#else - unsigned long start, end; - start = (unsigned long)ptr & ~(PAGESIZE - 1); - end = (unsigned long)ptr + length; - end = (end + PAGESIZE - 1) & ~(PAGESIZE - 1); - mprotect((void *)start, end - start, PROT_READ | PROT_WRITE | PROT_EXEC); -#endif -} - -/* memory management */ -#ifdef MEM_DEBUG -int mem_cur_size; -int mem_max_size; -unsigned malloc_usable_size(void*); -#endif - -void tcc_free(void *ptr) -{ -#ifdef MEM_DEBUG - mem_cur_size -= malloc_usable_size(ptr); -#endif - free(ptr); -} - -void *tcc_malloc(unsigned long size) -{ - void *ptr; - ptr = malloc(size); - if (!ptr && size) - error("memory full"); -#ifdef MEM_DEBUG - mem_cur_size += malloc_usable_size(ptr); - if (mem_cur_size > mem_max_size) - mem_max_size = mem_cur_size; -#endif - return ptr; -} - -void *tcc_mallocz(unsigned long size) -{ - void *ptr; - ptr = tcc_malloc(size); - memset(ptr, 0, size); - return ptr; -} - -void *tcc_realloc(void *ptr, unsigned long size) -{ - void *ptr1; -#ifdef MEM_DEBUG - mem_cur_size -= malloc_usable_size(ptr); -#endif - ptr1 = realloc(ptr, size); -#ifdef MEM_DEBUG - /* NOTE: count not correct if alloc error, but not critical */ - mem_cur_size += malloc_usable_size(ptr1); - if (mem_cur_size > mem_max_size) - mem_max_size = mem_cur_size; -#endif - return ptr1; -} - -char *tcc_strdup(const char *str) -{ - char *ptr; - ptr = tcc_malloc(strlen(str) + 1); - strcpy(ptr, str); - return ptr; -} - -#define free(p) use_tcc_free(p) -#define malloc(s) use_tcc_malloc(s) -#define realloc(p, s) use_tcc_realloc(p, s) - -void dynarray_add(void ***ptab, int *nb_ptr, void *data) -{ - int nb, nb_alloc; - void **pp; - - nb = *nb_ptr; - pp = *ptab; - /* every power of two we double array size */ - if ((nb & (nb - 1)) == 0) { - if (!nb) - nb_alloc = 1; - else - nb_alloc = nb * 2; - pp = tcc_realloc(pp, nb_alloc * sizeof(void *)); - if (!pp) - error("memory full"); - *ptab = pp; - } - pp[nb++] = data; - *nb_ptr = nb; -} - -void dynarray_reset(void *pp, int *n) -{ - void **p; - for (p = *(void***)pp; *n; ++p, --*n) - if (*p) - tcc_free(*p); - tcc_free(*(void**)pp); - *(void**)pp = NULL; -} - -/* symbol allocator */ -static Sym *__sym_malloc(void) -{ - Sym *sym_pool, *sym, *last_sym; - int i; - - sym_pool = tcc_malloc(SYM_POOL_NB * sizeof(Sym)); - dynarray_add(&sym_pools, &nb_sym_pools, sym_pool); - - last_sym = sym_free_first; - sym = sym_pool; - for(i = 0; i < SYM_POOL_NB; 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; -} - -Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags) -{ - Section *sec; - - sec = tcc_mallocz(sizeof(Section) + strlen(name)); - strcpy(sec->name, name); - sec->sh_type = sh_type; - sec->sh_flags = sh_flags; - switch(sh_type) { - case SHT_HASH: - case SHT_REL: - case SHT_RELA: - case SHT_DYNSYM: - case SHT_SYMTAB: - case SHT_DYNAMIC: - sec->sh_addralign = 4; - break; - case SHT_STRTAB: - sec->sh_addralign = 1; - break; - default: - sec->sh_addralign = 32; /* default conservative alignment */ - break; - } - - if (sh_flags & SHF_PRIVATE) { - dynarray_add((void ***)&s1->priv_sections, &s1->nb_priv_sections, sec); - } else { - sec->sh_num = s1->nb_sections; - dynarray_add((void ***)&s1->sections, &s1->nb_sections, sec); - } - - return sec; -} - -static void free_section(Section *s) -{ - tcc_free(s->data); -} - -/* realloc section and set its content to zero */ -static void section_realloc(Section *sec, unsigned long new_size) -{ - unsigned long size; - unsigned char *data; - - size = sec->data_allocated; - if (size == 0) - size = 1; - while (size < new_size) - size = size * 2; - data = tcc_realloc(sec->data, size); - if (!data) - error("memory full"); - memset(data + sec->data_allocated, 0, size - sec->data_allocated); - sec->data = data; - sec->data_allocated = size; -} - -/* reserve at least 'size' bytes in section 'sec' from - sec->data_offset. */ -static void *section_ptr_add(Section *sec, unsigned long size) -{ - unsigned long offset, offset1; - - offset = sec->data_offset; - offset1 = offset + size; - if (offset1 > sec->data_allocated) - section_realloc(sec, offset1); - sec->data_offset = offset1; - return sec->data + offset; -} - -/* return a reference to a section, and create it if it does not - exists */ -Section *find_section(TCCState *s1, const char *name) -{ - Section *sec; - int i; - for(i = 1; i < s1->nb_sections; i++) { - sec = s1->sections[i]; - if (!strcmp(name, sec->name)) - return sec; - } - /* sections are created as PROGBITS */ - return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC); -} - -/* update sym->c so that it points to an external symbol in section - 'section' with value 'value' */ -static void put_extern_sym2(Sym *sym, Section *section, - unsigned long value, unsigned long size, - int can_add_underscore) -{ - int sym_type, sym_bind, sh_num, info, other, attr; - ElfW(Sym) *esym; - const char *name; - char buf1[256]; - - if (section == NULL) - sh_num = SHN_UNDEF; - else if (section == SECTION_ABS) - sh_num = SHN_ABS; - else - sh_num = section->sh_num; - - other = attr = 0; - - if ((sym->type.t & VT_BTYPE) == VT_FUNC) { - sym_type = STT_FUNC; -#ifdef TCC_TARGET_PE - if (sym->type.ref) - attr = sym->type.ref->r; - if (FUNC_EXPORT(attr)) - other |= 1; - if (FUNC_CALL(attr) == FUNC_STDCALL) - other |= 2; -#endif - } else { - sym_type = STT_OBJECT; - } - - if (sym->type.t & VT_STATIC) - sym_bind = STB_LOCAL; - else - sym_bind = STB_GLOBAL; - - if (!sym->c) { - name = get_tok_str(sym->v, NULL); -#ifdef CONFIG_TCC_BCHECK - if (tcc_state->do_bounds_check) { - char buf[32]; - - /* XXX: avoid doing that for statics ? */ - /* if bound checking is activated, we change some function - names by adding the "__bound" prefix */ - switch(sym->v) { -#if 0 - /* XXX: we rely only on malloc hooks */ - case TOK_malloc: - case TOK_free: - case TOK_realloc: - case TOK_memalign: - case TOK_calloc: -#endif - 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; - } - } -#endif - -#ifdef TCC_TARGET_PE - if ((other & 2) && can_add_underscore) { - sprintf(buf1, "_%s@%d", name, FUNC_ARGS(attr)); - name = buf1; - } else -#endif - if (tcc_state->leading_underscore && can_add_underscore) { - buf1[0] = '_'; - pstrcpy(buf1 + 1, sizeof(buf1) - 1, name); - name = buf1; - } - info = ELF64_ST_INFO(sym_bind, sym_type); - sym->c = add_elf_sym(symtab_section, value, size, info, other, sh_num, name); - } else { - esym = &((ElfW(Sym) *)symtab_section->data)[sym->c]; - esym->st_value = value; - esym->st_size = size; - esym->st_shndx = sh_num; - esym->st_other |= other; - } -} - -static void put_extern_sym(Sym *sym, Section *section, - unsigned long value, unsigned long size) -{ - put_extern_sym2(sym, section, value, size, 1); -} - -/* add a new relocation entry to symbol 'sym' in section 's' */ -static void greloc(Section *s, Sym *sym, unsigned long offset, int type) -{ - if (!sym->c) - put_extern_sym(sym, NULL, 0, 0); - /* now we can add ELF relocation info */ - put_elf_reloc(symtab_section, s, offset, type, sym->c); -} - -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) -{ - if (c >= 'a' && c <= 'z') - return c - 'a' + 'A'; - else - return c; -} - -static void strcat_vprintf(char *buf, int buf_size, const char *fmt, va_list ap) -{ - int len; - len = strlen(buf); - vsnprintf(buf + len, buf_size - len, fmt, ap); -} - -static void strcat_printf(char *buf, int buf_size, const char *fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - strcat_vprintf(buf, buf_size, fmt, ap); - va_end(ap); -} - -void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap) -{ - char buf[2048]; - BufferedFile **f; - - buf[0] = '\0'; - if (file) { - for(f = s1->include_stack; f < s1->include_stack_ptr; f++) - strcat_printf(buf, sizeof(buf), "In file included from %s:%d:\n", - (*f)->filename, (*f)->line_num); - if (file->line_num > 0) { - strcat_printf(buf, sizeof(buf), - "%s:%d: ", file->filename, file->line_num); - } else { - strcat_printf(buf, sizeof(buf), - "%s: ", file->filename); - } - } else { - strcat_printf(buf, sizeof(buf), - "tcc: "); - } - if (is_warning) - strcat_printf(buf, sizeof(buf), "warning: "); - strcat_vprintf(buf, sizeof(buf), fmt, ap); - - if (!s1->error_func) { - /* default case: stderr */ - fprintf(stderr, "%s\n", buf); - } else { - s1->error_func(s1->error_opaque, buf); - } - if (!is_warning || s1->warn_error) - s1->nb_errors++; -} - -void tcc_set_error_func(TCCState *s, void *error_opaque, - void (*error_func)(void *opaque, const char *msg)) -{ - s->error_opaque = error_opaque; - s->error_func = error_func; -} - -/* error without aborting current compilation */ -void error_noabort(const char *fmt, ...) -{ - TCCState *s1 = tcc_state; - va_list ap; - - va_start(ap, fmt); - error1(s1, 0, fmt, ap); - va_end(ap); -} - -void error(const char *fmt, ...) -{ - TCCState *s1 = tcc_state; - va_list ap; - - va_start(ap, fmt); - error1(s1, 0, fmt, ap); - va_end(ap); - /* better than nothing: in some cases, we accept to handle errors */ - if (s1->error_set_jmp_enabled) { - longjmp(s1->error_jmp_buf, 1); - } else { - /* XXX: eliminate this someday */ - exit(1); - } -} - -void expect(const char *msg) -{ - error("%s expected", msg); -} - -void warning(const char *fmt, ...) -{ - TCCState *s1 = tcc_state; - va_list ap; - - if (s1->warn_none) - return; - - va_start(ap, fmt); - error1(s1, 1, fmt, ap); - va_end(ap); -} - -void skip(int c) -{ - if (tok != c) - error("'%c' expected", c); - next(); -} - -static void test_lvalue(void) -{ - if (!(vtop->r & VT_LVAL)) - expect("lvalue"); -} - -/* CString handling */ - -static void cstr_realloc(CString *cstr, int new_size) -{ - int size; - void *data; - - size = cstr->size_allocated; - if (size == 0) - size = 8; /* no need to allocate a too small first string */ - while (size < new_size) - size = size * 2; - data = tcc_realloc(cstr->data_allocated, size); - if (!data) - error("memory full"); - cstr->data_allocated = data; - cstr->size_allocated = size; - cstr->data = data; -} - -/* add a byte */ -static inline void cstr_ccat(CString *cstr, int ch) -{ - int size; - size = cstr->size + 1; - if (size > cstr->size_allocated) - cstr_realloc(cstr, size); - ((unsigned char *)cstr->data)[size - 1] = ch; - cstr->size = size; -} - -static void cstr_cat(CString *cstr, const char *str) -{ - int c; - for(;;) { - c = *str; - if (c == '\0') - break; - cstr_ccat(cstr, c); - str++; - } -} - -/* add a wide char */ -static void cstr_wccat(CString *cstr, int ch) -{ - int size; - size = cstr->size + sizeof(nwchar_t); - if (size > cstr->size_allocated) - cstr_realloc(cstr, size); - *(nwchar_t *)(((unsigned char *)cstr->data) + size - sizeof(nwchar_t)) = ch; - cstr->size = size; -} - -static void cstr_new(CString *cstr) -{ - memset(cstr, 0, sizeof(CString)); -} - -/* free string and reset it to NULL */ -static void cstr_free(CString *cstr) -{ - tcc_free(cstr->data_allocated); - cstr_new(cstr); -} - -#define cstr_reset(cstr) cstr_free(cstr) - -/* XXX: unicode ? */ -static void add_char(CString *cstr, int c) -{ - if (c == '\'' || c == '\"' || c == '\\') { - /* XXX: could be more precise if char or string */ - cstr_ccat(cstr, '\\'); - } - if (c >= 32 && c <= 126) { - cstr_ccat(cstr, c); - } else { - cstr_ccat(cstr, '\\'); - if (c == '\n') { - cstr_ccat(cstr, 'n'); - } else { - cstr_ccat(cstr, '0' + ((c >> 6) & 7)); - cstr_ccat(cstr, '0' + ((c >> 3) & 7)); - cstr_ccat(cstr, '0' + (c & 7)); - } - } -} - -/* push, without hashing */ -static Sym *sym_push2(Sym **ps, int v, int t, long c) -{ - Sym *s; - s = sym_malloc(); - s->v = v; - s->type.t = t; - s->c = c; - s->next = NULL; - /* add in stack */ - s->prev = *ps; - *ps = s; - return s; -} - -/* find a symbol and return its associated structure. 's' is the top - of the symbol stack */ -static Sym *sym_find2(Sym *s, int v) -{ - while (s) { - if (s->v == v) - return s; - s = s->prev; - } - return NULL; -} - -/* structure lookup */ -static inline Sym *struct_find(int v) -{ - v -= TOK_IDENT; - if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT)) - return NULL; - return table_ident[v]->sym_struct; -} - -/* find an identifier */ -static inline Sym *sym_find(int v) -{ - v -= TOK_IDENT; - if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT)) - return NULL; - return table_ident[v]->sym_identifier; -} - -/* push a given symbol on the symbol stack */ -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; - /* don't record fields or anonymous symbols */ - /* XXX: simplify */ - if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) { - /* record symbol in token array */ - ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT]; - if (v & SYM_STRUCT) - ps = &ts->sym_struct; - else - ps = &ts->sym_identifier; - s->prev_tok = *ps; - *ps = s; - } - return s; -} - -/* push a global identifier */ -static Sym *global_identifier_push(int v, int t, int c) -{ - Sym *s, **ps; - s = sym_push2(&global_stack, v, t, c); - /* don't record anonymous symbol */ - if (v < SYM_FIRST_ANOM) { - ps = &table_ident[v - TOK_IDENT]->sym_identifier; - /* modify the top most local identifier, so that - sym_identifier will point to 's' when popped */ - while (*ps != NULL) - ps = &(*ps)->prev_tok; - s->prev_tok = NULL; - *ps = s; - } - return s; -} - -/* pop symbols until top reaches 'b' */ -static void sym_pop(Sym **ptop, Sym *b) -{ - Sym *s, *ss, **ps; - TokenSym *ts; - int v; - - s = *ptop; - while(s != b) { - ss = s->prev; - v = s->v; - /* remove symbol in token array */ - /* XXX: simplify */ - if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) { - ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT]; - if (v & SYM_STRUCT) - ps = &ts->sym_struct; - else - ps = &ts->sym_identifier; - *ps = s->prev_tok; - } - sym_free(s); - s = ss; - } - *ptop = b; -} - -/* I/O layer */ - -BufferedFile *tcc_open(TCCState *s1, const char *filename) -{ - int fd; - BufferedFile *bf; - - if (strcmp(filename, "-") == 0) - fd = 0, filename = "stdin"; - else - fd = open(filename, O_RDONLY | O_BINARY); - if ((s1->verbose == 2 && fd >= 0) || s1->verbose == 3) - printf("%s %*s%s\n", fd < 0 ? "nf":"->", - (s1->include_stack_ptr - s1->include_stack), "", filename); - if (fd < 0) - return NULL; - bf = tcc_malloc(sizeof(BufferedFile)); - bf->fd = fd; - bf->buf_ptr = bf->buffer; - bf->buf_end = bf->buffer; - bf->buffer[0] = CH_EOB; /* put eob symbol */ - pstrcpy(bf->filename, sizeof(bf->filename), filename); -#ifdef _WIN32 - normalize_slashes(bf->filename); -#endif - bf->line_num = 1; - bf->ifndef_macro = 0; - bf->ifdef_stack_ptr = s1->ifdef_stack_ptr; - // printf("opening '%s'\n", filename); - return bf; -} - -void tcc_close(BufferedFile *bf) -{ - total_lines += bf->line_num; - close(bf->fd); - tcc_free(bf); -} - -#include "tccpp.c" -#include "tccgen.c" - - -/* compile the C file opened in 'file'. Return non zero if errors. */ -static int tcc_compile(TCCState *s1) -{ - Sym *define_start; - char buf[512]; - volatile int section_sym; - -#ifdef INC_DEBUG - printf("%s: **** new file\n", file->filename); -#endif - preprocess_init(s1); - - cur_text_section = NULL; - funcname = ""; - anon_sym = SYM_FIRST_ANOM; - - /* file info: full path + filename */ - section_sym = 0; /* avoid warning */ - if (s1->do_debug) { - section_sym = put_elf_sym(symtab_section, 0, 0, - ELF64_ST_INFO(STB_LOCAL, STT_SECTION), 0, - text_section->sh_num, NULL); - getcwd(buf, sizeof(buf)); -#ifdef _WIN32 - normalize_slashes(buf); -#endif - 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); - } - /* an elf symbol of type STT_FILE must be put so that STB_LOCAL - symbols can be safely used */ - put_elf_sym(symtab_section, 0, 0, - ELF64_ST_INFO(STB_LOCAL, STT_FILE), 0, - SHN_ABS, file->filename); - - /* define some often used types */ - int_type.t = VT_INT; - - char_pointer_type.t = VT_BYTE; - mk_pointer(&char_pointer_type); - - func_old_type.t = VT_FUNC; - func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD); - -#if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP) - float_type.t = VT_FLOAT; - double_type.t = VT_DOUBLE; - - func_float_type.t = VT_FUNC; - func_float_type.ref = sym_push(SYM_FIELD, &float_type, FUNC_CDECL, FUNC_OLD); - func_double_type.t = VT_FUNC; - func_double_type.ref = sym_push(SYM_FIELD, &double_type, FUNC_CDECL, FUNC_OLD); -#endif - -#if 0 - /* define 'void *alloca(unsigned int)' builtin function */ - { - Sym *s1; - - p = anon_sym++; - sym = sym_push(p, mk_pointer(VT_VOID), FUNC_CDECL, FUNC_NEW); - s1 = sym_push(SYM_FIELD, VT_UNSIGNED | VT_INT, 0, 0); - s1->next = NULL; - sym->next = s1; - sym_push(TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0); - } -#endif - - define_start = define_stack; - nocode_wanted = 1; - - if (setjmp(s1->error_jmp_buf) == 0) { - s1->nb_errors = 0; - s1->error_set_jmp_enabled = 1; - - ch = file->buf_ptr[0]; - tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF; - parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM; - next(); - decl(VT_CONST); - if (tok != TOK_EOF) - expect("declaration"); - - /* end of translation unit info */ - if (s1->do_debug) { - put_stabs_r(NULL, N_SO, 0, 0, - text_section->data_offset, text_section, section_sym); - } - } - s1->error_set_jmp_enabled = 0; - - /* reset define stack, but leave -Dsymbols (may be incorrect if - they are undefined) */ - free_defines(define_start); - - gen_inline_functions(); - - sym_pop(&global_stack, NULL); - sym_pop(&local_stack, NULL); - - return s1->nb_errors != 0 ? -1 : 0; -} - -int tcc_compile_string(TCCState *s, const char *str) -{ - BufferedFile bf1, *bf = &bf1; - int ret, len; - char *buf; - - /* init file structure */ - bf->fd = -1; - /* XXX: avoid copying */ - len = strlen(str); - buf = tcc_malloc(len + 1); - if (!buf) - return -1; - memcpy(buf, str, len); - buf[len] = CH_EOB; - bf->buf_ptr = buf; - bf->buf_end = buf + len; - pstrcpy(bf->filename, sizeof(bf->filename), ""); - bf->line_num = 1; - file = bf; - ret = tcc_compile(s); - file = NULL; - tcc_free(buf); - - /* currently, no need to close */ - return ret; -} - -/* define a preprocessor symbol. A value can also be provided with the '=' operator */ -void tcc_define_symbol(TCCState *s1, const char *sym, const char *value) -{ - BufferedFile bf1, *bf = &bf1; - - pstrcpy(bf->buffer, IO_BUF_SIZE, sym); - pstrcat(bf->buffer, IO_BUF_SIZE, " "); - /* default value */ - if (!value) - value = "1"; - pstrcat(bf->buffer, IO_BUF_SIZE, value); - - /* init file structure */ - bf->fd = -1; - bf->buf_ptr = bf->buffer; - bf->buf_end = bf->buffer + strlen(bf->buffer); - *bf->buf_end = CH_EOB; - bf->filename[0] = '\0'; - bf->line_num = 1; - file = bf; - - s1->include_stack_ptr = s1->include_stack; - - /* parse with define parser */ - ch = file->buf_ptr[0]; - next_nomacro(); - parse_define(); - file = NULL; -} - -/* undefine a preprocessor symbol */ -void tcc_undefine_symbol(TCCState *s1, const char *sym) -{ - TokenSym *ts; - Sym *s; - ts = tok_alloc(sym, strlen(sym)); - s = define_find(ts->tok); - /* undefine symbol by putting an invalid name */ - if (s) - define_undef(s); -} - -#ifdef CONFIG_TCC_ASM - -#ifdef TCC_TARGET_I386 -#include "i386-asm.c" -#endif -#include "tccasm.c" - -#else -static void asm_instr(void) -{ - error("inline asm() not supported"); -} -static void asm_global_instr(void) -{ - error("inline asm() not supported"); -} -#endif - -#include "tccelf.c" - -#ifdef TCC_TARGET_COFF -#include "tcccoff.c" -#endif - -#ifdef TCC_TARGET_PE -#include "tccpe.c" -#endif - -#ifdef CONFIG_TCC_BACKTRACE -/* print the position in the source file of PC value 'pc' by reading - the stabs debug information */ -static void rt_printline(unsigned long wanted_pc) -{ - Stab_Sym *sym, *sym_end; - char func_name[128], last_func_name[128]; - unsigned long func_addr, last_pc, pc; - const char *incl_files[INCLUDE_STACK_SIZE]; - int incl_index, len, last_line_num, i; - const char *str, *p; - - fprintf(stderr, "0x%08lx:", wanted_pc); - - func_name[0] = '\0'; - func_addr = 0; - incl_index = 0; - last_func_name[0] = '\0'; - last_pc = 0xffffffff; - last_line_num = 1; - sym = (Stab_Sym *)stab_section->data + 1; - sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset); - while (sym < sym_end) { - switch(sym->n_type) { - /* function start or end */ - case N_FUN: - if (sym->n_strx == 0) { - /* we test if between last line and end of function */ - pc = sym->n_value + func_addr; - if (wanted_pc >= last_pc && wanted_pc < pc) - goto found; - func_name[0] = '\0'; - func_addr = 0; - } else { - str = stabstr_section->data + sym->n_strx; - p = strchr(str, ':'); - if (!p) { - pstrcpy(func_name, sizeof(func_name), str); - } else { - len = p - str; - if (len > sizeof(func_name) - 1) - len = sizeof(func_name) - 1; - memcpy(func_name, str, len); - func_name[len] = '\0'; - } - func_addr = sym->n_value; - } - break; - /* line number info */ - case N_SLINE: - pc = sym->n_value + func_addr; - if (wanted_pc >= last_pc && wanted_pc < pc) - goto found; - last_pc = pc; - last_line_num = sym->n_desc; - /* XXX: slow! */ - strcpy(last_func_name, func_name); - break; - /* include files */ - case N_BINCL: - str = stabstr_section->data + sym->n_strx; - add_incl: - if (incl_index < INCLUDE_STACK_SIZE) { - incl_files[incl_index++] = str; - } - break; - case N_EINCL: - if (incl_index > 1) - incl_index--; - break; - case N_SO: - if (sym->n_strx == 0) { - incl_index = 0; /* end of translation unit */ - } else { - str = stabstr_section->data + sym->n_strx; - /* do not add path */ - len = strlen(str); - if (len > 0 && str[len - 1] != '/') - goto add_incl; - } - break; - } - sym++; - } - - /* second pass: we try symtab symbols (no line number info) */ - incl_index = 0; - { - ElfW(Sym) *sym, *sym_end; - int type; - - sym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset); - for(sym = (ElfW(Sym) *)symtab_section->data + 1; - sym < sym_end; - sym++) { - type = ELF64_ST_TYPE(sym->st_info); - if (type == STT_FUNC) { - if (wanted_pc >= sym->st_value && - wanted_pc < sym->st_value + sym->st_size) { - pstrcpy(last_func_name, sizeof(last_func_name), - strtab_section->data + sym->st_name); - goto found; - } - } - } - } - /* did not find any info: */ - fprintf(stderr, " ???\n"); - return; - found: - if (last_func_name[0] != '\0') { - fprintf(stderr, " %s()", last_func_name); - } - if (incl_index > 0) { - fprintf(stderr, " (%s:%d", - incl_files[incl_index - 1], last_line_num); - for(i = incl_index - 2; i >= 0; i--) - fprintf(stderr, ", included from %s", incl_files[i]); - fprintf(stderr, ")"); - } - fprintf(stderr, "\n"); -} - -#ifdef __i386__ -/* fix for glibc 2.1 */ -#ifndef REG_EIP -#define REG_EIP EIP -#define REG_EBP EBP -#endif - -/* return the PC at frame level 'level'. Return non zero if not found */ -static int rt_get_caller_pc(unsigned long *paddr, - ucontext_t *uc, int level) -{ - unsigned long fp; - int i; - - if (level == 0) { -#if defined(__FreeBSD__) - *paddr = uc->uc_mcontext.mc_eip; -#elif defined(__dietlibc__) - *paddr = uc->uc_mcontext.eip; -#else - *paddr = uc->uc_mcontext.gregs[REG_EIP]; -#endif - return 0; - } else { -#if defined(__FreeBSD__) - fp = uc->uc_mcontext.mc_ebp; -#elif defined(__dietlibc__) - fp = uc->uc_mcontext.ebp; -#else - fp = uc->uc_mcontext.gregs[REG_EBP]; -#endif - for(i=1;i= 0xc0000000) - return -1; - fp = ((unsigned long *)fp)[0]; - } - *paddr = ((unsigned long *)fp)[1]; - return 0; - } -} -#elif 1 -/* return the PC at frame level 'level'. Return non zero if not found */ -static int rt_get_caller_pc(unsigned long *paddr, - ucontext_t *uc, int level) -{ - unsigned long fp; - int i; - - if (level == 0) { - /* XXX: only support linux */ - *paddr = uc->uc_mcontext.gregs[REG_RIP]; - return 0; - } else { - fp = uc->uc_mcontext.gregs[REG_RBP]; - for(i=1;isi_code) { - case FPE_INTDIV: - case FPE_FLTDIV: - rt_error(uc, "division by zero"); - break; - default: - rt_error(uc, "floating point exception"); - break; - } - break; - case SIGBUS: - case SIGSEGV: - if (rt_bound_error_msg && *rt_bound_error_msg) - rt_error(uc, *rt_bound_error_msg); - else - rt_error(uc, "dereferencing invalid pointer"); - break; - case SIGILL: - rt_error(uc, "illegal instruction"); - break; - case SIGABRT: - rt_error(uc, "abort() called"); - break; - default: - rt_error(uc, "caught signal %d", signum); - break; - } - exit(255); -} - -#endif - -/* copy code into memory passed in by the caller and do all relocations - (needed before using tcc_get_symbol()). - returns -1 on error and required size if ptr is NULL */ -int tcc_relocate(TCCState *s1, void *ptr) -{ - Section *s; - unsigned long offset, length, mem; - int i; - - if (0 == s1->runtime_added) { - s1->runtime_added = 1; - s1->nb_errors = 0; -#ifdef TCC_TARGET_PE - pe_add_runtime(s1); - relocate_common_syms(); - tcc_add_linker_symbols(s1); -#else - tcc_add_runtime(s1); - relocate_common_syms(); - tcc_add_linker_symbols(s1); - build_got_entries(s1); -#endif - } - - offset = 0, mem = (unsigned long)ptr; - for(i = 1; i < s1->nb_sections; i++) { - s = s1->sections[i]; - if (0 == (s->sh_flags & SHF_ALLOC)) - continue; - length = s->data_offset; - s->sh_addr = mem ? (mem + offset + 15) & ~15 : 0; - offset = (offset + length + 15) & ~15; - } - - /* relocate symbols */ - relocate_syms(s1, 1); - if (s1->nb_errors) - return -1; - -#ifdef TCC_TARGET_X86_64 - s1->runtime_plt_and_got_offset = 0; - s1->runtime_plt_and_got = (char *)(mem + offset); - /* double the size of the buffer for got and plt entries - XXX: calculate exact size for them? */ - offset *= 2; -#endif - - if (0 == mem) - return offset + 15; - - /* relocate each section */ - for(i = 1; i < s1->nb_sections; i++) { - s = s1->sections[i]; - if (s->reloc) - relocate_section(s1, s); - } - - for(i = 1; i < s1->nb_sections; i++) { - s = s1->sections[i]; - if (0 == (s->sh_flags & SHF_ALLOC)) - continue; - length = s->data_offset; - // printf("%-12s %08x %04x\n", s->name, s->sh_addr, length); - ptr = (void*)s->sh_addr; - if (NULL == s->data || s->sh_type == SHT_NOBITS) - memset(ptr, 0, length); - else - memcpy(ptr, s->data, length); - /* mark executable sections as executable in memory */ - if (s->sh_flags & SHF_EXECINSTR) - set_pages_executable(ptr, length); - } -#ifdef TCC_TARGET_X86_64 - set_pages_executable(s1->runtime_plt_and_got, - s1->runtime_plt_and_got_offset); -#endif - return 0; -} - -/* launch the compiled program with the given arguments */ -int tcc_run(TCCState *s1, int argc, char **argv) -{ - int (*prog_main)(int, char **); - void *ptr; - int ret; - - ret = tcc_relocate(s1, NULL); - if (ret < 0) - return -1; - ptr = tcc_malloc(ret); - tcc_relocate(s1, ptr); - - prog_main = tcc_get_symbol_err(s1, "main"); - - if (s1->do_debug) { -#ifdef CONFIG_TCC_BACKTRACE - struct sigaction sigact; - /* install TCC signal handlers to print debug info on fatal - runtime errors */ - sigact.sa_flags = SA_SIGINFO | SA_RESETHAND; - sigact.sa_sigaction = sig_error; - sigemptyset(&sigact.sa_mask); - sigaction(SIGFPE, &sigact, NULL); - sigaction(SIGILL, &sigact, NULL); - sigaction(SIGSEGV, &sigact, NULL); - sigaction(SIGBUS, &sigact, NULL); - sigaction(SIGABRT, &sigact, NULL); -#else - error("debug mode not available"); -#endif - } - -#ifdef CONFIG_TCC_BCHECK - if (s1->do_bounds_check) { - void (*bound_init)(void); - - /* set error function */ - rt_bound_error_msg = tcc_get_symbol_err(s1, "__bound_error_msg"); - - /* XXX: use .init section so that it also work in binary ? */ - bound_init = (void *)tcc_get_symbol_err(s1, "__bound_init"); - bound_init(); - } -#endif - ret = (*prog_main)(argc, argv); - tcc_free(ptr); - return ret; -} - -void tcc_memstats(void) -{ -#ifdef MEM_DEBUG - printf("memory in use: %d\n", mem_cur_size); -#endif -} - -static void tcc_cleanup(void) -{ - int i, n; - - if (NULL == tcc_state) - return; - tcc_state = NULL; - - /* free -D defines */ - free_defines(NULL); - - /* free tokens */ - n = tok_ident - TOK_IDENT; - for(i = 0; i < n; i++) - tcc_free(table_ident[i]); - tcc_free(table_ident); - - /* free sym_pools */ - dynarray_reset(&sym_pools, &nb_sym_pools); - /* string buffer */ - cstr_free(&tokcstr); - /* reset symbol stack */ - sym_free_first = NULL; - /* cleanup from error/setjmp */ - macro_ptr = NULL; -} - -TCCState *tcc_new(void) -{ - TCCState *s; - - tcc_cleanup(); - - s = tcc_mallocz(sizeof(TCCState)); - if (!s) - return NULL; - tcc_state = s; - s->output_type = TCC_OUTPUT_MEMORY; - s->tcc_lib_path = CONFIG_TCCDIR; - - preprocess_new(); - - /* we add dummy defines for some special macros to speed up tests - and to have working defined() */ - define_push(TOK___LINE__, MACRO_OBJ, NULL, NULL); - define_push(TOK___FILE__, MACRO_OBJ, NULL, NULL); - define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL); - define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL); - - /* standard defines */ - tcc_define_symbol(s, "__STDC__", NULL); - tcc_define_symbol(s, "__STDC_VERSION__", "199901L"); -#if defined(TCC_TARGET_I386) - tcc_define_symbol(s, "__i386__", NULL); -#endif -#if defined(TCC_TARGET_X86_64) - tcc_define_symbol(s, "__x86_64__", NULL); -#endif -#if defined(TCC_TARGET_ARM) - tcc_define_symbol(s, "__ARM_ARCH_4__", NULL); - tcc_define_symbol(s, "__arm_elf__", NULL); - tcc_define_symbol(s, "__arm_elf", NULL); - tcc_define_symbol(s, "arm_elf", NULL); - tcc_define_symbol(s, "__arm__", NULL); - tcc_define_symbol(s, "__arm", NULL); - tcc_define_symbol(s, "arm", NULL); - tcc_define_symbol(s, "__APCS_32__", NULL); -#endif -#ifdef TCC_TARGET_PE - tcc_define_symbol(s, "_WIN32", NULL); -#else - tcc_define_symbol(s, "__unix__", NULL); - tcc_define_symbol(s, "__unix", NULL); -#if defined(__linux) - tcc_define_symbol(s, "__linux__", NULL); - tcc_define_symbol(s, "__linux", NULL); -#endif -#endif - /* tiny C specific defines */ - tcc_define_symbol(s, "__TINYC__", NULL); - - /* tiny C & gcc defines */ - tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned int"); - tcc_define_symbol(s, "__PTRDIFF_TYPE__", "int"); -#ifdef TCC_TARGET_PE - tcc_define_symbol(s, "__WCHAR_TYPE__", "unsigned short"); -#else - tcc_define_symbol(s, "__WCHAR_TYPE__", "int"); -#endif - -#ifndef TCC_TARGET_PE - /* default library paths */ - tcc_add_library_path(s, CONFIG_SYSROOT "/usr/local/lib"); - tcc_add_library_path(s, CONFIG_SYSROOT "/usr/lib"); - tcc_add_library_path(s, CONFIG_SYSROOT "/lib"); -#endif - - /* no section zero */ - dynarray_add((void ***)&s->sections, &s->nb_sections, NULL); - - /* create standard sections */ - text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR); - data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE); - bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE); - - /* symbols are always generated for linking stage */ - symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0, - ".strtab", - ".hashtab", SHF_PRIVATE); - strtab_section = symtab_section->link; - - /* private symbol table for dynamic symbols */ - s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE, - ".dynstrtab", - ".dynhashtab", SHF_PRIVATE); - s->alacarte_link = 1; - -#ifdef CHAR_IS_UNSIGNED - s->char_is_unsigned = 1; -#endif -#if defined(TCC_TARGET_PE) && 0 - /* XXX: currently the PE linker is not ready to support that */ - s->leading_underscore = 1; -#endif - return s; -} - -void tcc_delete(TCCState *s1) -{ - int i; - - tcc_cleanup(); - - /* free all sections */ - for(i = 1; i < s1->nb_sections; i++) - free_section(s1->sections[i]); - dynarray_reset(&s1->sections, &s1->nb_sections); - - for(i = 0; i < s1->nb_priv_sections; i++) - free_section(s1->priv_sections[i]); - dynarray_reset(&s1->priv_sections, &s1->nb_priv_sections); - - /* free any loaded DLLs */ - for ( i = 0; i < s1->nb_loaded_dlls; i++) { - DLLReference *ref = s1->loaded_dlls[i]; - if ( ref->handle ) - dlclose(ref->handle); - } - - /* free loaded dlls array */ - dynarray_reset(&s1->loaded_dlls, &s1->nb_loaded_dlls); - - /* free library paths */ - dynarray_reset(&s1->library_paths, &s1->nb_library_paths); - - /* free include paths */ - dynarray_reset(&s1->cached_includes, &s1->nb_cached_includes); - dynarray_reset(&s1->include_paths, &s1->nb_include_paths); - dynarray_reset(&s1->sysinclude_paths, &s1->nb_sysinclude_paths); - - tcc_free(s1); -} - -int tcc_add_include_path(TCCState *s1, const char *pathname) -{ - char *pathname1; - - pathname1 = tcc_strdup(pathname); - dynarray_add((void ***)&s1->include_paths, &s1->nb_include_paths, pathname1); - return 0; -} - -int tcc_add_sysinclude_path(TCCState *s1, const char *pathname) -{ - char *pathname1; - - pathname1 = tcc_strdup(pathname); - dynarray_add((void ***)&s1->sysinclude_paths, &s1->nb_sysinclude_paths, pathname1); - return 0; -} - -static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags) -{ - const char *ext; - ElfW(Ehdr) ehdr; - int fd, ret; - BufferedFile *saved_file; - - /* find source file type with extension */ - ext = tcc_fileextension(filename); - if (ext[0]) - ext++; - - /* open the file */ - saved_file = file; - file = tcc_open(s1, filename); - if (!file) { - if (flags & AFF_PRINT_ERROR) { - error_noabort("file '%s' not found", filename); - } - ret = -1; - goto fail1; - } - - if (flags & AFF_PREPROCESS) { - ret = tcc_preprocess(s1); - } else if (!ext[0] || !PATHCMP(ext, "c")) { - /* C file assumed */ - ret = tcc_compile(s1); - } else -#ifdef CONFIG_TCC_ASM - if (!strcmp(ext, "S")) { - /* preprocessed assembler */ - ret = tcc_assemble(s1, 1); - } else if (!strcmp(ext, "s")) { - /* non preprocessed assembler */ - ret = tcc_assemble(s1, 0); - } else -#endif -#ifdef TCC_TARGET_PE - if (!PATHCMP(ext, "def")) { - ret = pe_load_def_file(s1, file->fd); - } else -#endif - { - fd = file->fd; - /* assume executable format: auto guess file type */ - ret = read(fd, &ehdr, sizeof(ehdr)); - lseek(fd, 0, SEEK_SET); - if (ret <= 0) { - error_noabort("could not read header"); - goto fail; - } else if (ret != sizeof(ehdr)) { - goto try_load_script; - } - - if (ehdr.e_ident[0] == ELFMAG0 && - ehdr.e_ident[1] == ELFMAG1 && - ehdr.e_ident[2] == ELFMAG2 && - ehdr.e_ident[3] == ELFMAG3) { - file->line_num = 0; /* do not display line number if error */ - if (ehdr.e_type == ET_REL) { - ret = tcc_load_object_file(s1, fd, 0); - } else if (ehdr.e_type == ET_DYN) { - if (s1->output_type == TCC_OUTPUT_MEMORY) { -#ifdef TCC_TARGET_PE - ret = -1; -#else - void *h; - h = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY); - if (h) - ret = 0; - else - ret = -1; -#endif - } else { - ret = tcc_load_dll(s1, fd, filename, - (flags & AFF_REFERENCED_DLL) != 0); - } - } else { - error_noabort("unrecognized ELF file"); - goto fail; - } - } else if (memcmp((char *)&ehdr, ARMAG, 8) == 0) { - file->line_num = 0; /* do not display line number if error */ - ret = tcc_load_archive(s1, fd); - } else -#ifdef TCC_TARGET_COFF - if (*(uint16_t *)(&ehdr) == COFF_C67_MAGIC) { - ret = tcc_load_coff(s1, fd); - } else -#endif -#ifdef TCC_TARGET_PE - if (pe_test_res_file(&ehdr, ret)) { - ret = pe_load_res_file(s1, fd); - } else -#endif - { - /* as GNU ld, consider it is an ld script if not recognized */ - try_load_script: - ret = tcc_load_ldscript(s1); - if (ret < 0) { - error_noabort("unrecognized file type"); - goto fail; - } - } - } - the_end: - tcc_close(file); - fail1: - file = saved_file; - return ret; - fail: - ret = -1; - goto the_end; -} - -int tcc_add_file(TCCState *s, const char *filename) -{ - if (s->output_type == TCC_OUTPUT_PREPROCESS) - return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR | AFF_PREPROCESS); - else - return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR); -} - -int tcc_add_library_path(TCCState *s, const char *pathname) -{ - char *pathname1; - - pathname1 = tcc_strdup(pathname); - dynarray_add((void ***)&s->library_paths, &s->nb_library_paths, pathname1); - return 0; -} - -/* find and load a dll. Return non zero if not found */ -/* XXX: add '-rpath' option support ? */ -static int tcc_add_dll(TCCState *s, const char *filename, int flags) -{ - char buf[1024]; - int i; - - for(i = 0; i < s->nb_library_paths; i++) { - snprintf(buf, sizeof(buf), "%s/%s", - s->library_paths[i], filename); - if (tcc_add_file_internal(s, buf, flags) == 0) - return 0; - } - return -1; -} - -/* the library name is the same as the argument of the '-l' option */ -int tcc_add_library(TCCState *s, const char *libraryname) -{ - char buf[1024]; - int i; - - /* first we look for the dynamic library if not static linking */ - if (!s->static_link) { -#ifdef TCC_TARGET_PE - snprintf(buf, sizeof(buf), "%s.def", libraryname); -#else - snprintf(buf, sizeof(buf), "lib%s.so", libraryname); -#endif - if (tcc_add_dll(s, buf, 0) == 0) - return 0; - } - - /* then we look for the static library */ - for(i = 0; i < s->nb_library_paths; i++) { - snprintf(buf, sizeof(buf), "%s/lib%s.a", - s->library_paths[i], libraryname); - if (tcc_add_file_internal(s, buf, 0) == 0) - return 0; - } - return -1; -} - -int tcc_add_symbol(TCCState *s, const char *name, void *val) -{ - add_elf_sym(symtab_section, (unsigned long)val, 0, - ELF64_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0, - SHN_ABS, name); - return 0; -} - -int tcc_set_output_type(TCCState *s, int output_type) -{ - char buf[1024]; - - s->output_type = output_type; - - if (!s->nostdinc) { - /* default include paths */ - /* XXX: reverse order needed if -isystem support */ -#ifndef TCC_TARGET_PE - tcc_add_sysinclude_path(s, CONFIG_SYSROOT "/usr/local/include"); - tcc_add_sysinclude_path(s, CONFIG_SYSROOT "/usr/include"); -#endif - snprintf(buf, sizeof(buf), "%s/include", s->tcc_lib_path); - tcc_add_sysinclude_path(s, buf); -#ifdef TCC_TARGET_PE - snprintf(buf, sizeof(buf), "%s/include/winapi", s->tcc_lib_path); - tcc_add_sysinclude_path(s, buf); -#endif - } - - /* if bound checking, then add corresponding sections */ -#ifdef CONFIG_TCC_BCHECK - if (s->do_bounds_check) { - /* define symbol */ - tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL); - /* create bounds sections */ - bounds_section = new_section(s, ".bounds", - SHT_PROGBITS, SHF_ALLOC); - lbounds_section = new_section(s, ".lbounds", - SHT_PROGBITS, SHF_ALLOC); - } -#endif - - if (s->char_is_unsigned) { - tcc_define_symbol(s, "__CHAR_UNSIGNED__", NULL); - } - - /* add debug sections */ - if (s->do_debug) { - /* stab symbols */ - stab_section = new_section(s, ".stab", SHT_PROGBITS, 0); - stab_section->sh_entsize = sizeof(Stab_Sym); - stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0); - put_elf_str(stabstr_section, ""); - stab_section->link = stabstr_section; - /* put first entry */ - put_stabs("", 0, 0, 0, 0); - } - - /* add libc crt1/crti objects */ -#ifndef TCC_TARGET_PE - if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) && - !s->nostdlib) { - if (output_type != TCC_OUTPUT_DLL) - tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crt1.o"); - tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crti.o"); - } -#endif - -#ifdef TCC_TARGET_PE - snprintf(buf, sizeof(buf), "%s/lib", s->tcc_lib_path); - tcc_add_library_path(s, buf); -#endif - - return 0; -} - -#define WD_ALL 0x0001 /* warning is activated when using -Wall */ -#define FD_INVERT 0x0002 /* invert value before storing */ - -typedef struct FlagDef { - uint16_t offset; - uint16_t flags; - const char *name; -} FlagDef; - -static FlagDef warning_defs[] = { - { 0, 0, "unsupported" }, - { 0, 0, "write-strings" }, - { 0, 0, "error" }, - { 0, WD_ALL, "implicit-function-declaration" } -}; - -void _init_warning_defs(void) { - warning_defs[0].offset = offsetof(TCCState, warn_unsupported); - warning_defs[1].offset = offsetof(TCCState, warn_write_strings); - warning_defs[2].offset = offsetof(TCCState, warn_error); - warning_defs[3].offset = offsetof(TCCState, warn_implicit_function_declaration); -} - -static int set_flag(TCCState *s, const FlagDef *flags, int nb_flags, - const char *name, int value) -{ - int i; - const FlagDef *p; - const char *r; - - r = name; - if (r[0] == 'n' && r[1] == 'o' && r[2] == '-') { - r += 3; - value = !value; - } - for(i = 0, p = flags; i < nb_flags; i++, p++) { - if (!strcmp(r, p->name)) - goto found; - } - return -1; - found: - if (p->flags & FD_INVERT) - value = !value; - *(int *)((uint8_t *)s + p->offset) = value; - return 0; -} - - -/* set/reset a warning */ -int tcc_set_warning(TCCState *s, const char *warning_name, int value) -{ - int i; - const FlagDef *p; - - if (!strcmp(warning_name, "all")) { - for(i = 0, p = warning_defs; i < countof(warning_defs); i++, p++) { - if (p->flags & WD_ALL) - *(int *)((uint8_t *)s + p->offset) = 1; - } - return 0; - } else { - return set_flag(s, warning_defs, countof(warning_defs), - warning_name, value); - } -} - -static FlagDef flag_defs[] = { - { 0, 0, "unsigned-char" }, - { 0, FD_INVERT, "signed-char" }, - { 0, FD_INVERT, "common" }, - { 0, 0, "leading-underscore" } -}; -void _init_flag_defs(void) { - flag_defs[0].offset = offsetof(TCCState, char_is_unsigned); - flag_defs[1].offset = offsetof(TCCState, char_is_unsigned); - flag_defs[2].offset = offsetof(TCCState, nocommon); - flag_defs[3].offset = offsetof(TCCState, leading_underscore); -} - -/* set/reset a flag */ -int tcc_set_flag(TCCState *s, const char *flag_name, int value) -{ - return set_flag(s, flag_defs, countof(flag_defs), - flag_name, value); -} - -/* set CONFIG_TCCDIR at runtime */ -void tcc_set_lib_path(TCCState *s, const char *path) -{ - s->tcc_lib_path = tcc_strdup(path); -} - -void tcc_print_stats(TCCState *s, int64_t total_time) -{ - double tt; - tt = (double)total_time / 1000000.0; - if (tt < 0.001) - tt = 0.001; - if (total_bytes < 1) - total_bytes = 1; - printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n", - tok_ident - TOK_IDENT, total_lines, total_bytes, - tt, (int)(total_lines / tt), - total_bytes / tt / 1000000.0); -} -- cgit v1.2.3