v4 / vlib / v / gen / c / autofree_labeled_continue_codegen_test.v
216 lines · 203 sloc · 7.96 KB · 1a2d0e5b70d6dd1baaa60290f2446e9ece4324bf
Raw
1import os
2
3const vroot = os.dir(@VEXE)
4const test_vexe = os.quoted_path(@VEXE)
5const autofree_labeled_continue_testdata = os.join_path(vroot,
6 'vlib/v/tests/autofree_labeled_continue_scope_test.v')
7
8fn function_window(source string, signature string) string {
9 start := source.index(signature) or { return '' }
10 mut depth := 0
11 for i := start; i < source.len; i++ {
12 if source[i] == `{` {
13 depth++
14 } else if source[i] == `}` {
15 depth--
16 if depth == 0 {
17 return source[start..i + 1]
18 }
19 }
20 }
21 return source[start..]
22}
23
24fn test_labeled_loop_cleanup_codegen_order() {
25 cmd := '${test_vexe} -autofree -o - ${os.quoted_path(autofree_labeled_continue_testdata)}'
26 res := os.execute(cmd)
27 assert res.exit_code == 0, '${cmd}\n${res.output}'
28 generated := res.output
29
30 fallthrough_fn := function_window(generated,
31 'void main__labeled_fallthrough_cleanup_order(void) {')
32 inner_free_pos := fallthrough_fn.index('main__Tracked_free(&inner);') or {
33 assert false, fallthrough_fn
34 return
35 }
36 after_inner := fallthrough_fn[inner_free_pos..]
37 defer_pos := after_inner.index('main__push_event(7 + target.id - 1);') or {
38 assert false, fallthrough_fn
39 return
40 }
41 free_pos := after_inner.index('main__Tracked_free(&target);') or {
42 assert false, fallthrough_fn
43 return
44 }
45 assert defer_pos < free_pos
46
47 labeled_break_fn := function_window(generated, 'void main__labeled_break_cleanup_order(void) {')
48 labeled_break_goto_pos := labeled_break_fn.index('goto break_outer__break;') or {
49 assert false, labeled_break_fn
50 return
51 }
52 labeled_break_inner_defer_pos := labeled_break_fn.index('main__push_event(9);') or {
53 assert false, labeled_break_fn
54 return
55 }
56 labeled_break_inner_free_pos := labeled_break_fn.index('main__Tracked_free(&inner);') or {
57 assert false, labeled_break_fn
58 return
59 }
60 labeled_break_middle_defer_pos := labeled_break_fn.index('main__push_event(8);') or {
61 assert false, labeled_break_fn
62 return
63 }
64 labeled_break_middle_free_pos := labeled_break_fn.index('main__Tracked_free(&middle);') or {
65 assert false, labeled_break_fn
66 return
67 }
68 labeled_break_target_defer_pos := labeled_break_fn.index('main__push_event(7);') or {
69 assert false, labeled_break_fn
70 return
71 }
72 labeled_break_target_free_pos := labeled_break_fn.index('main__Tracked_free(&target);') or {
73 assert false, labeled_break_fn
74 return
75 }
76 assert labeled_break_inner_defer_pos < labeled_break_inner_free_pos
77 assert labeled_break_inner_free_pos < labeled_break_middle_defer_pos
78 assert labeled_break_middle_defer_pos < labeled_break_middle_free_pos
79 assert labeled_break_middle_free_pos < labeled_break_target_defer_pos
80 assert labeled_break_target_defer_pos < labeled_break_target_free_pos
81 assert labeled_break_target_free_pos < labeled_break_goto_pos
82
83 break_fn := function_window(generated, 'void main__for_c_labeled_break(void) {')
84 break_label_pos := break_fn.index('outer__break: {}') or {
85 assert false, break_fn
86 return
87 }
88 init_free_pos := break_fn.index('main__Tracked_free(&init);') or {
89 assert false, break_fn
90 return
91 }
92 assert break_label_pos < init_free_pos
93
94 nested_continue_fn := function_window(generated,
95 'void main__for_c_nested_continue_outer_init_cleanup(void) {')
96 nested_continue_body_free_pos := nested_continue_fn.index('main__Tracked_free(&body);') or {
97 assert false, nested_continue_fn
98 return
99 }
100 nested_continue_inner_free_pos := nested_continue_fn.index('main__Tracked_free(&inner_init);') or {
101 assert false, nested_continue_fn
102 return
103 }
104 nested_continue_goto_pos := nested_continue_fn.index('goto outer__continue_entry;') or {
105 assert false, nested_continue_fn
106 return
107 }
108 nested_continue_after_goto := nested_continue_fn[nested_continue_goto_pos..]
109 nested_continue_before_goto := nested_continue_fn[..nested_continue_goto_pos]
110 nested_continue_outer_free_after_goto_pos := nested_continue_after_goto.index('main__Tracked_free(&outer_init);') or {
111 assert false, nested_continue_fn
112 return
113 }
114 assert nested_continue_body_free_pos < nested_continue_inner_free_pos
115 assert nested_continue_inner_free_pos < nested_continue_goto_pos
116 assert !nested_continue_before_goto.contains('main__Tracked_free(&outer_init);')
117 assert nested_continue_outer_free_after_goto_pos > 0
118
119 nested_break_fn := function_window(generated,
120 'void main__for_c_nested_break_outer_init_cleanup(void) {')
121 nested_break_body_free_pos := nested_break_fn.index('main__Tracked_free(&body);') or {
122 assert false, nested_break_fn
123 return
124 }
125 nested_break_inner_free_pos := nested_break_fn.index('main__Tracked_free(&inner_init);') or {
126 assert false, nested_break_fn
127 return
128 }
129 nested_break_goto_pos := nested_break_fn.index('goto break_outer__break;') or {
130 assert false, nested_break_fn
131 return
132 }
133 nested_break_after_goto := nested_break_fn[nested_break_goto_pos..]
134 nested_break_before_goto := nested_break_fn[..nested_break_goto_pos]
135 nested_break_outer_free_after_goto_pos := nested_break_after_goto.index('main__Tracked_free(&outer_init);') or {
136 assert false, nested_break_fn
137 return
138 }
139 assert nested_break_body_free_pos < nested_break_inner_free_pos
140 assert nested_break_inner_free_pos < nested_break_goto_pos
141 assert !nested_break_before_goto.contains('main__Tracked_free(&outer_init);')
142 assert nested_break_outer_free_after_goto_pos > 0
143
144 return_second_fn := function_window(generated,
145 'main__Tracked main__for_c_multi_init_return_second(void) {')
146 return_pos := return_second_fn.index('return ') or {
147 assert false, return_second_fn
148 return
149 }
150 body_free_pos := return_second_fn.index('main__Tracked_free(&body);') or {
151 assert false, return_second_fn
152 return
153 }
154 first_free_pos := return_second_fn.index('main__Tracked_free(&first);') or {
155 assert false, return_second_fn
156 return
157 }
158 assert body_free_pos < return_pos
159 assert first_free_pos < return_pos
160 if second_free_pos := return_second_fn.index('main__Tracked_free(&second);') {
161 assert return_pos < second_free_pos
162 }
163
164 return_field_fn := function_window(generated,
165 'string main__for_c_return_init_field_string(void) {')
166 return_field_return_pos := return_field_fn.index('return ') or {
167 assert false, return_field_fn
168 return
169 }
170 return_field_return_path := return_field_fn[..return_field_return_pos]
171 assert !return_field_return_path.contains('main__Holder_free(&init);')
172 assert !return_field_return_path.contains('builtin__string_free(&(init.label));')
173 assert !return_field_fn.contains('builtin__string_free(&(init.other));')
174
175 return_alias_field_fn := function_window(generated,
176 'main__Label main__for_c_return_init_field_alias_string(void) {')
177 return_alias_field_return_pos := return_alias_field_fn.index('return ') or {
178 assert false, return_alias_field_fn
179 return
180 }
181 return_alias_field_return_path := return_alias_field_fn[..return_alias_field_return_pos]
182 assert !return_alias_field_return_path.contains('main__AliasHolder_free(&init);')
183 assert !return_alias_field_return_path.contains('builtin__string_free(&(init.label));')
184 assert !return_alias_field_fn.contains('builtin__string_free(&(init.other));')
185
186 return_id_fn := function_window(generated, 'int main__for_c_return_init_field_id(void) {')
187 return_id_holder_free_pos := return_id_fn.index('main__Holder_free(&init);') or {
188 assert false, return_id_fn
189 return
190 }
191 return_id_return_pos := return_id_fn.index('return ') or {
192 assert false, return_id_fn
193 return
194 }
195 assert return_id_holder_free_pos < return_id_return_pos
196
197 branch_body_fn := function_window(generated,
198 'main__Tracked main__for_c_branch_return_body_after_init_path(bool cond) {')
199 body_decl_pos := branch_body_fn.index('main__Tracked body = main__tracked(5);') or {
200 assert false, branch_body_fn
201 return
202 }
203 body_return_path := branch_body_fn[body_decl_pos..]
204 branch_body_return_pos := body_return_path.index('return ') or {
205 assert false, branch_body_fn
206 return
207 }
208 branch_init_free_pos := body_return_path.index('main__Tracked_free(&init);') or {
209 assert false, branch_body_fn
210 return
211 }
212 assert branch_init_free_pos < branch_body_return_pos
213 if branch_body_free_pos := body_return_path.index('main__Tracked_free(&body);') {
214 assert branch_body_return_pos < branch_body_free_pos
215 }
216}
217