https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105989
--- Comment #2 from Michal Jankovič <michal.jankovic59 at gmail dot com> ---
Reading through gcc/cp/coroutines.cc, it seems like the coroutine frame is
indeed composed as a flat struct with fields for all the local variables,
temps, and special stuff needed by the actor. 

Relevant code:
coro_make_frame_entry - adds a field to the coro_frame_type structure.
register_local_var_uses - here coro_make_frame_entry is called for each local
variable.
morph_fn_to_coro - here the coro_frame_type structure definition is created
from the collected fields.

Comments in the code state that the mid-end should be able to optimize out
unused fields from this struct, which currently does not happen, but even if it
did, this does not solve the overlapping of variables.

I think that instead of a flat struct, the frontend should generate a structure
recursively composed of unions of structures, having a union for each disjunct
scope (including an implicit scope for expression temporaries).

Example:

task task_1() {
  {
    char a[128];
    co_await task_2();
  }
  {
    char b[128];
    co_await task_3(get_temporary());

    static awaiter awaiter_not_stored_in_frame;
    co_await awaiter_not_stored_in_frame;
  }
}

Currently, this generates a coro frame struct that looks something like this:
struct coro_frame {
  // builtin state ...
  char a[128];
  awaiter task_2_awaiter;
  char b[128];
  int get_temporary_result;
  awaiter task_3_awaiter;  
  awaiter* awaiter_not_stored_in_frame;
};

Instead, the frontend could generate something like this:
struct coro_frame {
  // builtin state ...
  union {
    struct {
      char a[128];
      awaiter task_2_awaiter;
    };
    struct {
      char b[128];
      union {
        struct { 
          int get_temporary_result;
          awaiter task_3_awaiter; 
        };
        struct { awaiter* awaiter_not_stored_in_frame; };
      };
    };
  };
};

Reply via email to