]>
Commit | Line | Data |
---|---|---|
e440a328 | 1 | // statements.h -- Go frontend statements. -*- C++ -*- |
2 | ||
3 | // Copyright 2009 The Go Authors. All rights reserved. | |
4 | // Use of this source code is governed by a BSD-style | |
5 | // license that can be found in the LICENSE file. | |
6 | ||
7 | #ifndef GO_STATEMENTS_H | |
8 | #define GO_STATEMENTS_H | |
9 | ||
10 | #include "operator.h" | |
11 | ||
12 | class Gogo; | |
13 | class Traverse; | |
ceeb4318 | 14 | class Statement_inserter; |
e440a328 | 15 | class Block; |
16 | class Function; | |
17 | class Unnamed_label; | |
9890f25f | 18 | class Export_function_body; |
8415f0dd | 19 | class Import_function_body; |
da244e59 | 20 | class Assignment_statement; |
e440a328 | 21 | class Temporary_statement; |
22 | class Variable_declaration_statement; | |
f8bdf81a | 23 | class Expression_statement; |
85b13700 | 24 | class Block_statement; |
e440a328 | 25 | class Return_statement; |
26 | class Thunk_statement; | |
85b13700 | 27 | class Goto_statement; |
28 | class Goto_unnamed_statement; | |
e440a328 | 29 | class Label_statement; |
85b13700 | 30 | class Unnamed_label_statement; |
da244e59 | 31 | class If_statement; |
e440a328 | 32 | class For_statement; |
33 | class For_range_statement; | |
34 | class Switch_statement; | |
35 | class Type_switch_statement; | |
74cfc2e4 | 36 | class Send_statement; |
e440a328 | 37 | class Select_statement; |
38 | class Variable; | |
39 | class Named_object; | |
40 | class Label; | |
41 | class Translate_context; | |
42 | class Expression; | |
43 | class Expression_list; | |
44 | class Struct_type; | |
45 | class Call_expression; | |
46 | class Map_index_expression; | |
47 | class Receive_expression; | |
48 | class Case_clauses; | |
49 | class Type_case_clauses; | |
50 | class Select_clauses; | |
51 | class Typed_identifier_list; | |
8259743a | 52 | class Bexpression; |
53 | class Bstatement; | |
eefc1ed3 | 54 | class Bvariable; |
d751bb78 | 55 | class Ast_dump_context; |
e440a328 | 56 | |
57 | // This class is used to traverse assignments made by a statement | |
58 | // which makes assignments. | |
59 | ||
60 | class Traverse_assignments | |
61 | { | |
62 | public: | |
63 | Traverse_assignments() | |
64 | { } | |
65 | ||
66 | virtual ~Traverse_assignments() | |
67 | { } | |
68 | ||
69 | // This is called for a variable initialization. | |
70 | virtual void | |
71 | initialize_variable(Named_object*) = 0; | |
72 | ||
73 | // This is called for each assignment made by the statement. PLHS | |
74 | // points to the left hand side, and PRHS points to the right hand | |
75 | // side. PRHS may be NULL if there is no associated expression, as | |
76 | // in the bool set by a non-blocking receive. | |
77 | virtual void | |
78 | assignment(Expression** plhs, Expression** prhs) = 0; | |
79 | ||
80 | // This is called for each expression which is not passed to the | |
81 | // assignment function. This is used for some of the statements | |
82 | // which assign two values, for which there is no expression which | |
83 | // describes the value. For ++ and -- the value is passed to both | |
84 | // the assignment method and the rhs method. IS_STORED is true if | |
85 | // this value is being stored directly. It is false if the value is | |
86 | // computed but not stored. IS_LOCAL is true if the value is being | |
87 | // stored in a local variable or this is being called by a return | |
88 | // statement. | |
89 | virtual void | |
90 | value(Expression**, bool is_stored, bool is_local) = 0; | |
91 | }; | |
92 | ||
93 | // A single statement. | |
94 | ||
95 | class Statement | |
96 | { | |
97 | public: | |
98 | // The types of statements. | |
99 | enum Statement_classification | |
100 | { | |
101 | STATEMENT_ERROR, | |
102 | STATEMENT_VARIABLE_DECLARATION, | |
103 | STATEMENT_TEMPORARY, | |
104 | STATEMENT_ASSIGNMENT, | |
105 | STATEMENT_EXPRESSION, | |
106 | STATEMENT_BLOCK, | |
107 | STATEMENT_GO, | |
108 | STATEMENT_DEFER, | |
109 | STATEMENT_RETURN, | |
110 | STATEMENT_BREAK_OR_CONTINUE, | |
111 | STATEMENT_GOTO, | |
112 | STATEMENT_GOTO_UNNAMED, | |
113 | STATEMENT_LABEL, | |
114 | STATEMENT_UNNAMED_LABEL, | |
115 | STATEMENT_IF, | |
116 | STATEMENT_CONSTANT_SWITCH, | |
74cfc2e4 | 117 | STATEMENT_SEND, |
e440a328 | 118 | STATEMENT_SELECT, |
119 | ||
120 | // These statements types are created by the parser, but they | |
121 | // disappear during the lowering pass. | |
122 | STATEMENT_ASSIGNMENT_OPERATION, | |
123 | STATEMENT_TUPLE_ASSIGNMENT, | |
124 | STATEMENT_TUPLE_MAP_ASSIGNMENT, | |
e440a328 | 125 | STATEMENT_TUPLE_RECEIVE_ASSIGNMENT, |
126 | STATEMENT_TUPLE_TYPE_GUARD_ASSIGNMENT, | |
127 | STATEMENT_INCDEC, | |
128 | STATEMENT_FOR, | |
129 | STATEMENT_FOR_RANGE, | |
130 | STATEMENT_SWITCH, | |
131 | STATEMENT_TYPE_SWITCH | |
132 | }; | |
133 | ||
b13c66cd | 134 | Statement(Statement_classification, Location); |
e440a328 | 135 | |
136 | virtual ~Statement(); | |
137 | ||
138 | // Make a variable declaration. | |
139 | static Statement* | |
140 | make_variable_declaration(Named_object*); | |
141 | ||
142 | // Make a statement which creates a temporary variable and | |
143 | // initializes it to an expression. The block is used if the | |
144 | // temporary variable has to be explicitly destroyed; the variable | |
145 | // must still be added to the block. References to the temporary | |
146 | // variable may be constructed using make_temporary_reference. | |
147 | // Either the type or the initialization expression may be NULL, but | |
148 | // not both. | |
149 | static Temporary_statement* | |
b13c66cd | 150 | make_temporary(Type*, Expression*, Location); |
e440a328 | 151 | |
152 | // Make an assignment statement. | |
d3c55148 | 153 | static Assignment_statement* |
b13c66cd | 154 | make_assignment(Expression*, Expression*, Location); |
e440a328 | 155 | |
156 | // Make an assignment operation (+=, etc.). | |
157 | static Statement* | |
158 | make_assignment_operation(Operator, Expression*, Expression*, | |
b13c66cd | 159 | Location); |
e440a328 | 160 | |
161 | // Make a tuple assignment statement. | |
162 | static Statement* | |
b13c66cd | 163 | make_tuple_assignment(Expression_list*, Expression_list*, Location); |
e440a328 | 164 | |
165 | // Make an assignment from a map index to a pair of variables. | |
166 | static Statement* | |
167 | make_tuple_map_assignment(Expression* val, Expression* present, | |
b13c66cd | 168 | Expression*, Location); |
e440a328 | 169 | |
e440a328 | 170 | // Make an assignment from a nonblocking receive to a pair of |
f24f10bb | 171 | // variables. |
e440a328 | 172 | static Statement* |
66a133bf | 173 | make_tuple_receive_assignment(Expression* val, Expression* closed, |
f24f10bb | 174 | Expression* channel, Location); |
e440a328 | 175 | |
176 | // Make an assignment from a type guard to a pair of variables. | |
177 | static Statement* | |
178 | make_tuple_type_guard_assignment(Expression* val, Expression* ok, | |
179 | Expression* expr, Type* type, | |
b13c66cd | 180 | Location); |
e440a328 | 181 | |
a7549a6a | 182 | // Make an expression statement from an Expression. IS_IGNORED is |
183 | // true if the value is being explicitly ignored, as in an | |
184 | // assignment to _. | |
e440a328 | 185 | static Statement* |
a7549a6a | 186 | make_statement(Expression*, bool is_ignored); |
e440a328 | 187 | |
188 | // Make a block statement from a Block. This is an embedded list of | |
189 | // statements which may also include variable definitions. | |
1a82e1c1 | 190 | static Block_statement* |
b13c66cd | 191 | make_block_statement(Block*, Location); |
e440a328 | 192 | |
193 | // Make an increment statement. | |
194 | static Statement* | |
195 | make_inc_statement(Expression*); | |
196 | ||
197 | // Make a decrement statement. | |
198 | static Statement* | |
199 | make_dec_statement(Expression*); | |
200 | ||
201 | // Make a go statement. | |
202 | static Statement* | |
b13c66cd | 203 | make_go_statement(Call_expression* call, Location); |
e440a328 | 204 | |
205 | // Make a defer statement. | |
206 | static Statement* | |
b13c66cd | 207 | make_defer_statement(Call_expression* call, Location); |
e440a328 | 208 | |
209 | // Make a return statement. | |
a4f79468 | 210 | static Return_statement* |
b13c66cd | 211 | make_return_statement(Expression_list*, Location); |
e440a328 | 212 | |
0afbb937 | 213 | // Make a statement that returns the result of a call expression. |
214 | // If the call does not return any results, this just returns the | |
215 | // call expression as a statement, assuming that the function will | |
216 | // end immediately afterward. | |
217 | static Statement* | |
218 | make_return_from_call(Call_expression*, Location); | |
219 | ||
e440a328 | 220 | // Make a break statement. |
221 | static Statement* | |
b13c66cd | 222 | make_break_statement(Unnamed_label* label, Location); |
e440a328 | 223 | |
224 | // Make a continue statement. | |
225 | static Statement* | |
b13c66cd | 226 | make_continue_statement(Unnamed_label* label, Location); |
e440a328 | 227 | |
228 | // Make a goto statement. | |
229 | static Statement* | |
b13c66cd | 230 | make_goto_statement(Label* label, Location); |
e440a328 | 231 | |
232 | // Make a goto statement to an unnamed label. | |
233 | static Statement* | |
b13c66cd | 234 | make_goto_unnamed_statement(Unnamed_label* label, Location); |
e440a328 | 235 | |
236 | // Make a label statement--where the label is defined. | |
237 | static Statement* | |
b13c66cd | 238 | make_label_statement(Label* label, Location); |
e440a328 | 239 | |
240 | // Make an unnamed label statement--where the label is defined. | |
241 | static Statement* | |
242 | make_unnamed_label_statement(Unnamed_label* label); | |
243 | ||
244 | // Make an if statement. | |
245 | static Statement* | |
246 | make_if_statement(Expression* cond, Block* then_block, Block* else_block, | |
b13c66cd | 247 | Location); |
e440a328 | 248 | |
249 | // Make a switch statement. | |
250 | static Switch_statement* | |
b13c66cd | 251 | make_switch_statement(Expression* switch_val, Location); |
e440a328 | 252 | |
253 | // Make a type switch statement. | |
254 | static Type_switch_statement* | |
cc0446ba | 255 | make_type_switch_statement(const std::string&, Expression*, Location); |
e440a328 | 256 | |
74cfc2e4 | 257 | // Make a send statement. |
258 | static Send_statement* | |
b13c66cd | 259 | make_send_statement(Expression* channel, Expression* val, Location); |
74cfc2e4 | 260 | |
e440a328 | 261 | // Make a select statement. |
262 | static Select_statement* | |
b13c66cd | 263 | make_select_statement(Location); |
e440a328 | 264 | |
265 | // Make a for statement. | |
266 | static For_statement* | |
267 | make_for_statement(Block* init, Expression* cond, Block* post, | |
b13c66cd | 268 | Location location); |
e440a328 | 269 | |
270 | // Make a for statement with a range clause. | |
271 | static For_range_statement* | |
272 | make_for_range_statement(Expression* index_var, Expression* value_var, | |
b13c66cd | 273 | Expression* range, Location); |
e440a328 | 274 | |
275 | // Return the statement classification. | |
276 | Statement_classification | |
277 | classification() const | |
278 | { return this->classification_; } | |
279 | ||
280 | // Get the statement location. | |
b13c66cd | 281 | Location |
e440a328 | 282 | location() const |
283 | { return this->location_; } | |
284 | ||
285 | // Traverse the tree. | |
286 | int | |
287 | traverse(Block*, size_t* index, Traverse*); | |
288 | ||
289 | // Traverse the contents of this statement--the expressions and | |
290 | // statements which it contains. | |
291 | int | |
292 | traverse_contents(Traverse*); | |
293 | ||
294 | // If this statement assigns some values, it calls a function for | |
295 | // each value to which this statement assigns a value, and returns | |
296 | // true. If this statement does not assign any values, it returns | |
297 | // false. | |
298 | bool | |
299 | traverse_assignments(Traverse_assignments* tassign); | |
300 | ||
301 | // Lower a statement. This is called immediately after parsing to | |
302 | // simplify statements for further processing. It returns the same | |
66a133bf | 303 | // Statement or a new one. FUNCTION is the function containing this |
304 | // statement. BLOCK is the block containing this statement. | |
ceeb4318 | 305 | // INSERTER can be used to insert new statements before this one. |
e440a328 | 306 | Statement* |
ceeb4318 | 307 | lower(Gogo* gogo, Named_object* function, Block* block, |
308 | Statement_inserter* inserter) | |
309 | { return this->do_lower(gogo, function, block, inserter); } | |
e440a328 | 310 | |
3515aad4 | 311 | // Flatten a statement. This is called immediately after the order of |
312 | // evaluation rules are applied to statements. It returns the same | |
313 | // Statement or a new one. FUNCTION is the function containing this | |
314 | // statement. BLOCK is the block containing this statement. | |
315 | // INSERTER can be used to insert new statements before this one. | |
316 | Statement* | |
317 | flatten(Gogo* gogo, Named_object* function, Block* block, | |
318 | Statement_inserter* inserter) | |
319 | { return this->do_flatten(gogo, function, block, inserter); } | |
320 | ||
e440a328 | 321 | // Set type information for unnamed constants. |
322 | void | |
323 | determine_types(); | |
324 | ||
325 | // Check types in a statement. This simply checks that any | |
326 | // expressions used by the statement have the right type. | |
327 | void | |
328 | check_types(Gogo* gogo) | |
329 | { this->do_check_types(gogo); } | |
330 | ||
9890f25f | 331 | // Return the cost of this statement for inlining purposes. |
332 | int | |
333 | inlining_cost() | |
334 | { return this->do_inlining_cost(); } | |
335 | ||
8415f0dd | 336 | // Export data for this statement to BODY. |
9890f25f | 337 | void |
338 | export_statement(Export_function_body* efb) | |
339 | { this->do_export_statement(efb); } | |
340 | ||
e007b1eb | 341 | // Make implicit type conversions explicit. |
342 | void | |
343 | add_conversions() | |
344 | { this->do_add_conversions(); } | |
345 | ||
9b92780c | 346 | // Read a statement from export data. The location should be used |
347 | // for the returned statement. Errors should be reported using the | |
348 | // Import_function_body's location method. | |
81affb1d | 349 | static Statement* |
350 | import_statement(Import_function_body*, Location); | |
351 | ||
e440a328 | 352 | // Return whether this is a block statement. |
353 | bool | |
354 | is_block_statement() const | |
355 | { return this->classification_ == STATEMENT_BLOCK; } | |
356 | ||
da244e59 | 357 | // If this is an assignment statement, return it. Otherwise return |
358 | // NULL. | |
359 | Assignment_statement* | |
360 | assignment_statement() | |
361 | { | |
362 | return this->convert<Assignment_statement, STATEMENT_ASSIGNMENT>(); | |
363 | } | |
364 | ||
365 | // If this is an temporary statement, return it. Otherwise return | |
366 | // NULL. | |
367 | Temporary_statement* | |
368 | temporary_statement() | |
369 | { | |
370 | return this->convert<Temporary_statement, STATEMENT_TEMPORARY>(); | |
371 | } | |
372 | ||
e440a328 | 373 | // If this is a variable declaration statement, return it. |
374 | // Otherwise return NULL. | |
375 | Variable_declaration_statement* | |
376 | variable_declaration_statement() | |
377 | { | |
378 | return this->convert<Variable_declaration_statement, | |
379 | STATEMENT_VARIABLE_DECLARATION>(); | |
380 | } | |
381 | ||
f8bdf81a | 382 | // If this is an expression statement, return it. Otherwise return |
383 | // NULL. | |
384 | Expression_statement* | |
385 | expression_statement() | |
386 | { | |
387 | return this->convert<Expression_statement, STATEMENT_EXPRESSION>(); | |
388 | } | |
389 | ||
85b13700 | 390 | // If this is an block statement, return it. Otherwise return |
391 | // NULL. | |
392 | Block_statement* | |
393 | block_statement() | |
394 | { return this->convert<Block_statement, STATEMENT_BLOCK>(); } | |
395 | ||
e440a328 | 396 | // If this is a return statement, return it. Otherwise return NULL. |
397 | Return_statement* | |
398 | return_statement() | |
399 | { return this->convert<Return_statement, STATEMENT_RETURN>(); } | |
400 | ||
401 | // If this is a thunk statement (a go or defer statement), return | |
402 | // it. Otherwise return NULL. | |
403 | Thunk_statement* | |
404 | thunk_statement(); | |
405 | ||
85b13700 | 406 | // If this is a goto statement, return it. Otherwise return NULL. |
407 | Goto_statement* | |
408 | goto_statement() | |
409 | { return this->convert<Goto_statement, STATEMENT_GOTO>(); } | |
410 | ||
411 | // If this is a goto_unnamed statement, return it. Otherwise return NULL. | |
412 | Goto_unnamed_statement* | |
413 | goto_unnamed_statement() | |
414 | { return this->convert<Goto_unnamed_statement, STATEMENT_GOTO_UNNAMED>(); } | |
415 | ||
e440a328 | 416 | // If this is a label statement, return it. Otherwise return NULL. |
417 | Label_statement* | |
418 | label_statement() | |
419 | { return this->convert<Label_statement, STATEMENT_LABEL>(); } | |
420 | ||
85b13700 | 421 | // If this is an unnamed_label statement, return it. Otherwise return NULL. |
422 | Unnamed_label_statement* | |
423 | unnamed_label_statement() | |
424 | { return this->convert<Unnamed_label_statement, STATEMENT_UNNAMED_LABEL>(); } | |
425 | ||
da244e59 | 426 | // If this is an if statement, return it. Otherwise return NULL. |
427 | If_statement* | |
428 | if_statement() | |
429 | { return this->convert<If_statement, STATEMENT_IF>(); } | |
430 | ||
e440a328 | 431 | // If this is a for statement, return it. Otherwise return NULL. |
432 | For_statement* | |
433 | for_statement() | |
434 | { return this->convert<For_statement, STATEMENT_FOR>(); } | |
435 | ||
436 | // If this is a for statement over a range clause, return it. | |
437 | // Otherwise return NULL. | |
438 | For_range_statement* | |
439 | for_range_statement() | |
440 | { return this->convert<For_range_statement, STATEMENT_FOR_RANGE>(); } | |
441 | ||
442 | // If this is a switch statement, return it. Otherwise return NULL. | |
443 | Switch_statement* | |
444 | switch_statement() | |
445 | { return this->convert<Switch_statement, STATEMENT_SWITCH>(); } | |
446 | ||
447 | // If this is a type switch statement, return it. Otherwise return | |
448 | // NULL. | |
449 | Type_switch_statement* | |
450 | type_switch_statement() | |
451 | { return this->convert<Type_switch_statement, STATEMENT_TYPE_SWITCH>(); } | |
452 | ||
da244e59 | 453 | // If this is a send statement, return it. Otherwise return NULL. |
454 | Send_statement* | |
455 | send_statement() | |
456 | { return this->convert<Send_statement, STATEMENT_SEND>(); } | |
457 | ||
e440a328 | 458 | // If this is a select statement, return it. Otherwise return NULL. |
459 | Select_statement* | |
460 | select_statement() | |
461 | { return this->convert<Select_statement, STATEMENT_SELECT>(); } | |
462 | ||
463 | // Return true if this statement may fall through--if after | |
464 | // executing this statement we may go on to execute the following | |
465 | // statement, if any. | |
466 | bool | |
467 | may_fall_through() const | |
468 | { return this->do_may_fall_through(); } | |
469 | ||
4cf30692 | 470 | // Convert the statement to the backend representation. |
471 | Bstatement* | |
472 | get_backend(Translate_context*); | |
e440a328 | 473 | |
d751bb78 | 474 | // Dump AST representation of a statement to a dump context. |
475 | void | |
476 | dump_statement(Ast_dump_context*) const; | |
477 | ||
e440a328 | 478 | protected: |
479 | // Implemented by child class: traverse the tree. | |
480 | virtual int | |
481 | do_traverse(Traverse*) = 0; | |
482 | ||
483 | // Implemented by child class: traverse assignments. Any statement | |
484 | // which includes an assignment should implement this. | |
485 | virtual bool | |
486 | do_traverse_assignments(Traverse_assignments*) | |
487 | { return false; } | |
488 | ||
489 | // Implemented by the child class: lower this statement to a simpler | |
490 | // one. | |
491 | virtual Statement* | |
ceeb4318 | 492 | do_lower(Gogo*, Named_object*, Block*, Statement_inserter*) |
e440a328 | 493 | { return this; } |
494 | ||
3515aad4 | 495 | // Implemented by the child class: lower this statement to a simpler |
496 | // one. | |
497 | virtual Statement* | |
498 | do_flatten(Gogo*, Named_object*, Block*, Statement_inserter*) | |
499 | { return this; } | |
500 | ||
e440a328 | 501 | // Implemented by child class: set type information for unnamed |
502 | // constants. Any statement which includes an expression needs to | |
503 | // implement this. | |
504 | virtual void | |
505 | do_determine_types() | |
506 | { } | |
507 | ||
508 | // Implemented by child class: check types of expressions used in a | |
509 | // statement. | |
510 | virtual void | |
511 | do_check_types(Gogo*) | |
512 | { } | |
513 | ||
9890f25f | 514 | // Implemented by child class: return the cost of this statement for |
515 | // inlining. The default cost is high, so we only need to define | |
516 | // this method for statements that can be inlined. | |
517 | virtual int | |
518 | do_inlining_cost() | |
519 | { return 0x100000; } | |
520 | ||
521 | // Implemented by child class: write export data for this statement | |
8415f0dd | 522 | // to the string. This need only be implemented by classes that |
523 | // implement do_inlining_cost with a reasonable value. | |
9890f25f | 524 | virtual void |
525 | do_export_statement(Export_function_body*) | |
526 | { go_unreachable(); } | |
527 | ||
e440a328 | 528 | // Implemented by child class: return true if this statement may |
529 | // fall through. | |
530 | virtual bool | |
531 | do_may_fall_through() const | |
532 | { return true; } | |
533 | ||
4cf30692 | 534 | // Implemented by child class: convert to backend representation. |
535 | virtual Bstatement* | |
536 | do_get_backend(Translate_context*) = 0; | |
e440a328 | 537 | |
d751bb78 | 538 | // Implemented by child class: dump ast representation. |
539 | virtual void | |
540 | do_dump_statement(Ast_dump_context*) const = 0; | |
541 | ||
e007b1eb | 542 | // Implemented by child class: make implicit conversions explicit. |
543 | virtual void | |
544 | do_add_conversions() | |
545 | { } | |
546 | ||
e440a328 | 547 | // Traverse an expression in a statement. |
548 | int | |
549 | traverse_expression(Traverse*, Expression**); | |
550 | ||
551 | // Traverse an expression list in a statement. The Expression_list | |
552 | // may be NULL. | |
553 | int | |
554 | traverse_expression_list(Traverse*, Expression_list*); | |
555 | ||
556 | // Traverse a type in a statement. | |
557 | int | |
558 | traverse_type(Traverse*, Type*); | |
559 | ||
e440a328 | 560 | // For children to call when they detect that they are in error. |
561 | void | |
562 | set_is_error(); | |
563 | ||
564 | // For children to call to report an error conveniently. | |
565 | void | |
566 | report_error(const char*); | |
567 | ||
568 | // For children to return an error statement from lower(). | |
569 | static Statement* | |
b13c66cd | 570 | make_error_statement(Location); |
e440a328 | 571 | |
572 | private: | |
573 | // Convert to the desired statement classification, or return NULL. | |
574 | // This is a controlled dynamic cast. | |
575 | template<typename Statement_class, Statement_classification sc> | |
576 | Statement_class* | |
577 | convert() | |
578 | { | |
579 | return (this->classification_ == sc | |
580 | ? static_cast<Statement_class*>(this) | |
581 | : NULL); | |
582 | } | |
583 | ||
584 | template<typename Statement_class, Statement_classification sc> | |
585 | const Statement_class* | |
586 | convert() const | |
587 | { | |
588 | return (this->classification_ == sc | |
589 | ? static_cast<const Statement_class*>(this) | |
590 | : NULL); | |
591 | } | |
592 | ||
593 | // The statement classification. | |
594 | Statement_classification classification_; | |
595 | // The location in the input file of the start of this statement. | |
b13c66cd | 596 | Location location_; |
e440a328 | 597 | }; |
598 | ||
da244e59 | 599 | // An assignment statement. |
600 | ||
601 | class Assignment_statement : public Statement | |
602 | { | |
603 | public: | |
604 | Assignment_statement(Expression* lhs, Expression* rhs, | |
605 | Location location) | |
606 | : Statement(STATEMENT_ASSIGNMENT, location), | |
d3c55148 | 607 | lhs_(lhs), rhs_(rhs), omit_write_barrier_(false) |
da244e59 | 608 | { } |
609 | ||
610 | Expression* | |
611 | lhs() const | |
612 | { return this->lhs_; } | |
613 | ||
614 | Expression* | |
615 | rhs() const | |
616 | { return this->rhs_; } | |
617 | ||
d3c55148 | 618 | bool |
619 | omit_write_barrier() const | |
620 | { return this->omit_write_barrier_; } | |
621 | ||
622 | void | |
623 | set_omit_write_barrier() | |
624 | { this->omit_write_barrier_ = true; } | |
625 | ||
da244e59 | 626 | protected: |
627 | int | |
628 | do_traverse(Traverse* traverse); | |
629 | ||
630 | bool | |
631 | do_traverse_assignments(Traverse_assignments*); | |
632 | ||
0d5530d9 | 633 | virtual Statement* |
634 | do_lower(Gogo*, Named_object*, Block*, Statement_inserter*); | |
635 | ||
da244e59 | 636 | void |
637 | do_determine_types(); | |
638 | ||
639 | void | |
640 | do_check_types(Gogo*); | |
641 | ||
5f6f5357 | 642 | int |
643 | do_inlining_cost() | |
644 | { return 1; } | |
645 | ||
646 | void | |
647 | do_export_statement(Export_function_body*); | |
648 | ||
da244e59 | 649 | Statement* |
650 | do_flatten(Gogo*, Named_object*, Block*, Statement_inserter*); | |
651 | ||
652 | Bstatement* | |
653 | do_get_backend(Translate_context*); | |
654 | ||
655 | void | |
656 | do_dump_statement(Ast_dump_context*) const; | |
657 | ||
e007b1eb | 658 | void |
659 | do_add_conversions(); | |
660 | ||
da244e59 | 661 | private: |
662 | // Left hand side--the lvalue. | |
663 | Expression* lhs_; | |
664 | // Right hand side--the rvalue. | |
665 | Expression* rhs_; | |
d3c55148 | 666 | // True if we can omit a write barrier from this assignment. |
667 | bool omit_write_barrier_; | |
da244e59 | 668 | }; |
669 | ||
e440a328 | 670 | // A statement which creates and initializes a temporary variable. |
671 | ||
672 | class Temporary_statement : public Statement | |
673 | { | |
674 | public: | |
b13c66cd | 675 | Temporary_statement(Type* type, Expression* init, Location location) |
e440a328 | 676 | : Statement(STATEMENT_TEMPORARY, location), |
86a71ed0 | 677 | type_(type), init_(init), bvariable_(NULL), is_address_taken_(false), |
38ba9eec | 678 | value_escapes_(false), assigned_(false), uses_(0) |
e440a328 | 679 | { } |
680 | ||
681 | // Return the type of the temporary variable. | |
682 | Type* | |
683 | type() const; | |
684 | ||
a4a43c62 | 685 | // Return the initializer if there is one. |
686 | Expression* | |
687 | init() const | |
688 | { return this->init_; } | |
689 | ||
38ba9eec | 690 | // Set the initializer. |
691 | void | |
692 | set_init(Expression* expr) | |
693 | { this->init_ = expr; } | |
694 | ||
695 | // Whether something takes the address of this temporary | |
696 | // variable. | |
697 | bool | |
698 | is_address_taken() | |
699 | { return this->is_address_taken_; } | |
700 | ||
e440a328 | 701 | // Record that something takes the address of this temporary |
702 | // variable. | |
703 | void | |
704 | set_is_address_taken() | |
705 | { this->is_address_taken_ = true; } | |
706 | ||
86a71ed0 | 707 | // Whether the value escapes. |
708 | bool | |
709 | value_escapes() const | |
710 | { return this->value_escapes_; } | |
711 | ||
712 | // Record that the value escapes. | |
713 | void | |
714 | set_value_escapes() | |
715 | { this->value_escapes_ = true; } | |
716 | ||
38ba9eec | 717 | // Whether this temporary variable is assigned (after initialization). |
718 | bool | |
719 | assigned() | |
720 | { return this->assigned_; } | |
721 | ||
722 | // Record that this temporary variable is assigned. | |
723 | void | |
724 | set_assigned() | |
725 | { this->assigned_ = true; } | |
726 | ||
727 | // Number of uses of this temporary variable. | |
728 | int | |
729 | uses() | |
730 | { return this->uses_; } | |
731 | ||
732 | // Add one use of this temporary variable. | |
733 | void | |
734 | add_use() | |
735 | { this->uses_++; } | |
736 | ||
eefc1ed3 | 737 | // Return the temporary variable. This should not be called until |
738 | // after the statement itself has been converted. | |
739 | Bvariable* | |
740 | get_backend_variable(Translate_context*) const; | |
e440a328 | 741 | |
f6492beb | 742 | // Import the declaration of a temporary. |
743 | static Statement* | |
744 | do_import(Import_function_body*, Location); | |
745 | ||
e440a328 | 746 | protected: |
747 | int | |
748 | do_traverse(Traverse*); | |
749 | ||
750 | bool | |
751 | do_traverse_assignments(Traverse_assignments*); | |
752 | ||
753 | void | |
754 | do_determine_types(); | |
755 | ||
756 | void | |
757 | do_check_types(Gogo*); | |
758 | ||
f6492beb | 759 | int |
760 | do_inlining_cost() | |
761 | { return 1; } | |
762 | ||
763 | void | |
764 | do_export_statement(Export_function_body*); | |
765 | ||
16cb7fec | 766 | Statement* |
767 | do_flatten(Gogo*, Named_object*, Block*, Statement_inserter*); | |
768 | ||
4cf30692 | 769 | Bstatement* |
770 | do_get_backend(Translate_context*); | |
e440a328 | 771 | |
d751bb78 | 772 | void |
773 | do_dump_statement(Ast_dump_context*) const; | |
774 | ||
e007b1eb | 775 | void |
776 | do_add_conversions(); | |
777 | ||
e440a328 | 778 | private: |
779 | // The type of the temporary variable. | |
780 | Type* type_; | |
781 | // The initial value of the temporary variable. This may be NULL. | |
782 | Expression* init_; | |
eefc1ed3 | 783 | // The backend representation of the temporary variable. |
784 | Bvariable* bvariable_; | |
e440a328 | 785 | // True if something takes the address of this temporary variable. |
786 | bool is_address_taken_; | |
86a71ed0 | 787 | // True if the value assigned to this temporary variable escapes. |
788 | // This is used for select statements. | |
789 | bool value_escapes_; | |
38ba9eec | 790 | // True if this temporary variable is assigned (after initialization). |
791 | bool assigned_; | |
792 | // Number of uses of this temporary variable. | |
793 | int uses_; | |
e440a328 | 794 | }; |
795 | ||
796 | // A variable declaration. This marks the point in the code where a | |
797 | // variable is declared. The Variable is also attached to a Block. | |
798 | ||
799 | class Variable_declaration_statement : public Statement | |
800 | { | |
801 | public: | |
802 | Variable_declaration_statement(Named_object* var); | |
803 | ||
804 | // The variable being declared. | |
805 | Named_object* | |
806 | var() | |
807 | { return this->var_; } | |
808 | ||
8415f0dd | 809 | // Import a variable declaration. |
810 | static Statement* | |
811 | do_import(Import_function_body*, Location); | |
812 | ||
e440a328 | 813 | protected: |
814 | int | |
815 | do_traverse(Traverse*); | |
816 | ||
817 | bool | |
818 | do_traverse_assignments(Traverse_assignments*); | |
819 | ||
ceeb4318 | 820 | Statement* |
821 | do_lower(Gogo*, Named_object*, Block*, Statement_inserter*); | |
822 | ||
8415f0dd | 823 | int |
824 | do_inlining_cost() | |
825 | { return 1; } | |
826 | ||
827 | void | |
828 | do_export_statement(Export_function_body*); | |
829 | ||
3515aad4 | 830 | Statement* |
831 | do_flatten(Gogo*, Named_object*, Block*, Statement_inserter*); | |
832 | ||
4cf30692 | 833 | Bstatement* |
834 | do_get_backend(Translate_context*); | |
e440a328 | 835 | |
d751bb78 | 836 | void |
837 | do_dump_statement(Ast_dump_context*) const; | |
838 | ||
e007b1eb | 839 | void |
840 | do_add_conversions(); | |
841 | ||
e440a328 | 842 | private: |
843 | Named_object* var_; | |
844 | }; | |
845 | ||
846 | // A return statement. | |
847 | ||
848 | class Return_statement : public Statement | |
849 | { | |
850 | public: | |
b13c66cd | 851 | Return_statement(Expression_list* vals, Location location) |
e440a328 | 852 | : Statement(STATEMENT_RETURN, location), |
1eae365b | 853 | vals_(vals), is_lowered_(false) |
e440a328 | 854 | { } |
855 | ||
856 | // The list of values being returned. This may be NULL. | |
857 | const Expression_list* | |
858 | vals() const | |
859 | { return this->vals_; } | |
860 | ||
861 | protected: | |
862 | int | |
863 | do_traverse(Traverse* traverse) | |
864 | { return this->traverse_expression_list(traverse, this->vals_); } | |
865 | ||
866 | bool | |
867 | do_traverse_assignments(Traverse_assignments*); | |
868 | ||
869 | Statement* | |
ceeb4318 | 870 | do_lower(Gogo*, Named_object*, Block*, Statement_inserter*); |
e440a328 | 871 | |
e440a328 | 872 | bool |
873 | do_may_fall_through() const | |
874 | { return false; } | |
875 | ||
5f6f5357 | 876 | int |
877 | do_inlining_cost() | |
878 | { return 1; } | |
879 | ||
880 | void | |
881 | do_export_statement(Export_function_body*); | |
882 | ||
4cf30692 | 883 | Bstatement* |
884 | do_get_backend(Translate_context*); | |
e440a328 | 885 | |
d751bb78 | 886 | void |
887 | do_dump_statement(Ast_dump_context*) const; | |
888 | ||
e440a328 | 889 | private: |
e440a328 | 890 | // Return values. This may be NULL. |
891 | Expression_list* vals_; | |
be2fc38d | 892 | // True if this statement has been lowered. |
893 | bool is_lowered_; | |
e440a328 | 894 | }; |
895 | ||
f8bdf81a | 896 | // An expression statement. |
897 | ||
898 | class Expression_statement : public Statement | |
899 | { | |
900 | public: | |
901 | Expression_statement(Expression* expr, bool is_ignored); | |
902 | ||
903 | Expression* | |
904 | expr() | |
905 | { return this->expr_; } | |
906 | ||
907 | protected: | |
908 | int | |
909 | do_traverse(Traverse* traverse) | |
910 | { return this->traverse_expression(traverse, &this->expr_); } | |
911 | ||
912 | void | |
913 | do_determine_types(); | |
914 | ||
915 | void | |
916 | do_check_types(Gogo*); | |
917 | ||
918 | bool | |
919 | do_may_fall_through() const; | |
920 | ||
921 | Bstatement* | |
922 | do_get_backend(Translate_context* context); | |
923 | ||
924 | void | |
925 | do_dump_statement(Ast_dump_context*) const; | |
926 | ||
927 | private: | |
928 | Expression* expr_; | |
929 | // Whether the value of this expression is being explicitly ignored. | |
930 | bool is_ignored_; | |
931 | }; | |
932 | ||
85b13700 | 933 | // A block statement--a list of statements which may include variable |
934 | // definitions. | |
935 | ||
936 | class Block_statement : public Statement | |
937 | { | |
938 | public: | |
939 | Block_statement(Block* block, Location location) | |
940 | : Statement(STATEMENT_BLOCK, location), | |
941 | block_(block), is_lowered_for_statement_(false) | |
942 | { } | |
943 | ||
9890f25f | 944 | // Return the actual block. |
945 | Block* | |
946 | block() const | |
947 | { return this->block_; } | |
948 | ||
85b13700 | 949 | void |
950 | set_is_lowered_for_statement() | |
951 | { this->is_lowered_for_statement_ = true; } | |
952 | ||
953 | bool | |
954 | is_lowered_for_statement() | |
955 | { return this->is_lowered_for_statement_; } | |
956 | ||
ff9c899b | 957 | // Export a block for a block statement. |
958 | static void | |
1a82e1c1 | 959 | export_block(Export_function_body*, Block*, bool is_lowered_for_statement); |
ff9c899b | 960 | |
961 | // Import a block statement, returning the block. | |
1a82e1c1 | 962 | // *IS_LOWERED_FOR_STATEMENT reports whether this block statement |
963 | // was lowered from a for statement. | |
ff9c899b | 964 | static Block* |
1a82e1c1 | 965 | do_import(Import_function_body*, Location, bool* is_lowered_for_statement); |
ff9c899b | 966 | |
85b13700 | 967 | protected: |
968 | int | |
969 | do_traverse(Traverse* traverse) | |
970 | { return this->block_->traverse(traverse); } | |
971 | ||
972 | void | |
973 | do_determine_types() | |
974 | { this->block_->determine_types(); } | |
975 | ||
9890f25f | 976 | int |
977 | do_inlining_cost() | |
978 | { return 0; } | |
979 | ||
980 | void | |
981 | do_export_statement(Export_function_body*); | |
982 | ||
85b13700 | 983 | bool |
984 | do_may_fall_through() const | |
985 | { return this->block_->may_fall_through(); } | |
986 | ||
987 | Bstatement* | |
988 | do_get_backend(Translate_context* context); | |
989 | ||
990 | void | |
991 | do_dump_statement(Ast_dump_context*) const; | |
992 | ||
993 | private: | |
994 | Block* block_; | |
995 | // True if this block statement represents a lowered for statement. | |
996 | bool is_lowered_for_statement_; | |
997 | }; | |
998 | ||
74cfc2e4 | 999 | // A send statement. |
1000 | ||
1001 | class Send_statement : public Statement | |
1002 | { | |
1003 | public: | |
1004 | Send_statement(Expression* channel, Expression* val, | |
b13c66cd | 1005 | Location location) |
74cfc2e4 | 1006 | : Statement(STATEMENT_SEND, location), |
f24f10bb | 1007 | channel_(channel), val_(val) |
74cfc2e4 | 1008 | { } |
1009 | ||
da244e59 | 1010 | Expression* |
1011 | channel() | |
86a71ed0 | 1012 | { return this->channel_; } |
da244e59 | 1013 | |
1014 | Expression* | |
1015 | val() | |
1016 | { return this->val_; } | |
1017 | ||
74cfc2e4 | 1018 | protected: |
1019 | int | |
1020 | do_traverse(Traverse* traverse); | |
1021 | ||
1022 | void | |
1023 | do_determine_types(); | |
1024 | ||
1025 | void | |
1026 | do_check_types(Gogo*); | |
1027 | ||
8ba8cc87 | 1028 | Statement* |
1029 | do_flatten(Gogo*, Named_object*, Block*, Statement_inserter*); | |
1030 | ||
4cf30692 | 1031 | Bstatement* |
1032 | do_get_backend(Translate_context*); | |
74cfc2e4 | 1033 | |
d751bb78 | 1034 | void |
1035 | do_dump_statement(Ast_dump_context*) const; | |
1036 | ||
e007b1eb | 1037 | void |
1038 | do_add_conversions(); | |
1039 | ||
74cfc2e4 | 1040 | private: |
1041 | // The channel on which to send the value. | |
1042 | Expression* channel_; | |
1043 | // The value to send. | |
1044 | Expression* val_; | |
74cfc2e4 | 1045 | }; |
1046 | ||
e440a328 | 1047 | // Select_clauses holds the clauses of a select statement. This is |
1048 | // built by the parser. | |
1049 | ||
1050 | class Select_clauses | |
1051 | { | |
1052 | public: | |
1053 | Select_clauses() | |
1054 | : clauses_() | |
1055 | { } | |
1056 | ||
1057 | // Add a new clause. IS_SEND is true if this is a send clause, | |
1058 | // false for a receive clause. For a send clause CHANNEL is the | |
1059 | // channel and VAL is the value to send. For a receive clause | |
66a133bf | 1060 | // CHANNEL is the channel, VAL is either NULL or a Var_expression |
1061 | // for the variable to set, and CLOSED is either NULL or a | |
1062 | // Var_expression to set to whether the channel is closed. If VAL | |
1063 | // is NULL, VAR may be a variable to be initialized with the | |
1064 | // received value, and CLOSEDVAR ma be a variable to be initialized | |
1065 | // with whether the channel is closed. IS_DEFAULT is true if this | |
1066 | // is the default clause. STATEMENTS is the list of statements to | |
1067 | // execute. | |
e440a328 | 1068 | void |
66a133bf | 1069 | add(bool is_send, Expression* channel, Expression* val, Expression* closed, |
1070 | Named_object* var, Named_object* closedvar, bool is_default, | |
b13c66cd | 1071 | Block* statements, Location location) |
e440a328 | 1072 | { |
e36a5ff5 | 1073 | this->clauses_.push_back(Select_clause(is_send, channel, val, closed, var, |
1074 | closedvar, is_default, statements, | |
1075 | location)); | |
e440a328 | 1076 | } |
1077 | ||
f24f10bb | 1078 | size_t |
1079 | size() const | |
1080 | { return this->clauses_.size(); } | |
1081 | ||
e440a328 | 1082 | // Traverse the select clauses. |
1083 | int | |
1084 | traverse(Traverse*); | |
1085 | ||
1086 | // Lower statements. | |
1087 | void | |
86a71ed0 | 1088 | lower(Gogo*, Named_object*, Block*, Temporary_statement*, |
1089 | Temporary_statement*); | |
e440a328 | 1090 | |
1091 | // Determine types. | |
1092 | void | |
1093 | determine_types(); | |
1094 | ||
f24f10bb | 1095 | // Check types. |
1096 | void | |
1097 | check_types(); | |
1098 | ||
e440a328 | 1099 | // Whether the select clauses may fall through to the statement |
1100 | // which follows the overall select statement. | |
1101 | bool | |
1102 | may_fall_through() const; | |
1103 | ||
de0e0814 | 1104 | // Convert to the backend representation. |
1105 | Bstatement* | |
86a71ed0 | 1106 | get_backend(Translate_context*, Temporary_statement* index, |
f24f10bb | 1107 | Unnamed_label* break_label, Location); |
e440a328 | 1108 | |
d751bb78 | 1109 | // Dump AST representation. |
1110 | void | |
1111 | dump_clauses(Ast_dump_context*) const; | |
1112 | ||
e440a328 | 1113 | private: |
1114 | // A single clause. | |
1115 | class Select_clause | |
1116 | { | |
1117 | public: | |
1118 | Select_clause() | |
66a133bf | 1119 | : channel_(NULL), val_(NULL), closed_(NULL), var_(NULL), |
1120 | closedvar_(NULL), statements_(NULL), is_send_(false), | |
1121 | is_default_(false) | |
e440a328 | 1122 | { } |
1123 | ||
e36a5ff5 | 1124 | Select_clause(bool is_send, Expression* channel, Expression* val, |
1125 | Expression* closed, Named_object* var, | |
66a133bf | 1126 | Named_object* closedvar, bool is_default, Block* statements, |
b13c66cd | 1127 | Location location) |
e36a5ff5 | 1128 | : channel_(channel), val_(val), closed_(closed), var_(var), |
1129 | closedvar_(closedvar), statements_(statements), location_(location), | |
1130 | is_send_(is_send), is_default_(is_default), is_lowered_(false) | |
c484d925 | 1131 | { go_assert(is_default ? channel == NULL : channel != NULL); } |
e440a328 | 1132 | |
1133 | // Traverse the select clause. | |
1134 | int | |
1135 | traverse(Traverse*); | |
1136 | ||
1137 | // Lower statements. | |
1138 | void | |
86a71ed0 | 1139 | lower(Gogo*, Named_object*, Block*, Temporary_statement*, size_t, |
1140 | Temporary_statement*); | |
e440a328 | 1141 | |
1142 | // Determine types. | |
1143 | void | |
1144 | determine_types(); | |
1145 | ||
f24f10bb | 1146 | // Check types. |
1147 | void | |
1148 | check_types(); | |
1149 | ||
e440a328 | 1150 | // Return true if this is the default clause. |
1151 | bool | |
1152 | is_default() const | |
1153 | { return this->is_default_; } | |
1154 | ||
1155 | // Return the channel. This will return NULL for the default | |
1156 | // clause. | |
1157 | Expression* | |
1158 | channel() const | |
1159 | { return this->channel_; } | |
1160 | ||
e440a328 | 1161 | // Return true for a send, false for a receive. |
1162 | bool | |
1163 | is_send() const | |
1164 | { | |
c484d925 | 1165 | go_assert(!this->is_default_); |
e440a328 | 1166 | return this->is_send_; |
1167 | } | |
1168 | ||
1169 | // Return the statements. | |
1170 | const Block* | |
1171 | statements() const | |
1172 | { return this->statements_; } | |
1173 | ||
1174 | // Return the location. | |
b13c66cd | 1175 | Location |
e440a328 | 1176 | location() const |
1177 | { return this->location_; } | |
1178 | ||
1179 | // Whether this clause may fall through to the statement which | |
1180 | // follows the overall select statement. | |
1181 | bool | |
1182 | may_fall_through() const; | |
1183 | ||
519a82cb | 1184 | // Convert the statements to the backend representation. |
de0e0814 | 1185 | Bstatement* |
1186 | get_statements_backend(Translate_context*); | |
e440a328 | 1187 | |
d751bb78 | 1188 | // Dump AST representation. |
1189 | void | |
1190 | dump_clause(Ast_dump_context*) const; | |
1191 | ||
e440a328 | 1192 | private: |
86a71ed0 | 1193 | // These values must match the values in libgo/go/runtime/select.go. |
1194 | enum | |
1195 | { | |
1196 | caseRecv = 1, | |
1197 | caseSend = 2, | |
1198 | caseDefault = 3, | |
1199 | }; | |
1200 | ||
f24f10bb | 1201 | void |
e36a5ff5 | 1202 | lower_default(Block*, Expression*); |
f24f10bb | 1203 | |
1204 | void | |
e36a5ff5 | 1205 | lower_send(Block*, Expression*, Expression*); |
f24f10bb | 1206 | |
1207 | void | |
86a71ed0 | 1208 | lower_recv(Gogo*, Named_object*, Block*, Expression*, Expression*, |
1209 | Temporary_statement*); | |
1210 | ||
1211 | void | |
1212 | set_case(Block*, Expression*, Expression*, Expression*, int); | |
f24f10bb | 1213 | |
e440a328 | 1214 | // The channel. |
1215 | Expression* channel_; | |
66a133bf | 1216 | // The value to send or the lvalue to receive into. |
e440a328 | 1217 | Expression* val_; |
66a133bf | 1218 | // The lvalue to set to whether the channel is closed on a |
1219 | // receive. | |
1220 | Expression* closed_; | |
1221 | // The variable to initialize, for "case a := <-ch". | |
e440a328 | 1222 | Named_object* var_; |
66a133bf | 1223 | // The variable to initialize to whether the channel is closed, |
1224 | // for "case a, c := <-ch". | |
1225 | Named_object* closedvar_; | |
e440a328 | 1226 | // The statements to execute. |
1227 | Block* statements_; | |
1228 | // The location of this clause. | |
b13c66cd | 1229 | Location location_; |
e440a328 | 1230 | // Whether this is a send or a receive. |
1231 | bool is_send_; | |
1232 | // Whether this is the default. | |
1233 | bool is_default_; | |
1234 | // Whether this has been lowered. | |
1235 | bool is_lowered_; | |
1236 | }; | |
1237 | ||
e440a328 | 1238 | typedef std::vector<Select_clause> Clauses; |
1239 | ||
1240 | Clauses clauses_; | |
1241 | }; | |
1242 | ||
1243 | // A select statement. | |
1244 | ||
1245 | class Select_statement : public Statement | |
1246 | { | |
1247 | public: | |
b13c66cd | 1248 | Select_statement(Location location) |
e440a328 | 1249 | : Statement(STATEMENT_SELECT, location), |
86a71ed0 | 1250 | clauses_(NULL), index_(NULL), break_label_(NULL), is_lowered_(false) |
e440a328 | 1251 | { } |
1252 | ||
1253 | // Add the clauses. | |
1254 | void | |
1255 | add_clauses(Select_clauses* clauses) | |
1256 | { | |
c484d925 | 1257 | go_assert(this->clauses_ == NULL); |
e440a328 | 1258 | this->clauses_ = clauses; |
1259 | } | |
1260 | ||
1261 | // Return the break label for this select statement. | |
1262 | Unnamed_label* | |
1263 | break_label(); | |
1264 | ||
1265 | protected: | |
1266 | int | |
1267 | do_traverse(Traverse* traverse) | |
1268 | { return this->clauses_->traverse(traverse); } | |
1269 | ||
1270 | Statement* | |
ceeb4318 | 1271 | do_lower(Gogo*, Named_object*, Block*, Statement_inserter*); |
e440a328 | 1272 | |
1273 | void | |
1274 | do_determine_types() | |
1275 | { this->clauses_->determine_types(); } | |
1276 | ||
f24f10bb | 1277 | void |
1278 | do_check_types(Gogo*) | |
1279 | { this->clauses_->check_types(); } | |
1280 | ||
e440a328 | 1281 | bool |
270f533c | 1282 | do_may_fall_through() const; |
e440a328 | 1283 | |
4cf30692 | 1284 | Bstatement* |
1285 | do_get_backend(Translate_context*); | |
e440a328 | 1286 | |
d751bb78 | 1287 | void |
1288 | do_dump_statement(Ast_dump_context*) const; | |
1289 | ||
e440a328 | 1290 | private: |
1291 | // The select clauses. | |
1292 | Select_clauses* clauses_; | |
86a71ed0 | 1293 | // A temporary that holds the index value returned by selectgo. |
1294 | Temporary_statement* index_; | |
e440a328 | 1295 | // The break label. |
1296 | Unnamed_label* break_label_; | |
1297 | // Whether this statement has been lowered. | |
1298 | bool is_lowered_; | |
1299 | }; | |
1300 | ||
1301 | // A statement which requires a thunk: go or defer. | |
1302 | ||
1303 | class Thunk_statement : public Statement | |
1304 | { | |
1305 | public: | |
1306 | Thunk_statement(Statement_classification, Call_expression*, | |
b13c66cd | 1307 | Location); |
e440a328 | 1308 | |
1309 | // Return the call expression. | |
1310 | Expression* | |
d751bb78 | 1311 | call() const |
e440a328 | 1312 | { return this->call_; } |
1313 | ||
1314 | // Simplify a go or defer statement so that it only uses a single | |
1315 | // parameter. | |
1316 | bool | |
ca51434e | 1317 | simplify_statement(Gogo*, Named_object*, Block*); |
e440a328 | 1318 | |
1319 | protected: | |
1320 | int | |
1321 | do_traverse(Traverse* traverse); | |
1322 | ||
1323 | bool | |
1324 | do_traverse_assignments(Traverse_assignments*); | |
1325 | ||
1326 | void | |
1327 | do_determine_types(); | |
1328 | ||
1329 | void | |
1330 | do_check_types(Gogo*); | |
1331 | ||
519a82cb | 1332 | // Return the function and argument for the call. |
ca51434e | 1333 | bool |
1334 | get_fn_and_arg(Expression** pfn, Expression** parg); | |
e440a328 | 1335 | |
1336 | private: | |
1337 | // Return whether this is a simple go statement. | |
1338 | bool | |
1339 | is_simple(Function_type*) const; | |
1340 | ||
e0659c9e | 1341 | // Return whether the thunk function is a constant. |
1342 | bool | |
1343 | is_constant_function() const; | |
1344 | ||
e440a328 | 1345 | // Build the struct to use for a complex case. |
1346 | Struct_type* | |
1347 | build_struct(Function_type* fntype); | |
1348 | ||
1349 | // Build the thunk. | |
1350 | void | |
e0659c9e | 1351 | build_thunk(Gogo*, const std::string&); |
e440a328 | 1352 | |
1353 | // Set the name to use for thunk field N. | |
1354 | void | |
1355 | thunk_field_param(int n, char* buf, size_t buflen); | |
1356 | ||
1357 | // The function call to be executed in a separate thread (go) or | |
1358 | // later (defer). | |
1359 | Expression* call_; | |
1360 | // The type used for a struct to pass to a thunk, if this is not a | |
1361 | // simple call. | |
1362 | Struct_type* struct_type_; | |
1363 | }; | |
1364 | ||
1365 | // A go statement. | |
1366 | ||
1367 | class Go_statement : public Thunk_statement | |
1368 | { | |
1369 | public: | |
b13c66cd | 1370 | Go_statement(Call_expression* call, Location location) |
e440a328 | 1371 | : Thunk_statement(STATEMENT_GO, call, location) |
1372 | { } | |
1373 | ||
1374 | protected: | |
4cf30692 | 1375 | Bstatement* |
1376 | do_get_backend(Translate_context*); | |
d751bb78 | 1377 | |
1378 | void | |
1379 | do_dump_statement(Ast_dump_context*) const; | |
e440a328 | 1380 | }; |
1381 | ||
1382 | // A defer statement. | |
1383 | ||
1384 | class Defer_statement : public Thunk_statement | |
1385 | { | |
1386 | public: | |
b13c66cd | 1387 | Defer_statement(Call_expression* call, Location location) |
e440a328 | 1388 | : Thunk_statement(STATEMENT_DEFER, call, location) |
1389 | { } | |
1390 | ||
1391 | protected: | |
4cf30692 | 1392 | Bstatement* |
1393 | do_get_backend(Translate_context*); | |
d751bb78 | 1394 | |
1395 | void | |
1396 | do_dump_statement(Ast_dump_context*) const; | |
e440a328 | 1397 | }; |
1398 | ||
85b13700 | 1399 | // A goto statement. |
1400 | ||
1401 | class Goto_statement : public Statement | |
1402 | { | |
1403 | public: | |
1404 | Goto_statement(Label* label, Location location) | |
1405 | : Statement(STATEMENT_GOTO, location), | |
1406 | label_(label) | |
1407 | { } | |
1408 | ||
1409 | // Return the label being jumped to. | |
1410 | Label* | |
1411 | label() const | |
1412 | { return this->label_; } | |
1413 | ||
1a82e1c1 | 1414 | // Import a goto statement. |
1415 | static Statement* | |
1416 | do_import(Import_function_body*, Location); | |
1417 | ||
85b13700 | 1418 | protected: |
1419 | int | |
1420 | do_traverse(Traverse*); | |
1421 | ||
1422 | void | |
1423 | do_check_types(Gogo*); | |
1424 | ||
1425 | bool | |
1426 | do_may_fall_through() const | |
1427 | { return false; } | |
1428 | ||
1429 | Bstatement* | |
1430 | do_get_backend(Translate_context*); | |
1431 | ||
1a82e1c1 | 1432 | int |
1433 | do_inlining_cost() | |
1434 | { return 5; } | |
1435 | ||
1436 | void | |
1437 | do_export_statement(Export_function_body*); | |
1438 | ||
85b13700 | 1439 | void |
1440 | do_dump_statement(Ast_dump_context*) const; | |
1441 | ||
1442 | private: | |
1443 | Label* label_; | |
1444 | }; | |
1445 | ||
1446 | // A goto statement to an unnamed label. | |
1447 | ||
1448 | class Goto_unnamed_statement : public Statement | |
1449 | { | |
1450 | public: | |
1451 | Goto_unnamed_statement(Unnamed_label* label, Location location) | |
1452 | : Statement(STATEMENT_GOTO_UNNAMED, location), | |
1453 | label_(label) | |
1454 | { } | |
1455 | ||
1456 | Unnamed_label* | |
1457 | unnamed_label() const | |
1458 | { return this->label_; } | |
1459 | ||
1460 | protected: | |
1461 | int | |
1462 | do_traverse(Traverse*); | |
1463 | ||
1464 | bool | |
1465 | do_may_fall_through() const | |
1466 | { return false; } | |
1467 | ||
1468 | Bstatement* | |
1469 | do_get_backend(Translate_context* context); | |
1470 | ||
1a82e1c1 | 1471 | int |
1472 | do_inlining_cost() | |
1473 | { return 5; } | |
1474 | ||
1475 | void | |
1476 | do_export_statement(Export_function_body*); | |
1477 | ||
85b13700 | 1478 | void |
1479 | do_dump_statement(Ast_dump_context*) const; | |
1480 | ||
1481 | private: | |
1482 | Unnamed_label* label_; | |
1483 | }; | |
1484 | ||
e440a328 | 1485 | // A label statement. |
1486 | ||
1487 | class Label_statement : public Statement | |
1488 | { | |
1489 | public: | |
b13c66cd | 1490 | Label_statement(Label* label, Location location) |
e440a328 | 1491 | : Statement(STATEMENT_LABEL, location), |
1492 | label_(label) | |
1493 | { } | |
1494 | ||
1495 | // Return the label itself. | |
85b13700 | 1496 | Label* |
e440a328 | 1497 | label() const |
1498 | { return this->label_; } | |
1499 | ||
1a82e1c1 | 1500 | // Import a label or unnamed label. |
1501 | static Statement* | |
1502 | do_import(Import_function_body*, Location); | |
1503 | ||
e440a328 | 1504 | protected: |
1505 | int | |
1506 | do_traverse(Traverse*); | |
1507 | ||
4cf30692 | 1508 | Bstatement* |
1509 | do_get_backend(Translate_context*); | |
e440a328 | 1510 | |
1a82e1c1 | 1511 | int |
1512 | do_inlining_cost() | |
1513 | { return 1; } | |
1514 | ||
1515 | void | |
1516 | do_export_statement(Export_function_body*); | |
1517 | ||
d751bb78 | 1518 | void |
1519 | do_dump_statement(Ast_dump_context*) const; | |
1520 | ||
e440a328 | 1521 | private: |
1522 | // The label. | |
1523 | Label* label_; | |
1524 | }; | |
1525 | ||
85b13700 | 1526 | // An unnamed label statement. |
1527 | ||
1528 | class Unnamed_label_statement : public Statement | |
1529 | { | |
1530 | public: | |
1531 | Unnamed_label_statement(Unnamed_label* label); | |
1532 | ||
1533 | protected: | |
1534 | int | |
1535 | do_traverse(Traverse*); | |
1536 | ||
1537 | Bstatement* | |
1538 | do_get_backend(Translate_context* context); | |
1539 | ||
1a82e1c1 | 1540 | int |
1541 | do_inlining_cost() | |
1542 | { return 1; } | |
1543 | ||
1544 | void | |
1545 | do_export_statement(Export_function_body*); | |
1546 | ||
85b13700 | 1547 | void |
1548 | do_dump_statement(Ast_dump_context*) const; | |
1549 | ||
1550 | private: | |
1551 | // The label. | |
1552 | Unnamed_label* label_; | |
1553 | }; | |
1554 | ||
da244e59 | 1555 | // An if statement. |
1556 | ||
1557 | class If_statement : public Statement | |
1558 | { | |
1559 | public: | |
1560 | If_statement(Expression* cond, Block* then_block, Block* else_block, | |
1561 | Location location) | |
1562 | : Statement(STATEMENT_IF, location), | |
1563 | cond_(cond), then_block_(then_block), else_block_(else_block) | |
1564 | { } | |
1565 | ||
1566 | Expression* | |
1567 | condition() const | |
1568 | { return this->cond_; } | |
1569 | ||
ac7ef97d | 1570 | Block* |
1571 | then_block() const | |
1572 | { return this->then_block_; } | |
1573 | ||
1574 | Block* | |
1575 | else_block() const | |
1576 | { return this->else_block_; } | |
1577 | ||
ff9c899b | 1578 | // Import an if statement. |
1579 | static Statement* | |
1580 | do_import(Import_function_body*, Location); | |
1581 | ||
da244e59 | 1582 | protected: |
1583 | int | |
1584 | do_traverse(Traverse*); | |
1585 | ||
1586 | void | |
1587 | do_determine_types(); | |
1588 | ||
1589 | void | |
1590 | do_check_types(Gogo*); | |
1591 | ||
ff9c899b | 1592 | int |
1593 | do_inlining_cost() | |
1594 | { return 5; } | |
1595 | ||
1596 | void | |
1597 | do_export_statement(Export_function_body*); | |
1598 | ||
da244e59 | 1599 | bool |
1600 | do_may_fall_through() const; | |
1601 | ||
1602 | Bstatement* | |
1603 | do_get_backend(Translate_context*); | |
1604 | ||
1605 | void | |
1606 | do_dump_statement(Ast_dump_context*) const; | |
1607 | ||
1608 | private: | |
1609 | Expression* cond_; | |
1610 | Block* then_block_; | |
1611 | Block* else_block_; | |
1612 | }; | |
1613 | ||
e440a328 | 1614 | // A for statement. |
1615 | ||
1616 | class For_statement : public Statement | |
1617 | { | |
1618 | public: | |
1619 | For_statement(Block* init, Expression* cond, Block* post, | |
b13c66cd | 1620 | Location location) |
e440a328 | 1621 | : Statement(STATEMENT_FOR, location), |
1622 | init_(init), cond_(cond), post_(post), statements_(NULL), | |
1623 | break_label_(NULL), continue_label_(NULL) | |
1624 | { } | |
1625 | ||
1626 | // Add the statements. | |
1627 | void | |
1628 | add_statements(Block* statements) | |
1629 | { | |
c484d925 | 1630 | go_assert(this->statements_ == NULL); |
e440a328 | 1631 | this->statements_ = statements; |
1632 | } | |
1633 | ||
1634 | // Return the break label for this for statement. | |
1635 | Unnamed_label* | |
1636 | break_label(); | |
1637 | ||
1638 | // Return the continue label for this for statement. | |
1639 | Unnamed_label* | |
1640 | continue_label(); | |
1641 | ||
1642 | // Set the break and continue labels for this statement. | |
1643 | void | |
1644 | set_break_continue_labels(Unnamed_label* break_label, | |
1645 | Unnamed_label* continue_label); | |
1646 | ||
1647 | protected: | |
1648 | int | |
1649 | do_traverse(Traverse*); | |
1650 | ||
1651 | bool | |
1652 | do_traverse_assignments(Traverse_assignments*) | |
c3e6f413 | 1653 | { go_unreachable(); } |
e440a328 | 1654 | |
1655 | Statement* | |
ceeb4318 | 1656 | do_lower(Gogo*, Named_object*, Block*, Statement_inserter*); |
e440a328 | 1657 | |
270f533c | 1658 | bool |
1659 | do_may_fall_through() const; | |
1660 | ||
4cf30692 | 1661 | Bstatement* |
1662 | do_get_backend(Translate_context*) | |
c3e6f413 | 1663 | { go_unreachable(); } |
e440a328 | 1664 | |
d751bb78 | 1665 | void |
1666 | do_dump_statement(Ast_dump_context*) const; | |
1667 | ||
e440a328 | 1668 | private: |
1669 | // The initialization statements. This may be NULL. | |
1670 | Block* init_; | |
1671 | // The condition. This may be NULL. | |
1672 | Expression* cond_; | |
1673 | // The statements to run after each iteration. This may be NULL. | |
1674 | Block* post_; | |
1675 | // The statements in the loop itself. | |
1676 | Block* statements_; | |
1677 | // The break label, if needed. | |
1678 | Unnamed_label* break_label_; | |
1679 | // The continue label, if needed. | |
1680 | Unnamed_label* continue_label_; | |
1681 | }; | |
1682 | ||
1683 | // A for statement over a range clause. | |
1684 | ||
1685 | class For_range_statement : public Statement | |
1686 | { | |
1687 | public: | |
1688 | For_range_statement(Expression* index_var, Expression* value_var, | |
b13c66cd | 1689 | Expression* range, Location location) |
e440a328 | 1690 | : Statement(STATEMENT_FOR_RANGE, location), |
1691 | index_var_(index_var), value_var_(value_var), range_(range), | |
1692 | statements_(NULL), break_label_(NULL), continue_label_(NULL) | |
1693 | { } | |
1694 | ||
1695 | // Add the statements. | |
1696 | void | |
1697 | add_statements(Block* statements) | |
1698 | { | |
c484d925 | 1699 | go_assert(this->statements_ == NULL); |
e440a328 | 1700 | this->statements_ = statements; |
1701 | } | |
1702 | ||
1703 | // Return the break label for this for statement. | |
1704 | Unnamed_label* | |
1705 | break_label(); | |
1706 | ||
1707 | // Return the continue label for this for statement. | |
1708 | Unnamed_label* | |
1709 | continue_label(); | |
1710 | ||
1711 | protected: | |
1712 | int | |
1713 | do_traverse(Traverse*); | |
1714 | ||
1715 | bool | |
1716 | do_traverse_assignments(Traverse_assignments*) | |
c3e6f413 | 1717 | { go_unreachable(); } |
e440a328 | 1718 | |
1719 | Statement* | |
ceeb4318 | 1720 | do_lower(Gogo*, Named_object*, Block*, Statement_inserter*); |
e440a328 | 1721 | |
4cf30692 | 1722 | Bstatement* |
1723 | do_get_backend(Translate_context*) | |
c3e6f413 | 1724 | { go_unreachable(); } |
e440a328 | 1725 | |
d751bb78 | 1726 | void |
1727 | do_dump_statement(Ast_dump_context*) const; | |
1728 | ||
e440a328 | 1729 | private: |
1730 | Expression* | |
b13c66cd | 1731 | make_range_ref(Named_object*, Temporary_statement*, Location); |
e440a328 | 1732 | |
ccea2b36 | 1733 | Call_expression* |
b13c66cd | 1734 | call_builtin(Gogo*, const char* funcname, Expression* arg, Location); |
e440a328 | 1735 | |
1736 | void | |
1737 | lower_range_array(Gogo*, Block*, Block*, Named_object*, Temporary_statement*, | |
1738 | Temporary_statement*, Temporary_statement*, | |
1739 | Block**, Expression**, Block**, Block**); | |
4cfd64bd | 1740 | |
1741 | void | |
1742 | lower_range_slice(Gogo*, Block*, Block*, Named_object*, Temporary_statement*, | |
1743 | Temporary_statement*, Temporary_statement*, | |
1744 | Block**, Expression**, Block**, Block**); | |
e440a328 | 1745 | |
1746 | void | |
1747 | lower_range_string(Gogo*, Block*, Block*, Named_object*, Temporary_statement*, | |
1748 | Temporary_statement*, Temporary_statement*, | |
1749 | Block**, Expression**, Block**, Block**); | |
1750 | ||
1751 | void | |
0d5530d9 | 1752 | lower_range_map(Gogo*, Map_type*, Block*, Block*, Named_object*, |
e440a328 | 1753 | Temporary_statement*, Temporary_statement*, |
0d5530d9 | 1754 | Temporary_statement*, Block**, Expression**, Block**, |
1755 | Block**); | |
e440a328 | 1756 | |
1757 | void | |
1758 | lower_range_channel(Gogo*, Block*, Block*, Named_object*, | |
1759 | Temporary_statement*, Temporary_statement*, | |
1760 | Temporary_statement*, Block**, Expression**, Block**, | |
1761 | Block**); | |
1762 | ||
b52ffd74 | 1763 | Statement* |
1764 | lower_map_range_clear(Type*, Block*, Expression*, Named_object*, | |
1765 | Temporary_statement*, Location); | |
1766 | ||
d2199dbc | 1767 | Statement* |
1768 | lower_array_range_clear(Gogo*, Type*, Expression*, Block*, | |
1769 | Named_object*, Temporary_statement*, | |
1770 | Location); | |
1771 | ||
e440a328 | 1772 | // The variable which is set to the index value. |
1773 | Expression* index_var_; | |
1774 | // The variable which is set to the element value. This may be | |
1775 | // NULL. | |
1776 | Expression* value_var_; | |
1777 | // The expression we are ranging over. | |
1778 | Expression* range_; | |
1779 | // The statements in the block. | |
1780 | Block* statements_; | |
1781 | // The break label, if needed. | |
1782 | Unnamed_label* break_label_; | |
1783 | // The continue label, if needed. | |
1784 | Unnamed_label* continue_label_; | |
1785 | }; | |
1786 | ||
1787 | // Class Case_clauses holds the clauses of a switch statement. This | |
1788 | // is built by the parser. | |
1789 | ||
1790 | class Case_clauses | |
1791 | { | |
1792 | public: | |
1793 | Case_clauses() | |
1794 | : clauses_() | |
1795 | { } | |
1796 | ||
1797 | // Add a new clause. CASES is a list of case expressions; it may be | |
1798 | // NULL. IS_DEFAULT is true if this is the default case. | |
1799 | // STATEMENTS is a block of statements. IS_FALLTHROUGH is true if | |
1800 | // after the statements the case clause should fall through to the | |
1801 | // next clause. | |
1802 | void | |
1803 | add(Expression_list* cases, bool is_default, Block* statements, | |
b13c66cd | 1804 | bool is_fallthrough, Location location) |
e440a328 | 1805 | { |
1806 | this->clauses_.push_back(Case_clause(cases, is_default, statements, | |
1807 | is_fallthrough, location)); | |
1808 | } | |
1809 | ||
1810 | // Return whether there are no clauses. | |
1811 | bool | |
1812 | empty() const | |
1813 | { return this->clauses_.empty(); } | |
1814 | ||
1815 | // Traverse the case clauses. | |
1816 | int | |
1817 | traverse(Traverse*); | |
1818 | ||
1819 | // Lower for a nonconstant switch. | |
1820 | void | |
1821 | lower(Block*, Temporary_statement*, Unnamed_label*) const; | |
1822 | ||
1823 | // Determine types of expressions. The Type parameter is the type | |
1824 | // of the switch value. | |
1825 | void | |
1826 | determine_types(Type*); | |
1827 | ||
1828 | // Check types. The Type parameter is the type of the switch value. | |
1829 | bool | |
1830 | check_types(Type*); | |
1831 | ||
1832 | // Return true if all the clauses are constant values. | |
1833 | bool | |
1834 | is_constant() const; | |
1835 | ||
1836 | // Return true if these clauses may fall through to the statements | |
1837 | // following the switch statement. | |
1838 | bool | |
1839 | may_fall_through() const; | |
1840 | ||
1841 | // Return the body of a SWITCH_EXPR when all the clauses are | |
1842 | // constants. | |
8259743a | 1843 | void |
1844 | get_backend(Translate_context*, Unnamed_label* break_label, | |
1845 | std::vector<std::vector<Bexpression*> >* all_cases, | |
1846 | std::vector<Bstatement*>* all_statements) const; | |
e440a328 | 1847 | |
d751bb78 | 1848 | // Dump the AST representation to a dump context. |
1849 | void | |
1850 | dump_clauses(Ast_dump_context*) const; | |
86a71ed0 | 1851 | |
e440a328 | 1852 | private: |
519a82cb | 1853 | // For a constant switch we need to keep a record of constants we |
1854 | // have already seen. | |
8259743a | 1855 | class Hash_integer_value; |
1856 | class Eq_integer_value; | |
1857 | typedef Unordered_set_hash(Expression*, Hash_integer_value, | |
1858 | Eq_integer_value) Case_constants; | |
e440a328 | 1859 | |
1860 | // One case clause. | |
1861 | class Case_clause | |
1862 | { | |
1863 | public: | |
1864 | Case_clause() | |
1865 | : cases_(NULL), statements_(NULL), is_default_(false), | |
631d5788 | 1866 | is_fallthrough_(false), location_(Linemap::unknown_location()) |
e440a328 | 1867 | { } |
1868 | ||
1869 | Case_clause(Expression_list* cases, bool is_default, Block* statements, | |
b13c66cd | 1870 | bool is_fallthrough, Location location) |
e440a328 | 1871 | : cases_(cases), statements_(statements), is_default_(is_default), |
1872 | is_fallthrough_(is_fallthrough), location_(location) | |
1873 | { } | |
1874 | ||
1875 | // Whether this clause falls through to the next clause. | |
1876 | bool | |
1877 | is_fallthrough() const | |
1878 | { return this->is_fallthrough_; } | |
1879 | ||
1880 | // Whether this is the default. | |
1881 | bool | |
1882 | is_default() const | |
1883 | { return this->is_default_; } | |
1884 | ||
1885 | // The location of this clause. | |
b13c66cd | 1886 | Location |
e440a328 | 1887 | location() const |
1888 | { return this->location_; } | |
1889 | ||
1890 | // Traversal. | |
1891 | int | |
1892 | traverse(Traverse*); | |
1893 | ||
1894 | // Lower for a nonconstant switch. | |
1895 | void | |
1896 | lower(Block*, Temporary_statement*, Unnamed_label*, Unnamed_label*) const; | |
1897 | ||
1898 | // Determine types. | |
1899 | void | |
1900 | determine_types(Type*); | |
1901 | ||
1902 | // Check types. | |
1903 | bool | |
1904 | check_types(Type*); | |
1905 | ||
1906 | // Return true if all the case expressions are constant. | |
1907 | bool | |
1908 | is_constant() const; | |
1909 | ||
1910 | // Return true if this clause may fall through to execute the | |
1911 | // statements following the switch statement. This is not the | |
1912 | // same as whether this clause falls through to the next clause. | |
1913 | bool | |
1914 | may_fall_through() const; | |
1915 | ||
8259743a | 1916 | // Convert the case values and statements to the backend |
1917 | // representation. | |
1918 | Bstatement* | |
1919 | get_backend(Translate_context*, Unnamed_label* break_label, | |
1920 | Case_constants*, std::vector<Bexpression*>* cases) const; | |
e440a328 | 1921 | |
d751bb78 | 1922 | // Dump the AST representation to a dump context. |
1923 | void | |
1924 | dump_clause(Ast_dump_context*) const; | |
86a71ed0 | 1925 | |
e440a328 | 1926 | private: |
1927 | // The list of case expressions. | |
1928 | Expression_list* cases_; | |
1929 | // The statements to execute. | |
1930 | Block* statements_; | |
1931 | // Whether this is the default case. | |
1932 | bool is_default_; | |
1933 | // Whether this falls through after the statements. | |
1934 | bool is_fallthrough_; | |
1935 | // The location of this case clause. | |
b13c66cd | 1936 | Location location_; |
e440a328 | 1937 | }; |
1938 | ||
1939 | friend class Case_clause; | |
1940 | ||
1941 | // The type of the list of clauses. | |
1942 | typedef std::vector<Case_clause> Clauses; | |
1943 | ||
1944 | // All the case clauses. | |
1945 | Clauses clauses_; | |
1946 | }; | |
1947 | ||
1948 | // A switch statement. | |
1949 | ||
1950 | class Switch_statement : public Statement | |
1951 | { | |
1952 | public: | |
b13c66cd | 1953 | Switch_statement(Expression* val, Location location) |
e440a328 | 1954 | : Statement(STATEMENT_SWITCH, location), |
1955 | val_(val), clauses_(NULL), break_label_(NULL) | |
1956 | { } | |
1957 | ||
1958 | // Add the clauses. | |
1959 | void | |
1960 | add_clauses(Case_clauses* clauses) | |
1961 | { | |
c484d925 | 1962 | go_assert(this->clauses_ == NULL); |
e440a328 | 1963 | this->clauses_ = clauses; |
1964 | } | |
1965 | ||
1966 | // Return the break label for this switch statement. | |
1967 | Unnamed_label* | |
1968 | break_label(); | |
1969 | ||
1970 | protected: | |
1971 | int | |
1972 | do_traverse(Traverse*); | |
1973 | ||
1974 | Statement* | |
ceeb4318 | 1975 | do_lower(Gogo*, Named_object*, Block*, Statement_inserter*); |
e440a328 | 1976 | |
4cf30692 | 1977 | Bstatement* |
1978 | do_get_backend(Translate_context*) | |
c3e6f413 | 1979 | { go_unreachable(); } |
e440a328 | 1980 | |
d751bb78 | 1981 | void |
1982 | do_dump_statement(Ast_dump_context*) const; | |
1983 | ||
270f533c | 1984 | bool |
1985 | do_may_fall_through() const; | |
1986 | ||
e440a328 | 1987 | private: |
1988 | // The value to switch on. This may be NULL. | |
1989 | Expression* val_; | |
1990 | // The case clauses. | |
1991 | Case_clauses* clauses_; | |
1992 | // The break label, if needed. | |
1993 | Unnamed_label* break_label_; | |
1994 | }; | |
1995 | ||
1996 | // Class Type_case_clauses holds the clauses of a type switch | |
1997 | // statement. This is built by the parser. | |
1998 | ||
1999 | class Type_case_clauses | |
2000 | { | |
2001 | public: | |
2002 | Type_case_clauses() | |
2003 | : clauses_() | |
2004 | { } | |
2005 | ||
2006 | // Add a new clause. TYPE is the type for this clause; it may be | |
2007 | // NULL. IS_FALLTHROUGH is true if this falls through to the next | |
2008 | // clause; in this case STATEMENTS will be NULL. IS_DEFAULT is true | |
2009 | // if this is the default case. STATEMENTS is a block of | |
2010 | // statements; it may be NULL. | |
2011 | void | |
2012 | add(Type* type, bool is_fallthrough, bool is_default, Block* statements, | |
b13c66cd | 2013 | Location location) |
e440a328 | 2014 | { |
2015 | this->clauses_.push_back(Type_case_clause(type, is_fallthrough, is_default, | |
2016 | statements, location)); | |
2017 | } | |
2018 | ||
2019 | // Return whether there are no clauses. | |
2020 | bool | |
2021 | empty() const | |
2022 | { return this->clauses_.empty(); } | |
2023 | ||
2024 | // Traverse the type case clauses. | |
2025 | int | |
2026 | traverse(Traverse*); | |
2027 | ||
2028 | // Check for duplicates. | |
2029 | void | |
2030 | check_duplicates() const; | |
2031 | ||
2032 | // Lower to if and goto statements. | |
2033 | void | |
dc619250 | 2034 | lower(Type*, Block*, Temporary_statement* descriptor_temp, |
e440a328 | 2035 | Unnamed_label* break_label) const; |
2036 | ||
270f533c | 2037 | // Return true if these clauses may fall through to the statements |
2038 | // following the switch statement. | |
2039 | bool | |
2040 | may_fall_through() const; | |
2041 | ||
d751bb78 | 2042 | // Dump the AST representation to a dump context. |
2043 | void | |
2044 | dump_clauses(Ast_dump_context*) const; | |
2045 | ||
e440a328 | 2046 | private: |
2047 | // One type case clause. | |
2048 | class Type_case_clause | |
2049 | { | |
2050 | public: | |
2051 | Type_case_clause() | |
2052 | : type_(NULL), statements_(NULL), is_default_(false), | |
631d5788 | 2053 | location_(Linemap::unknown_location()) |
e440a328 | 2054 | { } |
2055 | ||
2056 | Type_case_clause(Type* type, bool is_fallthrough, bool is_default, | |
b13c66cd | 2057 | Block* statements, Location location) |
e440a328 | 2058 | : type_(type), statements_(statements), is_fallthrough_(is_fallthrough), |
2059 | is_default_(is_default), location_(location) | |
2060 | { } | |
2061 | ||
2062 | // The type. | |
2063 | Type* | |
2064 | type() const | |
2065 | { return this->type_; } | |
2066 | ||
2067 | // Whether this is the default. | |
2068 | bool | |
2069 | is_default() const | |
2070 | { return this->is_default_; } | |
2071 | ||
2072 | // The location of this type clause. | |
b13c66cd | 2073 | Location |
e440a328 | 2074 | location() const |
2075 | { return this->location_; } | |
2076 | ||
2077 | // Traversal. | |
2078 | int | |
2079 | traverse(Traverse*); | |
2080 | ||
2081 | // Lower to if and goto statements. | |
2082 | void | |
dc619250 | 2083 | lower(Type*, Block*, Temporary_statement* descriptor_temp, |
e440a328 | 2084 | Unnamed_label* break_label, Unnamed_label** stmts_label) const; |
2085 | ||
270f533c | 2086 | // Return true if this clause may fall through to execute the |
2087 | // statements following the switch statement. This is not the | |
2088 | // same as whether this clause falls through to the next clause. | |
2089 | bool | |
2090 | may_fall_through() const; | |
2091 | ||
d751bb78 | 2092 | // Dump the AST representation to a dump context. |
2093 | void | |
2094 | dump_clause(Ast_dump_context*) const; | |
2095 | ||
e440a328 | 2096 | private: |
2097 | // The type for this type clause. | |
2098 | Type* type_; | |
2099 | // The statements to execute. | |
2100 | Block* statements_; | |
2101 | // Whether this falls through--this is true for "case T1, T2". | |
2102 | bool is_fallthrough_; | |
2103 | // Whether this is the default case. | |
2104 | bool is_default_; | |
2105 | // The location of this type case clause. | |
b13c66cd | 2106 | Location location_; |
e440a328 | 2107 | }; |
2108 | ||
2109 | friend class Type_case_clause; | |
2110 | ||
2111 | // The type of the list of type clauses. | |
2112 | typedef std::vector<Type_case_clause> Type_clauses; | |
2113 | ||
2114 | // All the type case clauses. | |
2115 | Type_clauses clauses_; | |
2116 | }; | |
2117 | ||
2118 | // A type switch statement. | |
2119 | ||
2120 | class Type_switch_statement : public Statement | |
2121 | { | |
2122 | public: | |
cc0446ba | 2123 | Type_switch_statement(const std::string& name, Expression* expr, |
b13c66cd | 2124 | Location location) |
e440a328 | 2125 | : Statement(STATEMENT_TYPE_SWITCH, location), |
cc0446ba | 2126 | name_(name), expr_(expr), clauses_(NULL), break_label_(NULL) |
2127 | { } | |
e440a328 | 2128 | |
2129 | // Add the clauses. | |
2130 | void | |
2131 | add_clauses(Type_case_clauses* clauses) | |
2132 | { | |
c484d925 | 2133 | go_assert(this->clauses_ == NULL); |
e440a328 | 2134 | this->clauses_ = clauses; |
2135 | } | |
2136 | ||
2137 | // Return the break label for this type switch statement. | |
2138 | Unnamed_label* | |
2139 | break_label(); | |
2140 | ||
2141 | protected: | |
2142 | int | |
2143 | do_traverse(Traverse*); | |
2144 | ||
2145 | Statement* | |
ceeb4318 | 2146 | do_lower(Gogo*, Named_object*, Block*, Statement_inserter*); |
e440a328 | 2147 | |
4cf30692 | 2148 | Bstatement* |
2149 | do_get_backend(Translate_context*) | |
c3e6f413 | 2150 | { go_unreachable(); } |
e440a328 | 2151 | |
d751bb78 | 2152 | void |
2153 | do_dump_statement(Ast_dump_context*) const; | |
2154 | ||
270f533c | 2155 | bool |
2156 | do_may_fall_through() const; | |
2157 | ||
e440a328 | 2158 | private: |
cc0446ba | 2159 | // The name of the variable declared in the type switch guard. Empty if there |
2160 | // is no variable declared. | |
2161 | std::string name_; | |
e440a328 | 2162 | // The expression we are switching on if there is no variable. |
2163 | Expression* expr_; | |
2164 | // The type case clauses. | |
2165 | Type_case_clauses* clauses_; | |
2166 | // The break label, if needed. | |
2167 | Unnamed_label* break_label_; | |
2168 | }; | |
2169 | ||
2170 | #endif // !defined(GO_STATEMENTS_H) |