1 // wb.cc -- Add write barriers as needed.
2 
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.
6 
7 #include "go-system.h"
8 
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"
18 
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.
23 
24 class Mark_address_taken : public Traverse
25 {
26  public:
Mark_address_taken(Gogo * gogo)27   Mark_address_taken(Gogo* gogo)
28     : Traverse(traverse_expressions),
29       gogo_(gogo)
30   { }
31 
32   int
33   expression(Expression**);
34 
35  private:
36   Gogo* gogo_;
37 };
38 
39 // Mark variable addresses taken.
40 
41 int
expression(Expression ** pexpr)42 Mark_address_taken::expression(Expression** pexpr)
43 {
44   Expression* expr = *pexpr;
45   Unary_expression* ue = expr->unary_expression();
46   if (ue != NULL)
47     ue->check_operand_address_taken(this->gogo_);
48 
49   Array_index_expression* aie = expr->array_index_expression();
50   if (aie != NULL
51       && aie->end() != NULL
52       && !aie->array()->type()->is_slice_type())
53     {
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);
62     }
63 
64   if (expr->allocation_expression() != NULL)
65     {
66       Node* n = Node::make_node(expr);
67       if ((n->encoding() & ESCAPE_MASK) == Node::ESCAPE_NONE)
68         expr->allocation_expression()->set_allocate_on_stack();
69     }
70   if (expr->heap_expression() != NULL)
71     {
72       Node* n = Node::make_node(expr);
73       if ((n->encoding() & ESCAPE_MASK) == Node::ESCAPE_NONE)
74         expr->heap_expression()->set_allocate_on_stack();
75     }
76   if (expr->slice_literal() != NULL)
77     {
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();
81     }
82 
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)
90     {
91       Call_expression* call = uce->expr()->call_expression();
92       if (call->fn()->func_expression() != NULL
93           && call->fn()->func_expression()->runtime_code() == Runtime::MAKESLICE)
94         {
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)
105             {
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;
120             }
121         }
122     }
123   return TRAVERSE_CONTINUE;
124 }
125 
126 // Check variables and closures do not escape when compiling runtime.
127 
128 class Check_escape : public Traverse
129 {
130  public:
Check_escape(Gogo * gogo)131   Check_escape(Gogo* gogo)
132     : Traverse(traverse_expressions | traverse_variables),
133       gogo_(gogo)
134   { }
135 
136   int
137   expression(Expression**);
138 
139   int
140   variable(Named_object*);
141 
142  private:
143   Gogo* gogo_;
144 };
145 
146 int
variable(Named_object * no)147 Check_escape::variable(Named_object* no)
148 {
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;
156 }
157 
158 int
expression(Expression ** pexpr)159 Check_escape::expression(Expression** pexpr)
160 {
161   Expression* expr = *pexpr;
162   Func_expression* fe = expr->func_expression();
163   if (fe != NULL && fe->closure() != NULL)
164     {
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");
169     }
170   return TRAVERSE_CONTINUE;
171 }
172 
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.
180 //
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 //     }
189 //
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.
193 //
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.
198 //
199 // There are possible optimizations that are not implemented.
200 //
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.
205 //
206 // A slice could be handled with a call to writebarrierptr plus two
207 // integer moves.
208 
209 // Traverse the IR adding write barriers.
210 
211 class Write_barriers : public Traverse
212 {
213  public:
Write_barriers(Gogo * gogo)214   Write_barriers(Gogo* gogo)
215     : Traverse(traverse_functions | traverse_variables | traverse_statements),
216       gogo_(gogo), function_(NULL)
217   { }
218 
219   int
220   function(Named_object*);
221 
222   int
223   variable(Named_object*);
224 
225   int
226   statement(Block*, size_t* pindex, Statement*);
227 
228  private:
229   // General IR.
230   Gogo* gogo_;
231   // Current function.
232   Function* function_;
233 };
234 
235 // Traverse a function.  Just record it for later.
236 
237 int
function(Named_object * no)238 Write_barriers::function(Named_object* no)
239 {
240   go_assert(this->function_ == NULL);
241   this->function_ = no->func_value();
242   int t = this->function_->traverse(this);
243   this->function_ = NULL;
244 
245   if (t == TRAVERSE_EXIT)
246     return t;
247   return TRAVERSE_SKIP_COMPONENTS;
248 }
249 
250 // Insert write barriers for a global variable: ensure that variable
251 // initialization is handled correctly.  This is rarely needed, since
252 // we currently don't enable background GC until after all global
253 // variables are initialized.  But we do need this if an init function
254 // calls runtime.GC.
255 
256 int
variable(Named_object * no)257 Write_barriers::variable(Named_object* no)
258 {
259   // We handle local variables in the variable declaration statement.
260   // We only have to handle global variables here.
261   if (!no->is_variable())
262     return TRAVERSE_CONTINUE;
263   Variable* var = no->var_value();
264   if (!var->is_global())
265     return TRAVERSE_CONTINUE;
266 
267   // Nothing to do if there is no initializer.
268   Expression* init = var->init();
269   if (init == NULL)
270     return TRAVERSE_CONTINUE;
271 
272   // Nothing to do for variables that do not contain any pointers.
273   if (!var->type()->has_pointer())
274     return TRAVERSE_CONTINUE;
275 
276   // Nothing to do if the initializer is static.
277   init = Expression::make_cast(var->type(), init, var->location());
278   if (!var->has_pre_init() && init->is_static_initializer())
279     return TRAVERSE_CONTINUE;
280 
281   // Nothing to do for a type that can not be in the heap, or a
282   // pointer to a type that can not be in the heap.
283   if (!var->type()->in_heap())
284     return TRAVERSE_CONTINUE;
285   if (var->type()->points_to() != NULL && !var->type()->points_to()->in_heap())
286     return TRAVERSE_CONTINUE;
287 
288   // Otherwise change the initializer into a pre_init assignment
289   // statement with a write barrier.
290 
291   // We can't check for a dependency of the variable on itself after
292   // we make this change, because the preinit statement will always
293   // depend on the variable (since it assigns to it).  So check for a
294   // self-dependency now.
295   this->gogo_->check_self_dep(no);
296 
297   // Replace the initializer.
298   Location loc = init->location();
299   Expression* ref = Expression::make_var_reference(no, loc);
300 
301   Statement_inserter inserter(this->gogo_, var);
302   Statement* s = this->gogo_->assign_with_write_barrier(NULL, NULL, &inserter,
303 							ref, init, loc);
304 
305   var->add_preinit_statement(this->gogo_, s);
306   var->clear_init();
307 
308   return TRAVERSE_CONTINUE;
309 }
310 
311 // Insert write barriers for statements.
312 
313 int
statement(Block * block,size_t * pindex,Statement * s)314 Write_barriers::statement(Block* block, size_t* pindex, Statement* s)
315 {
316   switch (s->classification())
317     {
318     default:
319       break;
320 
321     case Statement::STATEMENT_VARIABLE_DECLARATION:
322       {
323 	Variable_declaration_statement* vds =
324 	  s->variable_declaration_statement();
325 	Named_object* no = vds->var();
326 	Variable* var = no->var_value();
327 
328 	// We may need to emit a write barrier for the initialization
329 	// of the variable.
330 
331 	// Nothing to do for a variable with no initializer.
332 	Expression* init = var->init();
333 	if (init == NULL)
334 	  break;
335 
336 	// Nothing to do if the variable is not in the heap.  Only
337 	// local variables get declaration statements, and local
338 	// variables on the stack do not require write barriers.
339 	if (!var->is_in_heap())
340 	  break;
341 
342 	// Nothing to do if the variable does not contain any pointers.
343 	if (!var->type()->has_pointer())
344 	  break;
345 
346 	// Nothing to do for a type that can not be in the heap, or a
347 	// pointer to a type that can not be in the heap.
348 	if (!var->type()->in_heap())
349 	  break;
350 	if (var->type()->points_to() != NULL
351 	    && !var->type()->points_to()->in_heap())
352 	  break;
353 
354 	// Otherwise initialize the variable with a write barrier.
355 
356 	Function* function = this->function_;
357 	Location loc = init->location();
358 	Statement_inserter inserter(block, pindex);
359 
360 	// Insert the variable declaration statement with no
361 	// initializer, so that the variable exists.
362 	var->clear_init();
363 	inserter.insert(s);
364 
365 	// Create a statement that initializes the variable with a
366 	// write barrier.
367 	Expression* ref = Expression::make_var_reference(no, loc);
368 	Statement* assign = this->gogo_->assign_with_write_barrier(function,
369 								   block,
370 								   &inserter,
371 								   ref, init,
372 								   loc);
373 
374 	// Replace the old variable declaration statement with the new
375 	// initialization.
376 	block->replace_statement(*pindex, assign);
377       }
378       break;
379 
380     case Statement::STATEMENT_ASSIGNMENT:
381       {
382 	Assignment_statement* as = s->assignment_statement();
383 	Expression* lhs = as->lhs();
384 	Expression* rhs = as->rhs();
385 
386 	// We may need to emit a write barrier for the assignment.
387 
388 	if (!this->gogo_->assign_needs_write_barrier(lhs))
389 	  break;
390 
391 	// Change the assignment to use a write barrier.
392 	Function* function = this->function_;
393 	Location loc = as->location();
394 	Statement_inserter inserter = Statement_inserter(block, pindex);
395 	Statement* assign = this->gogo_->assign_with_write_barrier(function,
396 								   block,
397 								   &inserter,
398 								   lhs, rhs,
399 								   loc);
400 	block->replace_statement(*pindex, assign);
401       }
402       break;
403     }
404 
405   return TRAVERSE_CONTINUE;
406 }
407 
408 // The write barrier pass.
409 
410 void
add_write_barriers()411 Gogo::add_write_barriers()
412 {
413   if (saw_errors())
414     return;
415 
416   Mark_address_taken mat(this);
417   this->traverse(&mat);
418 
419   if (this->compiling_runtime() && this->package_name() == "runtime")
420     {
421       Check_escape chk(this);
422       this->traverse(&chk);
423     }
424 
425   Write_barriers wb(this);
426   this->traverse(&wb);
427 }
428 
429 // Return the runtime.writeBarrier variable.
430 
431 Named_object*
write_barrier_variable()432 Gogo::write_barrier_variable()
433 {
434   static Named_object* write_barrier_var;
435   if (write_barrier_var == NULL)
436     {
437       Location bloc = Linemap::predeclared_location();
438 
439       // We pretend that writeBarrier is a uint32, so that we do a
440       // 32-bit load.  That is what the gc toolchain does.
441       Type* uint32_type = Type::lookup_integer_type("uint32");
442       Variable* var = new Variable(uint32_type, NULL, true, false, false,
443 				   bloc);
444 
445       bool add_to_globals;
446       Package* package = this->add_imported_package("runtime", "_", false,
447 						    "runtime", "runtime",
448 						    bloc, &add_to_globals);
449       write_barrier_var = Named_object::make_variable("writeBarrier",
450 						      package, var);
451     }
452 
453   return write_barrier_var;
454 }
455 
456 // Return whether an assignment that sets LHS needs a write barrier.
457 
458 bool
assign_needs_write_barrier(Expression * lhs)459 Gogo::assign_needs_write_barrier(Expression* lhs)
460 {
461   // Nothing to do if the variable does not contain any pointers.
462   if (!lhs->type()->has_pointer())
463     return false;
464 
465   // An assignment to a field is handled like an assignment to the
466   // struct.
467   while (true)
468     {
469       // Nothing to do for a type that can not be in the heap, or a
470       // pointer to a type that can not be in the heap.  We check this
471       // at each level of a struct.
472       if (!lhs->type()->in_heap())
473 	return false;
474       if (lhs->type()->points_to() != NULL
475 	  && !lhs->type()->points_to()->in_heap())
476 	return false;
477 
478       Field_reference_expression* fre = lhs->field_reference_expression();
479       if (fre == NULL)
480 	break;
481       lhs = fre->expr();
482     }
483 
484   // Nothing to do for an assignment to a temporary.
485   if (lhs->temporary_reference_expression() != NULL)
486     return false;
487 
488   // Nothing to do for an assignment to a sink.
489   if (lhs->is_sink_expression())
490     return false;
491 
492   // Nothing to do for an assignment to a local variable that is not
493   // on the heap.
494   Var_expression* ve = lhs->var_expression();
495   if (ve != NULL)
496     {
497       Named_object* no = ve->named_object();
498       if (no->is_variable())
499 	{
500 	  Variable* var = no->var_value();
501 	  if (!var->is_global() && !var->is_in_heap())
502 	    return false;
503 	}
504       else if (no->is_result_variable())
505 	{
506 	  Result_variable* rvar = no->result_var_value();
507 	  if (!rvar->is_in_heap())
508 	    return false;
509 	}
510     }
511 
512   // For a struct assignment, we don't need a write barrier if all the
513   // pointer types can not be in the heap.
514   Struct_type* st = lhs->type()->struct_type();
515   if (st != NULL)
516     {
517       bool in_heap = false;
518       const Struct_field_list* fields = st->fields();
519       for (Struct_field_list::const_iterator p = fields->begin();
520 	   p != fields->end();
521 	   p++)
522 	{
523 	  Type* ft = p->type();
524 	  if (!ft->has_pointer())
525 	    continue;
526 	  if (!ft->in_heap())
527 	    continue;
528 	  if (ft->points_to() != NULL && !ft->points_to()->in_heap())
529 	    continue;
530 	  in_heap = true;
531 	  break;
532 	}
533       if (!in_heap)
534 	return false;
535     }
536 
537   // Write barrier needed in other cases.
538   return true;
539 }
540 
541 // Return a statement that sets LHS to RHS using a write barrier.
542 // ENCLOSING is the enclosing block.
543 
544 Statement*
assign_with_write_barrier(Function * function,Block * enclosing,Statement_inserter * inserter,Expression * lhs,Expression * rhs,Location loc)545 Gogo::assign_with_write_barrier(Function* function, Block* enclosing,
546 				Statement_inserter* inserter, Expression* lhs,
547 				Expression* rhs, Location loc)
548 {
549   if (function != NULL
550       && ((function->pragmas() & GOPRAGMA_NOWRITEBARRIER) != 0
551 	  || (function->pragmas() & GOPRAGMA_NOWRITEBARRIERREC) != 0))
552     go_error_at(loc, "write barrier prohibited");
553 
554   Type* type = lhs->type();
555   go_assert(type->has_pointer());
556 
557   Expression* addr;
558   if (lhs->unary_expression() != NULL
559       && lhs->unary_expression()->op() == OPERATOR_MULT)
560     addr = lhs->unary_expression()->operand();
561   else
562     {
563       addr = Expression::make_unary(OPERATOR_AND, lhs, loc);
564       addr->unary_expression()->set_does_not_escape();
565     }
566   Temporary_statement* lhs_temp = Statement::make_temporary(NULL, addr, loc);
567   inserter->insert(lhs_temp);
568   lhs = Expression::make_temporary_reference(lhs_temp, loc);
569 
570   if (!Type::are_identical(type, rhs->type(), false, NULL)
571       && rhs->type()->interface_type() != NULL
572       && !rhs->is_variable())
573     {
574       // May need a temporary for interface conversion.
575       Temporary_statement* temp = Statement::make_temporary(NULL, rhs, loc);
576       inserter->insert(temp);
577       rhs = Expression::make_temporary_reference(temp, loc);
578     }
579   rhs = Expression::convert_for_assignment(this, type, rhs, loc);
580   Temporary_statement* rhs_temp = NULL;
581   if (!rhs->is_variable() && !rhs->is_constant())
582     {
583       rhs_temp = Statement::make_temporary(NULL, rhs, loc);
584       inserter->insert(rhs_temp);
585       rhs = Expression::make_temporary_reference(rhs_temp, loc);
586     }
587 
588   Expression* indir =
589       Expression::make_dereference(lhs, Expression::NIL_CHECK_DEFAULT, loc);
590   Statement* assign = Statement::make_assignment(indir, rhs, loc);
591 
592   lhs = Expression::make_temporary_reference(lhs_temp, loc);
593   if (rhs_temp != NULL)
594     rhs = Expression::make_temporary_reference(rhs_temp, loc);
595 
596   Type* unsafe_ptr_type = Type::make_pointer_type(Type::make_void_type());
597   lhs = Expression::make_unsafe_cast(unsafe_ptr_type, lhs, loc);
598 
599   Expression* call;
600   switch (type->base()->classification())
601     {
602     default:
603       go_unreachable();
604 
605     case Type::TYPE_ERROR:
606       return assign;
607 
608     case Type::TYPE_POINTER:
609     case Type::TYPE_FUNCTION:
610     case Type::TYPE_MAP:
611     case Type::TYPE_CHANNEL:
612       // These types are all represented by a single pointer.
613       call = Runtime::make_call(Runtime::WRITEBARRIERPTR, loc, 2, lhs, rhs);
614       break;
615 
616     case Type::TYPE_STRING:
617     case Type::TYPE_STRUCT:
618     case Type::TYPE_ARRAY:
619     case Type::TYPE_INTERFACE:
620       {
621 	rhs = Expression::make_unary(OPERATOR_AND, rhs, loc);
622 	rhs->unary_expression()->set_does_not_escape();
623 	call = Runtime::make_call(Runtime::TYPEDMEMMOVE, loc, 3,
624 				  Expression::make_type_descriptor(type, loc),
625 				  lhs, rhs);
626       }
627       break;
628     }
629 
630   return this->check_write_barrier(enclosing, assign,
631 				   Statement::make_statement(call, false));
632 }
633 
634 // Return a statement that tests whether write barriers are enabled
635 // and executes either the efficient code or the write barrier
636 // function call, depending.
637 
638 Statement*
check_write_barrier(Block * enclosing,Statement * without,Statement * with)639 Gogo::check_write_barrier(Block* enclosing, Statement* without,
640 			  Statement* with)
641 {
642   Location loc = without->location();
643   Named_object* wb = this->write_barrier_variable();
644   Expression* ref = Expression::make_var_reference(wb, loc);
645   Expression* zero = Expression::make_integer_ul(0, ref->type(), loc);
646   Expression* cond = Expression::make_binary(OPERATOR_EQEQ, ref, zero, loc);
647 
648   Block* then_block = new Block(enclosing, loc);
649   then_block->add_statement(without);
650 
651   Block* else_block = new Block(enclosing, loc);
652   else_block->add_statement(with);
653 
654   return Statement::make_if_statement(cond, then_block, else_block, loc);
655 }
656