The existing variable 'nocode_wanted' is now used to control output of static data too. So... (nocode_wanted == 0) code and data (normal within functions) (nocode_wanted < 0) means: no code, but data (global or static data) (nocode_wanted > 0) means: no code and no data (code and data suppressed) (nocode_wanted & 0xC0000000) means: we're in declaration of static data Also: new option '-dT' to be used with -run tcc -dT -run file.c This will look in file.c for certain comment-boundaries: /*-* test-xxx: ...some description */ and then for each test below run it from memory. This way various features and error messages can be tested with one single file. See 96_nodata_wanted.c for an example.
Unified · Split
| @@ -634,11 +634,9 @@ static int tcc_compile(TCCState *s1) · 633 unmodified lines | |||
| 634 | 634 | ||
| 635 | preprocess_start(s1); | 635 | preprocess_start(s1); |
| 636 | tccgen_start(s1); | 636 | tccgen_start(s1); |
| 637 | |||
| 638 | #ifdef INC_DEBUG | 637 | #ifdef INC_DEBUG |
| 639 | printf("%s: **** new file\n", file->filename); | 638 | printf("%s: **** new file\n", file->filename); |
| 640 | #endif | 639 | #endif |
| 641 | |||
| 642 | ch = file->buf_ptr[0]; | 640 | ch = file->buf_ptr[0]; |
| 643 | tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF; | 641 | tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF; |
| 644 | parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM | PARSE_FLAG_TOK_STR; | 642 | parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM | PARSE_FLAG_TOK_STR; |
| @@ -1801,6 +1799,8 @@ reparse: · 1156 unmodified lines | |||
| 1801 | s->dflag = 3; | 1799 | s->dflag = 3; |
| 1802 | else if (*optarg == 'M') | 1800 | else if (*optarg == 'M') |
| 1803 | s->dflag = 7; | 1801 | s->dflag = 7; |
| 1802 | else if (*optarg == 'T') | ||
| 1803 | s->do_test = argc; | ||
| 1804 | else if (isnum(*optarg)) | 1804 | else if (isnum(*optarg)) |
| 1805 | g_debug = atoi(optarg); | 1805 | g_debug = atoi(optarg); |
| 1806 | else | 1806 | else |
| @@ -282,6 +282,8 @@ redo: · 281 unmodified lines | |||
| 282 | n = s->nb_files; | 282 | n = s->nb_files; |
| 283 | if (n == 0) | 283 | if (n == 0) |
| 284 | tcc_error("no input files\n"); | 284 | tcc_error("no input files\n"); |
| 285 | if (s->do_test) | ||
| 286 | tcc_tool_test(s, argc, argv); /* maybe never returns */ | ||
| 285 | 287 | ||
| 286 | if (s->output_type == TCC_OUTPUT_PREPROCESS) { | 288 | if (s->output_type == TCC_OUTPUT_PREPROCESS) { |
| 287 | if (!s->outfile) { | 289 | if (!s->outfile) { |
| @@ -813,6 +813,7 @@ struct TCCState { · 812 unmodified lines | |||
| 813 | int option_pthread; /* -pthread option */ | 813 | int option_pthread; /* -pthread option */ |
| 814 | int argc; | 814 | int argc; |
| 815 | char **argv; | 815 | char **argv; |
| 816 | int do_test; | ||
| 816 | }; | 817 | }; |
| 817 | 818 | ||
| 818 | struct filespec { | 819 | struct filespec { |
| @@ -50,7 +50,9 @@ ST_DATA int vla_sp_loc; /* Pointer to variable holding location to store stack p · 49 unmodified lines | |||
| 50 | ST_DATA SValue __vstack[1+VSTACK_SIZE], *vtop, *pvtop; | 50 | ST_DATA SValue __vstack[1+VSTACK_SIZE], *vtop, *pvtop; |
| 51 | 51 | ||
| 52 | ST_DATA int const_wanted; /* true if constant wanted */ | 52 | ST_DATA int const_wanted; /* true if constant wanted */ |
| 53 | ST_DATA int nocode_wanted; /* true if no code generation wanted for an expression */ | 53 | ST_DATA int nocode_wanted; /* no code generation wanted */ |
| 54 | #define NODATA_WANTED (nocode_wanted > 0) /* no static data output wanted either */ | ||
| 55 | #define STATIC_DATA_WANTED (nocode_wanted & 0xC0000000) /* only static data output */ | ||
| 54 | ST_DATA int global_expr; /* true if compound literals must be allocated globally (used during initializers parsing */ | 56 | ST_DATA int global_expr; /* true if compound literals must be allocated globally (used during initializers parsing */ |
| 55 | ST_DATA CType func_vt; /* current function return type (used by return instruction) */ | 57 | ST_DATA CType func_vt; /* current function return type (used by return instruction) */ |
| 56 | ST_DATA int func_var; /* true if current function is variadic (used by return instruction) */ | 58 | ST_DATA int func_var; /* true if current function is variadic (used by return instruction) */ |
| @@ -230,7 +232,7 @@ ST_FUNC void tccgen_start(TCCState *s1) · 173 unmodified lines | |||
| 230 | anon_sym = SYM_FIRST_ANOM; | 232 | anon_sym = SYM_FIRST_ANOM; |
| 231 | section_sym = 0; | 233 | section_sym = 0; |
| 232 | const_wanted = 0; | 234 | const_wanted = 0; |
| 233 | nocode_wanted = 1; | 235 | nocode_wanted = 0x80000000; |
| 234 | 236 | ||
| 235 | /* define some often used types */ | 237 | /* define some often used types */ |
| 236 | int_type.t = VT_INT; | 238 | int_type.t = VT_INT; |
| @@ -1206,14 +1208,12 @@ ST_FUNC int gv(int rc) · 969 unmodified lines | |||
| 1206 | } else { | 1208 | } else { |
| 1207 | if (is_float(vtop->type.t) && | 1209 | if (is_float(vtop->type.t) && |
| 1208 | (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) { | 1210 | (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) { |
| 1209 | unsigned long offset; | ||
| 1210 | /* CPUs usually cannot use float constants, so we store them | 1211 | /* CPUs usually cannot use float constants, so we store them |
| 1211 | generically in data segment */ | 1212 | generically in data segment */ |
| 1212 | size = type_size(&vtop->type, &align); | 1213 | size = type_size(&vtop->type, &align); |
| 1213 | offset = section_add(data_section, size, align); | 1214 | vpush_ref(&vtop->type, data_section, data_section->data_offset, size); |
| 1214 | vpush_ref(&vtop->type, data_section, offset, size); | ||
| 1215 | vswap(); | 1215 | vswap(); |
| 1216 | init_putv(&vtop->type, data_section, offset); | 1216 | init_putv(&vtop->type, data_section, data_section->data_offset); |
| 1217 | vtop->r |= VT_LVAL; | 1217 | vtop->r |= VT_LVAL; |
| 1218 | } | 1218 | } |
| 1219 | #ifdef CONFIG_TCC_BCHECK | 1219 | #ifdef CONFIG_TCC_BCHECK |
| @@ -2329,6 +2329,11 @@ static void gen_cvt_ftoi1(int t) · 1109 unmodified lines | |||
| 2329 | static void force_charshort_cast(int t) | 2329 | static void force_charshort_cast(int t) |
| 2330 | { | 2330 | { |
| 2331 | int bits, dbt; | 2331 | int bits, dbt; |
| 2332 | |||
| 2333 | /* cannot cast static initializers */ | ||
| 2334 | if (STATIC_DATA_WANTED) | ||
| 2335 | return; | ||
| 2336 | |||
| 2332 | dbt = t & VT_BTYPE; | 2337 | dbt = t & VT_BTYPE; |
| 2333 | /* XXX: add optimization if lvalue : just change type and offset */ | 2338 | /* XXX: add optimization if lvalue : just change type and offset */ |
| 2334 | if (dbt == VT_BYTE) | 2339 | if (dbt == VT_BYTE) |
| @@ -3405,12 +3410,9 @@ static void struct_layout(CType *type, AttributeDef *ad) · 1070 unmodified lines | |||
| 3405 | //#define BF_DEBUG | 3410 | //#define BF_DEBUG |
| 3406 | 3411 | ||
| 3407 | for (f = type->ref->next; f; f = f->next) { | 3412 | for (f = type->ref->next; f; f = f->next) { |
| 3408 | if (f->type.t & VT_BITFIELD) { | 3413 | if (f->type.t & VT_BITFIELD) |
| 3409 | bit_size = BIT_SIZE(f->type.t); | 3414 | bit_size = BIT_SIZE(f->type.t); |
| 3410 | /* in pcc mode, long long bitfields have type int if they fit */ | 3415 | else |
| 3411 | if (pcc && (f->type.t & VT_BTYPE) == VT_LLONG && bit_size <= 32) | ||
| 3412 | f->type.t = (f->type.t & ~VT_BTYPE) | VT_INT; | ||
| 3413 | } else | ||
| 3414 | bit_size = -1; | 3416 | bit_size = -1; |
| 3415 | size = type_size(&f->type, &align); | 3417 | size = type_size(&f->type, &align); |
| 3416 | a = f->a.aligned ? 1 << (f->a.aligned - 1) : 0; | 3418 | a = f->a.aligned ? 1 << (f->a.aligned - 1) : 0; |
| @@ -3479,6 +3481,10 @@ static void struct_layout(CType *type, AttributeDef *ad) · 62 unmodified lines | |||
| 3479 | goto new_field; | 3481 | goto new_field; |
| 3480 | } | 3482 | } |
| 3481 | 3483 | ||
| 3484 | /* in pcc mode, long long bitfields have type int if they fit */ | ||
| 3485 | if (size == 8 && bit_size <= 32) | ||
| 3486 | f->type.t = (f->type.t & ~VT_BTYPE) | VT_INT, size = 4; | ||
| 3487 | |||
| 3482 | while (bit_pos >= align * 8) | 3488 | while (bit_pos >= align * 8) |
| 3483 | c += align, bit_pos -= align * 8; | 3489 | c += align, bit_pos -= align * 8; |
| 3484 | offset = c; | 3490 | offset = c; |
| @@ -4558,8 +4564,10 @@ ST_FUNC void unary(void) · 1073 unmodified lines | |||
| 4558 | type.t |= VT_ARRAY; | 4564 | type.t |= VT_ARRAY; |
| 4559 | type.ref->c = len; | 4565 | type.ref->c = len; |
| 4560 | vpush_ref(&type, data_section, data_section->data_offset, len); | 4566 | vpush_ref(&type, data_section, data_section->data_offset, len); |
| 4561 | ptr = section_ptr_add(data_section, len); | 4567 | if (!NODATA_WANTED) { |
| 4562 | memcpy(ptr, funcname, len); | 4568 | ptr = section_ptr_add(data_section, len); |
| 4569 | memcpy(ptr, funcname, len); | ||
| 4570 | } | ||
| 4563 | next(); | 4571 | next(); |
| 4564 | } | 4572 | } |
| 4565 | break; | 4573 | break; |
| @@ -6314,7 +6322,7 @@ static int decl_designator(CType *type, Section *sec, unsigned long c, · 1748 unmodified lines | |||
| 6314 | vstore(); | 6322 | vstore(); |
| 6315 | } | 6323 | } |
| 6316 | vpop(); | 6324 | vpop(); |
| 6317 | } else { | 6325 | } else if (!NODATA_WANTED) { |
| 6318 | c_end = c + nb_elems * elem_size; | 6326 | c_end = c + nb_elems * elem_size; |
| 6319 | if (c_end > sec->data_allocated) | 6327 | if (c_end > sec->data_allocated) |
| 6320 | section_realloc(sec, c_end); | 6328 | section_realloc(sec, c_end); |
| @@ -6348,9 +6356,25 @@ static void init_putv(CType *type, Section *sec, unsigned long c) · 27 unmodified lines | |||
| 6348 | /* XXX: generate error if incorrect relocation */ | 6356 | /* XXX: generate error if incorrect relocation */ |
| 6349 | gen_assign_cast(&dtype); | 6357 | gen_assign_cast(&dtype); |
| 6350 | bt = type->t & VT_BTYPE; | 6358 | bt = type->t & VT_BTYPE; |
| 6359 | |||
| 6360 | if ((vtop->r & VT_SYM) | ||
| 6361 | && bt != VT_PTR | ||
| 6362 | && bt != VT_FUNC | ||
| 6363 | && (bt != (PTR_SIZE == 8 ? VT_LLONG : VT_INT) | ||
| 6364 | || (type->t & VT_BITFIELD)) | ||
| 6365 | && !((vtop->r & VT_CONST) && vtop->sym->v >= SYM_FIRST_ANOM) | ||
| 6366 | ) | ||
| 6367 | tcc_error("initializer element is not computable at load time"); | ||
| 6368 | |||
| 6369 | if (NODATA_WANTED) { | ||
| 6370 | vtop--; | ||
| 6371 | return; | ||
| 6372 | } | ||
| 6373 | |||
| 6351 | size = type_size(type, &align); | 6374 | size = type_size(type, &align); |
| 6352 | section_reserve(sec, c + size); | 6375 | section_reserve(sec, c + size); |
| 6353 | ptr = sec->data + c; | 6376 | ptr = sec->data + c; |
| 6377 | |||
| 6354 | /* XXX: make code faster ? */ | 6378 | /* XXX: make code faster ? */ |
| 6355 | if ((vtop->r & (VT_SYM|VT_CONST)) == (VT_SYM|VT_CONST) && | 6379 | if ((vtop->r & (VT_SYM|VT_CONST)) == (VT_SYM|VT_CONST) && |
| 6356 | vtop->sym->v >= SYM_FIRST_ANOM && | 6380 | vtop->sym->v >= SYM_FIRST_ANOM && |
| @@ -6404,20 +6428,6 @@ static void init_putv(CType *type, Section *sec, unsigned long c) · 47 unmodified lines | |||
| 6404 | } | 6428 | } |
| 6405 | } | 6429 | } |
| 6406 | } else { | 6430 | } else { |
| 6407 | if ((vtop->r & VT_SYM) && | ||
| 6408 | (bt == VT_BYTE || | ||
| 6409 | bt == VT_SHORT || | ||
| 6410 | bt == VT_DOUBLE || | ||
| 6411 | bt == VT_LDOUBLE || | ||
| 6412 | #if PTR_SIZE == 8 | ||
| 6413 | bt == VT_INT || | ||
| 6414 | #else | ||
| 6415 | bt == VT_LLONG || | ||
| 6416 | #endif | ||
| 6417 | (type->t & VT_BITFIELD) | ||
| 6418 | )) | ||
| 6419 | tcc_error("initializer element is not computable at load time"); | ||
| 6420 | |||
| 6421 | if (type->t & VT_BITFIELD) { | 6431 | if (type->t & VT_BITFIELD) { |
| 6422 | int bit_pos, bit_size, bits, n; | 6432 | int bit_pos, bit_size, bits, n; |
| 6423 | unsigned char *p, v, m; | 6433 | unsigned char *p, v, m; |
| @@ -6598,7 +6608,8 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c, · 174 unmodified lines | |||
| 6598 | string in global variable, we handle it | 6608 | string in global variable, we handle it |
| 6599 | specifically */ | 6609 | specifically */ |
| 6600 | if (sec && tok == TOK_STR && size1 == 1) { | 6610 | if (sec && tok == TOK_STR && size1 == 1) { |
| 6601 | memcpy(sec->data + c + len, tokc.str.data, nb); | 6611 | if (!NODATA_WANTED) |
| 6612 | memcpy(sec->data + c + len, tokc.str.data, nb); | ||
| 6602 | } else { | 6613 | } else { |
| 6603 | for(i=0;i<nb;i++) { | 6614 | for(i=0;i<nb;i++) { |
| 6604 | if (tok == TOK_STR) | 6615 | if (tok == TOK_STR) |
| @@ -6714,6 +6725,13 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, · 109 unmodified lines | |||
| 6714 | Section *sec; | 6725 | Section *sec; |
| 6715 | Sym *flexible_array; | 6726 | Sym *flexible_array; |
| 6716 | Sym *sym = NULL; | 6727 | Sym *sym = NULL; |
| 6728 | int saved_nocode_wanted = nocode_wanted; | ||
| 6729 | #ifdef CONFIG_TCC_BCHECK | ||
| 6730 | int bcheck = tcc_state->do_bounds_check && !NODATA_WANTED; | ||
| 6731 | #endif | ||
| 6732 | |||
| 6733 | if (type->t & VT_STATIC) | ||
| 6734 | nocode_wanted |= NODATA_WANTED ? 0x40000000 : 0x80000000; | ||
| 6717 | 6735 | ||
| 6718 | flexible_array = NULL; | 6736 | flexible_array = NULL; |
| 6719 | if ((type->t & VT_BTYPE) == VT_STRUCT) { | 6737 | if ((type->t & VT_BTYPE) == VT_STRUCT) { |
| @@ -6779,10 +6797,14 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, · 59 unmodified lines | |||
| 6779 | } else if (ad->a.packed) { | 6797 | } else if (ad->a.packed) { |
| 6780 | align = 1; | 6798 | align = 1; |
| 6781 | } | 6799 | } |
| 6800 | |||
| 6801 | if (NODATA_WANTED) | ||
| 6802 | size = 0, align = 1; | ||
| 6803 | |||
| 6782 | if ((r & VT_VALMASK) == VT_LOCAL) { | 6804 | if ((r & VT_VALMASK) == VT_LOCAL) { |
| 6783 | sec = NULL; | 6805 | sec = NULL; |
| 6784 | #ifdef CONFIG_TCC_BCHECK | 6806 | #ifdef CONFIG_TCC_BCHECK |
| 6785 | if (tcc_state->do_bounds_check && (type->t & VT_ARRAY)) { | 6807 | if (bcheck && (type->t & VT_ARRAY)) { |
| 6786 | loc--; | 6808 | loc--; |
| 6787 | } | 6809 | } |
| 6788 | #endif | 6810 | #endif |
| @@ -6792,7 +6814,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, · 3 unmodified lines | |||
| 6792 | /* handles bounds */ | 6814 | /* handles bounds */ |
| 6793 | /* XXX: currently, since we do only one pass, we cannot track | 6815 | /* XXX: currently, since we do only one pass, we cannot track |
| 6794 | '&' operators, so we add only arrays */ | 6816 | '&' operators, so we add only arrays */ |
| 6795 | if (tcc_state->do_bounds_check && (type->t & VT_ARRAY)) { | 6817 | if (bcheck && (type->t & VT_ARRAY)) { |
| 6796 | addr_t *bounds_ptr; | 6818 | addr_t *bounds_ptr; |
| 6797 | /* add padding between regions */ | 6819 | /* add padding between regions */ |
| 6798 | loc--; | 6820 | loc--; |
| @@ -6860,7 +6882,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, · 61 unmodified lines | |||
| 6860 | addr = section_add(sec, size, align); | 6882 | addr = section_add(sec, size, align); |
| 6861 | #ifdef CONFIG_TCC_BCHECK | 6883 | #ifdef CONFIG_TCC_BCHECK |
| 6862 | /* add padding if bound check */ | 6884 | /* add padding if bound check */ |
| 6863 | if (tcc_state->do_bounds_check) | 6885 | if (bcheck) |
| 6864 | section_add(sec, 1, 1); | 6886 | section_add(sec, 1, 1); |
| 6865 | #endif | 6887 | #endif |
| 6866 | } else { | 6888 | } else { |
| @@ -6888,7 +6910,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, · 21 unmodified lines | |||
| 6888 | #ifdef CONFIG_TCC_BCHECK | 6910 | #ifdef CONFIG_TCC_BCHECK |
| 6889 | /* handles bounds now because the symbol must be defined | 6911 | /* handles bounds now because the symbol must be defined |
| 6890 | before for the relocation */ | 6912 | before for the relocation */ |
| 6891 | if (tcc_state->do_bounds_check) { | 6913 | if (bcheck) { |
| 6892 | addr_t *bounds_ptr; | 6914 | addr_t *bounds_ptr; |
| 6893 | 6915 | ||
| 6894 | greloca(bounds_section, sym, bounds_section->data_offset, R_DATA_PTR, 0); | 6916 | greloca(bounds_section, sym, bounds_section->data_offset, R_DATA_PTR, 0); |
| @@ -6903,6 +6925,9 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, · 8 unmodified lines | |||
| 6903 | if (type->t & VT_VLA) { | 6925 | if (type->t & VT_VLA) { |
| 6904 | int a; | 6926 | int a; |
| 6905 | 6927 | ||
| 6928 | if (NODATA_WANTED) | ||
| 6929 | goto no_alloc; | ||
| 6930 | |||
| 6906 | /* save current stack pointer */ | 6931 | /* save current stack pointer */ |
| 6907 | if (vlas_in_scope == 0) { | 6932 | if (vlas_in_scope == 0) { |
| 6908 | if (vla_sp_root_loc == -1) | 6933 | if (vla_sp_root_loc == -1) |
| @@ -6935,6 +6960,8 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, · 26 unmodified lines | |||
| 6935 | end_macro(); | 6960 | end_macro(); |
| 6936 | restore_parse_state(&saved_parse_state); | 6961 | restore_parse_state(&saved_parse_state); |
| 6937 | } | 6962 | } |
| 6963 | |||
| 6964 | nocode_wanted = saved_nocode_wanted; | ||
| 6938 | } | 6965 | } |
| 6939 | 6966 | ||
| 6940 | /* parse a function defined by symbol 'sym' and generate its code in | 6967 | /* parse a function defined by symbol 'sym' and generate its code in |
| @@ -6978,7 +7005,7 @@ static void gen_function(Sym *sym) · 37 unmodified lines | |||
| 6978 | func_vt.t = VT_VOID; /* for safety */ | 7005 | func_vt.t = VT_VOID; /* for safety */ |
| 6979 | func_var = 0; /* for safety */ | 7006 | func_var = 0; /* for safety */ |
| 6980 | ind = 0; /* for safety */ | 7007 | ind = 0; /* for safety */ |
| 6981 | nocode_wanted = 1; | 7008 | nocode_wanted = 0x80000000; |
| 6982 | check_vstack(); | 7009 | check_vstack(); |
| 6983 | } | 7010 | } |
| 6984 | 7011 | ||
| @@ -544,3 +544,108 @@ ST_FUNC void gen_makedeps(TCCState *s, const char *target, const char *filename) · 543 unmodified lines | |||
| 544 | } | 544 | } |
| 545 | 545 | ||
| 546 | /* -------------------------------------------------------------- */ | 546 | /* -------------------------------------------------------------- */ |
| 547 | /* run test snippets from file */ | ||
| 548 | |||
| 549 | static char *readfile(const char *fname) | ||
| 550 | { | ||
| 551 | char *buf; | ||
| 552 | int fsize; | ||
| 553 | FILE *fi; | ||
| 554 | fi = fopen(fname, "rb"); | ||
| 555 | if (!fi) | ||
| 556 | return NULL; | ||
| 557 | fseek(fi, 0, SEEK_END); | ||
| 558 | fsize = ftell(fi); | ||
| 559 | fseek(fi, 0, SEEK_SET); | ||
| 560 | buf = tcc_malloc(fsize + 1); | ||
| 561 | fread(buf, fsize, 1, fi); | ||
| 562 | fclose(fi); | ||
| 563 | buf[fsize] = 0; | ||
| 564 | return buf; | ||
| 565 | } | ||
| 566 | |||
| 567 | static int run_prog(const char *prog, int ac, char **av) | ||
| 568 | { | ||
| 569 | TCCState *s; | ||
| 570 | int (*func)(int, char**); | ||
| 571 | int ret = -10000; | ||
| 572 | |||
| 573 | s = tcc_new(); | ||
| 574 | tcc_parse_args(s, &ac, &av, 1); | ||
| 575 | tcc_set_output_type(s, TCC_OUTPUT_MEMORY); | ||
| 576 | if (tcc_compile_string(s, prog) == -1) | ||
| 577 | goto done; | ||
| 578 | if (tcc_relocate(s, TCC_RELOCATE_AUTO) < 0) | ||
| 579 | goto done; | ||
| 580 | func = tcc_get_symbol(s, "main"); | ||
| 581 | if (!func) | ||
| 582 | goto done; | ||
| 583 | ret = func(ac, av); | ||
| 584 | done: | ||
| 585 | tcc_delete(s); | ||
| 586 | return ret; | ||
| 587 | } | ||
| 588 | |||
| 589 | static char *trimback(char *a, char *e) | ||
| 590 | { | ||
| 591 | while (e > a && (unsigned char)e[-1] <= ' ') | ||
| 592 | --e; | ||
| 593 | *e = 0;; | ||
| 594 | return a; | ||
| 595 | } | ||
| 596 | |||
| 597 | ST_FUNC int tcc_tool_test(TCCState *s, int argc, char **argv) | ||
| 598 | { | ||
| 599 | const char *fname; | ||
| 600 | char *buf, *p, *a, *b, *e, tmp[100]; | ||
| 601 | int r = 0, c, n; | ||
| 602 | const char sep[] = "/*-* test"; | ||
| 603 | |||
| 604 | n = s->do_test - argc; | ||
| 605 | if (!n) | ||
| 606 | return 0; | ||
| 607 | fname = argv[0], argv -= n, argc += n; | ||
| 608 | |||
| 609 | buf = readfile(fname); | ||
| 610 | if (NULL == buf) | ||
| 611 | return -1; | ||
| 612 | p = strstr(buf, sep); | ||
| 613 | if (!p) { | ||
| 614 | tcc_free(buf); | ||
| 615 | return -1; | ||
| 616 | } | ||
| 617 | |||
| 618 | while (*p) { | ||
| 619 | a = p, p = strchr(p, '\n'); | ||
| 620 | if (NULL == p) | ||
| 621 | break; | ||
| 622 | *p++ = 0; | ||
| 623 | b = p, p = strstr(p, sep); | ||
| 624 | if (NULL == p) | ||
| 625 | p = strchr(b, 0); | ||
| 626 | c = *p, *p = 0; | ||
| 627 | |||
| 628 | trimback(a, b); | ||
| 629 | if (r) | ||
| 630 | printf("\n"); | ||
| 631 | printf("%s\n", a); | ||
| 632 | fflush(stdout); | ||
| 633 | |||
| 634 | e = a += sizeof sep - 5; | ||
| 635 | while (*e && *e != ':') | ||
| 636 | ++e; | ||
| 637 | if (!*e || e - a > 32) | ||
| 638 | e = a + 4; | ||
| 639 | n = snprintf(tmp, sizeof tmp, "#line 1 \"%.*s\"\n", (int)(e - a), a); | ||
| 640 | if (b - buf >= n) | ||
| 641 | b = memcpy(b - n, tmp, n); | ||
| 642 | n = run_prog(b, argc, argv); | ||
| 643 | if (n != -10000) | ||
| 644 | printf("returns %d\n", n); | ||
| 645 | *p = c, ++r; | ||
| 646 | } | ||
| 647 | tcc_free(buf); | ||
| 648 | exit(0); | ||
| 649 | } | ||
| 650 | |||
| 651 | /* -------------------------------------------------------------- */ | ||
| @@ -58,7 +58,7 @@ · 57 unmodified lines | |||
| 58 | struct M P __s { | 58 | struct M P __s { |
| 59 | long long x : 45; | 59 | long long x : 45; |
| 60 | long long : 2; | 60 | long long : 2; |
| 61 | long long y : 35; | 61 | long long y : 30; |
| 62 | unsigned long long z : 38; | 62 | unsigned long long z : 38; |
| 63 | char a; short b; | 63 | char a; short b; |
| 64 | }; | 64 | }; |
| @@ -23,8 +23,8 @@ values : 03 ffffffff 0f fffffff8 78 · 22 unmodified lines | |||
| 23 | align/size : 4 8 | 23 | align/size : 4 8 |
| 24 | 24 | ||
| 25 | ---- TEST 5 - MS-BITFIELDS ---- | 25 | ---- TEST 5 - MS-BITFIELDS ---- |
| 26 | bits in use : 00000000FFFF00FF0000003FFFFFFFFF00000007FFFFFFFF00001FFFFFFFFFFF | 26 | bits in use : 00000000FFFF00FF0000003FFFFFFFFF000000003FFFFFFF00001FFFFFFFFFFF |
| 27 | bits as set : 0000000000770044000000000000007800000007F00000000000000123456789 | 27 | bits as set : 0000000000770044000000000000007800000000300000000000000123456789 |
| 28 | values : 0000000123456789 fffffffff0000000 0000000000000078 44 77 | 28 | values : 0000000123456789 fffffffff0000000 0000000000000078 44 77 |
| 29 | align/size : 8 32 | 29 | align/size : 8 32 |
| 30 | 30 | ||
| @@ -61,8 +61,8 @@ values : 03 ffffffff 0f fffffff8 78 · 30 unmodified lines | |||
| 61 | align/size : 1 8 | 61 | align/size : 1 8 |
| 62 | 62 | ||
| 63 | ---- TEST 5 - MS-BITFIELDS - PACKED ---- | 63 | ---- TEST 5 - MS-BITFIELDS - PACKED ---- |
| 64 | bits in use : FFFFFF0000003FFFFFFFFF00000007FFFFFFFF00001FFFFFFFFFFF | 64 | bits in use : FFFFFF0000003FFFFFFFFF000000003FFFFFFF00001FFFFFFFFFFF |
| 65 | bits as set : 007744000000000000007800000007F00000000000000123456789 | 65 | bits as set : 007744000000000000007800000000300000000000000123456789 |
| 66 | values : 0000000123456789 fffffffff0000000 0000000000000078 44 77 | 66 | values : 0000000123456789 fffffffff0000000 0000000000000078 44 77 |
| 67 | align/size : 1 27 | 67 | align/size : 1 27 |
| 68 | 68 | ||
| @@ -99,8 +99,8 @@ values : 03 ffffffff 0f fffffff8 78 · 30 unmodified lines | |||
| 99 | align/size : 4 8 | 99 | align/size : 4 8 |
| 100 | 100 | ||
| 101 | ---- TEST 5 - MS-BITFIELDS - WITH ALIGN ---- | 101 | ---- TEST 5 - MS-BITFIELDS - WITH ALIGN ---- |
| 102 | bits in use : 00000000FFFF00FF0000003FFFFFFFFF00000007FFFFFFFF00001FFFFFFFFFFF | 102 | bits in use : 00000000FFFF00FF0000003FFFFFFFFF000000003FFFFFFF00001FFFFFFFFFFF |
| 103 | bits as set : 0000000000770044000000000000007800000007F00000000000000123456789 | 103 | bits as set : 0000000000770044000000000000007800000000300000000000000123456789 |
| 104 | values : 0000000123456789 fffffffff0000000 0000000000000078 44 77 | 104 | values : 0000000123456789 fffffffff0000000 0000000000000078 44 77 |
| 105 | align/size : 8 32 | 105 | align/size : 8 32 |
| 106 | 106 | ||
| @@ -137,8 +137,8 @@ values : 03 ffffffff 0f fffffff8 78 · 30 unmodified lines | |||
| 137 | align/size : 1 8 | 137 | align/size : 1 8 |
| 138 | 138 | ||
| 139 | ---- TEST 5 - MS-BITFIELDS - PACKED - WITH ALIGN ---- | 139 | ---- TEST 5 - MS-BITFIELDS - PACKED - WITH ALIGN ---- |
| 140 | bits in use : FFFFFF0000003FFFFFFFFF00000007FFFFFFFF00001FFFFFFFFFFF | 140 | bits in use : FFFFFF0000003FFFFFFFFF000000003FFFFFFF00001FFFFFFFFFFF |
| 141 | bits as set : 007744000000000000007800000007F00000000000000123456789 | 141 | bits as set : 007744000000000000007800000000300000000000000123456789 |
| 142 | values : 0000000123456789 fffffffff0000000 0000000000000078 44 77 | 142 | values : 0000000123456789 fffffffff0000000 0000000000000078 44 77 |
| 143 | align/size : 1 27 | 143 | align/size : 1 27 |
| 144 | 144 | ||
| @@ -0,0 +1,74 @@ | |||
| 1 | /*****************************************************************************/ | ||
| 2 | /* test 'nodata_wanted' data output suppression */ | ||
| 3 | |||
| 4 | /*-* test 1: initializer not computable 1 */ | ||
| 5 | void foo() { | ||
| 6 | if (1) { | ||
| 7 | static short w = (int)&foo; /* error */ | ||
| 8 | } | ||
| 9 | } | ||
| 10 | |||
| 11 | /*-* test 2: initializer not computable 2 */ | ||
| 12 | void foo() { | ||
| 13 | if (0) { | ||
| 14 | static short w = (int)&foo; /* error */ | ||
| 15 | } | ||
| 16 | } | ||
| 17 | |||
| 18 | /*-* test 3: initializer not computable 3 */ | ||
| 19 | void foo(); | ||
| 20 | static short w = (int)&foo; /* error */ | ||
| 21 | |||
| 22 | |||
| 23 | /*-* test 4: 2 cast warnings */ | ||
| 24 | void foo() { | ||
| 25 | short w = &foo; /* no error */ | ||
| 26 | } | ||
| 27 | |||
| 28 | /*-* test 5; nodata_wanted test */ | ||
| 29 | #include <stdio.h> | ||
| 30 | |||
| 31 | #define DATA_LBL(s) \ | ||
| 32 | __asm__(".global d"#s",t"#s"\n.data\nd"#s":\n.text\nt"#s":\n"); \ | ||
| 33 | extern char d##s[],t##s[]; | ||
| 34 | |||
| 35 | #define PROG \ | ||
| 36 | static void *p = (void*)&main;\ | ||
| 37 | static char cc[] = "static string";\ | ||
| 38 | static double d = 8.0;\ | ||
| 39 | static struct __attribute__((packed)) {\ | ||
| 40 | unsigned x : 12;\ | ||
| 41 | unsigned char y : 7;\ | ||
| 42 | unsigned z : 28, a: 4, b: 5;\ | ||
| 43 | } s = { 0x333,0x44,0x555555,6,7 };\ | ||
| 44 | printf(" static data: %d - %.1f - %.1f - %s - %s\n",\ | ||
| 45 | sizeof 8.0, 8.0, d, __FUNCTION__, cc);\ | ||
| 46 | printf(" static bitfields: %x %x %x %x %x\n", s.x, s.y, s.z, s.a, s.b); | ||
| 47 | |||
| 48 | int main() | ||
| 49 | { | ||
| 50 | printf("suppression off\n"); | ||
| 51 | DATA_LBL(s1); | ||
| 52 | if (1) { | ||
| 53 | PROG | ||
| 54 | } | ||
| 55 | DATA_LBL(e1); | ||
| 56 | printf(" data length is %s\n", de1 - ds1 ? "not 0":"0"); | ||
| 57 | //printf(" text length is %s\n", te1 - ts1 ? "not 0":"0"); | ||
| 58 | |||
| 59 | printf("suppression on\n"); | ||
| 60 | DATA_LBL(s2); | ||
| 61 | if (0) { | ||
| 62 | PROG | ||
| 63 | } | ||
| 64 | DATA_LBL(e2); | ||
| 65 | printf(" data length is %x\n", de2 - ds2); | ||
| 66 | //printf(" text length is %X\n", te2 - ts2); | ||
| 67 | return 0; | ||
| 68 | } | ||
| 69 | |||
| 70 | /*-* test 6: some test */ | ||
| 71 | int main() | ||
| 72 | { | ||
| 73 | return 34; | ||
| 74 | } | ||
| @@ -0,0 +1,24 @@ | |||
| 1 | /*-* test 1: initializer not computable 1 */ | ||
| 2 | test 1:3: error: initializer element is not computable at load time | ||
| 3 | |||
| 4 | /*-* test 2: initializer not computable 2 */ | ||
| 5 | test 2:3: error: initializer element is not computable at load time | ||
| 6 | |||
| 7 | /*-* test 3: initializer not computable 3 */ | ||
| 8 | test 3:2: error: initializer element is not computable at load time | ||
| 9 | |||
| 10 | /*-* test 4: 2 cast warnings */ | ||
| 11 | test 4:2: warning: assignment makes integer from pointer without a cast | ||
| 12 | test 4:2: warning: nonportable conversion from pointer to char/short | ||
| 13 | |||
| 14 | /*-* test 5; nodata_wanted test */ | ||
| 15 | suppression off | ||
| 16 | static data: 8 - 8.0 - 8.0 - main - static string | ||
| 17 | static bitfields: 333 44 555555 6 7 | ||
| 18 | data length is not 0 | ||
| 19 | suppression on | ||
| 20 | data length is 0 | ||
| 21 | returns 0 | ||
| 22 | |||
| 23 | /*-* test 6: some test */ | ||
| 24 | returns 34 | ||
| @@ -5,29 +5,6 @@ VPATH = $(SRC) · 4 unmodified lines | |||
| 5 | 5 | ||
| 6 | TESTS = $(patsubst %.c,%.test,$(sort $(notdir $(wildcard $(SRC)/*.c)))) | 6 | TESTS = $(patsubst %.c,%.test,$(sort $(notdir $(wildcard $(SRC)/*.c)))) |
| 7 | 7 | ||
| 8 | # Some tests might need arguments | ||
| 9 | ARGS = | ||
| 10 | 31_args.test : ARGS = arg1 arg2 arg3 arg4 arg5 | ||
| 11 | 46_grep.test : ARGS = '[^* ]*[:a:d: ]+\:\*-/: $$' $(SRC)/46_grep.c | ||
| 12 | |||
| 13 | # And some tests don't test the right thing with -run | ||
| 14 | NORUN = | ||
| 15 | 42_function_pointer.test : NORUN = true | ||
| 16 | |||
| 17 | # Some tests might need different flags | ||
| 18 | FLAGS = | ||
| 19 | 76_dollars_in_identifiers.test : FLAGS += -fdollars-in-identifiers | ||
| 20 | |||
| 21 | # Always generate certain .expects (don't put these in the GIT), | ||
| 22 | GEN-ALWAYS = 95_bitfields.expect | ||
| 23 | |||
| 24 | # Filter source directory in warnings/errors (out-of-tree builds) | ||
| 25 | FILTER = 2>&1 | sed 's,$(SRC)/,,g' | ||
| 26 | # Filter some always-warning | ||
| 27 | ifeq (-$(findstring arm,$(ARCH))-,-arm-) | ||
| 28 | FILTER += 2>&1 | grep -v 'warning: soft float ABI currently not supported' | ||
| 29 | endif | ||
| 30 | |||
| 31 | # some tests do not pass on all platforms, remove them for now | 8 | # some tests do not pass on all platforms, remove them for now |
| 32 | SKIP = 34_array_assignment.test # array assignment is not in C standard | 9 | SKIP = 34_array_assignment.test # array assignment is not in C standard |
| 33 | ifeq ($(CONFIG_arm_eabi),yes) # not ARM soft-float | 10 | ifeq ($(CONFIG_arm_eabi),yes) # not ARM soft-float |
| @@ -50,46 +27,80 @@ ifeq (-$(CONFIG_WIN32)-$(CONFIG_i386)$(CONFIG_arm)-,--yes-) · 16 unmodified lines | |||
| 50 | SKIP += 95_bitfields_ms.test # type_align is differnt on 32bit-non-windows | 27 | SKIP += 95_bitfields_ms.test # type_align is differnt on 32bit-non-windows |
| 51 | endif | 28 | endif |
| 52 | 29 | ||
| 30 | # Some tests might need arguments | ||
| 31 | ARGS = | ||
| 32 | 31_args.test : ARGS = arg1 arg2 arg3 arg4 arg5 | ||
| 33 | 46_grep.test : ARGS = '[^* ]*[:a:d: ]+\:\*-/: $$' $(SRC)/46_grep.c | ||
| 34 | |||
| 35 | # And some tests don't test the right thing with -run | ||
| 36 | NORUN = | ||
| 37 | 42_function_pointer.test : NORUN = true | ||
| 38 | |||
| 39 | # Some tests might need different flags | ||
| 40 | FLAGS = | ||
| 41 | 76_dollars_in_identifiers.test : FLAGS += -fdollars-in-identifiers | ||
| 42 | |||
| 43 | # run the source file cut into snippets | ||
| 44 | 96_nodata_wanted.test : FLAGS = -dT | ||
| 45 | |||
| 46 | # Always generate certain .expects (don't put these in the GIT), | ||
| 47 | GEN-ALWAYS = | ||
| 48 | GEN-ALWAYS += 95_bitfields.expect | ||
| 49 | |||
| 50 | # using the ms compiler for the really ms-compatible bitfields | ||
| 51 | 95_bitfields_ms.test : GEN = $(GEN-MSC) | ||
| 52 | |||
| 53 | # Filter source directory in warnings/errors (out-of-tree builds) | ||
| 54 | FILTER = 2>&1 | sed 's,$(SRC)/,,g' | ||
| 55 | # Filter some always-warning | ||
| 56 | ifeq (-$(findstring arm,$(ARCH))-,-arm-) | ||
| 57 | FILTER += 2>&1 | grep -v 'warning: soft float ABI currently not supported' | ||
| 58 | endif | ||
| 59 | |||
| 53 | all test tests2.all: $(filter-out $(SKIP),$(TESTS)) ; | 60 | all test tests2.all: $(filter-out $(SKIP),$(TESTS)) ; |
| 54 | 61 | ||
| 55 | %.test: %.c %.expect | 62 | %.test: %.c %.expect |
| 56 | @echo Test: $*... | 63 | @echo Test: $*... |
| 57 | @$(if $(NORUN),\ | 64 | @$(if $(NORUN),$(T1),$(T2)) $(if $(NODIFF),,$(T3)) |
| 58 | ($(TCC) $(FLAGS) $< -o a.exe && ./a.exe $(ARGS)),\ | ||
| 59 | $(TCC) $(FLAGS) -run $< $(ARGS)\ | ||
| 60 | ) $(FILTER) >$*.output 2>&1 || true | ||
| 61 | @diff -Nbu $(filter %.expect,$^) $*.output \ | ||
| 62 | && rm -f $*.output $(filter $*.expect,$(GEN-ALWAYS)) | ||
| 63 | 65 | ||
| 64 | F1 = $(or $(filter $1_%,$(TESTS)),$1_???.test) | 66 | T1 = $(TCC) $(FLAGS) $< -o a.exe && ./a.exe $(ARGS) |
| 65 | F2 = $1 UPDATE="$(patsubst %.test,%.expect,$1)" | 67 | T2 = $(TCC) $(FLAGS) -run $< $(ARGS) |
| 68 | T3 = $(FILTER) >$*.output 2>&1 || true \ | ||
| 69 | && diff -Nbu $(filter %.expect,$^) $*.output \ | ||
| 70 | && rm -f $*.output $(filter $*.expect,$(GEN-ALWAYS)) | ||
| 66 | 71 | ||
| 67 | # run single test and update .expect file, e.g. "make tests2.37+" | 72 | # run single test and update .expect file, e.g. "make tests2.37+" |
| 68 | tests2.%+: | 73 | tests2.%+: |
| 69 | @$(MAKE) $(call F2,$(call F1,$*)) --no-print-directory | 74 | @$(MAKE) $(call F2,$(call F1,$*)) --no-print-directory |
| 70 | 75 | ||
| 76 | # just run tcc to see the output, e.g. "make tests2.37-" | ||
| 77 | tests2.%-: | ||
| 78 | @$(MAKE) $(call F1,$*) NODIFF=true --no-print-directory | ||
| 79 | |||
| 71 | # run single test, e.g. "make tests2.37" | 80 | # run single test, e.g. "make tests2.37" |
| 72 | tests2.%: | 81 | tests2.%: |
| 73 | @$(MAKE) $(call F1,$*) --no-print-directory | 82 | @$(MAKE) $(call F1,$*) --no-print-directory |
| 74 | 83 | ||
| 84 | F1 = $(or $(filter $1_%,$(TESTS)),$1_???.test) | ||
| 85 | F2 = $1 UPDATE="$(patsubst %.test,%.expect,$1)" | ||
| 86 | |||
| 75 | # automatically generate .expect files with gcc: | 87 | # automatically generate .expect files with gcc: |
| 76 | %.expect : | 88 | %.expect : |
| 77 | @echo Generating: $@ | 89 | @echo Generating: $@ |
| 78 | @$(CC) -w -std=gnu99 $(FLAGS) $(SRC)/$*.c -o a.exe | 90 | @$(call GEN,$(SRC)/$*.c) $(FILTER) >$@ 2>&1 |
| 79 | @./a.exe $(ARGS) $(FILTER) >$@ 2>&1 | 91 | @rm -f *.exe *.obj *.pdb |
| 80 | @rm -f a.exe | ||
| 81 | 92 | ||
| 82 | # using the ms compiler for the really ms-compatible bitfields | 93 | # using TCC for .expect if -dT in FLAGS |
| 94 | GEN = $(if $(findstring -dT,$(FLAGS)),$(GEN-TCC),$(GEN-CC)) | ||
| 95 | GEN-CC = $(CC) -w -std=gnu99 $(FLAGS) $1 -o a.exe && ./a.exe $(ARGS) | ||
| 96 | GEN-TCC = $(TCC) $(FLAGS) -run $1 $(ARGS) | ||
| 97 | GEN-MSC = $(MS-CC) $1 && ./$(basename $@).exe | ||
| 83 | MS-CC = cl | 98 | MS-CC = cl |
| 84 | 95_bitfields_ms.expect : | ||
| 85 | @echo Generating: $@ | ||
| 86 | @$(MS-CC) $(basename $@).c | ||
| 87 | @./$(basename $@).exe >$@ 2>&1 | ||
| 88 | @rm -f *.exe *.obj *.pdb | ||
| 89 | 99 | ||
| 90 | # tell make not to delete | 100 | # tell make not to delete |
| 91 | .PRECIOUS: %.expect | 101 | .PRECIOUS: %.expect |
| 92 | 102 | ||
| 103 | # force .expect generation for these files | ||
| 93 | $(sort $(GEN-ALWAYS) $(UPDATE)) : force | 104 | $(sort $(GEN-ALWAYS) $(UPDATE)) : force |
| 94 | force: | 105 | force: |
| 95 | 106 | ||