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
merge done from the gofrontend repository.
......@@ -206,7 +206,9 @@ class Node
void
set_encoding(int enc);
// Is this node a sink?
bool
is_big(Escape_context*) const;
bool
is_sink() const;
......@@ -250,6 +252,11 @@ class Node
static int
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:
// The classification of this Node.
Node_classification classification_;
......
......@@ -2578,7 +2578,7 @@ class Label
public:
Label(const std::string& name)
: 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.
......@@ -2601,6 +2601,26 @@ class Label
set_is_used()
{ 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.
Location
location() const
......@@ -2660,6 +2680,16 @@ class Label
is_dummy_label() const
{ 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:
// The name of the label.
std::string name_;
......@@ -2675,6 +2705,8 @@ class Label
bool is_used_;
// The backend representation.
Blabel* blabel_;
// The looping depth of this label, for escape analysis.
Loop_depth depth_;
};
// An unnamed label. These are used when lowering loops.
......
......@@ -1793,40 +1793,6 @@ Statement::make_statement(Expression* expr, bool 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.
Bstatement*
......@@ -2944,37 +2910,13 @@ Statement::make_continue_statement(Unnamed_label* label,
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:
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_;
};
return TRAVERSE_CONTINUE;
}
// 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.
......@@ -3016,35 +2958,21 @@ Statement::make_goto_statement(Label* label, Location 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:
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()); }
return TRAVERSE_CONTINUE;
}
void
do_dump_statement(Ast_dump_context*) const;
// Convert the goto unnamed statement to the backend representation.
private:
Unnamed_label* label_;
};
Bstatement*
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
......@@ -3109,32 +3037,27 @@ Statement::make_label_statement(Label* label, Location location)
return new Label_statement(label, location);
}
// An unnamed label statement.
// Class Unnamed_label_statement.
class Unnamed_label_statement : public Statement
{
public:
Unnamed_label_statement(Unnamed_label* label)
: Statement(STATEMENT_UNNAMED_LABEL, label->location()),
label_(label)
{ }
Unnamed_label_statement::Unnamed_label_statement(Unnamed_label* label)
: Statement(STATEMENT_UNNAMED_LABEL, label->location()),
label_(label)
{ }
protected:
int
do_traverse(Traverse*)
{ return TRAVERSE_CONTINUE; }
int
Unnamed_label_statement::do_traverse(Traverse*)
{
return TRAVERSE_CONTINUE;
}
Bstatement*
do_get_backend(Translate_context* context)
{ return this->label_->get_definition(context); }
// Get the backend definition for this unnamed label statement.
void
do_dump_statement(Ast_dump_context*) const;
Bstatement*
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.
......@@ -5209,7 +5132,9 @@ For_statement::do_lower(Gogo*, Named_object*, Block* enclosing,
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.
......
......@@ -19,9 +19,13 @@ class Assignment_statement;
class Temporary_statement;
class Variable_declaration_statement;
class Expression_statement;
class Block_statement;
class Return_statement;
class Thunk_statement;
class Goto_statement;
class Goto_unnamed_statement;
class Label_statement;
class Unnamed_label_statement;
class If_statement;
class For_statement;
class For_range_statement;
......@@ -366,6 +370,12 @@ class Statement
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.
Return_statement*
return_statement()
......@@ -376,11 +386,26 @@ class 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.
Label_statement*
label_statement()
{ 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_statement*
if_statement()
......@@ -762,6 +787,50 @@ class Expression_statement : public Statement
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.
class Send_statement : public Statement
......@@ -1162,6 +1231,74 @@ class Defer_statement : public Thunk_statement
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.
class Label_statement : public Statement
......@@ -1173,7 +1310,7 @@ class Label_statement : public Statement
{ }
// Return the label itself.
const Label*
Label*
label() const
{ return this->label_; }
......@@ -1192,6 +1329,28 @@ class Label_statement : public Statement
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.
class If_statement : public Statement
......
......@@ -4502,10 +4502,7 @@ class Call_multiple_result_type : public Type
protected:
bool
do_has_pointer() const
{
go_assert(saw_errors());
return false;
}
{ return false; }
bool
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