Add myself to RELICENSING file Use locking when writing tcov file Fixed sometimes last line of function not shown Merge tcc_tcov_add_file and tcc_add_tcov Allow absolute file names Count case labels with no code better
Unified · Split
| @@ -35,6 +35,7 @@ · 34 unmodified lines | ||
| 35 | 35 | Frédéric Féret YES x86 64/16 bit asm |
| 36 | 36 | grischka YES tccpe.c |
| 37 | 37 | Henry Kroll YES |
| 38 | + Herman ten Brugge YES | |
| 38 | 39 | Joe Soroka YES |
| 39 | 40 | Kirill Smelkov YES |
| 40 | 41 | mingodad YES |
| @@ -1,6 +1,14 @@ | ||
| 1 | 1 | #include <stdio.h> |
| 2 | 2 | #include <string.h> |
| 3 | 3 | #include <stdlib.h> |
| 4 | +#include <fcntl.h> | |
| 5 | +#ifndef _WIN32 | |
| 6 | +#include <unistd.h> | |
| 7 | +#include <errno.h> | |
| 8 | +#else | |
| 9 | +#include <windows.h> | |
| 10 | +#include <io.h> | |
| 11 | +#endif | |
| 4 | 12 | |
| 5 | 13 | /* section layout (all little endian): |
| 6 | 14 | 32bit offset to executable/so file name |
| @@ -38,6 +46,32 @@ typedef struct tcov_file { · 31 unmodified lines | ||
| 38 | 46 | struct tcov_file *next; |
| 39 | 47 | } tcov_file; |
| 40 | 48 | |
| 49 | +static FILE *open_tcov_file (char *cov_filename) | |
| 50 | +{ | |
| 51 | + int fd; | |
| 52 | +#ifndef _WIN32 | |
| 53 | + struct flock lock; | |
| 54 | + | |
| 55 | + lock.l_type = F_WRLCK; | |
| 56 | + lock.l_whence = SEEK_SET; | |
| 57 | + lock.l_start = 0; | |
| 58 | + lock.l_len = 0; /* Until EOF. */ | |
| 59 | + lock.l_pid = getpid (); | |
| 60 | +#endif | |
| 61 | + fd = open (cov_filename, O_RDWR | O_CREAT, 0666); | |
| 62 | + if (fd < 0) | |
| 63 | + return NULL; | |
| 64 | + | |
| 65 | +#ifndef _WIN32 | |
| 66 | + while (fcntl (fd, F_SETLKW, &lock) && errno == EINTR) | |
| 67 | + continue; | |
| 68 | +#else | |
| 69 | + LockFile((HANDLE)_get_osfhandle(fd), 0, 0, 1, 0); | |
| 70 | +#endif | |
| 71 | + | |
| 72 | + return fdopen (fd, "r+"); | |
| 73 | +} | |
| 74 | + | |
| 41 | 75 | static unsigned long long get_value(unsigned char *p, int size) |
| 42 | 76 | { |
| 43 | 77 | unsigned long long value = 0; |
| @@ -176,11 +210,10 @@ static tcov_file *sort_test_coverage (unsigned char *p) · 132 unmodified lines | ||
| 176 | 210 | } |
| 177 | 211 | |
| 178 | 212 | /* merge with previous tcov file */ |
| 179 | −static void merge_test_coverage (tcov_file *file, char *cov_filename, | |
| 213 | +static void merge_test_coverage (tcov_file *file, FILE *fp, | |
| 180 | 214 | unsigned int *pruns) |
| 181 | 215 | { |
| 182 | 216 | unsigned int runs; |
| 183 | − FILE *fp = fopen (cov_filename, "r"); | |
| 184 | 217 | char *p; |
| 185 | 218 | char str[10000]; |
| 186 | 219 | |
| @@ -228,7 +261,6 @@ static void merge_test_coverage (tcov_file *file, char *cov_filename, · 41 unmodified lines | ||
| 228 | 261 | } |
| 229 | 262 | file = file->next; |
| 230 | 263 | } |
| 231 | − fclose (fp); | |
| 232 | 264 | } |
| 233 | 265 | |
| 234 | 266 | /* store tcov data in file */ |
| @@ -247,13 +279,14 @@ void __store_test_coverage (unsigned char * p) · 12 unmodified lines | ||
| 247 | 279 | tcov_file *nfile; |
| 248 | 280 | tcov_function *func; |
| 249 | 281 | |
| 250 | − file = sort_test_coverage (p); | |
| 251 | − merge_test_coverage (file, cov_filename, &runs); | |
| 252 | − fp = fopen (cov_filename, "w"); | |
| 282 | + fp = open_tcov_file (cov_filename); | |
| 253 | 283 | if (fp == NULL) { |
| 254 | 284 | fprintf (stderr, "Cannot create coverage file: %s\n", cov_filename); |
| 255 | 285 | return; |
| 256 | 286 | } |
| 287 | + file = sort_test_coverage (p); | |
| 288 | + merge_test_coverage (file, fp, &runs); | |
| 289 | + fseek (fp, 0, SEEK_SET); | |
| 257 | 290 | fprintf (fp, " -: 0:Runs:%u\n", runs); |
| 258 | 291 | files = 0; |
| 259 | 292 | funcs = 0; |
| @@ -346,12 +379,11 @@ void __store_test_coverage (unsigned char * p) · 86 unmodified lines | ||
| 346 | 379 | lline = nlline; |
| 347 | 380 | j++; |
| 348 | 381 | } |
| 349 | − else { | |
| 350 | − if (same_line) | |
| 351 | − lline++; | |
| 382 | + else | |
| 352 | 383 | break; |
| 353 | − } | |
| 354 | 384 | } |
| 385 | + if (same_line) | |
| 386 | + lline++; | |
| 355 | 387 | |
| 356 | 388 | while (curline < fline) |
| 357 | 389 | if (fgets(str, sizeof(str), src)) |
| @@ -1467,7 +1467,6 @@ ST_FUNC void tcc_debug_end(TCCState *s1); · 1466 unmodified lines | ||
| 1467 | 1467 | ST_FUNC void tcc_debug_bincl(TCCState *s1); |
| 1468 | 1468 | ST_FUNC void tcc_debug_eincl(TCCState *s1); |
| 1469 | 1469 | ST_FUNC void tcc_debug_putfile(TCCState *s1, const char *filename); |
| 1470 | −ST_FUNC void tcc_add_tcov(TCCState *s1); | |
| 1471 | 1470 | |
| 1472 | 1471 | ST_FUNC void tccgen_init(TCCState *s1); |
| 1473 | 1472 | ST_FUNC int tccgen_compile(TCCState *s1); |
| @@ -1438,9 +1438,13 @@ static void tcc_tcov_add_file(TCCState *s1, const char *filename) · 1437 unmodified lines | ||
| 1438 | 1438 | section_ptr_add(tcov_section, 1); |
| 1439 | 1439 | write32le (tcov_section->data, tcov_section->data_offset); |
| 1440 | 1440 | |
| 1441 | − getcwd (wd, sizeof(wd)); | |
| 1442 | 1441 | cstr_new (&cstr); |
| 1443 | − cstr_printf (&cstr, "%s/%s.tcov", wd, filename); | |
| 1442 | + if (filename[0] == '/') | |
| 1443 | + cstr_printf (&cstr, "%s.tcov", filename); | |
| 1444 | + else { | |
| 1445 | + getcwd (wd, sizeof(wd)); | |
| 1446 | + cstr_printf (&cstr, "%s/%s.tcov", wd, filename); | |
| 1447 | + } | |
| 1444 | 1448 | ptr = section_ptr_add(tcov_section, cstr.size + 1); |
| 1445 | 1449 | strncpy((char *)ptr, cstr.data, cstr.size); |
| 1446 | 1450 | unlink((char *)ptr); |
| @@ -1448,11 +1452,6 @@ static void tcc_tcov_add_file(TCCState *s1, const char *filename) · 1 unmodified line | ||
| 1448 | 1452 | normalize_slashes((char *)ptr); |
| 1449 | 1453 | #endif |
| 1450 | 1454 | cstr_free (&cstr); |
| 1451 | −} | |
| 1452 | − | |
| 1453 | −ST_FUNC void tcc_add_tcov(TCCState *s1) | |
| 1454 | −{ | |
| 1455 | − CString cstr; | |
| 1456 | 1455 | |
| 1457 | 1456 | cstr_new(&cstr); |
| 1458 | 1457 | cstr_printf(&cstr, |
| @@ -1512,8 +1511,6 @@ ST_FUNC void tcc_add_runtime(TCCState *s1) · 53 unmodified lines | ||
| 1512 | 1511 | tcc_add_btstub(s1); |
| 1513 | 1512 | } |
| 1514 | 1513 | #endif |
| 1515 | − if (s1->test_coverage) | |
| 1516 | − tcc_add_tcov(s1); | |
| 1517 | 1514 | if (strlen(TCC_LIBTCC1) > 0) |
| 1518 | 1515 | tcc_add_support(s1, TCC_LIBTCC1); |
| 1519 | 1516 | #if TARGETOS_OpenBSD || TARGETOS_FreeBSD || TARGETOS_NetBSD |
| @@ -208,7 +208,6 @@ static struct debug_info { · 207 unmodified lines | ||
| 208 | 208 | |
| 209 | 209 | static struct { |
| 210 | 210 | unsigned long offset; |
| 211 | − unsigned long last_offset; | |
| 212 | 211 | unsigned long last_file_name; |
| 213 | 212 | unsigned long last_func_name; |
| 214 | 213 | int ind; |
| @@ -822,6 +821,7 @@ static void tcc_tcov_block_begin(void) · 607 unmodified lines | ||
| 822 | 821 | { |
| 823 | 822 | SValue sv; |
| 824 | 823 | void *ptr; |
| 824 | + unsigned long last_offset = tcov_data.offset; | |
| 825 | 825 | |
| 826 | 826 | tcc_tcov_block_end (0); |
| 827 | 827 | if (tcc_state->test_coverage == 0 || nocode_wanted) |
| @@ -837,11 +837,17 @@ static void tcc_tcov_block_begin(void) · 9 unmodified lines | ||
| 837 | 837 | section_ptr_add(tcov_section, 1); |
| 838 | 838 | if (tcov_data.last_file_name) |
| 839 | 839 | section_ptr_add(tcov_section, 1); |
| 840 | − getcwd (wd, sizeof(wd)); | |
| 841 | − tcov_data.last_file_name = tcov_section->data_offset + strlen(wd) + 1; | |
| 842 | 840 | tcov_data.last_func_name = 0; |
| 843 | 841 | cstr_new (&cstr); |
| 844 | − cstr_printf (&cstr, "%s/%s", wd, file->true_filename); | |
| 842 | + if (file->true_filename[0] == '/') { | |
| 843 | + tcov_data.last_file_name = tcov_section->data_offset; | |
| 844 | + cstr_printf (&cstr, "%s", file->true_filename); | |
| 845 | + } | |
| 846 | + else { | |
| 847 | + getcwd (wd, sizeof(wd)); | |
| 848 | + tcov_data.last_file_name = tcov_section->data_offset + strlen(wd) + 1; | |
| 849 | + cstr_printf (&cstr, "%s/%s", wd, file->true_filename); | |
| 850 | + } | |
| 845 | 851 | ptr = section_ptr_add(tcov_section, cstr.size + 1); |
| 846 | 852 | strncpy((char *)ptr, cstr.data, cstr.size); |
| 847 | 853 | #ifdef _WIN32 |
| @@ -865,7 +871,7 @@ static void tcc_tcov_block_begin(void) · 17 unmodified lines | ||
| 865 | 871 | write64le (ptr, file->line_num); |
| 866 | 872 | } |
| 867 | 873 | if (ind == tcov_data.ind && tcov_data.line == file->line_num) |
| 868 | − tcov_data.offset = tcov_data.last_offset; | |
| 874 | + tcov_data.offset = last_offset; | |
| 869 | 875 | else { |
| 870 | 876 | Sym label = {0}; |
| 871 | 877 | label.type.t = VT_LLONG | VT_STATIC; |
| @@ -903,7 +909,6 @@ static void tcc_tcov_block_end(int line) · 31 unmodified lines | ||
| 903 | 909 | unsigned long long nline = line ? line : file->line_num; |
| 904 | 910 | |
| 905 | 911 | write64le (ptr, (read64le (ptr) & 0xfffffffffull) | (nline << 36)); |
| 906 | − tcov_data.last_offset = tcov_data.offset; | |
| 907 | 912 | tcov_data.offset = 0; |
| 908 | 913 | } |
| 909 | 914 | } |
| @@ -5744,6 +5749,7 @@ static inline int is_memory_model(const SValue *sv) · 4834 unmodified lines | ||
| 5744 | 5749 | * Ideally we should check whether the model matches 1:1. |
| 5745 | 5750 | * If it is possible, we should check by the name of the value. |
| 5746 | 5751 | */ |
| 5752 | +int t = 0; // XXX: HACK | |
| 5747 | 5753 | return (((t & VT_BTYPE) == VT_INT) && (sv->c.i < 6)); |
| 5748 | 5754 | } |
| 5749 | 5755 | |
| @@ -7576,6 +7582,7 @@ again: · 1826 unmodified lines | ||
| 7576 | 7582 | || (cur_switch->sv.type.t & VT_UNSIGNED && (uint64_t)cr->v2 < (uint64_t)cr->v1)) |
| 7577 | 7583 | tcc_warning("empty case range"); |
| 7578 | 7584 | } |
| 7585 | + tcov_data.ind = 0; | |
| 7579 | 7586 | cr->sym = gind(); |
| 7580 | 7587 | dynarray_add(&cur_switch->p, &cur_switch->n, cr); |
| 7581 | 7588 | skip(':'); |
| @@ -7587,6 +7594,7 @@ again: · 5 unmodified lines | ||
| 7587 | 7594 | expect("switch"); |
| 7588 | 7595 | if (cur_switch->def_sym) |
| 7589 | 7596 | tcc_error("too many 'default'"); |
| 7597 | + tcov_data.ind = 0; | |
| 7590 | 7598 | cur_switch->def_sym = gind(); |
| 7591 | 7599 | skip(':'); |
| 7592 | 7600 | is_expr = 0; |
| @@ -1915,8 +1915,6 @@ static void pe_add_runtime(TCCState *s1, struct pe_info *pe) · 1914 unmodified lines | ||
| 1915 | 1915 | tcc_add_btstub(s1); |
| 1916 | 1916 | } |
| 1917 | 1917 | #endif |
| 1918 | − if (s1->test_coverage) | |
| 1919 | − tcc_add_tcov(s1); | |
| 1920 | 1918 | |
| 1921 | 1919 | /* grab the startup code from libtcc1.a */ |
| 1922 | 1920 | #ifdef TCC_IS_NATIVE |