-97b949f249515a61d3c09e9e06f08c8af189e967
+b7bad96ce0af50a1129eaab9aa110d68a601917b
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.
true, copy_to_heap, false,
bexpr);
bexpr = gogo->backend()->var_expression(implicit, loc);
+
+ // If we are not copying a slice initializer to the heap,
+ // then it can be changed by the program, so if it can
+ // contain pointers we must register it as a GC root.
+ if (this->is_slice_init_
+ && !copy_to_heap
+ && this->expr_->type()->has_pointer())
+ {
+ Bexpression* root =
+ gogo->backend()->var_expression(implicit, loc);
+ root = gogo->backend()->address_expression(root, loc);
+ Type* type = Type::make_pointer_type(this->expr_->type());
+ gogo->add_gc_root(Expression::make_backend(root, type, loc));
+ }
}
else if ((this->expr_->is_composite_literal()
|| this->expr_->string_expression() != NULL)
return new Compound_expression(init, expr, location);
}
+// Class Backend_expression.
+
+int
+Backend_expression::do_traverse(Traverse*)
+{
+ return TRAVERSE_CONTINUE;
+}
+
+void
+Backend_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const
+{
+ ast_dump_context->ostream() << "backend_expression<";
+ ast_dump_context->dump_type(this->type_);
+ ast_dump_context->ostream() << ">";
+}
+
+Expression*
+Expression::make_backend(Bexpression* bexpr, Type* type, Location location)
+{
+ return new Backend_expression(bexpr, type, location);
+}
+
// Import an expression. This comes at the end in order to see the
// various class definitions.
EXPRESSION_STRUCT_FIELD_OFFSET,
EXPRESSION_LABEL_ADDR,
EXPRESSION_CONDITIONAL,
- EXPRESSION_COMPOUND
+ EXPRESSION_COMPOUND,
+ EXPRESSION_BACKEND
};
Expression(Expression_classification, Location);
static Expression*
make_compound(Expression*, Expression*, Location);
+ // Make a backend expression.
+ static Expression*
+ make_backend(Bexpression*, Type*, Location);
+
// Return the expression classification.
Expression_classification
classification() const
Expression* expr_;
};
+// A backend expression. This is a backend expression wrapped in an
+// Expression, for convenience during backend generation.
+
+class Backend_expression : public Expression
+{
+ public:
+ Backend_expression(Bexpression* bexpr, Type* type, Location location)
+ : Expression(EXPRESSION_BACKEND, location), bexpr_(bexpr), type_(type)
+ {}
+
+ protected:
+ int
+ do_traverse(Traverse*);
+
+ // For now these are always valid static initializers. If that
+ // changes we can change this.
+ bool
+ do_is_static_initializer() const
+ { return true; }
+
+ Type*
+ do_type()
+ { return this->type_; }
+
+ void
+ do_determine_type(const Type_context*)
+ { }
+
+ Expression*
+ do_copy()
+ {
+ return new Backend_expression(this->bexpr_, this->type_, this->location());
+ }
+
+ Bexpression*
+ do_get_backend(Translate_context*)
+ { return this->bexpr_; }
+
+ void
+ do_dump_expression(Ast_dump_context*) const;
+
+ private:
+ // The backend expression we are wrapping.
+ Bexpression* bexpr_;
+ // The type of the expression;
+ Type* type_;
+};
+
// A numeric constant. This is used both for untyped constants and
// for constants that have a type.
interface_types_(),
specific_type_functions_(),
specific_type_functions_are_written_(false),
- named_types_are_converted_(false)
+ named_types_are_converted_(false),
+ analysis_sets_(),
+ gc_roots_()
{
const Location loc = Linemap::predeclared_location();
Expression_list* roots_init = new Expression_list();
- size_t i = 0;
for (std::vector<Named_object*>::const_iterator p = var_gc.begin();
p != var_gc.end();
- ++p, ++i)
+ ++p)
{
Expression_list* init = new Expression_list();
roots_init->push_back(root_ctor);
}
+ for (std::vector<Expression*>::const_iterator p = this->gc_roots_.begin();
+ p != this->gc_roots_.end();
+ ++p)
+ {
+ Expression_list *init = new Expression_list();
+
+ Expression* expr = *p;
+ Location eloc = expr->location();
+ init->push_back(expr);
+
+ Type* type = expr->type()->points_to();
+ go_assert(type != NULL);
+ Expression* size =
+ Expression::make_type_info(type, Expression::TYPE_INFO_SIZE);
+ init->push_back(size);
+
+ Expression* root_ctor =
+ Expression::make_struct_composite_literal(root_type, init, eloc);
+ roots_init->push_back(root_ctor);
+ }
+
// The list ends with a NULL entry.
Expression_list* null_init = new Expression_list();
class Typed_identifier_list;
class Function_type;
class Expression;
+class Expression_list;
class Statement;
class Temporary_statement;
class Block;
specific_type_functions_are_written() const
{ return this->specific_type_functions_are_written_; }
+ // Add a pointer that needs to be added to the list of objects
+ // traversed by the garbage collector. This should be an expression
+ // of pointer type that points to static storage. It's not
+ // necessary to add global variables to this list, just global
+ // variable initializers that would otherwise not be seen.
+ void
+ add_gc_root(Expression* expr)
+ { this->gc_roots_.push_back(expr); }
+
// Traverse the tree. See the Traverse class.
void
traverse(Traverse*);
// A list containing groups of possibly mutually recursive functions to be
// considered during escape analysis.
std::vector<Analysis_set> analysis_sets_;
+ // A list of objects to add to the GC roots.
+ std::vector<Expression*> gc_roots_;
};
// A block of statements.