@@ -4318,6 +4318,186 @@ output_funcall_item (cb_tree x, const int i, unsigned int func_nolitcast)
43184318}
43194319
43204320
4321+
4322+ /* Use constant strings to replace string comparisons by more
4323+ * efficient pointer comparisons */
4324+ static const char * cob_prof_function_call_str = "cob_prof_function_call" ;
4325+
4326+ /* Allocate a procedure description record and add it at the end of
4327+ * the procedure_list of the current program. The index of the
4328+ * procedure will be the position in the list. There is an invariant
4329+ * that 0 is reserved for the record of the program module. */
4330+ static int
4331+ procedure_list_add (
4332+ struct cb_program * program ,
4333+ enum cob_prof_procedure_kind kind ,
4334+ const char * text ,
4335+ int section ,
4336+ const char * file ,
4337+ int line
4338+ )
4339+ {
4340+ struct cb_procedure_list * p ;
4341+ int ret = program -> procedure_list_len ;
4342+
4343+ p = cobc_main_malloc (sizeof (struct cb_procedure_list ));
4344+ if (text ){ p -> proc .text = cobc_main_strdup (text ); }
4345+ p -> proc .kind = kind ;
4346+ p -> proc .file = file ;
4347+ p -> proc .line = line ;
4348+ p -> proc .section = section ;
4349+ p -> next = NULL ;
4350+
4351+ if (program -> procedure_list == NULL ){
4352+ program -> procedure_list = p ;
4353+ } else {
4354+ program -> procedure_list_last -> next = p ;
4355+ }
4356+ program -> procedure_list_last = p ;
4357+
4358+ program -> procedure_list_len ++ ;
4359+ return ret ;
4360+ }
4361+
4362+ void
4363+ cb_prof_procedure_division (struct cb_program * program ,
4364+ const char * source_file ,
4365+ int source_line )
4366+ {
4367+ /* invariant: program always has index 0 */
4368+ procedure_list_add (
4369+ program ,
4370+ COB_PROF_PROCEDURE_MODULE ,
4371+ program -> program_id ,
4372+ 0 ,
4373+ source_file ,
4374+ source_line );
4375+ }
4376+
4377+ /* Returns a tree node for a funcall to one of the profiling
4378+ functions, with the index of the procedure as argument (and a second
4379+ argument for the entry point if meaningful). If the program, section
4380+ or paragraph are being entered for the first time, register them into
4381+ the procedure_list of the program.
4382+
4383+ To avoid lookups, the current section and current paragraph are kept
4384+ in the program record for immediate use when exiting.
4385+ */
4386+ cb_tree
4387+ cb_build_prof_call (enum cb_prof_call prof_call ,
4388+ struct cb_program * program ,
4389+ struct cb_label * section ,
4390+ struct cb_label * paragraph ,
4391+ const char * entry ,
4392+ cb_tree location )
4393+ {
4394+ const char * func_name = cob_prof_function_call_str ;
4395+ int func_arg1 ;
4396+ int func_arg2 = -1 ;
4397+
4398+ switch (prof_call ){
4399+
4400+ case COB_PROF_ENTER_SECTION :
4401+
4402+ /* allocate section record and remember current section */
4403+ program -> prof_current_section =
4404+ procedure_list_add (
4405+ program ,
4406+ COB_PROF_PROCEDURE_SECTION ,
4407+ section -> name ,
4408+ /* the current section will have
4409+ * procedure_list_list as index */
4410+ program -> procedure_list_len ,
4411+ section -> common .source_file ,
4412+ section -> common .source_line );
4413+ program -> prof_current_paragraph = -1 ;
4414+ func_arg1 = program -> prof_current_section ;
4415+ break ;
4416+
4417+ case COB_PROF_ENTER_PARAGRAPH :
4418+
4419+ /* allocate section record and remember current section */
4420+ program -> prof_current_paragraph =
4421+ procedure_list_add (
4422+ program ,
4423+ COB_PROF_PROCEDURE_PARAGRAPH ,
4424+ paragraph -> name ,
4425+ program -> prof_current_section ,
4426+ paragraph -> common .source_file ,
4427+ paragraph -> common .source_line );
4428+ func_arg1 = program -> prof_current_paragraph ;
4429+ break ;
4430+
4431+ /* In the case of an ENTRY statement, add code before
4432+ * to the falling-through paragraph to avoid
4433+ * re-registering the entry into the paragraph. */
4434+ case COB_PROF_STAYIN_PARAGRAPH :
4435+
4436+ func_arg1 = program -> prof_current_paragraph ;
4437+ break ;
4438+
4439+ case COB_PROF_USE_PARAGRAPH_ENTRY :
4440+
4441+ func_arg1 = program -> prof_current_paragraph ;
4442+ func_arg2 =
4443+ procedure_list_add (
4444+ program ,
4445+ COB_PROF_PROCEDURE_ENTRY ,
4446+ entry ,
4447+ /* section field of entry is in fact its paragraph */
4448+ program -> prof_current_paragraph ,
4449+ location -> source_file ,
4450+ location -> source_line );
4451+ break ;
4452+
4453+ case COB_PROF_EXIT_PARAGRAPH :
4454+
4455+ func_arg1 = program -> prof_current_paragraph ;
4456+ /* Do not reinitialize, because we may have several of these
4457+ EXIT_PARAGRAPH, for example at EXIT SECTION.
4458+ program->prof_current_paragraph = -1; */
4459+ break ;
4460+
4461+ case COB_PROF_EXIT_SECTION :
4462+
4463+ func_arg1 = program -> prof_current_section ;
4464+ /* reset current paragraph and section */
4465+ program -> prof_current_section = -1 ;
4466+ program -> prof_current_paragraph = -1 ;
4467+ break ;
4468+
4469+ case COB_PROF_ENTER_CALL :
4470+
4471+ /* allocate call record and remember current call */
4472+ program -> prof_current_call =
4473+ procedure_list_add (
4474+ program ,
4475+ COB_PROF_PROCEDURE_CALL ,
4476+ NULL ,
4477+ program -> prof_current_paragraph ,
4478+ paragraph -> common .source_file ,
4479+ paragraph -> common .source_line );
4480+ func_arg1 = program -> prof_current_call ;
4481+ break ;
4482+
4483+ case COB_PROF_EXIT_CALL :
4484+
4485+ /* We need to patch the last procedure to add the callee name and loc */
4486+ program -> procedure_list_last -> proc .text = cobc_main_strdup (entry );
4487+ program -> procedure_list_last -> proc .file = location -> source_file ;
4488+ program -> procedure_list_last -> proc .line = location -> source_line ;
4489+
4490+ func_arg1 = program -> prof_current_call ;
4491+ program -> prof_current_call = -1 ;
4492+ break ;
4493+
4494+ }
4495+ if (func_arg2 < 0 ){
4496+ return CB_BUILD_FUNCALL_2 (func_name , cb_int (prof_call ), cb_int (func_arg1 ));
4497+ }
4498+ return CB_BUILD_FUNCALL_3 (func_name , cb_int (prof_call ), cb_int (func_arg1 ), cb_int (func_arg2 ));
4499+ }
4500+
43214501static void
43224502output_funcall (cb_tree x )
43234503{
@@ -4333,6 +4513,55 @@ output_funcall (cb_tree x)
43334513 return ;
43344514 }
43354515
4516+ if ( cb_flag_prof && p -> name == cob_prof_function_call_str ) {
4517+
4518+ int proc_idx ;
4519+
4520+ switch ( CB_INTEGER (p -> argv [0 ])-> val ){
4521+
4522+ case COB_PROF_EXIT_PARAGRAPH :
4523+ proc_idx = CB_INTEGER (p -> argv [1 ])-> val ;
4524+ output ("cob_prof_exit_procedure (prof_info, %d)" , proc_idx );
4525+ break ;
4526+ case COB_PROF_ENTER_SECTION :
4527+ proc_idx = CB_INTEGER (p -> argv [1 ])-> val ;
4528+ output ("cob_prof_enter_section (prof_info, %d)" , proc_idx );
4529+ break ;
4530+ case COB_PROF_EXIT_SECTION :
4531+ proc_idx = CB_INTEGER (p -> argv [1 ])-> val ;
4532+ output ("cob_prof_exit_section (prof_info, %d)" , proc_idx );
4533+ break ;
4534+ case COB_PROF_ENTER_CALL :
4535+ proc_idx = CB_INTEGER (p -> argv [1 ])-> val ;
4536+ output ("cob_prof_enter_procedure (prof_info, %d)" , proc_idx );
4537+ break ;
4538+ case COB_PROF_EXIT_CALL :
4539+ proc_idx = CB_INTEGER (p -> argv [1 ])-> val ;
4540+ output ("cob_prof_exit_procedure (prof_info, %d)" , proc_idx );
4541+ break ;
4542+ case COB_PROF_ENTER_PARAGRAPH :
4543+ proc_idx = CB_INTEGER (p -> argv [1 ])-> val ;
4544+ output ("cob_prof_enter_procedure (prof_info, %d);\n" , proc_idx );
4545+ output (" cob_prof_fallthrough_entry = 0" );
4546+ break ;
4547+ case COB_PROF_USE_PARAGRAPH_ENTRY : {
4548+ int paragraph_idx = CB_INTEGER (p -> argv [1 ])-> val ;
4549+ int entry_idx = CB_INTEGER (p -> argv [2 ])-> val ;
4550+ output ("if (!cob_prof_fallthrough_entry){\n" );
4551+ output ("\tcob_prof_use_paragraph_entry (prof_info, %d, %d);\n" ,
4552+ paragraph_idx , entry_idx );
4553+ output (" }\n" );
4554+ output (" cob_prof_fallthrough_entry = 0" );
4555+ break ;
4556+ }
4557+ case COB_PROF_STAYIN_PARAGRAPH :
4558+ output ("cob_prof_fallthrough_entry = 1" );
4559+ break ;
4560+ }
4561+ return ;
4562+ }
4563+
4564+
43364565 screenptr = p -> screenptr ;
43374566 output ("%s (" , p -> name );
43384567 for (i = 0 ; i < p -> argc ; i ++ ) {
@@ -7925,6 +8154,13 @@ output_goto (struct cb_goto *p)
79258154 struct cb_field * f ;
79268155 int i ;
79278156
8157+ if (cb_flag_prof ) {
8158+ /* Output this only if we are exiting the paragraph... */
8159+ if ( !(p -> flags & CB_GOTO_FLAG_SAME_PARAGRAPH ) ){
8160+ output_line ("cob_prof_goto (prof_info);" );
8161+ }
8162+ }
8163+
79288164 i = 1 ;
79298165 if (p -> depending ) {
79308166 /* Check for debugging on the DEPENDING item */
@@ -12206,6 +12442,19 @@ output_internal_function (struct cb_program *prog, cb_tree parameter_list)
1220612442
1220712443 /* Entry dispatch */
1220812444 output_line ("/* Entry dispatch */" );
12445+ if (cb_flag_prof ) {
12446+ output_line ("if (!prof_info) {" );
12447+ output_line (
12448+ "\tprof_info = cob_prof_init_module (module, prof_procedures, %d);" ,
12449+ prog -> procedure_list_len );
12450+ output_line ("}" );
12451+
12452+ /* Prevent CANCEL from dlclose() the module, because
12453+ we keep pointers to static data there. */
12454+ output_line ("if (prof_info){ module->flag_no_phys_canc = 1; }" );
12455+
12456+ output_line ("cob_prof_enter_procedure (prof_info, 0);" );
12457+ }
1220912458 if (cb_flag_stack_extended ) {
1221012459 /* entry marker = first frameptr is the one with
1221112460 an empty (instead of NULL) section name */ ;
@@ -12300,7 +12549,9 @@ output_internal_function (struct cb_program *prog, cb_tree parameter_list)
1230012549 output_newline ();
1230112550 }
1230212551 }
12303-
12552+ if (cb_flag_prof ){
12553+ output_line ("cob_prof_exit_procedure (prof_info, 0);" );
12554+ }
1230412555 if (!prog -> flag_recursive ) {
1230512556 output_line ("/* Decrement module active count */" );
1230612557 output_line ("if (module->module_active) {" );
@@ -13629,6 +13880,45 @@ output_header (const char *locbuff, const struct cb_program *cp)
1362913880 }
1363013881}
1363113882
13883+ static void
13884+ output_cob_prof_data ( struct cb_program * program )
13885+ {
13886+ if (cb_flag_prof ) {
13887+ struct cb_procedure_list * l ;
13888+ char sep = ' ' ;
13889+
13890+ output_local ("/* cob_prof data */\n\n" );
13891+
13892+ output_local ("static const int nprocedures = %d;\n" ,
13893+ program -> procedure_list_len );
13894+ output_local ("static struct cob_prof_procedure prof_procedures[%d] = {\n" ,
13895+ program -> procedure_list_len );
13896+ sep = ' ' ;
13897+ for (l = program -> procedure_list ; l ; l = l -> next ) {
13898+ output_local (" %c { \"%s\", \"%s\", %d, %d, %d }\n" ,
13899+ sep ,
13900+ l -> proc .text ,
13901+ l -> proc .file ,
13902+ l -> proc .line ,
13903+ l -> proc .section ,
13904+ l -> proc .kind
13905+ );
13906+ sep = ',' ;
13907+ }
13908+ output_local ("};\n" );
13909+
13910+ output_local ("static int cob_prof_fallthrough_entry = 0;\n" );
13911+ output_local ("static struct cob_prof_module *prof_info;\n" );
13912+
13913+ output_local ("\n/* End of cob_prof data */\n" );
13914+
13915+ program -> procedure_list = NULL ;
13916+ program -> procedure_list_len = 0 ;
13917+ program -> prof_current_section = -1 ;
13918+ program -> prof_current_paragraph = -1 ;
13919+ }
13920+ }
13921+
1363213922void
1363313923codegen (struct cb_program * prog , const char * translate_name )
1363413924{
@@ -13904,6 +14194,7 @@ codegen_internal (struct cb_program *prog, const int subsequent_call)
1390414194
1390514195 output_local_base_cache ();
1390614196 output_local_field_cache (prog );
14197+ output_cob_prof_data (prog );
1390714198
1390814199 /* Report data fields */
1390914200 if (prog -> report_storage ) {
0 commit comments