| @@ -38,10 +38,6 @@ ST_DATA int total_bytes; · 37 unmodified lines |
| 38 | 38 | ST_DATA int tok_ident; |
| 39 | 39 | ST_DATA TokenSym **table_ident; |
| 40 | 40 | |
| 41 | | −ST_DATA TinyAlloc *toksym_alloc; |
| 42 | | −ST_DATA TinyAlloc *tokstr_alloc; |
| 43 | | −ST_DATA TinyAlloc *cstr_alloc; |
| 44 | | − |
| 45 | 41 | /* ------------------------------------------------------------------------- */ |
| 46 | 42 | |
| 47 | 43 | static TokenSym *hash_ident[TOK_HASH_SIZE]; |
| @@ -53,6 +49,10 @@ static int pp_debug_tok, pp_debug_symv; · 5 unmodified lines |
| 53 | 49 | static int pp_once; |
| 54 | 50 | static void tok_print(const char *msg, const int *str); |
| 55 | 51 | |
| 52 | +static struct TinyAlloc *toksym_alloc; |
| 53 | +static struct TinyAlloc *tokstr_alloc; |
| 54 | +static struct TinyAlloc *cstr_alloc; |
| 55 | + |
| 56 | 56 | /* isidnum_table flags: */ |
| 57 | 57 | #define IS_SPC 1 |
| 58 | 58 | #define IS_ID 2 |
| @@ -110,31 +110,54 @@ ST_FUNC void expect(const char *msg) · 51 unmodified lines |
| 110 | 110 | tcc_error("%s expected", msg); |
| 111 | 111 | } |
| 112 | 112 | |
| 113 | | −ST_FUNC void begin_macro(TokenString *str, int alloc) |
| 114 | | −{ |
| 115 | | − str->alloc = alloc; |
| 116 | | − str->prev = macro_stack; |
| 117 | | − str->prev_ptr = macro_ptr; |
| 118 | | − macro_ptr = str->str; |
| 119 | | − macro_stack = str; |
| 120 | | −} |
| 113 | +/* ------------------------------------------------------------------------- */ |
| 114 | +/* Custom allocator for tiny objects */ |
| 121 | 115 | |
| 122 | | −ST_FUNC void end_macro(void) |
| 123 | | −{ |
| 124 | | − TokenString *str = macro_stack; |
| 125 | | − macro_stack = str->prev; |
| 126 | | − macro_ptr = str->prev_ptr; |
| 127 | | − if (str->alloc == 2) { |
| 128 | | − str->alloc = 3; /* just mark as finished */ |
| 129 | | − } else { |
| 130 | | − tok_str_free(str->str); |
| 131 | | − if (str->alloc == 1) |
| 132 | | − tcc_free(str); |
| 133 | | − } |
| 134 | | −} |
| 116 | +#define USE_TAL |
| 117 | + |
| 118 | +#ifndef USE_TAL |
| 119 | +#define tal_free(al, p) tcc_free(p) |
| 120 | +#define tal_realloc(al, p, size) tcc_realloc(p, size) |
| 121 | +#define tal_new(a,b,c) |
| 122 | +#define tal_delete(a) |
| 123 | +#else |
| 124 | +#if !defined(MEM_DEBUG) |
| 125 | +#define tal_free(al, p) tal_free_impl(al, p) |
| 126 | +#define tal_realloc(al, p, size) tal_realloc_impl(&al, p, size) |
| 127 | +#define TAL_DEBUG_PARAMS |
| 128 | +#else |
| 129 | +#define TAL_DEBUG 1 |
| 130 | +#define tal_free(al, p) tal_free_impl(al, p, __FILE__, __LINE__) |
| 131 | +#define tal_realloc(al, p, size) tal_realloc_impl(&al, p, size, __FILE__, __LINE__) |
| 132 | +#define TAL_DEBUG_PARAMS , const char *file, int line |
| 133 | +#define TAL_DEBUG_FILE_LEN 15 |
| 134 | +#endif |
| 135 | +//#define TAL_INFO 1 /* collect and dump allocators stats */ |
| 136 | + |
| 137 | +typedef struct TinyAlloc { |
| 138 | + size_t limit; |
| 139 | + size_t size; |
| 140 | + uint8_t *buffer; |
| 141 | + uint8_t *p; |
| 142 | + size_t nb_allocs; |
| 143 | + struct TinyAlloc *next, *top; |
| 144 | +#ifdef TAL_INFO |
| 145 | + size_t nb_peak; |
| 146 | + size_t nb_total; |
| 147 | + size_t nb_missed; |
| 148 | + uint8_t *peak_p; |
| 149 | +#endif |
| 150 | +} TinyAlloc; |
| 151 | + |
| 152 | +typedef struct tal_header_t { |
| 153 | + size_t size; |
| 154 | +#ifdef TAL_DEBUG |
| 155 | + int line_num; /* negative line_num used for double free check */ |
| 156 | + char file_name[TAL_DEBUG_FILE_LEN + 1]; |
| 157 | +#endif |
| 158 | +} tal_header_t; |
| 135 | 159 | |
| 136 | 160 | /* ------------------------------------------------------------------------- */ |
| 137 | | −/* Custom allocator for tiny objects */ |
| 138 | 161 | |
| 139 | 162 | ST_FUNC TinyAlloc *tal_new(TinyAlloc **pal, size_t limit, size_t size) |
| 140 | 163 | { |
| @@ -160,9 +183,10 @@ tail_call: · 19 unmodified lines |
| 160 | 183 | #endif |
| 161 | 184 | #ifdef TAL_DEBUG |
| 162 | 185 | if (al->nb_allocs > 0) { |
| 186 | + uint8_t *p; |
| 163 | 187 | fprintf(stderr, "TAL_DEBUG: mem leak %d chunks (limit= %d)\n", |
| 164 | 188 | al->nb_allocs, al->limit); |
| 165 | | − uint8_t *p = al->buffer; |
| 189 | + p = al->buffer; |
| 166 | 190 | while (p < al->p) { |
| 167 | 191 | tal_header_t *header = (tal_header_t *)p; |
| 168 | 192 | if (header->line_num > 0) { |
| @@ -222,10 +246,10 @@ tail_call: · 53 unmodified lines |
| 222 | 246 | header = (tal_header_t *)al->p; |
| 223 | 247 | header->size = adj_size; |
| 224 | 248 | #ifdef TAL_DEBUG |
| 225 | | − int ofs = strlen(file) - TAL_DEBUG_FILE_LEN; |
| 249 | + { int ofs = strlen(file) - TAL_DEBUG_FILE_LEN; |
| 226 | 250 | strncpy(header->file_name, file + (ofs > 0 ? ofs : 0), TAL_DEBUG_FILE_LEN); |
| 227 | 251 | header->file_name[TAL_DEBUG_FILE_LEN] = 0; |
| 228 | | − header->line_num = line; |
| 252 | + header->line_num = line; } |
| 229 | 253 | #endif |
| 230 | 254 | ret = al->p + sizeof(tal_header_t); |
| 231 | 255 | al->p += adj_size + sizeof(tal_header_t); |
| @@ -286,26 +310,25 @@ tail_call: · 54 unmodified lines |
| 286 | 310 | return ret; |
| 287 | 311 | } |
| 288 | 312 | |
| 313 | +#endif /* USE_TAL */ |
| 314 | + |
| 289 | 315 | /* ------------------------------------------------------------------------- */ |
| 290 | 316 | /* CString handling */ |
| 291 | 317 | static void cstr_realloc(CString *cstr, int new_size) |
| 292 | 318 | { |
| 293 | 319 | int size; |
| 294 | | − void *data; |
| 295 | 320 | |
| 296 | 321 | size = cstr->size_allocated; |
| 297 | 322 | if (size < 8) |
| 298 | 323 | size = 8; /* no need to allocate a too small first string */ |
| 299 | 324 | while (size < new_size) |
| 300 | 325 | size = size * 2; |
| 301 | | − data = tal_realloc(cstr_alloc, cstr->data_allocated, size); |
| 302 | | − cstr->data_allocated = data; |
| 326 | + cstr->data = tal_realloc(cstr_alloc, cstr->data, size); |
| 303 | 327 | cstr->size_allocated = size; |
| 304 | | − cstr->data = data; |
| 305 | 328 | } |
| 306 | 329 | |
| 307 | 330 | /* add a byte */ |
| 308 | | −ST_FUNC void cstr_ccat(CString *cstr, int ch) |
| 331 | +ST_INLN void cstr_ccat(CString *cstr, int ch) |
| 309 | 332 | { |
| 310 | 333 | int size; |
| 311 | 334 | size = cstr->size + 1; |
| @@ -346,7 +369,7 @@ ST_FUNC void cstr_new(CString *cstr) · 34 unmodified lines |
| 346 | 369 | /* free string and reset it to NULL */ |
| 347 | 370 | ST_FUNC void cstr_free(CString *cstr) |
| 348 | 371 | { |
| 349 | | − tal_free(cstr_alloc, cstr->data_allocated); |
| 372 | + tal_free(cstr_alloc, cstr->data); |
| 350 | 373 | cstr_new(cstr); |
| 351 | 374 | } |
| 352 | 375 | |
| @@ -1026,6 +1049,13 @@ ST_INLN void tok_str_new(TokenString *s) · 673 unmodified lines |
| 1026 | 1049 | s->last_line_num = -1; |
| 1027 | 1050 | } |
| 1028 | 1051 | |
| 1052 | +ST_FUNC TokenString *tok_str_alloc(void) |
| 1053 | +{ |
| 1054 | + TokenString *str = tal_realloc(tokstr_alloc, 0, sizeof *str); |
| 1055 | + tok_str_new(str); |
| 1056 | + return str; |
| 1057 | +} |
| 1058 | + |
| 1029 | 1059 | ST_FUNC int *tok_str_dup(TokenString *s) |
| 1030 | 1060 | { |
| 1031 | 1061 | int *str; |
| @@ -1049,7 +1079,6 @@ ST_FUNC int *tok_str_realloc(TokenString *s, int new_size) · 17 unmodified lines |
| 1049 | 1079 | size = 16; |
| 1050 | 1080 | while (size < new_size) |
| 1051 | 1081 | size = size * 2; |
| 1052 | | − TCC_ASSERT((size & (size -1)) == 0); |
| 1053 | 1082 | if (size > s->allocated_len) { |
| 1054 | 1083 | str = tal_realloc(tokstr_alloc, s->str, size * sizeof(int)); |
| 1055 | 1084 | s->allocated_len = size; |
| @@ -1070,6 +1099,29 @@ ST_FUNC void tok_str_add(TokenString *s, int t) · 14 unmodified lines |
| 1070 | 1099 | s->len = len; |
| 1071 | 1100 | } |
| 1072 | 1101 | |
| 1102 | +ST_FUNC void begin_macro(TokenString *str, int alloc) |
| 1103 | +{ |
| 1104 | + str->alloc = alloc; |
| 1105 | + str->prev = macro_stack; |
| 1106 | + str->prev_ptr = macro_ptr; |
| 1107 | + macro_ptr = str->str; |
| 1108 | + macro_stack = str; |
| 1109 | +} |
| 1110 | + |
| 1111 | +ST_FUNC void end_macro(void) |
| 1112 | +{ |
| 1113 | + TokenString *str = macro_stack; |
| 1114 | + macro_stack = str->prev; |
| 1115 | + macro_ptr = str->prev_ptr; |
| 1116 | + if (str->alloc == 2) { |
| 1117 | + str->alloc = 3; /* just mark as finished */ |
| 1118 | + } else { |
| 1119 | + tok_str_free(str->str); |
| 1120 | + if (str->alloc == 1) |
| 1121 | + tal_free(tokstr_alloc, str); |
| 1122 | + } |
| 1123 | +} |
| 1124 | + |
| 1073 | 1125 | static void tok_str_add2(TokenString *s, int t, CValue *cv) |
| 1074 | 1126 | { |
| 1075 | 1127 | int len, *str; |
| @@ -1172,7 +1224,6 @@ static inline void TOK_GET(int *t, const int **pp, CValue *cv) · 96 unmodified lines |
| 1172 | 1224 | case TOK_PPSTR: |
| 1173 | 1225 | cv->str.size = *p++; |
| 1174 | 1226 | cv->str.data = p; |
| 1175 | | − cv->str.data_allocated = 0; |
| 1176 | 1227 | p += (cv->str.size + sizeof(int) - 1) / sizeof(int); |
| 1177 | 1228 | break; |
| 1178 | 1229 | case TOK_CDOUBLE: |
| @@ -1235,13 +1286,13 @@ static int macro_is_equal(const int *a, const int *b) · 56 unmodified lines |
| 1235 | 1286 | } |
| 1236 | 1287 | |
| 1237 | 1288 | /* defines handling */ |
| 1238 | | −ST_INLN void define_push(int v, int macro_type, TokenString *str, Sym *first_arg) |
| 1289 | +ST_INLN void define_push(int v, int macro_type, int *str, Sym *first_arg) |
| 1239 | 1290 | { |
| 1240 | 1291 | Sym *s, *o; |
| 1241 | 1292 | |
| 1242 | 1293 | o = define_find(v); |
| 1243 | 1294 | s = sym_push2(&define_stack, v, macro_type, 0); |
| 1244 | | − s->d = str ? tok_str_dup(str) : NULL; |
| 1295 | + s->d = str; |
| 1245 | 1296 | s->next = first_arg; |
| 1246 | 1297 | table_ident[v - TOK_IDENT]->sym_define = s; |
| 1247 | 1298 | |
| @@ -1344,9 +1395,9 @@ ST_FUNC void label_pop(Sym **ptop, Sym *slast) · 96 unmodified lines |
| 1344 | 1395 | static int expr_preprocess(void) |
| 1345 | 1396 | { |
| 1346 | 1397 | int c, t; |
| 1347 | | − TokenString str; |
| 1398 | + TokenString *str; |
| 1348 | 1399 | |
| 1349 | | − tok_str_new(&str); |
| 1400 | + str = tok_str_alloc(); |
| 1350 | 1401 | while (tok != TOK_LINEFEED && tok != TOK_EOF) { |
| 1351 | 1402 | next(); /* do macro subst */ |
| 1352 | 1403 | if (tok == TOK_DEFINED) { |
| @@ -1364,12 +1415,12 @@ static int expr_preprocess(void) · 11 unmodified lines |
| 1364 | 1415 | tok = TOK_CINT; |
| 1365 | 1416 | tokc.i = 0; |
| 1366 | 1417 | } |
| 1367 | | − tok_str_add_tok(&str); |
| 1418 | + tok_str_add_tok(str); |
| 1368 | 1419 | } |
| 1369 | | − tok_str_add(&str, -1); /* simulate end of file */ |
| 1370 | | − tok_str_add(&str, 0); |
| 1420 | + tok_str_add(str, -1); /* simulate end of file */ |
| 1421 | + tok_str_add(str, 0); |
| 1371 | 1422 | /* now evaluate C constant expression */ |
| 1372 | | − begin_macro(&str, 0); |
| 1423 | + begin_macro(str, 1); |
| 1373 | 1424 | next(); |
| 1374 | 1425 | c = expr_const(); |
| 1375 | 1426 | end_macro(); |
| @@ -1457,7 +1508,7 @@ ST_FUNC void parse_define(void) · 81 unmodified lines |
| 1457 | 1508 | if (3 == spc) |
| 1458 | 1509 | bad_twosharp: |
| 1459 | 1510 | tcc_error("'##' cannot appear at either end of macro"); |
| 1460 | | − define_push(v, t, &tokstr_buf, first); |
| 1511 | + define_push(v, t, tok_str_dup(&tokstr_buf), first); |
| 1461 | 1512 | } |
| 1462 | 1513 | |
| 1463 | 1514 | static CachedInclude *search_cached_include(TCCState *s1, const char *filename, int add) |
| @@ -2061,7 +2112,6 @@ static void parse_string(const char *s, int len) · 597 unmodified lines |
| 2061 | 2112 | } else { |
| 2062 | 2113 | tokc.str.size = tokcstr.size; |
| 2063 | 2114 | tokc.str.data = tokcstr.data; |
| 2064 | | − tokc.str.data_allocated = tokcstr.data_allocated; |
| 2065 | 2115 | if (!is_long) |
| 2066 | 2116 | tok = TOK_STR; |
| 2067 | 2117 | else |
| @@ -2403,11 +2453,6 @@ static inline void next_nomacro1(void) · 335 unmodified lines |
| 2403 | 2453 | p = file->buf_ptr; |
| 2404 | 2454 | redo_no_start: |
| 2405 | 2455 | c = *p; |
| 2406 | | −#if (__TINYC__ || __GNUC__) |
| 2407 | | −#else |
| 2408 | | − if (c & 0x80) |
| 2409 | | − goto parse_ident_fast; |
| 2410 | | −#endif |
| 2411 | 2456 | switch(c) { |
| 2412 | 2457 | case ' ': |
| 2413 | 2458 | case '\t': |
| @@ -2513,13 +2558,6 @@ maybe_newline: · 99 unmodified lines |
| 2513 | 2558 | || (parse_flags & PARSE_FLAG_ASM_FILE)) |
| 2514 | 2559 | goto parse_simple; |
| 2515 | 2560 | |
| 2516 | | −#if (__TINYC__ || __GNUC__) |
| 2517 | | − case 'a' ... 'z': |
| 2518 | | − case 'A' ... 'K': |
| 2519 | | − case 'M' ... 'Z': |
| 2520 | | − case '_': |
| 2521 | | − case 0x80 ... 0xFF: |
| 2522 | | −#else |
| 2523 | 2561 | case 'a': case 'b': case 'c': case 'd': |
| 2524 | 2562 | case 'e': case 'f': case 'g': case 'h': |
| 2525 | 2563 | case 'i': case 'j': case 'k': case 'l': |
| @@ -2535,7 +2573,6 @@ maybe_newline: · 9 unmodified lines |
| 2535 | 2573 | case 'U': case 'V': case 'W': case 'X': |
| 2536 | 2574 | case 'Y': case 'Z': |
| 2537 | 2575 | case '_': |
| 2538 | | −#endif |
| 2539 | 2576 | parse_ident_fast: |
| 2540 | 2577 | p1 = p; |
| 2541 | 2578 | h = TOK_HASH_INIT; |
| @@ -2617,7 +2654,6 @@ maybe_newline: · 75 unmodified lines |
| 2617 | 2654 | cstr_ccat(&tokcstr, '\0'); |
| 2618 | 2655 | tokc.str.size = tokcstr.size; |
| 2619 | 2656 | tokc.str.data = tokcstr.data; |
| 2620 | | − tokc.str.data_allocated = tokcstr.data_allocated; |
| 2621 | 2657 | tok = TOK_PPNUM; |
| 2622 | 2658 | break; |
| 2623 | 2659 | |
| @@ -2658,7 +2694,6 @@ maybe_newline: · 34 unmodified lines |
| 2658 | 2694 | cstr_ccat(&tokcstr, '\0'); |
| 2659 | 2695 | tokc.str.size = tokcstr.size; |
| 2660 | 2696 | tokc.str.data = tokcstr.data; |
| 2661 | | − tokc.str.data_allocated = tokcstr.data_allocated; |
| 2662 | 2697 | tok = TOK_PPSTR; |
| 2663 | 2698 | break; |
| 2664 | 2699 | |
| @@ -2796,6 +2831,8 @@ maybe_newline: · 131 unmodified lines |
| 2796 | 2831 | p++; |
| 2797 | 2832 | break; |
| 2798 | 2833 | default: |
| 2834 | + if (c >= 0x80 && c <= 0xFF) /* utf8 identifiers */ |
| 2835 | + goto parse_ident_fast; |
| 2799 | 2836 | if (parse_flags & PARSE_FLAG_ASM_FILE) |
| 2800 | 2837 | goto parse_simple; |
| 2801 | 2838 | tcc_error("unrecognized character \\x%02x", c); |
| @@ -2895,7 +2932,6 @@ static int *macro_arg_subst(Sym **nested_list, const int *macro_str, Sym *args) · 93 unmodified lines |
| 2895 | 2932 | /* add string */ |
| 2896 | 2933 | cval.str.size = cstr.size; |
| 2897 | 2934 | cval.str.data = cstr.data; |
| 2898 | | − cval.str.data_allocated = cstr.data_allocated; |
| 2899 | 2935 | tok_str_add2(&str, TOK_PPSTR, &cval); |
| 2900 | 2936 | cstr_free(&cstr); |
| 2901 | 2937 | } else { |
| @@ -3062,7 +3098,6 @@ static int macro_subst_tok( · 160 unmodified lines |
| 3062 | 3098 | cstr_cat(&cstr, cstrval, 0); |
| 3063 | 3099 | cval.str.size = cstr.size; |
| 3064 | 3100 | cval.str.data = cstr.data; |
| 3065 | | − cval.str.data_allocated = cstr.data_allocated; |
| 3066 | 3101 | tok_str_add2(tok_str, t1, &cval); |
| 3067 | 3102 | cstr_free(&cstr); |
| 3068 | 3103 | } else { |
| @@ -3381,7 +3416,6 @@ ST_FUNC void next(void) · 312 unmodified lines |
| 3381 | 3416 | if (s) { |
| 3382 | 3417 | Sym *nested_list = NULL; |
| 3383 | 3418 | tokstr_buf.len = 0; |
| 3384 | | − nested_list = NULL; |
| 3385 | 3419 | macro_subst_tok(&tokstr_buf, &nested_list, s, 1); |
| 3386 | 3420 | tok_str_add(&tokstr_buf, 0); |
| 3387 | 3421 | begin_macro(&tokstr_buf, 2); |
| @@ -3402,8 +3436,8 @@ ST_FUNC void next(void) · 14 unmodified lines |
| 3402 | 3436 | identifier case handled for labels. */ |
| 3403 | 3437 | ST_INLN void unget_tok(int last_tok) |
| 3404 | 3438 | { |
| 3405 | | − TokenString *str = tcc_malloc(sizeof *str); |
| 3406 | | − tok_str_new(str); |
| 3439 | + |
| 3440 | + TokenString *str = tok_str_alloc(); |
| 3407 | 3441 | tok_str_add2(str, tok, &tokc); |
| 3408 | 3442 | tok_str_add(str, 0); |
| 3409 | 3443 | begin_macro(str, 1); |
| @@ -3529,10 +3563,8 @@ static void tok_print(const char *msg, const int *str) · 119 unmodified lines |
| 3529 | 3563 | static void pp_line(TCCState *s1, BufferedFile *f, int level) |
| 3530 | 3564 | { |
| 3531 | 3565 | int d = f->line_num - f->line_ref; |
| 3532 | | − |
| 3533 | 3566 | if (s1->dflag & 4) |
| 3534 | 3567 | return; |
| 3535 | | − |
| 3536 | 3568 | if (s1->Pflag == LINE_MACRO_OUTPUT_FORMAT_NONE) { |
| 3537 | 3569 | if (level == 0 && f->line_ref && d) { |
| 3538 | 3570 | d = 1; |