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

Bug: FTG inserts code inside an #ifdef .. #endif if it is placed at the end of the declarative region #12

Closed
vectorflux opened this issue May 25, 2018 · 5 comments
Assignees

Comments

@vectorflux
Copy link

vectorflux commented May 25, 2018

FTG 2.3.0 and 2.3.1 both insert the ftg initialization incorrectly in the following code:

Original code:

#ifdef _OPENACC
    REAL(wp), DIMENSION(:,:,:),   POINTER  :: vn_tmp, w_tmp
    REAL(vp), DIMENSION(:,:,:),   POINTER  :: vt_tmp, vn_ie_tmp
    REAL(vp), DIMENSION(:,:,:),   POINTER  :: w_concorr_c_tmp
    REAL(vp), DIMENSION(:,:,:,:), POINTER  :: ddt_vn_adv_tmp
    REAL(vp), DIMENSION(:,:,:,:), POINTER  :: ddt_w_adv_tmp
#endif
    !--------------------------------------------------------------------------

    IF (timers_level > 5) CALL timer_start(timer_solve_nh_veltend)
     :

FTG generated:

#ifdef _OPENACC
    REAL(wp), DIMENSION(:,:,:),   POINTER  :: vn_tmp, w_tmp
    REAL(vp), DIMENSION(:,:,:),   POINTER  :: vt_tmp, vn_ie_tmp
    REAL(vp), DIMENSION(:,:,:),   POINTER  :: w_concorr_c_tmp
    REAL(vp), DIMENSION(:,:,:,:), POINTER  :: ddt_vn_adv_tmp
    REAL(vp), DIMENSION(:,:,:,:), POINTER  :: ddt_w_adv_tmp

  ! ================= BEGIN FORTRAN TEST GENERATOR (FTG) =======================

  ftg_velocity_tendencies_round = ftg_velocity_tendencies_round + 1
  CALL ftg_velocity_tendencies_capture_input(p_prog, p_patch, p_int, p_metrics, p_diag, z_w_concorr_me, z_kin_hor_e, z_vt_ie, &
  &  ntnd, istep, lvn_only, dtime)

  ! ================= END FORTRAN TEST GENERATOR (FTG) =========================

#endif
    !--------------------------------------------------------------------------

    IF (timers_level > 5) CALL timer_start(timer_solve_nh_veltend)
     :

This means that the input was not being captured, despite all my head-scratching...

@chovyy
Copy link
Member

chovyy commented May 28, 2018

Thanks for reporting. This issue should be present with all FTG and Serialbox2 versions, since I have never made any attempt to take care of preprocessor directives for the code generation and left it to the user to shift the generated lines if needed.
But since this seems to be quite annoying, I will see if there is an easy solution for this.

@vectorflux
Copy link
Author

Yes, it happens in all the FTG versions I've tried. But it is no big deal, now that I know to look for it -- it was only annoying in that the first time it took a while to discover. That said, it would probably be quite easy to avoid with a Boolean to notice if one is in an #ifdef at the declaration/executable boundary of the subroutine FTG is applied to.

@chovyy
Copy link
Member

chovyy commented Jun 13, 2018

I have just closed #11 which is duplicate to this one.

@chovyy
Copy link
Member

chovyy commented Jun 13, 2018

The whole thing is bit tricky. Currently, FTG puts the capture-input code directly after the last variable declaration, like this:

SUBROUTINE example(arg)
   INTEGER, INTENT(in) :: arg
#ifdef __SWITCH__
   LOGIGAL :: whatever
#endif

  CALL do_something()

becomes

SUBROUTINE example(arg)
   INTEGER, INTENT(in) :: arg
#ifdef __SWITCH__
   LOGIGAL :: whatever

! ================= BEGIN FORTRAN TEST GENERATOR (FTG) =======================

ftg_example_round = ftg_example_round + 1
CALL ftg_example_capture_input(arg)

! ================= END FORTRAN TEST GENERATOR (FTG) =========================

#endif

  CALL do_something()

I could change it to not put it after the last declaration, but before the first statement, which in most cases should be the same. But then, we have a similar issue:

SUBROUTINE example(arg)
   INTEGER, INTENT(in) :: arg

#ifdef __SWITCH__
  CALL do_sometimes()
#endif

became:

SUBROUTINE example(arg)
   INTEGER, INTENT(in) :: arg

#ifdef __SWITCH__

! ================= BEGIN FORTRAN TEST GENERATOR (FTG) =======================

ftg_example_round = ftg_example_round + 1
CALL ftg_example_capture_input(arg)

! ================= END FORTRAN TEST GENERATOR (FTG) =========================

  CALL do_sometimes()
#endif

Another solution would be to search specifically for #endif directives following the last specification and then put the input code just after the last one found. I think, this would be the best way, but also no solution for cases like that:

SUBROUTINE example(arg)
   INTEGER, INTENT(in) :: arg
#ifdef __SWITCH__
  LOGIGAL :: whatever

  CALL do_sometimes()
#endif

In general, there is no common solution for the preprocessor problem which can also occur at every other location where code is inserted and I would still say that FTG generally ignores it, so one has to fix problems either manually or let FTG work with the already preprocessed code. But for this specific case, where one or more #endifs directly follow the last variable declaration, I will try to build a solution.

@chovyy
Copy link
Member

chovyy commented Jun 13, 2018

Fixed in v1.5.0.

@chovyy chovyy closed this as completed Jun 13, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants