diff --git a/cobc/codegen.c b/cobc/codegen.c index ef3a4aa36..651165127 100644 --- a/cobc/codegen.c +++ b/cobc/codegen.c @@ -13366,7 +13366,7 @@ output_entry_function (struct cb_program *prog, cb_tree entry, if (prog->flag_void) { output ("(void)"); } else { - output ("int res = "); + output ("return "); } if (!prog->nested_level) { output ("%s_ (%d", prog->program_id, progid); @@ -13428,9 +13428,6 @@ output_entry_function (struct cb_program *prog, cb_tree entry, } output (");"); output_newline (); - if (!prog->flag_void) { - output_line("return res;"); - } output_block_close (); output_newline (); } diff --git a/libcob/cobperf.c b/libcob/cobperf.c index 4f0a14ac0..86eec0c14 100644 --- a/libcob/cobperf.c +++ b/libcob/cobperf.c @@ -54,7 +54,7 @@ get_str_index(const char *str, const char **arr, size_t arr_len) { for (size_t i = 0; i < arr_len; i++) { if (arr[i] == NULL) return ULONG_MAX; - if (!strcmp(str, arr[i])) return i; + if (!strcmp (str, arr[i])) return i; } return ULONG_MAX; @@ -105,14 +105,14 @@ cob_perf_enter_paragraph(const char *section, const char *paragraph) // We should always have a section when entering a paragraph. if (!section) return; - sec_idx = get_str_index(section, sections, sections_count); + sec_idx = get_str_index (section, sections, sections_count); if (sec_idx == ULONG_MAX) { fprintf (stderr, "[cob_perf] Could not find section %s, aborting profiling.\n", section); is_init = false; return; } - para_idx = get_str_index(paragraph, para_per_sections[sec_idx], max_paragraphs_count); + para_idx = get_str_index (paragraph, para_per_sections[sec_idx], max_paragraphs_count); if (para_idx == ULONG_MAX) { fprintf (stderr, "[cob_perf] Could not find paragraph %s IN %s, aborting profiling.\n", section, paragraph); @@ -120,11 +120,7 @@ cob_perf_enter_paragraph(const char *section, const char *paragraph) return; } - // If the paragraph entered is in another section than the current one, then we want to - // enter it too. - if (called_paragraphs[current_idx][0] != sec_idx) cob_perf_enter_section(section); - - clock_gettime(CLOCK_MONOTONIC, &ts); + clock_gettime (CLOCK_MONOTONIC, &ts); current_idx++; @@ -140,7 +136,7 @@ cob_perf_enter_section(const char *section) struct timespec ts; if (!is_init) return; - sec_idx = get_str_index(section, sections, sections_count); + sec_idx = get_str_index (section, sections, sections_count); if (sec_idx == ULONG_MAX) { fprintf (stderr, "[cob_perf] Could not find section %s, aborting profiling.\n", section); @@ -148,7 +144,7 @@ cob_perf_enter_section(const char *section) return; } - clock_gettime(CLOCK_MONOTONIC, &ts); + clock_gettime (CLOCK_MONOTONIC, &ts); current_idx++; @@ -165,24 +161,24 @@ cob_perf_exit_paragraph(const char *section, const char *paragraph) struct timespec ts; if (!is_init) return; - sec_idx = get_str_index(section, sections, sections_count); + sec_idx = get_str_index (section, sections, sections_count); if (sec_idx == ULONG_MAX) { - fprintf(stderr, "[cob_perf] Could not find section %s, aborting profiling.\n", section); + fprintf (stderr, "[cob_perf] Could not find section %s, aborting profiling.\n", section); is_init = false; return; } - para_idx = get_str_index(paragraph, para_per_sections[sec_idx], max_paragraphs_count); + para_idx = get_str_index (paragraph, para_per_sections[sec_idx], max_paragraphs_count); if (para_idx == ULONG_MAX) { - fprintf(stderr, "[cob_perf] Could not find paragraph %s IN %s, aborting profiling.\n", + fprintf (stderr, "[cob_perf] Could not find paragraph %s IN %s, aborting profiling.\n", section, paragraph); is_init = false; return; } - clock_gettime(CLOCK_MONOTONIC, &ts); + clock_gettime (CLOCK_MONOTONIC, &ts); while (current_idx != ULONG_MAX) { size_t curr_sec = called_paragraphs[current_idx][0]; @@ -205,7 +201,7 @@ cob_perf_exit_section(const char *section) if (!is_init) return; - sec_idx = get_str_index(section, sections, sections_count); + sec_idx = get_str_index (section, sections, sections_count); if (sec_idx == ULONG_MAX) { fprintf (stderr, "[cob_perf] Could not find section %s, aborting profiling.\n", section); @@ -213,25 +209,30 @@ cob_perf_exit_section(const char *section) return; } - clock_gettime(CLOCK_MONOTONIC, &ts); + clock_gettime (CLOCK_MONOTONIC, &ts); while (current_idx != ULONG_MAX) { size_t curr_sec = called_paragraphs[current_idx][0]; size_t curr_para = called_paragraphs[current_idx][1]; + if (curr_sec != sec_idx) return; // We exited all paragraphs entered in this section + if (curr_para == ULONG_MAX) { total_times[curr_sec][254] += ts.tv_nsec - start_times[current_idx]; } else { total_times[curr_sec][curr_para] += ts.tv_nsec - start_times[current_idx]; } current_idx--; - if (curr_sec == sec_idx && curr_para == ULONG_MAX) return; + if (curr_sec == sec_idx && curr_para == ULONG_MAX) { + // We exit the last PERFORM of this section + return; + } } } /* GO TO are generated for both explicit COBOL GO TO statements and COBOL EXIT ... statements. * We do not need to have a paragraph/section enter function since these will be executed when - * the c goto is executed. */ + * the c goto is executed, just after the targeted label. */ void cob_perf_goto(const char *section, const char *paragraph) { @@ -244,19 +245,19 @@ cob_perf_goto(const char *section, const char *paragraph) if (section == NULL) { // GO TO exit : section = NULL, paragraph = invalid section name - if (get_str_index(paragraph, sections, sections_count) == ULONG_MAX) { + if (get_str_index (paragraph, sections, sections_count) == ULONG_MAX) { return; } // GO TO section : section = NULL, paragraph = target section name while (current_idx != ULONG_MAX) { - cob_perf_exit_section(sections[called_paragraphs[current_idx][0]]); + cob_perf_exit_section (sections[called_paragraphs[current_idx][0]]); } return; } - sec_idx = get_str_index(section, sections, sections_count); + sec_idx = get_str_index (section, sections, sections_count); if (sec_idx == ULONG_MAX) { fprintf (stderr, "[cob_perf] Could not find section %s, aborting profiling.\n", section); @@ -264,7 +265,7 @@ cob_perf_goto(const char *section, const char *paragraph) return; } - para_idx = get_str_index(paragraph, para_per_sections[sec_idx], max_paragraphs_count); + para_idx = get_str_index (paragraph, para_per_sections[sec_idx], max_paragraphs_count); if (para_idx == ULONG_MAX) { fprintf (stderr, "[cob_perf] Could not find paragraph %s IN %s, aborting profiling\n", @@ -284,11 +285,24 @@ cob_perf_goto(const char *section, const char *paragraph) } } else { while (current_idx != ULONG_MAX) { - cob_perf_exit_section(sections[called_paragraphs[current_idx][0]]); + cob_perf_exit_section (sections[called_paragraphs[current_idx][0]]); } } } +#if WITH_XLSXWRITER +static unsigned +size_t_len(size_t s) +{ + unsigned l = 1; + while (s > 9) { + l++; + s /= 10; + } + return l; +} +#endif + void cob_perf_end() { @@ -296,7 +310,12 @@ cob_perf_end() #if WITH_XLSXWRITER lxw_workbook *workbook; lxw_worksheet *worksheet; + lxw_format *merge_format; size_t row = 1; + size_t longest_sec = 7; + size_t longest_para = 9; + size_t longest_time = 9; + size_t longest_perform = 26; #else FILE *file; #endif @@ -304,52 +323,76 @@ cob_perf_end() if (!is_init) return; while (current_idx != ULONG_MAX) { - cob_perf_exit_section(sections[called_paragraphs[current_idx][0]]); + cob_perf_exit_section (sections[called_paragraphs[current_idx][0]]); } #if WITH_XLSXWRITER - workbook = workbook_new("perf.xlsx"); - worksheet = workbook_add_worksheet(workbook, NULL); + workbook = workbook_new ("perf.xlsx"); + worksheet = workbook_add_worksheet (workbook, NULL); + merge_format = workbook_add_format(workbook); - worksheet_write_string(worksheet, 0, 0, "Section", NULL); - worksheet_write_string(worksheet, 0, 1, "Paragraph", NULL); - worksheet_write_string(worksheet, 0, 2, "Time (ns)", NULL); + format_set_align(merge_format, LXW_ALIGN_CENTER); + format_set_align(merge_format, LXW_ALIGN_VERTICAL_CENTER); + worksheet_write_string (worksheet, 0, 0, "Section", NULL); + worksheet_write_string (worksheet, 0, 1, "Paragraph", NULL); + worksheet_write_string (worksheet, 0, 2, "Time (ns)", NULL); + worksheet_write_string (worksheet, 0, 3, "Explicit section time (ns)", NULL); for (size_t i = 0; i < sections_count; i++) { + size_t curr_sec_row = row; + long total_sec_time = 0; - worksheet_write_string(worksheet, row, 0, sections[i], NULL); - worksheet_write_number(worksheet, row, 2, (double)total_times[i][254], NULL); + worksheet_write_number (worksheet, row, 3, (double)total_times[i][254], NULL); + if (size_t_len (total_times[i][254]) > longest_time) longest_time = + size_t_len (total_times[i][254]); row++; for (size_t j = 0; j < max_paragraphs_count; j++) { const char *para = para_per_sections[i][j]; if (para == NULL) break; - worksheet_write_string(worksheet, row, 0, sections[i], NULL); - worksheet_write_string(worksheet, row, 1, para, NULL); - worksheet_write_number(worksheet, row, 2, (double)total_times[i][j], NULL); + if (longest_para < strlen (para)) longest_para = strlen (para); + total_sec_time += total_times[i][j]; + worksheet_write_string (worksheet, row, 1, para, NULL); + worksheet_write_number (worksheet, row, 2, (double)total_times[i][j], NULL); + if (size_t_len (total_times[i][j]) > longest_time) longest_time = + size_t_len (total_times[i][j]); row++; } + worksheet_write_number (worksheet, curr_sec_row, 2, total_sec_time, NULL); + worksheet_merge_range (worksheet, curr_sec_row, 0, row-1, 0, sections[i], merge_format); + if (strlen (sections[i]) > longest_sec) longest_sec = strlen (sections[i]); + if (size_t_len (total_sec_time) > longest_perform) longest_perform = + size_t_len (total_sec_time); } - workbook_close(workbook); + worksheet_set_column (worksheet, 0, 0, ((double)longest_sec) + 0.43, NULL); + worksheet_set_column (worksheet, 1, 1, ((double)longest_para) + 0.43, NULL); + worksheet_set_column (worksheet, 2, 2, ((double)longest_time) + 0.43, NULL); + worksheet_set_column (worksheet, 3, 3, ((double)longest_perform) + 0.43, NULL); + + workbook_close (workbook); #else + file = fopen ("prof.csv", "W"); if (!!file) { - fprintf (file, "section, time\n"); + fprintf (file, "section,paragraph,time,PERFORM section time\n"); for (size_t i = 0; i < sections_count; i++) { - fprintf (file, "%s, %lu ns\n", sections[i], total_times[i][254]); + long total_sec_time = 0; + fprintf (file, "%s, , , %lu ns\n", sections[i], total_times[i][254]); for (size_t j = 0; j < max_paragraphs_count; j++) { const char *para = para_per_sections[i][j]; if (para == NULL) break; fprintf (file, "%s, %lu ns\n", para, total_times[i][j]); + total_sec_time += total_times[i][j]; } + fprintf (file, "%s, ,%lu ns, ", sections[i], total_sec_time); } - fclose(file); + fclose (file); } #endif