Commit 3db5773f by Ian Lance Taylor

escape: Implement assign phase.

    
    Implementation of the assign/connect phase.
    Statements containing expressions which alias local, parameter,
    and global objects are analyzed and the alias relationship between
    objects containing pointers are captured in a connection graph to
    summarize the assignments within a function.
    
    Reviewed-on: https://go-review.googlesource.com/18302

From-SVN: r237424
parent c8aa46d6
054ff1ece3dd5888a445efeaf3ae197b16d4186f f768153eb2a7a72587c9c0997955cdbbc70322d0
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.
...@@ -206,7 +206,9 @@ class Node ...@@ -206,7 +206,9 @@ class Node
void void
set_encoding(int enc); set_encoding(int enc);
// Is this node a sink? bool
is_big(Escape_context*) const;
bool bool
is_sink() const; is_sink() const;
...@@ -250,6 +252,11 @@ class Node ...@@ -250,6 +252,11 @@ class Node
static int static int
max_encoding(int e, int etype); max_encoding(int e, int etype);
// Return a modified encoding for an input parameter that flows into an
// output parameter.
static int
note_inout_flows(int e, int index, Level level);
private: private:
// The classification of this Node. // The classification of this Node.
Node_classification classification_; Node_classification classification_;
......
...@@ -2578,7 +2578,7 @@ class Label ...@@ -2578,7 +2578,7 @@ class Label
public: public:
Label(const std::string& name) Label(const std::string& name)
: name_(name), location_(Linemap::unknown_location()), snapshot_(NULL), : name_(name), location_(Linemap::unknown_location()), snapshot_(NULL),
refs_(), is_used_(false), blabel_(NULL) refs_(), is_used_(false), blabel_(NULL), depth_(DEPTH_UNKNOWN)
{ } { }
// Return the label's name. // Return the label's name.
...@@ -2601,6 +2601,26 @@ class Label ...@@ -2601,6 +2601,26 @@ class Label
set_is_used() set_is_used()
{ this->is_used_ = true; } { this->is_used_ = true; }
// Return whether this label is looping.
bool
looping() const
{ return this->depth_ == DEPTH_LOOPING; }
// Set this label as looping.
void
set_looping()
{ this->depth_ = DEPTH_LOOPING; }
// Return whether this label is nonlooping.
bool
nonlooping() const
{ return this->depth_ == DEPTH_NONLOOPING; }
// Set this label as nonlooping.
void
set_nonlooping()
{ this->depth_ = DEPTH_NONLOOPING; }
// Return the location of the definition. // Return the location of the definition.
Location Location
location() const location() const
...@@ -2660,6 +2680,16 @@ class Label ...@@ -2660,6 +2680,16 @@ class Label
is_dummy_label() const is_dummy_label() const
{ return this->name_ == "_"; } { return this->name_ == "_"; }
// A classification of a label's looping depth.
enum Loop_depth
{
DEPTH_UNKNOWN,
// A label never jumped to.
DEPTH_NONLOOPING,
// A label jumped to.
DEPTH_LOOPING
};
private: private:
// The name of the label. // The name of the label.
std::string name_; std::string name_;
...@@ -2675,6 +2705,8 @@ class Label ...@@ -2675,6 +2705,8 @@ class Label
bool is_used_; bool is_used_;
// The backend representation. // The backend representation.
Blabel* blabel_; Blabel* blabel_;
// The looping depth of this label, for escape analysis.
Loop_depth depth_;
}; };
// An unnamed label. These are used when lowering loops. // An unnamed label. These are used when lowering loops.
......
...@@ -1793,40 +1793,6 @@ Statement::make_statement(Expression* expr, bool is_ignored) ...@@ -1793,40 +1793,6 @@ Statement::make_statement(Expression* expr, bool is_ignored)
return new Expression_statement(expr, is_ignored); return new Expression_statement(expr, is_ignored);
} }
// A block statement--a list of statements which may include variable
// definitions.
class Block_statement : public Statement
{
public:
Block_statement(Block* block, Location location)
: Statement(STATEMENT_BLOCK, location),
block_(block)
{ }
protected:
int
do_traverse(Traverse* traverse)
{ return this->block_->traverse(traverse); }
void
do_determine_types()
{ this->block_->determine_types(); }
bool
do_may_fall_through() const
{ return this->block_->may_fall_through(); }
Bstatement*
do_get_backend(Translate_context* context);
void
do_dump_statement(Ast_dump_context*) const;
private:
Block* block_;
};
// Convert a block to the backend representation of a statement. // Convert a block to the backend representation of a statement.
Bstatement* Bstatement*
...@@ -2944,37 +2910,13 @@ Statement::make_continue_statement(Unnamed_label* label, ...@@ -2944,37 +2910,13 @@ Statement::make_continue_statement(Unnamed_label* label,
return new Bc_statement(false, label, location); return new Bc_statement(false, label, location);
} }
// A goto statement. // Class Goto_statement.
class Goto_statement : public Statement int
Goto_statement::do_traverse(Traverse*)
{ {
public: return TRAVERSE_CONTINUE;
Goto_statement(Label* label, Location location) }
: Statement(STATEMENT_GOTO, location),
label_(label)
{ }
protected:
int
do_traverse(Traverse*)
{ return TRAVERSE_CONTINUE; }
void
do_check_types(Gogo*);
bool
do_may_fall_through() const
{ return false; }
Bstatement*
do_get_backend(Translate_context*);
void
do_dump_statement(Ast_dump_context*) const;
private:
Label* label_;
};
// Check types for a label. There aren't any types per se, but we use // Check types for a label. There aren't any types per se, but we use
// this to give an error if the label was never defined. // this to give an error if the label was never defined.
...@@ -3016,35 +2958,21 @@ Statement::make_goto_statement(Label* label, Location location) ...@@ -3016,35 +2958,21 @@ Statement::make_goto_statement(Label* label, Location location)
return new Goto_statement(label, location); return new Goto_statement(label, location);
} }
// A goto statement to an unnamed label. // Class Goto_unnamed_statement.
class Goto_unnamed_statement : public Statement int
Goto_unnamed_statement::do_traverse(Traverse*)
{ {
public: return TRAVERSE_CONTINUE;
Goto_unnamed_statement(Unnamed_label* label, Location location) }
: Statement(STATEMENT_GOTO_UNNAMED, location),
label_(label)
{ }
protected:
int
do_traverse(Traverse*)
{ return TRAVERSE_CONTINUE; }
bool
do_may_fall_through() const
{ return false; }
Bstatement*
do_get_backend(Translate_context* context)
{ return this->label_->get_goto(context, this->location()); }
void // Convert the goto unnamed statement to the backend representation.
do_dump_statement(Ast_dump_context*) const;
private: Bstatement*
Unnamed_label* label_; Goto_unnamed_statement::do_get_backend(Translate_context* context)
}; {
return this->label_->get_goto(context, this->location());
}
// Dump the AST representation for an unnamed goto statement // Dump the AST representation for an unnamed goto statement
...@@ -3109,32 +3037,27 @@ Statement::make_label_statement(Label* label, Location location) ...@@ -3109,32 +3037,27 @@ Statement::make_label_statement(Label* label, Location location)
return new Label_statement(label, location); return new Label_statement(label, location);
} }
// An unnamed label statement. // Class Unnamed_label_statement.
class Unnamed_label_statement : public Statement Unnamed_label_statement::Unnamed_label_statement(Unnamed_label* label)
{ : Statement(STATEMENT_UNNAMED_LABEL, label->location()),
public: label_(label)
Unnamed_label_statement(Unnamed_label* label) { }
: Statement(STATEMENT_UNNAMED_LABEL, label->location()),
label_(label)
{ }
protected: int
int Unnamed_label_statement::do_traverse(Traverse*)
do_traverse(Traverse*) {
{ return TRAVERSE_CONTINUE; } return TRAVERSE_CONTINUE;
}
Bstatement* // Get the backend definition for this unnamed label statement.
do_get_backend(Translate_context* context)
{ return this->label_->get_definition(context); }
void Bstatement*
do_dump_statement(Ast_dump_context*) const; Unnamed_label_statement::do_get_backend(Translate_context* context)
{
return this->label_->get_definition(context);
}
private:
// The label.
Unnamed_label* label_;
};
// Dump the AST representation for an unnamed label definition statement. // Dump the AST representation for an unnamed label definition statement.
...@@ -5209,7 +5132,9 @@ For_statement::do_lower(Gogo*, Named_object*, Block* enclosing, ...@@ -5209,7 +5132,9 @@ For_statement::do_lower(Gogo*, Named_object*, Block* enclosing,
b->set_end_location(end_loc); b->set_end_location(end_loc);
return Statement::make_block_statement(b, loc); Statement* bs = Statement::make_block_statement(b, loc);
bs->block_statement()->set_is_lowered_for_statement();
return bs;
} }
// Return the break label, creating it if necessary. // Return the break label, creating it if necessary.
......
...@@ -19,9 +19,13 @@ class Assignment_statement; ...@@ -19,9 +19,13 @@ class Assignment_statement;
class Temporary_statement; class Temporary_statement;
class Variable_declaration_statement; class Variable_declaration_statement;
class Expression_statement; class Expression_statement;
class Block_statement;
class Return_statement; class Return_statement;
class Thunk_statement; class Thunk_statement;
class Goto_statement;
class Goto_unnamed_statement;
class Label_statement; class Label_statement;
class Unnamed_label_statement;
class If_statement; class If_statement;
class For_statement; class For_statement;
class For_range_statement; class For_range_statement;
...@@ -366,6 +370,12 @@ class Statement ...@@ -366,6 +370,12 @@ class Statement
return this->convert<Expression_statement, STATEMENT_EXPRESSION>(); return this->convert<Expression_statement, STATEMENT_EXPRESSION>();
} }
// If this is an block statement, return it. Otherwise return
// NULL.
Block_statement*
block_statement()
{ return this->convert<Block_statement, STATEMENT_BLOCK>(); }
// If this is a return statement, return it. Otherwise return NULL. // If this is a return statement, return it. Otherwise return NULL.
Return_statement* Return_statement*
return_statement() return_statement()
...@@ -376,11 +386,26 @@ class Statement ...@@ -376,11 +386,26 @@ class Statement
Thunk_statement* Thunk_statement*
thunk_statement(); thunk_statement();
// If this is a goto statement, return it. Otherwise return NULL.
Goto_statement*
goto_statement()
{ return this->convert<Goto_statement, STATEMENT_GOTO>(); }
// If this is a goto_unnamed statement, return it. Otherwise return NULL.
Goto_unnamed_statement*
goto_unnamed_statement()
{ return this->convert<Goto_unnamed_statement, STATEMENT_GOTO_UNNAMED>(); }
// If this is a label statement, return it. Otherwise return NULL. // If this is a label statement, return it. Otherwise return NULL.
Label_statement* Label_statement*
label_statement() label_statement()
{ return this->convert<Label_statement, STATEMENT_LABEL>(); } { return this->convert<Label_statement, STATEMENT_LABEL>(); }
// If this is an unnamed_label statement, return it. Otherwise return NULL.
Unnamed_label_statement*
unnamed_label_statement()
{ return this->convert<Unnamed_label_statement, STATEMENT_UNNAMED_LABEL>(); }
// If this is an if statement, return it. Otherwise return NULL. // If this is an if statement, return it. Otherwise return NULL.
If_statement* If_statement*
if_statement() if_statement()
...@@ -762,6 +787,50 @@ class Expression_statement : public Statement ...@@ -762,6 +787,50 @@ class Expression_statement : public Statement
bool is_ignored_; bool is_ignored_;
}; };
// A block statement--a list of statements which may include variable
// definitions.
class Block_statement : public Statement
{
public:
Block_statement(Block* block, Location location)
: Statement(STATEMENT_BLOCK, location),
block_(block), is_lowered_for_statement_(false)
{ }
void
set_is_lowered_for_statement()
{ this->is_lowered_for_statement_ = true; }
bool
is_lowered_for_statement()
{ return this->is_lowered_for_statement_; }
protected:
int
do_traverse(Traverse* traverse)
{ return this->block_->traverse(traverse); }
void
do_determine_types()
{ this->block_->determine_types(); }
bool
do_may_fall_through() const
{ return this->block_->may_fall_through(); }
Bstatement*
do_get_backend(Translate_context* context);
void
do_dump_statement(Ast_dump_context*) const;
private:
Block* block_;
// True if this block statement represents a lowered for statement.
bool is_lowered_for_statement_;
};
// A send statement. // A send statement.
class Send_statement : public Statement class Send_statement : public Statement
...@@ -1162,6 +1231,74 @@ class Defer_statement : public Thunk_statement ...@@ -1162,6 +1231,74 @@ class Defer_statement : public Thunk_statement
do_dump_statement(Ast_dump_context*) const; do_dump_statement(Ast_dump_context*) const;
}; };
// A goto statement.
class Goto_statement : public Statement
{
public:
Goto_statement(Label* label, Location location)
: Statement(STATEMENT_GOTO, location),
label_(label)
{ }
// Return the label being jumped to.
Label*
label() const
{ return this->label_; }
protected:
int
do_traverse(Traverse*);
void
do_check_types(Gogo*);
bool
do_may_fall_through() const
{ return false; }
Bstatement*
do_get_backend(Translate_context*);
void
do_dump_statement(Ast_dump_context*) const;
private:
Label* label_;
};
// A goto statement to an unnamed label.
class Goto_unnamed_statement : public Statement
{
public:
Goto_unnamed_statement(Unnamed_label* label, Location location)
: Statement(STATEMENT_GOTO_UNNAMED, location),
label_(label)
{ }
Unnamed_label*
unnamed_label() const
{ return this->label_; }
protected:
int
do_traverse(Traverse*);
bool
do_may_fall_through() const
{ return false; }
Bstatement*
do_get_backend(Translate_context* context);
void
do_dump_statement(Ast_dump_context*) const;
private:
Unnamed_label* label_;
};
// A label statement. // A label statement.
class Label_statement : public Statement class Label_statement : public Statement
...@@ -1173,7 +1310,7 @@ class Label_statement : public Statement ...@@ -1173,7 +1310,7 @@ class Label_statement : public Statement
{ } { }
// Return the label itself. // Return the label itself.
const Label* Label*
label() const label() const
{ return this->label_; } { return this->label_; }
...@@ -1192,6 +1329,28 @@ class Label_statement : public Statement ...@@ -1192,6 +1329,28 @@ class Label_statement : public Statement
Label* label_; Label* label_;
}; };
// An unnamed label statement.
class Unnamed_label_statement : public Statement
{
public:
Unnamed_label_statement(Unnamed_label* label);
protected:
int
do_traverse(Traverse*);
Bstatement*
do_get_backend(Translate_context* context);
void
do_dump_statement(Ast_dump_context*) const;
private:
// The label.
Unnamed_label* label_;
};
// An if statement. // An if statement.
class If_statement : public Statement class If_statement : public Statement
......
...@@ -4502,10 +4502,7 @@ class Call_multiple_result_type : public Type ...@@ -4502,10 +4502,7 @@ class Call_multiple_result_type : public Type
protected: protected:
bool bool
do_has_pointer() const do_has_pointer() const
{ { return false; }
go_assert(saw_errors());
return false;
}
bool bool
do_compare_is_identity(Gogo*) do_compare_is_identity(Gogo*)
......
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