Commit 39de1955 by Ian Lance Taylor

compiler: rework static initializer code

    
    Rename is_immutable to is_static_initializer to try to capture what it
    really means.  Be more precise about when an address expression, or a
    binary expression, can be a static initializer.  Don't check whether a
    type has pointers when deciding whether an initializer must be
    read-write, just check whether it is being used to initialize a global
    variable.  To make that work set the Translate_context function to NULL
    for a global variable with a static initializer.
    
    The effect of this is to let more global variables be initialized
    directly, rather than being initialized in the generated init function.
    
    Reviewed-on: https://go-review.googlesource.com/32917

From-SVN: r242024
parent 677aa9b4
afe0456d25e3c6c0d91a8fd4c0fdfdbaa35cc251 cac897bd27885c18a16dacfe27d5efd4526455c5
The first line of this file holds the git revision number of the last The first line of this file holds the git revision number of the last
merge done from the gofrontend repository. merge done from the gofrontend repository.
...@@ -500,10 +500,20 @@ class Expression ...@@ -500,10 +500,20 @@ class Expression
is_constant() const is_constant() const
{ return this->do_is_constant(); } { return this->do_is_constant(); }
// Return whether this is an immutable expression. // Return whether this expression can be used as a static
bool // initializer. This is true for an expression that has only
is_immutable() const // numbers and pointers to global variables or composite literals
{ return this->do_is_immutable(); } // that do not require runtime initialization. It is false if we
// must generate code to compute this expression when it is used to
// initialize a global variable. This is not a language-level
// concept, but an implementation-level one. If this expression is
// used to initialize a global variable, this is true if we can pass
// an initializer to the backend, false if we must generate code to
// initialize the variable. It is always safe for this method to
// return false, but the resulting code may be less efficient.
bool
is_static_initializer() const
{ return this->do_is_static_initializer(); }
// If this is not a numeric constant, return false. If it is one, // If this is not a numeric constant, return false. If it is one,
// return true, and set VAL to hold the value. // return true, and set VAL to hold the value.
...@@ -991,9 +1001,10 @@ class Expression ...@@ -991,9 +1001,10 @@ class Expression
do_is_constant() const do_is_constant() const
{ return false; } { return false; }
// Return whether this is an immutable expression. // Return whether this expression can be used as a constant
// initializer.
virtual bool virtual bool
do_is_immutable() const do_is_static_initializer() const
{ return false; } { return false; }
// Return whether this is a constant expression of numeric type, and // Return whether this is a constant expression of numeric type, and
...@@ -1508,7 +1519,7 @@ class String_expression : public Expression ...@@ -1508,7 +1519,7 @@ class String_expression : public Expression
{ return true; } { return true; }
bool bool
do_is_immutable() const do_is_static_initializer() const
{ return true; } { return true; }
bool bool
...@@ -1595,7 +1606,7 @@ class Type_conversion_expression : public Expression ...@@ -1595,7 +1606,7 @@ class Type_conversion_expression : public Expression
do_is_constant() const; do_is_constant() const;
bool bool
do_is_immutable() const; do_is_static_initializer() const;
bool bool
do_numeric_constant_value(Numeric_constant*) const; do_numeric_constant_value(Numeric_constant*) const;
...@@ -1659,7 +1670,7 @@ class Unsafe_type_conversion_expression : public Expression ...@@ -1659,7 +1670,7 @@ class Unsafe_type_conversion_expression : public Expression
do_traverse(Traverse* traverse); do_traverse(Traverse* traverse);
bool bool
do_is_immutable() const; do_is_static_initializer() const;
Type* Type*
do_type() do_type()
...@@ -1770,11 +1781,7 @@ class Unary_expression : public Expression ...@@ -1770,11 +1781,7 @@ class Unary_expression : public Expression
do_is_constant() const; do_is_constant() const;
bool bool
do_is_immutable() const do_is_static_initializer() const;
{
return (this->expr_->is_immutable()
|| (this->op_ == OPERATOR_AND && this->expr_->is_variable()));
}
bool bool
do_numeric_constant_value(Numeric_constant*) const; do_numeric_constant_value(Numeric_constant*) const;
...@@ -1913,8 +1920,7 @@ class Binary_expression : public Expression ...@@ -1913,8 +1920,7 @@ class Binary_expression : public Expression
{ return this->left_->is_constant() && this->right_->is_constant(); } { return this->left_->is_constant() && this->right_->is_constant(); }
bool bool
do_is_immutable() const do_is_static_initializer() const;
{ return this->left_->is_immutable() && this->right_->is_immutable(); }
bool bool
do_numeric_constant_value(Numeric_constant*) const; do_numeric_constant_value(Numeric_constant*) const;
...@@ -2029,7 +2035,7 @@ class String_concat_expression : public Expression ...@@ -2029,7 +2035,7 @@ class String_concat_expression : public Expression
do_is_constant() const; do_is_constant() const;
bool bool
do_is_immutable() const; do_is_static_initializer() const;
Type* Type*
do_type(); do_type();
...@@ -3295,7 +3301,7 @@ class Struct_construction_expression : public Expression, ...@@ -3295,7 +3301,7 @@ class Struct_construction_expression : public Expression,
do_traverse(Traverse* traverse); do_traverse(Traverse* traverse);
bool bool
do_is_immutable() const; do_is_static_initializer() const;
Type* Type*
do_type() do_type()
...@@ -3370,7 +3376,7 @@ protected: ...@@ -3370,7 +3376,7 @@ protected:
do_traverse(Traverse* traverse); do_traverse(Traverse* traverse);
bool bool
do_is_immutable() const; do_is_static_initializer() const;
Type* Type*
do_type() do_type()
......
...@@ -1299,29 +1299,35 @@ Gogo::write_globals() ...@@ -1299,29 +1299,35 @@ Gogo::write_globals()
// The initializer is constant if it is the zero-value of the // The initializer is constant if it is the zero-value of the
// variable's type or if the initial value is an immutable value // variable's type or if the initial value is an immutable value
// that is not copied to the heap. // that is not copied to the heap.
bool is_constant_initializer = false; bool is_static_initializer = false;
if (var->init() == NULL) if (var->init() == NULL)
is_constant_initializer = true; is_static_initializer = true;
else else
{ {
Type* var_type = var->type(); Type* var_type = var->type();
Expression* init = var->init(); Expression* init = var->init();
Expression* init_cast = Expression* init_cast =
Expression::make_cast(var_type, init, var->location()); Expression::make_cast(var_type, init, var->location());
is_constant_initializer = is_static_initializer = init_cast->is_static_initializer();
init_cast->is_immutable() && !var_type->has_pointer();
} }
// Non-constant variable initializations might need to create // Non-constant variable initializations might need to create
// temporary variables, which will need the initialization // temporary variables, which will need the initialization
// function as context. // function as context.
if (!is_constant_initializer && init_fndecl == NULL) Named_object* var_init_fn;
if (is_static_initializer)
var_init_fn = NULL;
else
{
if (init_fndecl == NULL)
init_fndecl = this->initialization_function_decl(); init_fndecl = this->initialization_function_decl();
Bexpression* var_binit = var->get_init(this, init_fndecl); var_init_fn = init_fndecl;
}
Bexpression* var_binit = var->get_init(this, var_init_fn);
if (var_binit == NULL) if (var_binit == NULL)
; ;
else if (is_constant_initializer) else if (is_static_initializer)
{ {
if (expression_requires(var->init(), NULL, if (expression_requires(var->init(), NULL,
this->var_depends_on(var), no)) this->var_depends_on(var), no))
......
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