Commit 5ee9259f by Ian Lance Taylor

Generate an init function if any global variable needs a preinit.

From-SVN: r169023
parent e9dd48d9
...@@ -1395,8 +1395,6 @@ Gogo::determine_types() ...@@ -1395,8 +1395,6 @@ Gogo::determine_types()
// initialization, we need an initialization function. // initialization, we need an initialization function.
if (!variable->is_global()) if (!variable->is_global())
; ;
else if (variable->has_pre_init())
this->need_init_fn_ = true;
else if (variable->init() == NULL) else if (variable->init() == NULL)
; ;
else if (variable->type()->interface_type() != NULL) else if (variable->type()->interface_type() != NULL)
...@@ -1604,9 +1602,10 @@ Find_shortcut::expression(Expression** pexpr) ...@@ -1604,9 +1602,10 @@ Find_shortcut::expression(Expression** pexpr)
class Shortcuts : public Traverse class Shortcuts : public Traverse
{ {
public: public:
Shortcuts() Shortcuts(Gogo* gogo)
: Traverse(traverse_variables : Traverse(traverse_variables
| traverse_statements) | traverse_statements),
gogo_(gogo)
{ } { }
protected: protected:
...@@ -1620,6 +1619,9 @@ class Shortcuts : public Traverse ...@@ -1620,6 +1619,9 @@ class Shortcuts : public Traverse
// Convert a shortcut operator. // Convert a shortcut operator.
Statement* Statement*
convert_shortcut(Block* enclosing, Expression** pshortcut); convert_shortcut(Block* enclosing, Expression** pshortcut);
// The IR.
Gogo* gogo_;
}; };
// Remove shortcut operators in a single statement. // Remove shortcut operators in a single statement.
...@@ -1687,7 +1689,7 @@ Shortcuts::variable(Named_object* no) ...@@ -1687,7 +1689,7 @@ Shortcuts::variable(Named_object* no)
return TRAVERSE_CONTINUE; return TRAVERSE_CONTINUE;
Statement* snew = this->convert_shortcut(NULL, pshortcut); Statement* snew = this->convert_shortcut(NULL, pshortcut);
var->add_preinit_statement(snew); var->add_preinit_statement(this->gogo_, snew);
if (pshortcut == &init) if (pshortcut == &init)
var->set_init(init); var->set_init(init);
} }
...@@ -1730,7 +1732,7 @@ Shortcuts::convert_shortcut(Block* enclosing, Expression** pshortcut) ...@@ -1730,7 +1732,7 @@ Shortcuts::convert_shortcut(Block* enclosing, Expression** pshortcut)
delete shortcut; delete shortcut;
// Now convert any shortcut operators in LEFT and RIGHT. // Now convert any shortcut operators in LEFT and RIGHT.
Shortcuts shortcuts; Shortcuts shortcuts(this->gogo_);
retblock->traverse(&shortcuts); retblock->traverse(&shortcuts);
return Statement::make_block_statement(retblock, loc); return Statement::make_block_statement(retblock, loc);
...@@ -1742,7 +1744,7 @@ Shortcuts::convert_shortcut(Block* enclosing, Expression** pshortcut) ...@@ -1742,7 +1744,7 @@ Shortcuts::convert_shortcut(Block* enclosing, Expression** pshortcut)
void void
Gogo::remove_shortcuts() Gogo::remove_shortcuts()
{ {
Shortcuts shortcuts; Shortcuts shortcuts(this);
this->traverse(&shortcuts); this->traverse(&shortcuts);
} }
...@@ -1812,9 +1814,10 @@ Find_eval_ordering::expression(Expression** expression_pointer) ...@@ -1812,9 +1814,10 @@ Find_eval_ordering::expression(Expression** expression_pointer)
class Order_eval : public Traverse class Order_eval : public Traverse
{ {
public: public:
Order_eval() Order_eval(Gogo* gogo)
: Traverse(traverse_variables : Traverse(traverse_variables
| traverse_statements) | traverse_statements),
gogo_(gogo)
{ } { }
int int
...@@ -1822,6 +1825,10 @@ class Order_eval : public Traverse ...@@ -1822,6 +1825,10 @@ class Order_eval : public Traverse
int int
statement(Block*, size_t*, Statement*); statement(Block*, size_t*, Statement*);
private:
// The IR.
Gogo* gogo_;
}; };
// Implement the order of evaluation rules for a statement. // Implement the order of evaluation rules for a statement.
...@@ -1942,7 +1949,7 @@ Order_eval::variable(Named_object* no) ...@@ -1942,7 +1949,7 @@ Order_eval::variable(Named_object* no)
Expression** pexpr = *p; Expression** pexpr = *p;
source_location loc = (*pexpr)->location(); source_location loc = (*pexpr)->location();
Temporary_statement* ts = Statement::make_temporary(NULL, *pexpr, loc); Temporary_statement* ts = Statement::make_temporary(NULL, *pexpr, loc);
var->add_preinit_statement(ts); var->add_preinit_statement(this->gogo_, ts);
*pexpr = Expression::make_temporary_reference(ts, loc); *pexpr = Expression::make_temporary_reference(ts, loc);
} }
...@@ -1954,7 +1961,7 @@ Order_eval::variable(Named_object* no) ...@@ -1954,7 +1961,7 @@ Order_eval::variable(Named_object* no)
void void
Gogo::order_evaluations() Gogo::order_evaluations()
{ {
Order_eval order_eval; Order_eval order_eval(this);
this->traverse(&order_eval); this->traverse(&order_eval);
} }
...@@ -3155,20 +3162,25 @@ Variable::lower_init_expression(Gogo* gogo, Named_object* function) ...@@ -3155,20 +3162,25 @@ Variable::lower_init_expression(Gogo* gogo, Named_object* function)
// Get the preinit block. // Get the preinit block.
Block* Block*
Variable::preinit_block() Variable::preinit_block(Gogo* gogo)
{ {
gcc_assert(this->is_global_); gcc_assert(this->is_global_);
if (this->preinit_ == NULL) if (this->preinit_ == NULL)
this->preinit_ = new Block(NULL, this->location()); this->preinit_ = new Block(NULL, this->location());
// If a global variable has a preinitialization statement, then we
// need to have an initialization function.
gogo->set_need_init_fn();
return this->preinit_; return this->preinit_;
} }
// Add a statement to be run before the initialization expression. // Add a statement to be run before the initialization expression.
void void
Variable::add_preinit_statement(Statement* s) Variable::add_preinit_statement(Gogo* gogo, Statement* s)
{ {
Block* b = this->preinit_block(); Block* b = this->preinit_block(gogo);
b->add_statement(s); b->add_statement(s);
b->set_end_location(s->location()); b->set_end_location(s->location());
} }
......
...@@ -318,6 +318,11 @@ class Gogo ...@@ -318,6 +318,11 @@ class Gogo
void void
record_interface_type(Interface_type*); record_interface_type(Interface_type*);
// Note that we need an initialization function.
void
set_need_init_fn()
{ this->need_init_fn_ = true; }
// Clear out all names in file scope. This is called when we start // Clear out all names in file scope. This is called when we start
// parsing a new file. // parsing a new file.
void void
...@@ -1143,12 +1148,12 @@ class Variable ...@@ -1143,12 +1148,12 @@ class Variable
// Get the preinit block, a block of statements to be run before the // Get the preinit block, a block of statements to be run before the
// initialization expression. // initialization expression.
Block* Block*
preinit_block(); preinit_block(Gogo*);
// Add a statement to be run before the initialization expression. // Add a statement to be run before the initialization expression.
// This is only used for global variables. // This is only used for global variables.
void void
add_preinit_statement(Statement*); add_preinit_statement(Gogo*, Statement*);
// Lower the initialization expression after parsing is complete. // Lower the initialization expression after parsing is complete.
void void
......
...@@ -1657,12 +1657,12 @@ Parse::init_vars_from_map(const Typed_identifier_list* vars, Type* type, ...@@ -1657,12 +1657,12 @@ Parse::init_vars_from_map(const Typed_identifier_list* vars, Type* type,
else if (!val_no->is_sink()) else if (!val_no->is_sink())
{ {
if (val_no->is_variable()) if (val_no->is_variable())
val_no->var_value()->add_preinit_statement(s); val_no->var_value()->add_preinit_statement(this->gogo_, s);
} }
else if (!no->is_sink()) else if (!no->is_sink())
{ {
if (no->is_variable()) if (no->is_variable())
no->var_value()->add_preinit_statement(s); no->var_value()->add_preinit_statement(this->gogo_, s);
} }
else else
{ {
...@@ -1670,7 +1670,7 @@ Parse::init_vars_from_map(const Typed_identifier_list* vars, Type* type, ...@@ -1670,7 +1670,7 @@ Parse::init_vars_from_map(const Typed_identifier_list* vars, Type* type,
// the map is nil. // the map is nil.
Named_object* dummy = this->create_dummy_global(Type::lookup_bool_type(), Named_object* dummy = this->create_dummy_global(Type::lookup_bool_type(),
NULL, location); NULL, location);
dummy->var_value()->add_preinit_statement(s); dummy->var_value()->add_preinit_statement(this->gogo_, s);
} }
return true; return true;
...@@ -1724,18 +1724,18 @@ Parse::init_vars_from_receive(const Typed_identifier_list* vars, Type* type, ...@@ -1724,18 +1724,18 @@ Parse::init_vars_from_receive(const Typed_identifier_list* vars, Type* type,
else if (!val_no->is_sink()) else if (!val_no->is_sink())
{ {
if (val_no->is_variable()) if (val_no->is_variable())
val_no->var_value()->add_preinit_statement(s); val_no->var_value()->add_preinit_statement(this->gogo_, s);
} }
else if (!no->is_sink()) else if (!no->is_sink())
{ {
if (no->is_variable()) if (no->is_variable())
no->var_value()->add_preinit_statement(s); no->var_value()->add_preinit_statement(this->gogo_, s);
} }
else else
{ {
Named_object* dummy = this->create_dummy_global(Type::lookup_bool_type(), Named_object* dummy = this->create_dummy_global(Type::lookup_bool_type(),
NULL, location); NULL, location);
dummy->var_value()->add_preinit_statement(s); dummy->var_value()->add_preinit_statement(this->gogo_, s);
} }
return true; return true;
...@@ -1790,17 +1790,17 @@ Parse::init_vars_from_type_guard(const Typed_identifier_list* vars, ...@@ -1790,17 +1790,17 @@ Parse::init_vars_from_type_guard(const Typed_identifier_list* vars,
else if (!val_no->is_sink()) else if (!val_no->is_sink())
{ {
if (val_no->is_variable()) if (val_no->is_variable())
val_no->var_value()->add_preinit_statement(s); val_no->var_value()->add_preinit_statement(this->gogo_, s);
} }
else if (!no->is_sink()) else if (!no->is_sink())
{ {
if (no->is_variable()) if (no->is_variable())
no->var_value()->add_preinit_statement(s); no->var_value()->add_preinit_statement(this->gogo_, s);
} }
else else
{ {
Named_object* dummy = this->create_dummy_global(type, NULL, location); Named_object* dummy = this->create_dummy_global(type, NULL, location);
dummy->var_value()->add_preinit_statement(s); dummy->var_value()->add_preinit_statement(this->gogo_, s);
} }
return true; return true;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment