compiler: don't set btype_ too early for alias type
[official-gcc.git] / gcc / go / gofrontend / wb.cc
blob99f467ef90d7a30d573ada789c836e3b3bb1853f
1 // wb.cc -- Add write barriers as needed.
3 // Copyright 2017 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.
7 #include "go-system.h"
9 #include "go-c.h"
10 #include "go-diagnostics.h"
11 #include "operator.h"
12 #include "lex.h"
13 #include "types.h"
14 #include "expressions.h"
15 #include "statements.h"
16 #include "runtime.h"
17 #include "gogo.h"
19 // Mark variables whose addresses are taken. This has to be done
20 // before the write barrier pass and after the escape analysis pass.
21 // It would be nice to do this elsewhere but there isn't an obvious
22 // place.
24 class Mark_address_taken : public Traverse
26 public:
27 Mark_address_taken(Gogo* gogo)
28 : Traverse(traverse_expressions),
29 gogo_(gogo)
30 { }
32 int
33 expression(Expression**);
35 private:
36 Gogo* gogo_;
39 // Mark variable addresses taken.
41 int
42 Mark_address_taken::expression(Expression** pexpr)
44 Expression* expr = *pexpr;
45 Unary_expression* ue = expr->unary_expression();
46 if (ue != NULL)
47 ue->check_operand_address_taken(this->gogo_);
49 Array_index_expression* aie = expr->array_index_expression();
50 if (aie != NULL
51 && aie->end() != NULL
52 && !aie->array()->type()->is_slice_type())
54 // Slice of an array. The escape analysis models this with
55 // a child Node representing the address of the array.
56 bool escapes = false;
57 Node* n = Node::make_node(expr);
58 if (n->child() == NULL
59 || (n->child()->encoding() & ESCAPE_MASK) != Node::ESCAPE_NONE)
60 escapes = true;
61 aie->array()->address_taken(escapes);
64 if (expr->allocation_expression() != NULL)
66 Node* n = Node::make_node(expr);
67 if ((n->encoding() & ESCAPE_MASK) == Node::ESCAPE_NONE)
68 expr->allocation_expression()->set_allocate_on_stack();
70 if (expr->heap_expression() != NULL)
72 Node* n = Node::make_node(expr);
73 if ((n->encoding() & ESCAPE_MASK) == Node::ESCAPE_NONE)
74 expr->heap_expression()->set_allocate_on_stack();
76 if (expr->slice_literal() != NULL)
78 Node* n = Node::make_node(expr);
79 if ((n->encoding() & ESCAPE_MASK) == Node::ESCAPE_NONE)
80 expr->slice_literal()->set_storage_does_not_escape();
83 // Rewrite non-escaping makeslice with constant size to stack allocation.
84 Unsafe_type_conversion_expression* uce =
85 expr->unsafe_conversion_expression();
86 if (uce != NULL
87 && uce->type()->is_slice_type()
88 && Node::make_node(uce->expr())->encoding() == Node::ESCAPE_NONE
89 && uce->expr()->call_expression() != NULL)
91 Call_expression* call = uce->expr()->call_expression();
92 if (call->fn()->func_expression() != NULL
93 && call->fn()->func_expression()->runtime_code() == Runtime::MAKESLICE)
95 Expression* len_arg = call->args()->at(1);
96 Expression* cap_arg = call->args()->at(2);
97 Numeric_constant nclen;
98 Numeric_constant nccap;
99 unsigned long vlen;
100 unsigned long vcap;
101 if (len_arg->numeric_constant_value(&nclen)
102 && cap_arg->numeric_constant_value(&nccap)
103 && nclen.to_unsigned_long(&vlen) == Numeric_constant::NC_UL_VALID
104 && nccap.to_unsigned_long(&vcap) == Numeric_constant::NC_UL_VALID)
106 // Turn it into a slice expression of an addressable array,
107 // which is allocated on stack.
108 Location loc = expr->location();
109 Type* elmt_type = expr->type()->array_type()->element_type();
110 Expression* len_expr =
111 Expression::make_integer_ul(vcap, cap_arg->type(), loc);
112 Type* array_type = Type::make_array_type(elmt_type, len_expr);
113 Expression* alloc = Expression::make_allocation(array_type, loc);
114 alloc->allocation_expression()->set_allocate_on_stack();
115 Expression* array = Expression::make_unary(OPERATOR_MULT, alloc, loc);
116 Expression* zero = Expression::make_integer_ul(0, len_arg->type(), loc);
117 Expression* slice =
118 Expression::make_array_index(array, zero, len_arg, cap_arg, loc);
119 *pexpr = slice;
123 return TRAVERSE_CONTINUE;
126 // Check variables and closures do not escape when compiling runtime.
128 class Check_escape : public Traverse
130 public:
131 Check_escape(Gogo* gogo)
132 : Traverse(traverse_expressions | traverse_variables),
133 gogo_(gogo)
137 expression(Expression**);
140 variable(Named_object*);
142 private:
143 Gogo* gogo_;
147 Check_escape::variable(Named_object* no)
149 if ((no->is_variable() && no->var_value()->is_in_heap())
150 || (no->is_result_variable()
151 && no->result_var_value()->is_in_heap()))
152 go_error_at(no->location(),
153 "%s escapes to heap, not allowed in runtime",
154 no->message_name().c_str());
155 return TRAVERSE_CONTINUE;
159 Check_escape::expression(Expression** pexpr)
161 Expression* expr = *pexpr;
162 Func_expression* fe = expr->func_expression();
163 if (fe != NULL && fe->closure() != NULL)
165 Node* n = Node::make_node(expr);
166 if (n->encoding() == Node::ESCAPE_HEAP)
167 go_error_at(expr->location(),
168 "heap-allocated closure, not allowed in runtime");
170 return TRAVERSE_CONTINUE;
173 // Add write barriers to the IR. This are required by the concurrent
174 // garbage collector. A write barrier is needed for any write of a
175 // pointer into memory controlled by the garbage collector. Write
176 // barriers are not required for writes to local variables that live
177 // on the stack. Write barriers are only required when the runtime
178 // enables them, which can be checked using a run time check on
179 // runtime.writeBarrier.enabled.
181 // Essentially, for each assignment A = B, where A is or contains a
182 // pointer, and where A is not, or at any rate may not be, a stack
183 // variable, we rewrite it into
184 // if runtime.writeBarrier.enabled {
185 // typedmemmove(typeof(A), &A, &B)
186 // } else {
187 // A = B
188 // }
190 // The test of runtime.writeBarrier.Enabled is implemented by treating
191 // the variable as a *uint32, and testing *runtime.writeBarrier != 0.
192 // This is compatible with the definition in the runtime package.
194 // For types that are pointer shared (pointers, maps, chans, funcs),
195 // we replaced the call to typedmemmove with writebarrierptr(&A, B).
196 // As far as the GC is concerned, all pointers are the same, so it
197 // doesn't need the type descriptor.
199 // There are possible optimizations that are not implemented.
201 // runtime.writeBarrier can only change when the goroutine is
202 // preempted, which in practice means when a call is made into the
203 // runtime package, so we could optimize by only testing it once
204 // between function calls.
206 // A slice could be handled with a call to writebarrierptr plus two
207 // integer moves.
209 // Traverse the IR adding write barriers.
211 class Write_barriers : public Traverse
213 public:
214 Write_barriers(Gogo* gogo)
215 : Traverse(traverse_functions | traverse_variables | traverse_statements),
216 gogo_(gogo), function_(NULL), statements_added_()
220 function(Named_object*);
223 variable(Named_object*);
226 statement(Block*, size_t* pindex, Statement*);
228 private:
229 // General IR.
230 Gogo* gogo_;
231 // Current function.
232 Function* function_;
233 // Statements introduced.
234 Statement_inserter::Statements statements_added_;
237 // Traverse a function. Just record it for later.
240 Write_barriers::function(Named_object* no)
242 go_assert(this->function_ == NULL);
243 this->function_ = no->func_value();
244 int t = this->function_->traverse(this);
245 this->function_ = NULL;
247 if (t == TRAVERSE_EXIT)
248 return t;
249 return TRAVERSE_SKIP_COMPONENTS;
252 // Insert write barriers for a global variable: ensure that variable
253 // initialization is handled correctly. This is rarely needed, since
254 // we currently don't enable background GC until after all global
255 // variables are initialized. But we do need this if an init function
256 // calls runtime.GC.
259 Write_barriers::variable(Named_object* no)
261 // We handle local variables in the variable declaration statement.
262 // We only have to handle global variables here.
263 if (!no->is_variable())
264 return TRAVERSE_CONTINUE;
265 Variable* var = no->var_value();
266 if (!var->is_global())
267 return TRAVERSE_CONTINUE;
269 // Nothing to do if there is no initializer.
270 Expression* init = var->init();
271 if (init == NULL)
272 return TRAVERSE_CONTINUE;
274 // Nothing to do for variables that do not contain any pointers.
275 if (!var->type()->has_pointer())
276 return TRAVERSE_CONTINUE;
278 // Nothing to do if the initializer is static.
279 init = Expression::make_cast(var->type(), init, var->location());
280 if (!var->has_pre_init() && init->is_static_initializer())
281 return TRAVERSE_CONTINUE;
283 // Nothing to do for a type that can not be in the heap, or a
284 // pointer to a type that can not be in the heap.
285 if (!var->type()->in_heap())
286 return TRAVERSE_CONTINUE;
287 if (var->type()->points_to() != NULL && !var->type()->points_to()->in_heap())
288 return TRAVERSE_CONTINUE;
290 // Otherwise change the initializer into a pre_init assignment
291 // statement with a write barrier.
293 // We can't check for a dependency of the variable on itself after
294 // we make this change, because the preinit statement will always
295 // depend on the variable (since it assigns to it). So check for a
296 // self-dependency now.
297 this->gogo_->check_self_dep(no);
299 // Replace the initializer.
300 Location loc = init->location();
301 Expression* ref = Expression::make_var_reference(no, loc);
303 Statement_inserter inserter(this->gogo_, var, &this->statements_added_);
304 Statement* s = this->gogo_->assign_with_write_barrier(NULL, NULL, &inserter,
305 ref, init, loc);
306 this->statements_added_.insert(s);
308 var->add_preinit_statement(this->gogo_, s);
309 var->clear_init();
311 return TRAVERSE_CONTINUE;
314 // Insert write barriers for statements.
317 Write_barriers::statement(Block* block, size_t* pindex, Statement* s)
319 if (this->statements_added_.find(s) != this->statements_added_.end())
320 return TRAVERSE_SKIP_COMPONENTS;
322 switch (s->classification())
324 default:
325 break;
327 case Statement::STATEMENT_VARIABLE_DECLARATION:
329 Variable_declaration_statement* vds =
330 s->variable_declaration_statement();
331 Named_object* no = vds->var();
332 Variable* var = no->var_value();
334 // We may need to emit a write barrier for the initialization
335 // of the variable.
337 // Nothing to do for a variable with no initializer.
338 Expression* init = var->init();
339 if (init == NULL)
340 break;
342 // Nothing to do if the variable is not in the heap. Only
343 // local variables get declaration statements, and local
344 // variables on the stack do not require write barriers.
345 if (!var->is_in_heap())
346 break;
348 // Nothing to do if the variable does not contain any pointers.
349 if (!var->type()->has_pointer())
350 break;
352 // Nothing to do for a type that can not be in the heap, or a
353 // pointer to a type that can not be in the heap.
354 if (!var->type()->in_heap())
355 break;
356 if (var->type()->points_to() != NULL
357 && !var->type()->points_to()->in_heap())
358 break;
360 // Otherwise initialize the variable with a write barrier.
362 Function* function = this->function_;
363 Location loc = init->location();
364 Statement_inserter inserter(block, pindex, &this->statements_added_);
366 // Insert the variable declaration statement with no
367 // initializer, so that the variable exists.
368 var->clear_init();
369 inserter.insert(s);
371 // Create a statement that initializes the variable with a
372 // write barrier.
373 Expression* ref = Expression::make_var_reference(no, loc);
374 Statement* assign = this->gogo_->assign_with_write_barrier(function,
375 block,
376 &inserter,
377 ref, init,
378 loc);
379 this->statements_added_.insert(assign);
381 // Replace the old variable declaration statement with the new
382 // initialization.
383 block->replace_statement(*pindex, assign);
385 break;
387 case Statement::STATEMENT_ASSIGNMENT:
389 Assignment_statement* as = s->assignment_statement();
390 Expression* lhs = as->lhs();
391 Expression* rhs = as->rhs();
393 // We may need to emit a write barrier for the assignment.
395 if (!this->gogo_->assign_needs_write_barrier(lhs))
396 break;
398 // Change the assignment to use a write barrier.
399 Function* function = this->function_;
400 Location loc = as->location();
401 Statement_inserter inserter =
402 Statement_inserter(block, pindex, &this->statements_added_);
403 Statement* assign = this->gogo_->assign_with_write_barrier(function,
404 block,
405 &inserter,
406 lhs, rhs,
407 loc);
408 this->statements_added_.insert(assign);
409 block->replace_statement(*pindex, assign);
411 break;
414 return TRAVERSE_CONTINUE;
417 // The write barrier pass.
419 void
420 Gogo::add_write_barriers()
422 if (saw_errors())
423 return;
425 Mark_address_taken mat(this);
426 this->traverse(&mat);
428 if (this->compiling_runtime() && this->package_name() == "runtime")
430 Check_escape chk(this);
431 this->traverse(&chk);
434 Write_barriers wb(this);
435 this->traverse(&wb);
438 // Return the runtime.writeBarrier variable.
440 Named_object*
441 Gogo::write_barrier_variable()
443 static Named_object* write_barrier_var;
444 if (write_barrier_var == NULL)
446 Location bloc = Linemap::predeclared_location();
448 // We pretend that writeBarrier is a uint32, so that we do a
449 // 32-bit load. That is what the gc toolchain does.
450 Type* uint32_type = Type::lookup_integer_type("uint32");
451 Variable* var = new Variable(uint32_type, NULL, true, false, false,
452 bloc);
454 bool add_to_globals;
455 Package* package = this->add_imported_package("runtime", "_", false,
456 "runtime", "runtime",
457 bloc, &add_to_globals);
458 write_barrier_var = Named_object::make_variable("writeBarrier",
459 package, var);
462 return write_barrier_var;
465 // Return whether an assignment that sets LHS needs a write barrier.
467 bool
468 Gogo::assign_needs_write_barrier(Expression* lhs)
470 // Nothing to do if the variable does not contain any pointers.
471 if (!lhs->type()->has_pointer())
472 return false;
474 // An assignment to a field is handled like an assignment to the
475 // struct.
476 while (true)
478 // Nothing to do for a type that can not be in the heap, or a
479 // pointer to a type that can not be in the heap. We check this
480 // at each level of a struct.
481 if (!lhs->type()->in_heap())
482 return false;
483 if (lhs->type()->points_to() != NULL
484 && !lhs->type()->points_to()->in_heap())
485 return false;
487 Field_reference_expression* fre = lhs->field_reference_expression();
488 if (fre == NULL)
489 break;
490 lhs = fre->expr();
493 // Nothing to do for an assignment to a temporary.
494 if (lhs->temporary_reference_expression() != NULL)
495 return false;
497 // Nothing to do for an assignment to a sink.
498 if (lhs->is_sink_expression())
499 return false;
501 // Nothing to do for an assignment to a local variable that is not
502 // on the heap.
503 Var_expression* ve = lhs->var_expression();
504 if (ve != NULL)
506 Named_object* no = ve->named_object();
507 if (no->is_variable())
509 Variable* var = no->var_value();
510 if (!var->is_global() && !var->is_in_heap())
511 return false;
513 else if (no->is_result_variable())
515 Result_variable* rvar = no->result_var_value();
516 if (!rvar->is_in_heap())
517 return false;
521 // For a struct assignment, we don't need a write barrier if all the
522 // pointer types can not be in the heap.
523 Struct_type* st = lhs->type()->struct_type();
524 if (st != NULL)
526 bool in_heap = false;
527 const Struct_field_list* fields = st->fields();
528 for (Struct_field_list::const_iterator p = fields->begin();
529 p != fields->end();
530 p++)
532 Type* ft = p->type();
533 if (!ft->has_pointer())
534 continue;
535 if (!ft->in_heap())
536 continue;
537 if (ft->points_to() != NULL && !ft->points_to()->in_heap())
538 continue;
539 in_heap = true;
540 break;
542 if (!in_heap)
543 return false;
546 // Write barrier needed in other cases.
547 return true;
550 // Return a statement that sets LHS to RHS using a write barrier.
551 // ENCLOSING is the enclosing block.
553 Statement*
554 Gogo::assign_with_write_barrier(Function* function, Block* enclosing,
555 Statement_inserter* inserter, Expression* lhs,
556 Expression* rhs, Location loc)
558 if (function != NULL
559 && ((function->pragmas() & GOPRAGMA_NOWRITEBARRIER) != 0
560 || (function->pragmas() & GOPRAGMA_NOWRITEBARRIERREC) != 0))
561 go_error_at(loc, "write barrier prohibited");
563 Type* type = lhs->type();
564 go_assert(type->has_pointer());
566 Expression* addr;
567 if (lhs->unary_expression() != NULL
568 && lhs->unary_expression()->op() == OPERATOR_MULT)
569 addr = lhs->unary_expression()->operand();
570 else
572 addr = Expression::make_unary(OPERATOR_AND, lhs, loc);
573 addr->unary_expression()->set_does_not_escape();
575 Temporary_statement* lhs_temp = Statement::make_temporary(NULL, addr, loc);
576 inserter->insert(lhs_temp);
577 lhs = Expression::make_temporary_reference(lhs_temp, loc);
579 if (!Type::are_identical(type, rhs->type(), false, NULL)
580 && rhs->type()->interface_type() != NULL
581 && !rhs->is_variable())
583 // May need a temporary for interface conversion.
584 Temporary_statement* temp = Statement::make_temporary(NULL, rhs, loc);
585 inserter->insert(temp);
586 rhs = Expression::make_temporary_reference(temp, loc);
588 rhs = Expression::convert_for_assignment(this, type, rhs, loc);
589 Temporary_statement* rhs_temp = NULL;
590 if (!rhs->is_variable() && !rhs->is_constant())
592 rhs_temp = Statement::make_temporary(NULL, rhs, loc);
593 inserter->insert(rhs_temp);
594 rhs = Expression::make_temporary_reference(rhs_temp, loc);
597 Expression* indir =
598 Expression::make_dereference(lhs, Expression::NIL_CHECK_DEFAULT, loc);
599 Statement* assign = Statement::make_assignment(indir, rhs, loc);
601 lhs = Expression::make_temporary_reference(lhs_temp, loc);
602 if (rhs_temp != NULL)
603 rhs = Expression::make_temporary_reference(rhs_temp, loc);
605 Type* unsafe_ptr_type = Type::make_pointer_type(Type::make_void_type());
606 lhs = Expression::make_unsafe_cast(unsafe_ptr_type, lhs, loc);
608 Expression* call;
609 switch (type->base()->classification())
611 default:
612 go_unreachable();
614 case Type::TYPE_ERROR:
615 return assign;
617 case Type::TYPE_POINTER:
618 case Type::TYPE_FUNCTION:
619 case Type::TYPE_MAP:
620 case Type::TYPE_CHANNEL:
621 // These types are all represented by a single pointer.
622 call = Runtime::make_call(Runtime::WRITEBARRIERPTR, loc, 2, lhs, rhs);
623 break;
625 case Type::TYPE_STRING:
626 case Type::TYPE_STRUCT:
627 case Type::TYPE_ARRAY:
628 case Type::TYPE_INTERFACE:
630 rhs = Expression::make_unary(OPERATOR_AND, rhs, loc);
631 rhs->unary_expression()->set_does_not_escape();
632 call = Runtime::make_call(Runtime::TYPEDMEMMOVE, loc, 3,
633 Expression::make_type_descriptor(type, loc),
634 lhs, rhs);
636 break;
639 return this->check_write_barrier(enclosing, assign,
640 Statement::make_statement(call, false));
643 // Return a statement that tests whether write barriers are enabled
644 // and executes either the efficient code or the write barrier
645 // function call, depending.
647 Statement*
648 Gogo::check_write_barrier(Block* enclosing, Statement* without,
649 Statement* with)
651 Location loc = without->location();
652 Named_object* wb = this->write_barrier_variable();
653 Expression* ref = Expression::make_var_reference(wb, loc);
654 Expression* zero = Expression::make_integer_ul(0, ref->type(), loc);
655 Expression* cond = Expression::make_binary(OPERATOR_EQEQ, ref, zero, loc);
657 Block* then_block = new Block(enclosing, loc);
658 then_block->add_statement(without);
660 Block* else_block = new Block(enclosing, loc);
661 else_block->add_statement(with);
663 return Statement::make_if_statement(cond, then_block, else_block, loc);