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
merge done from the gofrontend repository.
......@@ -500,10 +500,20 @@ class Expression
is_constant() const
{ return this->do_is_constant(); }
// Return whether this is an immutable expression.
bool
is_immutable() const
{ return this->do_is_immutable(); }
// Return whether this expression can be used as a static
// initializer. This is true for an expression that has only
// numbers and pointers to global variables or composite literals
// 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,
// return true, and set VAL to hold the value.
......@@ -991,9 +1001,10 @@ class Expression
do_is_constant() const
{ return false; }
// Return whether this is an immutable expression.
// Return whether this expression can be used as a constant
// initializer.
virtual bool
do_is_immutable() const
do_is_static_initializer() const
{ return false; }
// Return whether this is a constant expression of numeric type, and
......@@ -1508,7 +1519,7 @@ class String_expression : public Expression
{ return true; }
bool
do_is_immutable() const
do_is_static_initializer() const
{ return true; }
bool
......@@ -1595,7 +1606,7 @@ class Type_conversion_expression : public Expression
do_is_constant() const;
bool
do_is_immutable() const;
do_is_static_initializer() const;
bool
do_numeric_constant_value(Numeric_constant*) const;
......@@ -1659,7 +1670,7 @@ class Unsafe_type_conversion_expression : public Expression
do_traverse(Traverse* traverse);
bool
do_is_immutable() const;
do_is_static_initializer() const;
Type*
do_type()
......@@ -1770,11 +1781,7 @@ class Unary_expression : public Expression
do_is_constant() const;
bool
do_is_immutable() const
{
return (this->expr_->is_immutable()
|| (this->op_ == OPERATOR_AND && this->expr_->is_variable()));
}
do_is_static_initializer() const;
bool
do_numeric_constant_value(Numeric_constant*) const;
......@@ -1913,8 +1920,7 @@ class Binary_expression : public Expression
{ return this->left_->is_constant() && this->right_->is_constant(); }
bool
do_is_immutable() const
{ return this->left_->is_immutable() && this->right_->is_immutable(); }
do_is_static_initializer() const;
bool
do_numeric_constant_value(Numeric_constant*) const;
......@@ -2029,7 +2035,7 @@ class String_concat_expression : public Expression
do_is_constant() const;
bool
do_is_immutable() const;
do_is_static_initializer() const;
Type*
do_type();
......@@ -3295,7 +3301,7 @@ class Struct_construction_expression : public Expression,
do_traverse(Traverse* traverse);
bool
do_is_immutable() const;
do_is_static_initializer() const;
Type*
do_type()
......@@ -3370,7 +3376,7 @@ protected:
do_traverse(Traverse* traverse);
bool
do_is_immutable() const;
do_is_static_initializer() const;
Type*
do_type()
......
......@@ -1299,29 +1299,35 @@ Gogo::write_globals()
// The initializer is constant if it is the zero-value of the
// variable's type or if the initial value is an immutable value
// that is not copied to the heap.
bool is_constant_initializer = false;
bool is_static_initializer = false;
if (var->init() == NULL)
is_constant_initializer = true;
is_static_initializer = true;
else
{
Type* var_type = var->type();
Expression* init = var->init();
Expression* init_cast =
Expression::make_cast(var_type, init, var->location());
is_constant_initializer =
init_cast->is_immutable() && !var_type->has_pointer();
is_static_initializer = init_cast->is_static_initializer();
}
// Non-constant variable initializations might need to create
// temporary variables, which will need the initialization
// function as context.
if (!is_constant_initializer && init_fndecl == NULL)
init_fndecl = this->initialization_function_decl();
Bexpression* var_binit = var->get_init(this, init_fndecl);
Named_object* var_init_fn;
if (is_static_initializer)
var_init_fn = NULL;
else
{
if (init_fndecl == NULL)
init_fndecl = this->initialization_function_decl();
var_init_fn = init_fndecl;
}
Bexpression* var_binit = var->get_init(this, var_init_fn);
if (var_binit == NULL)
;
else if (is_constant_initializer)
else if (is_static_initializer)
{
if (expression_requires(var->init(), NULL,
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