1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
|
/* This caches information that we determine about function params,
their uses and copies in the coroutine frame. */
struct param_info
{
tree field_id; /* The name of the copy in the coroutine frame. */
tree copy_var; /* The local var proxy for the frame copy. */
vec<tree *> *body_uses; /* Worklist of uses, void if there are none. */
tree frame_type; /* The type used to represent this parm in the frame. */
tree orig_type; /* The original type of the parm (not as passed). */
tree guard_var; /* If we need a DTOR on exception, this bool guards it. */
tree fr_copy_dtor; /* If we need a DTOR on exception, this is it. */
bool by_ref; /* Was passed by reference. */
bool pt_ref; /* Was a pointer to object. */
bool rv_ref; /* Was an rvalue ref. */
bool trivial_dtor; /* The frame type has a trivial DTOR. */
bool this_ptr; /* Is 'this' */
bool lambda_cobj; /* Lambda capture object */
};
/* Suspend point hash_map. */
struct suspend_point_info
{
/* coro frame field type. */
tree awaitable_type;
/* coro frame field name. */
tree await_field_id;
};
/* This data set is used when analyzing statements for await expressions. */
struct susp_frame_data
{
/* Function-wide. */
tree fs_label; /* The destination for co_returns. */
hash_map<tree, suspend_point_info> *suspend_points; /* Not owned. */
vec<tree, va_gc> *block_stack; /* Track block scopes. */
vec<tree, va_gc> *bind_stack; /* Track current bind expr. */
unsigned await_number = 0; /* Which await in the function. */
unsigned cond_number = 0; /* Which replaced condition in the fn. */
/* Temporary values for one statement or expression being analyzed. */
/* The set of TRUTH exprs to expand. */
hash_set<tree> *truth_aoif_to_expand = nullptr;
/* Count of awaits in this statement */
unsigned saw_awaits = 0;
/* This expr captures temps by ref. */
bool captures_temporary = false;
/* We must expand a truth_if expression. */
bool needs_truth_if_exp = false;
/* We must handle initializing an awaiter. */
bool has_awaiter_init = false;
susp_frame_data (tree _final_susp, hash_map<tree, suspend_point_info> *_spt)
: fs_label (_final_susp), suspend_points (_spt)
{
block_stack = make_tree_vector ();
bind_stack = make_tree_vector ();
}
};
struct local_var_info
{
tree field_id;
tree field_idx;
tree frame_type;
bool is_lambda_capture;
bool is_static;
bool has_value_expr_p;
location_t def_loc;
};
/* For recording local variable usage. */
struct local_vars_frame_data
{
tree *field_list;
hash_map<tree, local_var_info> *local_var_uses;
unsigned int nest_depth = 0;
unsigned int bind_indx = 0;
location_t loc = UNKNOWN_LOCATION;
bool saw_capture = false;
bool local_var_seen = false;
local_vars_frame_data (tree *_fl, hash_map<tree, local_var_info> *_lvu)
: field_list (_fl), local_var_uses (_lvu) {}
};
class cp_coroutine_transform {
public:
cp_coroutine_transform (tree, bool);
~cp_coroutine_transform ();
bool cp_valid_coroutine () const { return valid_coroutine; }
void apply_transforms ();
void finish_transforms ();
tree get_resumer () { return resumer; }
tree get_destroyer () { return destroyer; }
private:
tree orig_fn_decl; /* The original function decl. */
tree orig_fn_body = NULL_TREE; /* The original function body. */
location_t fn_start = UNKNOWN_LOCATION;
tree resumer = error_mark_node;
tree destroyer = error_mark_node;
tree coroutine_body = NULL_TREE;
tree body_blocks = NULL_TREE;
/* Types for this coroutine. */
tree frame_type;
tree frame_ptr_type;
tree act_des_fn_type;
tree act_des_fn_ptr_type;
/* Cached information about the transformed function. */
tree resume_idx_var = NULL_TREE;
tree fs_label = NULL_TREE;
hash_map<tree, param_info> param_uses;
hash_map<tree, suspend_point_info> suspend_points;
hash_map<tree, local_var_info> local_var_uses;
vec<tree> param_dtor_list = vNULL;
tree frame_size = NULL_TREE;
unsigned int await_count = 0;
bool inline_p = false;
bool valid_coroutine = false;
void wrap_original_function_body ();
bool build_ramp_function ();
};
|