Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix profiling of EVALUATE #208

Open
wants to merge 3 commits into
base: gcos4gnucobol-3.x
Choose a base branch
from

Conversation

lefessan
Copy link
Member

@lefessan lefessan commented Jan 3, 2025

Try to fix issue reported in #110 (comment) and meyfa/CobolCraft#214 (comment).

@lefessan lefessan force-pushed the z-2025-01-03-fix-profile-evaluate branch from 93347f5 to 1d7aadb Compare January 3, 2025 13:46
@GitMensch
Copy link
Collaborator

please add the test case from the original example to the testsuite, then that's good to upstream

cobc/typeck.c Outdated Show resolved Hide resolved
@lefessan lefessan force-pushed the z-2025-01-03-fix-profile-evaluate branch 2 times, most recently from 276e97a to 0867bf3 Compare January 3, 2025 14:42
@lefessan
Copy link
Member Author

lefessan commented Jan 3, 2025

I added the test, and also fixed the same code for break, though I don't have a test case for that one...

LK-OFFSET: 0000000006
])

AT_CLEANUP
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please include also the expected profiling output here.

@lefessan
Copy link
Member Author

lefessan commented Jan 3, 2025

Is it still ok for SVN with the change to the break function ?

@GitMensch
Copy link
Collaborator

I'm not sure yet to get the complete picture,

What are the elements of the chain(s) with and what without -fperf?
How does this change if we actually have a GO TO at the last position of the imperative statements of a WHEN?

[I'll check fir the break part in the meantime]

@lefessan
Copy link
Member Author

lefessan commented Jan 3, 2025

For example, in the test, the chain would be [ CALL TestRecurse ] in the non-profiling case, and [ C_CALL "prof_begin_call" ; CALL TestRecurse ; C_CALL "prof_end_call" ] in the profiling case. The C_CALL are not "CB_STATEMENT_P", so the previous test was failing and behaving the same as if it was a GOTO, because the test was not correctly written.

I think that, in the case of a GOTO, profiling does not add any information before and after (it adds information to the GOTO itself), so it should be the same as without profiling.

@GitMensch
Copy link
Collaborator

Updated testcase:

       IDENTIFICATION DIVISION.
       PROGRAM-ID. Main.
       
       DATA DIVISION.
       WORKING-STORAGE SECTION.
           01 STR PIC X(6) VALUE "..-..-".
           01 OFFSET BINARY-LONG UNSIGNED.
       
       PROCEDURE DIVISION.
           MOVE 1 TO OFFSET
           PERFORM UNTIL OFFSET > LENGTH OF STR
               CALL "TestRecurse" USING STR OFFSET
           END-PERFORM.
       
       END PROGRAM Main.
       
       
       IDENTIFICATION DIVISION.
       PROGRAM-ID. TestRecurse IS RECURSIVE.
       
       DATA DIVISION.
       LINKAGE SECTION.
           01 LK-STR.
              03 LK-CHR PIC X OCCURS 6
        >> IF BREAK IS DEFINED
                 INDEXED BY LK-IDX
        >> END-IF

                 .
           01 LK-OFFSET BINARY-LONG UNSIGNED.
       
       PROCEDURE DIVISION USING LK-STR LK-OFFSET.
           DISPLAY "LK-OFFSET: " LK-OFFSET
        >> IF BREAK IS DEFINED
           SET LK-IDX TO LK-OFFSET
           SEARCH LK-CHR
               AT END
                   IF LK-OFFSET > 20
                      GOBACK
                   END-IF
                   ADD 1 TO LK-OFFSET
                   CALL "TestRecurse" USING LK-STR LK-OFFSET
               WHEN LK-CHR (LK-IDX) = "."
                   ADD 1 TO LK-OFFSET
           END-SEARCH.
        >> ELSE
           EVALUATE LK-STR(LK-OFFSET:1)
               WHEN "."
                   ADD 1 TO LK-OFFSET
                   CALL "TestRecurse" USING LK-STR LK-OFFSET
               WHEN OTHER
                   ADD 1 TO LK-OFFSET
           END-EVALUATE.
        >> END-IF
       
       END PROGRAM TestRecurse.

compile with -DBREAK for the second testcase (which actually breaks at runtime because of memory issues with current codegen).

maybe rename the testcase as "profiling and codegen" or something similar, with keywords EVALUATE and SEARCH.

Please add both expected profiling results to the testcase as well.

@lefessan
Copy link
Member Author

lefessan commented Jan 3, 2025

In your example, where is the break supposed to be inserted ? In the WHEN of the SEARCH ?

Note that on my computer, this program with -DBREAK fails to compile without profiling, but works ok with profiling...

@GitMensch
Copy link
Collaborator

The break is not inserted with the current svn version:

        /* Line: 42        : CALL               : prof.cob */
#line 42 "prof.cob"
        cob_nop ();
#line 448 "prof.c"
        cob_procedure_params[0] = COB_SET_DATA (f_36, b_36);
        cob_procedure_params[1] = COB_SET_DATA (f_39, b_39);
        cob_glob_ptr->cob_call_params = 2;
        cob_glob_ptr->cob_stmt_exception = 0;
        if (unlikely((cob_glob_ptr->cob_exception_code & 0x0b00) == 0x0b00)) cob_glob_ptr->cob_exception_code = 0;
                if (unlikely(call_TestRecurse.funcvoid == NULL || cob_glob_ptr->cob_physical_cancel == 1))
        {
          call_TestRecurse.funcvoid = cob_resolve_cobol ("TestRecurse", 0, 1);
        }
        b_21 = ((int (*)(void *, void *))call_TestRecurse.funcint) (b_36, b_39);
        cob_prof_exit_procedure (prof_info, 3);
      }

      /* Line: 43        : WHEN               : prof.cob */

without:

        /* Line: 42        : CALL               : prof.cob */
#line 42 "prof.cob"
        cob_nop ();
#line 425 "prof.c"
        cob_procedure_params[0] = COB_SET_DATA (f_36, b_36);
        cob_procedure_params[1] = COB_SET_DATA (f_39, b_39);
        cob_glob_ptr->cob_call_params = 2;
        cob_glob_ptr->cob_stmt_exception = 0;
        if (unlikely((cob_glob_ptr->cob_exception_code & 0x0b00) == 0x0b00)) cob_glob_ptr->cob_exception_code = 0;
                if (unlikely(call_TestRecurse.funcvoid == NULL || cob_glob_ptr->cob_physical_cancel == 1))
        {
          call_TestRecurse.funcvoid = cob_resolve_cobol ("TestRecurse", 0, 1);
        }
        b_21 = ((int (*)(void *, void *))call_TestRecurse.funcint) (b_36, b_39);
        break;
      }

      /* Line: 43        : WHEN               : prof.cob */

@GitMensch
Copy link
Collaborator

If the program fails to compile, then please recode it to just do some addition in the sub-program no recursive calls (at least that would be my guess for the error). This also helps to keep that test to be more focused.

rechecked: The compile error got in with GnuCOBOL 3.2 (3.1.2 compiles it clean, 3.3 dev doesn't) - that should get a new upstream bug report (and be fixed until 3.3 final, rc1 would be nice, but not necessary as the error was already released).

Fix a bug where INDEXED BY in LINKAGE SECTION would cause the variable
not to be added to the local include file, causing a compile error of
the C code.
@lefessan lefessan force-pushed the z-2025-01-03-fix-profile-evaluate branch from 0867bf3 to e259ff7 Compare January 6, 2025 23:03
@lefessan
Copy link
Member Author

lefessan commented Jan 6, 2025

I think I found the bug with the program: the INDEXED BY appearing in LINKAGE SECTION was not correctly handled by gnucobol, I had to modify parser.y to set its index_type to CB_INT_INDEX, as if it were defined in the LOCAL-STORAGE section.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants