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 | 635 | preprocess_start(s1); |
| 636 | 636 | tccgen_start(s1); |
| 637 | − | |
| 638 | 637 | #ifdef INC_DEBUG |
| 639 | 638 | printf("%s: **** new file\n", file->filename); |
| 640 | 639 | #endif |
| 641 | − | |
| 642 | 640 | ch = file->buf_ptr[0]; |
| 643 | 641 | tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF; |
| 644 | 642 | parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM | PARSE_FLAG_TOK_STR; |
| @@ -1801,6 +1799,8 @@ reparse: · 1156 unmodified lines | ||
| 1801 | 1799 | s->dflag = 3; |
| 1802 | 1800 | else if (*optarg == 'M') |
| 1803 | 1801 | s->dflag = 7; |
| 1802 | + else if (*optarg == 'T') | |
| 1803 | + s->do_test = argc; | |
| 1804 | 1804 | else if (isnum(*optarg)) |
| 1805 | 1805 | g_debug = atoi(optarg); |
| 1806 | 1806 | else |
| @@ -282,6 +282,8 @@ redo: · 281 unmodified lines | ||
| 282 | 282 | n = s->nb_files; |
| 283 | 283 | if (n == 0) |
| 284 | 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 | 288 | if (s->output_type == TCC_OUTPUT_PREPROCESS) { |
| 287 | 289 | if (!s->outfile) { |
| @@ -813,6 +813,7 @@ struct TCCState { · 812 unmodified lines | ||
| 813 | 813 | int option_pthread; /* -pthread option */ |
| 814 | 814 | int argc; |
| 815 | 815 | char **argv; |
| 816 | + int do_test; | |
| 816 | 817 | }; |
| 817 | 818 | |
| 818 | 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 | 50 | ST_DATA SValue __vstack[1+VSTACK_SIZE], *vtop, *pvtop; |
| 51 | 51 | |
| 52 | 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 | 56 | ST_DATA int global_expr; /* true if compound literals must be allocated globally (used during initializers parsing */ |
| 55 | 57 | ST_DATA CType func_vt; /* current function return type (used by return instruction) */ |
| 56 | 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 | 232 | anon_sym = SYM_FIRST_ANOM; |
| 231 | 233 | section_sym = 0; |
| 232 | 234 | const_wanted = 0; |
| 233 | − nocode_wanted = 1; | |
| 235 | + nocode_wanted = 0x80000000; | |
| 234 | 236 | |
| 235 | 237 | /* define some often used types */ |
| 236 | 238 | int_type.t = VT_INT; |
| @@ -1206,14 +1208,12 @@ ST_FUNC int gv(int rc) · 969 unmodified lines | ||
| 1206 | 1208 | } else { |
| 1207 | 1209 | if (is_float(vtop->type.t) && |
| 1208 | 1210 | (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) { |
| 1209 | − unsigned long offset; | |
| 1210 | 1211 | /* CPUs usually cannot use float constants, so we store them |
| 1211 | 1212 | generically in data segment */ |
| 1212 | 1213 | size = type_size(&vtop->type, &align); |
| 1213 | − offset = section_add(data_section, size, align); | |
| 1214 | − vpush_ref(&vtop->type, data_section, offset, size); | |
| 1214 | + vpush_ref(&vtop->type, data_section, data_section->data_offset, size); | |
| 1215 | 1215 | vswap(); |
| 1216 | − init_putv(&vtop->type, data_section, offset); | |
| 1216 | + init_putv(&vtop->type, data_section, data_section->data_offset); | |
| 1217 | 1217 | vtop->r |= VT_LVAL; |
| 1218 | 1218 | } |
| 1219 | 1219 | #ifdef CONFIG_TCC_BCHECK |
| @@ -2329,6 +2329,11 @@ static void gen_cvt_ftoi1(int t) · 1109 unmodified lines | ||
| 2329 | 2329 | static void force_charshort_cast(int t) |
| 2330 | 2330 | { |
| 2331 | 2331 | int bits, dbt; |
| 2332 | + | |
| 2333 | + /* cannot cast static initializers */ | |
| 2334 | + if (STATIC_DATA_WANTED) | |
| 2335 | + return; | |
| 2336 | + | |
| 2332 | 2337 | dbt = t & VT_BTYPE; |
| 2333 | 2338 | /* XXX: add optimization if lvalue : just change type and offset */ |
| 2334 | 2339 | if (dbt == VT_BYTE) |
| @@ -3405,12 +3410,9 @@ static void struct_layout(CType *type, AttributeDef *ad) · 1070 unmodified lines | ||
| 3405 | 3410 | //#define BF_DEBUG |
| 3406 | 3411 | |
| 3407 | 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 | 3414 | bit_size = BIT_SIZE(f->type.t); |
| 3410 | − /* in pcc mode, long long bitfields have type int if they fit */ | |
| 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 | |
| 3415 | + else | |
| 3414 | 3416 | bit_size = -1; |
| 3415 | 3417 | size = type_size(&f->type, &align); |
| 3416 | 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 | 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 | 3488 | while (bit_pos >= align * 8) |
| 3483 | 3489 | c += align, bit_pos -= align * 8; |
| 3484 | 3490 | offset = c; |
| @@ -4558,8 +4564,10 @@ ST_FUNC void unary(void) · 1073 unmodified lines | ||
| 4558 | 4564 | type.t |= VT_ARRAY; |
| 4559 | 4565 | type.ref->c = len; |
| 4560 | 4566 | vpush_ref(&type, data_section, data_section->data_offset, len); |
| 4561 | − ptr = section_ptr_add(data_section, len); | |
| 4562 | − memcpy(ptr, funcname, len); | |
| 4567 | + if (!NODATA_WANTED) { | |
| 4568 | + ptr = section_ptr_add(data_section, len); | |
| 4569 | + memcpy(ptr, funcname, len); | |
| 4570 | + } | |
| 4563 | 4571 | next(); |
| 4564 | 4572 | } |
| 4565 | 4573 | break; |
| @@ -6314,7 +6322,7 @@ static int decl_designator(CType *type, Section *sec, unsigned long c, · 1748 unmodified lines | ||
| 6314 | 6322 | vstore(); |
| 6315 | 6323 | } |
| 6316 | 6324 | vpop(); |
| 6317 | − } else { | |
| 6325 | + } else if (!NODATA_WANTED) { | |
| 6318 | 6326 | c_end = c + nb_elems * elem_size; |
| 6319 | 6327 | if (c_end > sec->data_allocated) |
| 6320 | 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 | 6356 | /* XXX: generate error if incorrect relocation */ |
| 6349 | 6357 | gen_assign_cast(&dtype); |
| 6350 | 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 | 6374 | size = type_size(type, &align); |
| 6352 | 6375 | section_reserve(sec, c + size); |
| 6353 | 6376 | ptr = sec->data + c; |
| 6377 | + | |
| 6354 | 6378 | /* XXX: make code faster ? */ |
| 6355 | 6379 | if ((vtop->r & (VT_SYM|VT_CONST)) == (VT_SYM|VT_CONST) && |
| 6356 | 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 | 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 | 6431 | if (type->t & VT_BITFIELD) { |
| 6422 | 6432 | int bit_pos, bit_size, bits, n; |
| 6423 | 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 | 6608 | string in global variable, we handle it |
| 6599 | 6609 | specifically */ |
| 6600 | 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 | 6613 | } else { |
| 6603 | 6614 | for(i=0;i<nb;i++) { |
| 6604 | 6615 | if (tok == TOK_STR) |
| @@ -6714,6 +6725,13 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, · 109 unmodified lines | ||
| 6714 | 6725 | Section *sec; |
| 6715 | 6726 | Sym *flexible_array; |
| 6716 | 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 | 6736 | flexible_array = NULL; |
| 6719 | 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 | 6797 | } else if (ad->a.packed) { |
| 6780 | 6798 | align = 1; |
| 6781 | 6799 | } |
| 6800 | + | |
| 6801 | + if (NODATA_WANTED) | |
| 6802 | + size = 0, align = 1; | |
| 6803 | + | |
| 6782 | 6804 | if ((r & VT_VALMASK) == VT_LOCAL) { |
| 6783 | 6805 | sec = NULL; |
| 6784 | 6806 | #ifdef CONFIG_TCC_BCHECK |
| 6785 | − if (tcc_state->do_bounds_check && (type->t & VT_ARRAY)) { | |
| 6807 | + if (bcheck && (type->t & VT_ARRAY)) { | |
| 6786 | 6808 | loc--; |
| 6787 | 6809 | } |
| 6788 | 6810 | #endif |
| @@ -6792,7 +6814,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, · 3 unmodified lines | ||
| 6792 | 6814 | /* handles bounds */ |
| 6793 | 6815 | /* XXX: currently, since we do only one pass, we cannot track |
| 6794 | 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 | 6818 | addr_t *bounds_ptr; |
| 6797 | 6819 | /* add padding between regions */ |
| 6798 | 6820 | loc--; |
| @@ -6860,7 +6882,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, · 61 unmodified lines | ||
| 6860 | 6882 | addr = section_add(sec, size, align); |
| 6861 | 6883 | #ifdef CONFIG_TCC_BCHECK |
| 6862 | 6884 | /* add padding if bound check */ |
| 6863 | − if (tcc_state->do_bounds_check) | |
| 6885 | + if (bcheck) | |
| 6864 | 6886 | section_add(sec, 1, 1); |
| 6865 | 6887 | #endif |
| 6866 | 6888 | } else { |
| @@ -6888,7 +6910,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, · 21 unmodified lines | ||
| 6888 | 6910 | #ifdef CONFIG_TCC_BCHECK |
| 6889 | 6911 | /* handles bounds now because the symbol must be defined |
| 6890 | 6912 | before for the relocation */ |
| 6891 | − if (tcc_state->do_bounds_check) { | |
| 6913 | + if (bcheck) { | |
| 6892 | 6914 | addr_t *bounds_ptr; |
| 6893 | 6915 | |
| 6894 | 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 | 6925 | if (type->t & VT_VLA) { |
| 6904 | 6926 | int a; |
| 6905 | 6927 | |
| 6928 | + if (NODATA_WANTED) | |
| 6929 | + goto no_alloc; | |
| 6930 | + | |
| 6906 | 6931 | /* save current stack pointer */ |
| 6907 | 6932 | if (vlas_in_scope == 0) { |
| 6908 | 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 | 6960 | end_macro(); |
| 6936 | 6961 | restore_parse_state(&saved_parse_state); |
| 6937 | 6962 | } |
| 6963 | + | |
| 6964 | + nocode_wanted = saved_nocode_wanted; | |
| 6938 | 6965 | } |
| 6939 | 6966 | |
| 6940 | 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 | 7005 | func_vt.t = VT_VOID; /* for safety */ |
| 6979 | 7006 | func_var = 0; /* for safety */ |
| 6980 | 7007 | ind = 0; /* for safety */ |
| 6981 | − nocode_wanted = 1; | |
| 7008 | + nocode_wanted = 0x80000000; | |
| 6982 | 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 | 58 | struct M P __s { |
| 59 | 59 | long long x : 45; |
| 60 | 60 | long long : 2; |
| 61 | − long long y : 35; | |
| 61 | + long long y : 30; | |
| 62 | 62 | unsigned long long z : 38; |
| 63 | 63 | char a; short b; |
| 64 | 64 | }; |
| @@ -23,8 +23,8 @@ values : 03 ffffffff 0f fffffff8 78 · 22 unmodified lines | ||
| 23 | 23 | align/size : 4 8 |
| 24 | 24 | |
| 25 | 25 | ---- TEST 5 - MS-BITFIELDS ---- |
| 26 | −bits in use : 00000000FFFF00FF0000003FFFFFFFFF00000007FFFFFFFF00001FFFFFFFFFFF | |
| 27 | −bits as set : 0000000000770044000000000000007800000007F00000000000000123456789 | |
| 26 | +bits in use : 00000000FFFF00FF0000003FFFFFFFFF000000003FFFFFFF00001FFFFFFFFFFF | |
| 27 | +bits as set : 0000000000770044000000000000007800000000300000000000000123456789 | |
| 28 | 28 | values : 0000000123456789 fffffffff0000000 0000000000000078 44 77 |
| 29 | 29 | align/size : 8 32 |
| 30 | 30 | |
| @@ -61,8 +61,8 @@ values : 03 ffffffff 0f fffffff8 78 · 30 unmodified lines | ||
| 61 | 61 | align/size : 1 8 |
| 62 | 62 | |
| 63 | 63 | ---- TEST 5 - MS-BITFIELDS - PACKED ---- |
| 64 | −bits in use : FFFFFF0000003FFFFFFFFF00000007FFFFFFFF00001FFFFFFFFFFF | |
| 65 | −bits as set : 007744000000000000007800000007F00000000000000123456789 | |
| 64 | +bits in use : FFFFFF0000003FFFFFFFFF000000003FFFFFFF00001FFFFFFFFFFF | |
| 65 | +bits as set : 007744000000000000007800000000300000000000000123456789 | |
| 66 | 66 | values : 0000000123456789 fffffffff0000000 0000000000000078 44 77 |
| 67 | 67 | align/size : 1 27 |
| 68 | 68 | |
| @@ -99,8 +99,8 @@ values : 03 ffffffff 0f fffffff8 78 · 30 unmodified lines | ||
| 99 | 99 | align/size : 4 8 |
| 100 | 100 | |
| 101 | 101 | ---- TEST 5 - MS-BITFIELDS - WITH ALIGN ---- |
| 102 | −bits in use : 00000000FFFF00FF0000003FFFFFFFFF00000007FFFFFFFF00001FFFFFFFFFFF | |
| 103 | −bits as set : 0000000000770044000000000000007800000007F00000000000000123456789 | |
| 102 | +bits in use : 00000000FFFF00FF0000003FFFFFFFFF000000003FFFFFFF00001FFFFFFFFFFF | |
| 103 | +bits as set : 0000000000770044000000000000007800000000300000000000000123456789 | |
| 104 | 104 | values : 0000000123456789 fffffffff0000000 0000000000000078 44 77 |
| 105 | 105 | align/size : 8 32 |
| 106 | 106 | |
| @@ -137,8 +137,8 @@ values : 03 ffffffff 0f fffffff8 78 · 30 unmodified lines | ||
| 137 | 137 | align/size : 1 8 |
| 138 | 138 | |
| 139 | 139 | ---- TEST 5 - MS-BITFIELDS - PACKED - WITH ALIGN ---- |
| 140 | −bits in use : FFFFFF0000003FFFFFFFFF00000007FFFFFFFF00001FFFFFFFFFFF | |
| 141 | −bits as set : 007744000000000000007800000007F00000000000000123456789 | |
| 140 | +bits in use : FFFFFF0000003FFFFFFFFF000000003FFFFFFF00001FFFFFFFFFFF | |
| 141 | +bits as set : 007744000000000000007800000000300000000000000123456789 | |
| 142 | 142 | values : 0000000123456789 fffffffff0000000 0000000000000078 44 77 |
| 143 | 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 | 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 | 8 | # some tests do not pass on all platforms, remove them for now |
| 32 | 9 | SKIP = 34_array_assignment.test # array assignment is not in C standard |
| 33 | 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 | 27 | SKIP += 95_bitfields_ms.test # type_align is differnt on 32bit-non-windows |
| 51 | 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 | 60 | all test tests2.all: $(filter-out $(SKIP),$(TESTS)) ; |
| 54 | 61 | |
| 55 | 62 | %.test: %.c %.expect |
| 56 | 63 | @echo Test: $*... |
| 57 | − @$(if $(NORUN),\ | |
| 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)) | |
| 64 | + @$(if $(NORUN),$(T1),$(T2)) $(if $(NODIFF),,$(T3)) | |
| 63 | 65 | |
| 64 | −F1 = $(or $(filter $1_%,$(TESTS)),$1_???.test) | |
| 65 | −F2 = $1 UPDATE="$(patsubst %.test,%.expect,$1)" | |
| 66 | +T1 = $(TCC) $(FLAGS) $< -o a.exe && ./a.exe $(ARGS) | |
| 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 | 72 | # run single test and update .expect file, e.g. "make tests2.37+" |
| 68 | 73 | tests2.%+: |
| 69 | 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 | 80 | # run single test, e.g. "make tests2.37" |
| 72 | 81 | tests2.%: |
| 73 | 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 | 87 | # automatically generate .expect files with gcc: |
| 76 | 88 | %.expect : |
| 77 | 89 | @echo Generating: $@ |
| 78 | − @$(CC) -w -std=gnu99 $(FLAGS) $(SRC)/$*.c -o a.exe | |
| 79 | − @./a.exe $(ARGS) $(FILTER) >$@ 2>&1 | |
| 80 | − @rm -f a.exe | |
| 90 | + @$(call GEN,$(SRC)/$*.c) $(FILTER) >$@ 2>&1 | |
| 91 | + @rm -f *.exe *.obj *.pdb | |
| 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 | 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 | 100 | # tell make not to delete |
| 91 | 101 | .PRECIOUS: %.expect |
| 92 | 102 | |
| 103 | +# force .expect generation for these files | |
| 93 | 104 | $(sort $(GEN-ALWAYS) $(UPDATE)) : force |
| 94 | 105 | force: |
| 95 | 106 | |