📄 tcc.c
字号:
#define VT_TYPE (~(VT_STORAGE))/* token values *//* warning: the following compare tokens depend on i386 asm code */#define TOK_ULT 0x92#define TOK_UGE 0x93#define TOK_EQ 0x94#define TOK_NE 0x95#define TOK_ULE 0x96#define TOK_UGT 0x97#define TOK_LT 0x9c#define TOK_GE 0x9d#define TOK_LE 0x9e#define TOK_GT 0x9f#define TOK_LAND 0xa0#define TOK_LOR 0xa1#define TOK_DEC 0xa2#define TOK_MID 0xa3 /* inc/dec, to void constant */#define TOK_INC 0xa4#define TOK_UDIV 0xb0 /* unsigned division */#define TOK_UMOD 0xb1 /* unsigned modulo */#define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */#define TOK_CINT 0xb3 /* number in tokc */#define TOK_CCHAR 0xb4 /* char constant in tokc */#define TOK_STR 0xb5 /* pointer to string in tokc */#define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */#define TOK_LCHAR 0xb7#define TOK_LSTR 0xb8#define TOK_CFLOAT 0xb9 /* float constant */#define TOK_LINENUM 0xba /* line number info */#define TOK_CDOUBLE 0xc0 /* double constant */#define TOK_CLDOUBLE 0xc1 /* long double constant */#define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */#define TOK_ADDC1 0xc3 /* add with carry generation */#define TOK_ADDC2 0xc4 /* add with carry use */#define TOK_SUBC1 0xc5 /* add with carry generation */#define TOK_SUBC2 0xc6 /* add with carry use */#define TOK_CUINT 0xc8 /* unsigned int constant */#define TOK_CLLONG 0xc9 /* long long constant */#define TOK_CULLONG 0xca /* unsigned long long constant */#define TOK_ARROW 0xcb#define TOK_DOTS 0xcc /* three dots */#define TOK_SHR 0xcd /* unsigned shift right */#define TOK_PPNUM 0xce /* preprocessor number */#define TOK_SHL 0x01 /* shift left */#define TOK_SAR 0x02 /* signed shift right */ /* assignement operators : normal operator or 0x80 */#define TOK_A_MOD 0xa5#define TOK_A_AND 0xa6#define TOK_A_MUL 0xaa#define TOK_A_ADD 0xab#define TOK_A_SUB 0xad#define TOK_A_DIV 0xaf#define TOK_A_XOR 0xde#define TOK_A_OR 0xfc#define TOK_A_SHL 0x81#define TOK_A_SAR 0x82#ifndef offsetof#define offsetof(type, field) ((size_t) &((type *)0)->field)#endif#ifndef countof#define countof(tab) (sizeof(tab) / sizeof((tab)[0]))#endif/* WARNING: the content of this string encodes token numbers */static char tok_two_chars[] = "<=\236>=\235!=\225&&\240||\241++\244--\242==\224<<\1>>\2+=\253-=\255*=\252/=\257%=\245&=\246^=\336|=\374->\313..\250##\266";#define TOK_EOF (-1) /* end of file */#define TOK_LINEFEED 10 /* line feed *//* all identificators and strings have token above that */#define TOK_IDENT 256/* only used for i386 asm opcodes definitions */#define DEF_ASM(x) DEF(TOK_ASM_ ## x, #x)#define DEF_BWL(x) \ DEF(TOK_ASM_ ## x ## b, #x "b") \ DEF(TOK_ASM_ ## x ## w, #x "w") \ DEF(TOK_ASM_ ## x ## l, #x "l") \ DEF(TOK_ASM_ ## x, #x)#define DEF_WL(x) \ DEF(TOK_ASM_ ## x ## w, #x "w") \ DEF(TOK_ASM_ ## x ## l, #x "l") \ DEF(TOK_ASM_ ## x, #x)#define DEF_FP1(x) \ DEF(TOK_ASM_ ## f ## x ## s, "f" #x "s") \ DEF(TOK_ASM_ ## fi ## x ## l, "fi" #x "l") \ DEF(TOK_ASM_ ## f ## x ## l, "f" #x "l") \ DEF(TOK_ASM_ ## fi ## x ## s, "fi" #x "s")#define DEF_FP(x) \ DEF(TOK_ASM_ ## f ## x, "f" #x ) \ DEF(TOK_ASM_ ## f ## x ## p, "f" #x "p") \ DEF_FP1(x)#define DEF_ASMTEST(x) \ DEF_ASM(x ## o) \ DEF_ASM(x ## no) \ DEF_ASM(x ## b) \ DEF_ASM(x ## c) \ DEF_ASM(x ## nae) \ DEF_ASM(x ## nb) \ DEF_ASM(x ## nc) \ DEF_ASM(x ## ae) \ DEF_ASM(x ## e) \ DEF_ASM(x ## z) \ DEF_ASM(x ## ne) \ DEF_ASM(x ## nz) \ DEF_ASM(x ## be) \ DEF_ASM(x ## na) \ DEF_ASM(x ## nbe) \ DEF_ASM(x ## a) \ DEF_ASM(x ## s) \ DEF_ASM(x ## ns) \ DEF_ASM(x ## p) \ DEF_ASM(x ## pe) \ DEF_ASM(x ## np) \ DEF_ASM(x ## po) \ DEF_ASM(x ## l) \ DEF_ASM(x ## nge) \ DEF_ASM(x ## nl) \ DEF_ASM(x ## ge) \ DEF_ASM(x ## le) \ DEF_ASM(x ## ng) \ DEF_ASM(x ## nle) \ DEF_ASM(x ## g)#define TOK_ASM_int TOK_INTenum { TOK_LAST = TOK_IDENT - 1,#define DEF(id, str) id,#include "tcctok.h"#undef DEF};static const char tcc_keywords[] = #define DEF(id, str) str "\0"#include "tcctok.h"#undef DEF;#define TOK_UIDENT TOK_DEFINE#ifdef WIN32#define snprintf _snprintf#define vsnprintf _vsnprintf#endif#if defined(WIN32) || defined(TCC_UCLIBC) || defined(__FreeBSD__)/* currently incorrect */long double strtold(const char *nptr, char **endptr){ return (long double)strtod(nptr, endptr);}float strtof(const char *nptr, char **endptr){ return (float)strtod(nptr, endptr);}#else/* XXX: need to define this to use them in non ISOC99 context */extern float strtof (const char *__nptr, char **__endptr);extern long double strtold (const char *__nptr, char **__endptr);#endifstatic char *pstrcpy(char *buf, int buf_size, const char *s);static char *pstrcat(char *buf, int buf_size, const char *s);static void next(void);static void next_nomacro(void);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 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);static void macro_subst(TokenString *tok_str, Sym **nested_list, const int *macro_str, int can_read_stream);int save_reg_forced(int r);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 is_compatible_types(CType *type1, CType *type2);void error(const char *fmt, ...);void vpushi(int v);void vset(CType *type, int r, int v);void type_to_str(char *buf, int buf_size, CType *type, const char *varstr);char *get_tok_str(int v, CValue *cv);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 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 */static int tcc_add_file_internal(TCCState *s, const char *filename, int flags);/* tccasm.c */#ifdef CONFIG_TCC_ASMtypedef struct ExprValue { uint32_t v; Sym *sym;} ExprValue;#define MAX_ASM_OPERANDS 30typedef struct ASMOperand { int id; /* GCC 3 optionnal identifier (0 if number only supported */ char *constraint; char asm_str[16]; /* computed asm string for operand */ SValue *vt; /* C value of the expression */ int ref_index; /* if >= 0, gives reference to a output constraint */ int priority; /* priority, used to assign registers */ int reg; /* if >= 0, register number used for this operand */ int is_llong; /* true if double register value */} ASMOperand;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);#endifstatic void asm_instr(void);/* true if float/double/long double type */static inline int is_float(int t){ int bt; bt = t & VT_BTYPE; return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT;}#ifdef TCC_TARGET_I386#include "i386-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;}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[] = { TCCSYM(printf) TCCSYM(fprintf) TCCSYM(fopen) TCCSYM(fclose) { NULL, NULL },};void *dlsym(void *handle, const char *symbol){ TCCSyms *p; p = tcc_syms; while (p->str != NULL) { if (!strcmp(p->str, symbol)) return p->ptr; p++; } return NULL;}#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. */static 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. */static 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;}/* memory management */#ifdef MEM_DEBUGint mem_cur_size;int mem_max_size;#endifstatic inline void tcc_free(void *ptr){#ifdef MEM_DEBUG mem_cur_size -= malloc_usable_size(ptr);#endif free(ptr);}static 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;}static void *tcc_mallocz(unsigned long size){ void *ptr; ptr = tcc_malloc(size); memset(ptr, 0, size); return ptr;}static inline 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;}static 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)static 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;}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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -