escape: Remove previously existing analysis.

* Make-lang.in (GO_OBJS): Remove go/dataflow.o, go/escape.o.

    Reviewed-on: https://go-review.googlesource.com/18261

From-SVN: r235649
This commit is contained in:
Chris Manghane 2016-04-29 17:33:01 +00:00 committed by Ian Lance Taylor
parent 52d11a4bbf
commit e49aacaf30
17 changed files with 11 additions and 2742 deletions

View File

@ -1,3 +1,7 @@
2016-04-29 Chris Manghane <cmang@google.com>
* Make-lang.in (GO_OBJS): Remove go/dataflow.o, go/escape.o.
2016-04-18 Michael Matz <matz@suse.de>
* go-gcc.cc (Gcc_backend::implicit_variable): Use SET_DECL_ALIGN.

View File

@ -50,8 +50,6 @@ go-warn = $(STRICT_WARN)
GO_OBJS = \
go/ast-dump.o \
go/dataflow.o \
go/escape.o \
go/export.o \
go/expressions.o \
go/go-backend.o \

View File

@ -1,4 +1,4 @@
50b2b468a85045c66d60112dc094c31ec4897123
46b108136c0d102f181f0cc7c398e3db8c4d08a3
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.

View File

@ -1,299 +0,0 @@
// dataflow.cc -- Go frontend dataflow.
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#include "go-system.h"
#include "gogo.h"
#include "expressions.h"
#include "statements.h"
#include "dataflow.h"
// This class is used to traverse the tree to look for uses of
// variables.
class Dataflow_traverse_expressions : public Traverse
{
public:
Dataflow_traverse_expressions(Dataflow* dataflow, Statement* statement)
: Traverse(traverse_blocks | traverse_expressions),
dataflow_(dataflow), statement_(statement)
{ }
protected:
// Only look at top-level expressions: do not descend into blocks.
// They will be examined via Dataflow_traverse_statements.
int
block(Block*)
{ return TRAVERSE_SKIP_COMPONENTS; }
int
expression(Expression**);
private:
// The dataflow information.
Dataflow* dataflow_;
// The Statement in which we are looking.
Statement* statement_;
};
// Given an expression, return the Named_object that it refers to, if
// it is a local variable.
static Named_object*
get_var(Expression* expr)
{
Var_expression* ve = expr->var_expression();
if (ve == NULL)
return NULL;
Named_object* no = ve->named_object();
go_assert(no->is_variable() || no->is_result_variable());
if (no->is_variable() && no->var_value()->is_global())
return NULL;
return no;
}
// Look for a reference to a variable in an expression.
int
Dataflow_traverse_expressions::expression(Expression** expr)
{
Named_object* no = get_var(*expr);
if (no != NULL)
this->dataflow_->add_ref(no, this->statement_);
return TRAVERSE_CONTINUE;
}
// This class is used to handle an assignment statement.
class Dataflow_traverse_assignment : public Traverse_assignments
{
public:
Dataflow_traverse_assignment(Dataflow* dataflow, Statement* statement)
: dataflow_(dataflow), statement_(statement)
{ }
protected:
void
initialize_variable(Named_object*);
void
assignment(Expression** lhs, Expression** rhs);
void
value(Expression**, bool, bool);
private:
// The dataflow information.
Dataflow* dataflow_;
// The Statement in which we are looking.
Statement* statement_;
};
// Handle a variable initialization.
void
Dataflow_traverse_assignment::initialize_variable(Named_object* var)
{
Expression* init = var->var_value()->init();
this->dataflow_->add_def(var, init, this->statement_, true);
if (init != NULL)
{
Expression* e = init;
this->value(&e, true, true);
go_assert(e == init);
}
}
// Handle an assignment in a statement.
void
Dataflow_traverse_assignment::assignment(Expression** plhs, Expression** prhs)
{
Named_object* no = get_var(*plhs);
if (no != NULL)
{
Expression* rhs = prhs == NULL ? NULL : *prhs;
this->dataflow_->add_def(no, rhs, this->statement_, false);
}
else
{
// If this is not a variable it may be some computed lvalue, and
// we want to look for references to variables in that lvalue.
this->value(plhs, false, false);
}
if (prhs != NULL)
this->value(prhs, true, false);
}
// Handle a value in a statement.
void
Dataflow_traverse_assignment::value(Expression** pexpr, bool, bool)
{
Named_object* no = get_var(*pexpr);
if (no != NULL)
this->dataflow_->add_ref(no, this->statement_);
else
{
Dataflow_traverse_expressions dte(this->dataflow_, this->statement_);
Expression::traverse(pexpr, &dte);
}
}
// This class is used to traverse the tree to look for statements.
class Dataflow_traverse_statements : public Traverse
{
public:
Dataflow_traverse_statements(Dataflow* dataflow)
: Traverse(traverse_statements),
dataflow_(dataflow)
{ }
protected:
int
statement(Block*, size_t* pindex, Statement*);
private:
// The dataflow information.
Dataflow* dataflow_;
};
// For each Statement, we look for expressions.
int
Dataflow_traverse_statements::statement(Block* block, size_t* pindex,
Statement *statement)
{
Dataflow_traverse_assignment dta(this->dataflow_, statement);
// For thunk statements, make sure to traverse the call expression to
// find any reference to a variable being used as an argument.
if (!statement->traverse_assignments(&dta)
|| statement->thunk_statement() != NULL)
{
// Case statements in selects will be lowered into temporaries at this
// point so our dataflow analysis will miss references between a/c and ch
// in case statements of the form a,c := <-ch. Do a special dataflow
// analysis for select statements here; the analysis for the blocks will
// be handled as usual.
if (statement->select_statement() != NULL)
statement->select_statement()->analyze_dataflow(this->dataflow_);
Dataflow_traverse_expressions dte(this->dataflow_, statement);
statement->traverse(block, pindex, &dte);
}
return TRAVERSE_CONTINUE;
}
// Compare variables.
bool
Dataflow::Compare_vars::operator()(const Named_object* no1,
const Named_object* no2) const
{
if (no1->name() < no2->name())
return true;
if (no1->name() > no2->name())
return false;
// We can have two different variables with the same name.
Location loc1 = no1->location();
Location loc2 = no2->location();
if (loc1 < loc2)
return false;
if (loc1 > loc2)
return true;
if (Linemap::is_predeclared_location(loc1))
return false;
if (no1 == no2
|| (no1->is_result_variable()
&& no2->is_result_variable())
|| ((no1->is_variable()
&& no1->var_value()->is_type_switch_var())
&& (no2->is_variable()
&& no2->var_value()->is_type_switch_var())))
return false;
// We can't have two variables with the same name in the same
// location unless they are type switch variables which share the same
// fake location.
go_unreachable();
}
// Class Dataflow.
Dataflow::Dataflow()
: defs_(), refs_()
{
}
// Build the dataflow information.
void
Dataflow::initialize(Gogo* gogo)
{
Dataflow_traverse_statements dts(this);
gogo->traverse(&dts);
}
// Add a definition of a variable.
void
Dataflow::add_def(Named_object* var, Expression* val, Statement* statement,
bool is_init)
{
Defs* defnull = NULL;
std::pair<Defmap::iterator, bool> ins =
this->defs_.insert(std::make_pair(var, defnull));
if (ins.second)
ins.first->second = new Defs;
Def def;
def.statement = statement;
def.val = val;
def.is_init = is_init;
ins.first->second->push_back(def);
}
// Add a reference to a variable.
void
Dataflow::add_ref(Named_object* var, Statement* statement)
{
Refs* refnull = NULL;
std::pair<Refmap::iterator, bool> ins =
this->refs_.insert(std::make_pair(var, refnull));
if (ins.second)
ins.first->second = new Refs;
Ref ref;
ref.statement = statement;
ins.first->second->push_back(ref);
}
// Return the definitions of a variable.
const Dataflow::Defs*
Dataflow::find_defs(Named_object* var) const
{
Defmap::const_iterator p = this->defs_.find(var);
if (p == this->defs_.end())
return NULL;
else
return p->second;
}
// Return the references of a variable.
const Dataflow::Refs*
Dataflow::find_refs(Named_object* var) const
{
Refmap::const_iterator p = this->refs_.find(var);
if (p == this->refs_.end())
return NULL;
else
return p->second;
}

View File

@ -1,91 +0,0 @@
// dataflow.h -- Go frontend dataflow. -*- C++ -*-
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#ifndef GO_DATAFLOW_H
#define GO_DATAFLOW_H
class Expression;
class Named_object;
class Statement;
// Dataflow information about the Go program.
class Dataflow
{
public:
// A variable definition.
struct Def
{
// The statement where the variable is defined.
Statement* statement;
// The value to which the variable is set. This may be NULL.
Expression* val;
// Whether this is an initialization of the variable.
bool is_init;
};
// A variable reference.
struct Ref
{
// The statement where the variable is referenced.
Statement* statement;
};
// A list of defs.
typedef std::vector<Def> Defs;
// A list of refs.
typedef std::vector<Ref> Refs;
Dataflow();
// Initialize the dataflow information.
void
initialize(Gogo*);
// Add a definition of a variable. STATEMENT assigns a value to
// VAR. VAL is the value if it is known, NULL otherwise.
void
add_def(Named_object* var, Expression* val, Statement* statement,
bool is_init);
// Add a reference to a variable. VAR is the variable, and
// STATEMENT is the statement which refers to it.
void
add_ref(Named_object* var, Statement* statement);
// Return the definitions of VAR--the places where it is set.
const Defs*
find_defs(Named_object* var) const;
// Return the references to VAR--the places where it is used.
const Refs*
find_refs(Named_object* var) const;
private:
// Order variables in the map.
struct Compare_vars
{
bool
operator()(const Named_object*, const Named_object*) const;
};
// Map from variables to a list of defs of the variable. We use a
// map rather than a hash table because the order in which we
// process variables may affect the resulting code.
typedef std::map<Named_object*, Defs*, Compare_vars> Defmap;
// Map from variables to a list of refs to the vairable.
typedef std::map<Named_object*, Refs*, Compare_vars> Refmap;
// Variable defs.
Defmap defs_;
// Variable refs;
Refmap refs_;
};
#endif // !defined(GO_DATAFLOW_H)

File diff suppressed because it is too large Load Diff

View File

@ -1,310 +0,0 @@
// escape.h -- Go frontend escape analysis. -*- C++ -*-
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#ifndef GO_ESCAPE_H
#define GO_ESCAPE_H
#include "go-system.h"
#include "string-dump.h"
class Call_node;
class Connection_node;
class Connection_dump_context;
class Gogo;
class Named_object;
// A basic escape analysis implementation for the Go frontend based on the
// algorithm from "Escape Analysis for Java" by Choi et. al in OOPSLA '99.
// This is a simplified version of the flow insensitive analysis with the goal
// of reducing the overhead cost of garbage collection by allocating objects
// on the stack when they do not escape the function they were created in.
//
// A major simplification is that the analysis only implements what Choi refers
// to as "deferred edges" which are used to used model assignments that copy
// references from one variable to another e.g. a := b. It is unnecessary to
// consider assignments to the fields of an object because, in general, if a
// field of an object escapes and must be heap-allocated, there is no way to
// heap-allocate that escaping field without heap-allocating the entire object.
// That is, for some globally escaping object GVAR, if there is an assignment
// of the form GVAR = t.f such that field f of object t escapes, it is likely
// that t must be heap-allocated as well. In the analysis, this assignment
// will be simplified to GVAR = t, which is imprecise but has the same effect.
// This is a general graph node representing a named object used in a call graph
// or connection graph. In a call graph, each named object is either a Function
// or Function_declaration representing a function called during the program
// execution (which isn't necessarily every function declared). In a connection
// graph, there is a node for each node in the call graph, which forms the root
// of that connection graph. Each connection graph root contains nodes whose
// objects are either variables used in the function defintion or are nested
// closures created within the function definition. The connection graph is
// a way of modeling the connectivity between all objects created in a given
// function as well as understanding the relationship between input arguments
// in the caller and the formal parameters in the callee.
class Node
{
public:
enum Node_classification
{
NODE_CALL,
NODE_CONNECTION
};
virtual ~Node();
// Make a call node for FUNCTION.
static Node*
make_call(Named_object* function);
// Make a connection node for OBJECT.
// Note: values in this enum appear in export data, and therefore MUST NOT
// change.
enum Escapement_lattice
{
// ESCAPE_GLOBAL means that the object escapes all functions globally.
ESCAPE_GLOBAL = 0,
// ESCAPE_ARG with respect to a function means that the object escapes that
// function it is created in via the function's arguments or results.
ESCAPE_ARG = 1,
// ESCAPE_NONE means that the object does not escape the function in which
// it was created.
ESCAPE_NONE = 2
};
// A list of states usually corresponding to a list of function parameters.
typedef std::vector<Escapement_lattice> Escape_states;
static Node*
make_connection(Named_object* object, Escapement_lattice e);
// Return the node classification.
Node_classification
classification() const
{ return this->classification_; }
// Return whether this is a call node.
bool
is_call() const
{ return this->classification_ == NODE_CALL; }
// Return whether this is a connection node.
bool
is_connection() const
{ return this->classification_ == NODE_CONNECTION; }
// If this is a connection node, return the Connection_node.
// Otherwise, return NULL.
Connection_node*
connection_node()
{ return this->convert<Connection_node, NODE_CONNECTION>(); }
// Return this node's unique id.
unsigned int
id() const
{ return this->id_; }
// Return this node's generated name for GraphViz.
virtual const std::string&
name() = 0;
// Return this node's generated label for GraphViz.
virtual const std::string&
label();
// Return the object this node represents.
Named_object*
object() const
{ return this->object_; }
void
add_edge(Node* v)
{ this->edges_.insert(v); }
const std::set<Node*>&
edges() const
{ return this->edges_; }
protected:
Node(Node_classification, Named_object* object);
const std::string&
get_name() const
{ return this->name_; }
void
set_name(const std::string& name)
{ this->name_ = name; }
const std::string&
get_label() const
{ return this->label_; }
void
set_label(const std::string& label)
{ this->label_ = label; }
private:
template<typename Node_class,
Node_classification node_classification>
const Node_class*
convert() const
{
return (this->classification_ == node_classification
? static_cast<const Node_class*>(this)
: NULL);
}
template<typename Node_class,
Node_classification node_classification>
Node_class*
convert()
{
return (this->classification_ == node_classification
? static_cast<Node_class*>(this)
: NULL);
}
// The classification of this node.
Node_classification classification_;
// A unique ID for this node.
unsigned int id_;
// The name for this node e.g. "Node<ID>" used as a GraphViz identifier.
std::string name_;
// The label for this node in the GraphViz representation.
std::string label_;
// The object represented by this node.
Named_object* object_;
// A distinct set of nodes that this node has edges to.
std::set<Node*> edges_;
};
// A node representing a function that might be called during program execution.
class Call_node : public Node
{
public:
Call_node(Named_object* function);
const std::string&
name();
};
// A node representing an object in the connection graph built for each function
// in the call graph.
class Connection_node : public Node
{
public:
Connection_node(Named_object* object, Escapement_lattice e)
: Node(NODE_CONNECTION, object),
escape_state_(e)
{ }
// Return this node's generated name for GraphViz.
const std::string&
name();
// Return this node's generated label for GraphViz.
const std::string&
label();
// Return the escape state for this node.
Escapement_lattice
escape_state() const
{ return this->escape_state_; }
// Set the escape state for this node.
void
set_escape_state(Escapement_lattice e)
{ this->escape_state_ = e; }
// Return the objects inside of this connection graph.
// This is empty for all connection nodes that are not the root of a
// connection graph. Each node in the call graph is a root of a connection
// graph.
const std::set<Node*>&
objects() const
{ return this->objects_; }
void
add_object(Node* object)
{ this->objects_.insert(object); }
void
dump_connection(Connection_dump_context*);
private:
// The escapement of this node.
Escapement_lattice escape_state_;
// The set of nodes contained within this connection node. If this node is
// not a root of a connection graph, this will be empty.
std::set<Node*> objects_;
};
// This class implements fgo-dump-calls. The Call graph dump of a Go program.
class Call_dump_context : public String_dump
{
public:
Call_dump_context(std::ostream* out = NULL);
// Initialize the dump context.
void
dump(Gogo*, const char* basename);
// Get dump output stream.
std::ostream&
ostream()
{ return *this->ostream_; }
// Implementation of String_dump interface.
void
write_c_string(const char*);
void
write_string(const std::string&);
private:
// Stream on output dump file.
std::ostream* ostream_;
Gogo* gogo_;
};
// This class implements fgo-dump-conns. The connection graph dump of
// the functions called in a Go program.
class Connection_dump_context : public String_dump
{
public:
Connection_dump_context(std::ostream* out = NULL);
// Initialize the dump context.
void
dump(Gogo*, const char* basename);
// Get dump output stream.
std::ostream&
ostream()
{ return *this->ostream_; }
// Implementation of String_dump interface.
void
write_c_string(const char*);
void
write_string(const std::string&);
private:
// Stream on output dump file.
std::ostream* ostream_;
Gogo* gogo_;
};
#endif // !defined(GO_ESCAPE_H)

View File

@ -436,17 +436,6 @@ Export::write_type(const Type* type)
this->type_refs_[type] = index;
}
// Export escape information.
void
Export::write_escape(const Node::Escapement_lattice& e)
{
char buf[30];
snprintf(buf, sizeof buf, "<escape %d>", e);
this->write_c_string(buf);
return;
}
// Add the builtin types to the export table.
void

View File

@ -7,7 +7,6 @@
#ifndef GO_EXPORT_H
#define GO_EXPORT_H
#include "escape.h"
#include "string-dump.h"
struct sha1_ctx;
@ -162,10 +161,6 @@ class Export : public String_dump
void
write_type(const Type*);
// Write out escape information.
void
write_escape(const Node::Escapement_lattice& e);
private:
Export(const Export&);
Export& operator=(const Export&);

View File

@ -110,10 +110,6 @@ go_parse_input_files(const char** filenames, unsigned int filename_count,
if (only_check_syntax)
return;
// Consider escape analysis information when deciding if a variable should
// live on the heap or on the stack.
::gogo->optimize_allocations(filenames);
// Export global identifiers as appropriate.
::gogo->do_exports();

View File

@ -18,7 +18,6 @@
#include "runtime.h"
#include "import.h"
#include "export.h"
#include "escape.h"
#include "backend.h"
#include "gogo.h"
@ -156,19 +155,11 @@ Gogo::Gogo(Backend* backend, Linemap* linemap, int, int pointer_size)
Function_type* new_type = Type::make_function_type(NULL, NULL, NULL, loc);
new_type->set_is_varargs();
new_type->set_is_builtin();
Node::Escape_states* new_escapes =
new Node::Escape_states(1, Node::ESCAPE_NONE);
new_type->set_parameter_escape_states(new_escapes);
new_type->set_has_escape_info();
this->globals_->add_function_declaration("new", NULL, new_type, loc);
Function_type* make_type = Type::make_function_type(NULL, NULL, NULL, loc);
make_type->set_is_varargs();
make_type->set_is_builtin();
Node::Escape_states* make_escapes =
new Node::Escape_states(2, Node::ESCAPE_NONE);
make_type->set_parameter_escape_states(make_escapes);
make_type->set_has_escape_info();
this->globals_->add_function_declaration("make", NULL, make_type, loc);
Typed_identifier_list* len_result = new Typed_identifier_list();
@ -176,10 +167,6 @@ Gogo::Gogo(Backend* backend, Linemap* linemap, int, int pointer_size)
Function_type* len_type = Type::make_function_type(NULL, NULL, len_result,
loc);
len_type->set_is_builtin();
Node::Escape_states* len_escapes =
new Node::Escape_states(1, Node::ESCAPE_NONE);
len_type->set_parameter_escape_states(len_escapes);
len_type->set_has_escape_info();
this->globals_->add_function_declaration("len", NULL, len_type, loc);
Typed_identifier_list* cap_result = new Typed_identifier_list();
@ -187,26 +174,16 @@ Gogo::Gogo(Backend* backend, Linemap* linemap, int, int pointer_size)
Function_type* cap_type = Type::make_function_type(NULL, NULL, len_result,
loc);
cap_type->set_is_builtin();
Node::Escape_states* cap_escapes =
new Node::Escape_states(1, Node::ESCAPE_NONE);
cap_type->set_parameter_escape_states(cap_escapes);
cap_type->set_has_escape_info();
this->globals_->add_function_declaration("cap", NULL, cap_type, loc);
Function_type* print_type = Type::make_function_type(NULL, NULL, NULL, loc);
print_type->set_is_varargs();
print_type->set_is_builtin();
Node::Escape_states* print_escapes =
new Node::Escape_states(1, Node::ESCAPE_NONE);
print_type->set_parameter_escape_states(print_escapes);
print_type->set_has_escape_info();
this->globals_->add_function_declaration("print", NULL, print_type, loc);
print_type = Type::make_function_type(NULL, NULL, NULL, loc);
print_type->set_is_varargs();
print_type->set_is_builtin();
print_type->set_parameter_escape_states(print_escapes);
print_type->set_has_escape_info();
this->globals_->add_function_declaration("println", NULL, print_type, loc);
Type *empty = Type::make_empty_interface_type(loc);
@ -215,10 +192,6 @@ Gogo::Gogo(Backend* backend, Linemap* linemap, int, int pointer_size)
Function_type *panic_type = Type::make_function_type(NULL, panic_parms,
NULL, loc);
panic_type->set_is_builtin();
Node::Escape_states* panic_escapes =
new Node::Escape_states(1, Node::ESCAPE_ARG);
panic_type->set_parameter_escape_states(panic_escapes);
panic_type->set_has_escape_info();
this->globals_->add_function_declaration("panic", NULL, panic_type, loc);
Typed_identifier_list* recover_result = new Typed_identifier_list();
@ -232,10 +205,6 @@ Gogo::Gogo(Backend* backend, Linemap* linemap, int, int pointer_size)
Function_type* close_type = Type::make_function_type(NULL, NULL, NULL, loc);
close_type->set_is_varargs();
close_type->set_is_builtin();
Node::Escape_states* close_escapes =
new Node::Escape_states(1, Node::ESCAPE_NONE);
close_type->set_parameter_escape_states(close_escapes);
close_type->set_has_escape_info();
this->globals_->add_function_declaration("close", NULL, close_type, loc);
Typed_identifier_list* copy_result = new Typed_identifier_list();
@ -244,56 +213,31 @@ Gogo::Gogo(Backend* backend, Linemap* linemap, int, int pointer_size)
copy_result, loc);
copy_type->set_is_varargs();
copy_type->set_is_builtin();
Node::Escape_states* copy_escapes =
new Node::Escape_states(2, Node::ESCAPE_NONE);
copy_type->set_parameter_escape_states(copy_escapes);
copy_type->set_has_escape_info();
this->globals_->add_function_declaration("copy", NULL, copy_type, loc);
Function_type* append_type = Type::make_function_type(NULL, NULL, NULL, loc);
append_type->set_is_varargs();
append_type->set_is_builtin();
Node::Escape_states* append_escapes = new Node::Escape_states;
append_escapes->push_back(Node::ESCAPE_ARG);
append_escapes->push_back(Node::ESCAPE_NONE);
append_type->set_parameter_escape_states(append_escapes);
append_type->set_has_escape_info();
this->globals_->add_function_declaration("append", NULL, append_type, loc);
Function_type* complex_type = Type::make_function_type(NULL, NULL, NULL, loc);
complex_type->set_is_varargs();
complex_type->set_is_builtin();
Node::Escape_states* complex_escapes =
new Node::Escape_states(2, Node::ESCAPE_NONE);
complex_type->set_parameter_escape_states(complex_escapes);
complex_type->set_has_escape_info();
this->globals_->add_function_declaration("complex", NULL, complex_type, loc);
Function_type* real_type = Type::make_function_type(NULL, NULL, NULL, loc);
real_type->set_is_varargs();
real_type->set_is_builtin();
Node::Escape_states* real_escapes =
new Node::Escape_states(1, Node::ESCAPE_NONE);
real_type->set_parameter_escape_states(real_escapes);
real_type->set_has_escape_info();
this->globals_->add_function_declaration("real", NULL, real_type, loc);
Function_type* imag_type = Type::make_function_type(NULL, NULL, NULL, loc);
imag_type->set_is_varargs();
imag_type->set_is_builtin();
Node::Escape_states* imag_escapes =
new Node::Escape_states(1, Node::ESCAPE_NONE);
imag_type->set_parameter_escape_states(imag_escapes);
imag_type->set_has_escape_info();
this->globals_->add_function_declaration("imag", NULL, imag_type, loc);
Function_type* delete_type = Type::make_function_type(NULL, NULL, NULL, loc);
delete_type->set_is_varargs();
delete_type->set_is_builtin();
Node::Escape_states* delete_escapes =
new Node::Escape_states(2, Node::ESCAPE_NONE);
delete_type->set_parameter_escape_states(delete_escapes);
delete_type->set_has_escape_info();
this->globals_->add_function_declaration("delete", NULL, delete_type, loc);
}
@ -1889,74 +1833,6 @@ Gogo::add_label_reference(const std::string& label_name,
issue_goto_errors);
}
// Add a function to the call graph.
Node*
Gogo::add_call_node(Named_object* function)
{
Node* call = this->lookup_call_node(function);
if (call == NULL)
{
call = Node::make_call(function);
this->call_graph_.insert(call);
this->named_call_nodes_[function] = call;
}
return call;
}
// Find the call node that represents FUNCTION. Return NULL if it does not
// exist.
Node*
Gogo::lookup_call_node(Named_object* function) const
{
Named_escape_nodes::const_iterator p = this->named_call_nodes_.find(function);
if (p == this->named_call_nodes_.end())
return NULL;
return p->second;
}
// Add a connection node for OBJECT.
Node*
Gogo::add_connection_node(Named_object* object)
{
Node* connection = this->lookup_connection_node(object);
if (connection == NULL)
{
connection = Node::make_connection(object, Node::ESCAPE_NONE);
// Each global variable is a part of the global connection graph.
if (object->is_variable()
&& object->var_value()->is_global())
{
connection->connection_node()->set_escape_state(Node::ESCAPE_GLOBAL);
this->global_connections_.insert(connection);
}
// Each function declaration or definition is the root of its own
// connection graph. This means closures will have their own
// connection graph that objects in the enclosing function might
// refer to.
if (object->is_function() || object->is_function_declaration())
this->connection_roots_.insert(connection);
this->named_connection_nodes_[object] = connection;
}
return connection;
}
// Find the connection node for OBJECT. Return NULL if it does not exist.
Node*
Gogo::lookup_connection_node(Named_object* object) const
{
Named_escape_nodes::const_iterator p =
this->named_connection_nodes_.find(object);
if (p == this->named_connection_nodes_.end())
return NULL;
return p->second;
}
// Return the current binding state.
Bindings_snapshot*
@ -4918,13 +4794,6 @@ Function::export_func_with_type(Export* exp, const std::string& name,
exp->write_c_string("(");
const Typed_identifier* receiver = fntype->receiver();
exp->write_name(receiver->name());
if (fntype->has_escape_info())
{
exp->write_c_string(" ");
exp->write_escape(fntype->receiver_escape_state());
}
exp->write_c_string(" ");
exp->write_type(receiver->type());
exp->write_c_string(") ");
@ -4948,13 +4817,6 @@ Function::export_func_with_type(Export* exp, const std::string& name,
else
exp->write_c_string(", ");
exp->write_name(p->name());
if (fntype->has_escape_info())
{
exp->write_c_string(" ");
exp->write_escape(fntype->parameter_escape_states()->at(i));
}
exp->write_c_string(" ");
if (!is_varargs || p + 1 != parameters->end())
exp->write_type(p->type());
@ -5002,29 +4864,17 @@ Function::export_func_with_type(Export* exp, const std::string& name,
void
Function::import_func(Import* imp, std::string* pname,
Typed_identifier** preceiver,
Node::Escapement_lattice* rcvr_escape,
Typed_identifier_list** pparameters,
Node::Escape_states** pparam_escapes,
Typed_identifier_list** presults,
bool* is_varargs, bool* has_escape_info)
bool* is_varargs)
{
*has_escape_info = false;
imp->require_c_string("func ");
*preceiver = NULL;
*rcvr_escape = Node::ESCAPE_NONE;
if (imp->peek_char() == '(')
{
imp->require_c_string("(");
std::string name = imp->read_name();
if (imp->match_c_string(" <escape")){
*has_escape_info = true;
imp->require_c_string(" ");
*rcvr_escape = imp->read_escape_info();
}
imp->require_c_string(" ");
Type* rtype = imp->read_type();
*preceiver = new Typed_identifier(name, rtype, imp->location());
@ -5034,27 +4884,16 @@ Function::import_func(Import* imp, std::string* pname,
*pname = imp->read_identifier();
Typed_identifier_list* parameters;
Node::Escape_states* param_escapes;
*is_varargs = false;
imp->require_c_string(" (");
if (imp->peek_char() == ')')
{
parameters = NULL;
param_escapes = NULL;
}
parameters = NULL;
else
{
parameters = new Typed_identifier_list();
param_escapes = new Node::Escape_states();
while (true)
{
std::string name = imp->read_name();
if (imp->match_c_string(" <escape")){
*has_escape_info = true;
imp->require_c_string(" ");
param_escapes->push_back(imp->read_escape_info());
}
imp->require_c_string(" ");
if (imp->match_c_string("..."))
@ -5076,7 +4915,6 @@ Function::import_func(Import* imp, std::string* pname,
}
imp->require_c_string(")");
*pparameters = parameters;
*pparam_escapes = param_escapes;
Typed_identifier_list* results;
if (imp->peek_char() != ' ')

View File

@ -7,7 +7,6 @@
#ifndef GO_GOGO_H
#define GO_GOGO_H
#include "escape.h"
#include "go-linemap.h"
class Traverse;
@ -126,21 +125,6 @@ class Gogo
linemap()
{ return this->linemap_; }
// Get the Call Graph.
const std::set<Node*>&
call_graph() const
{ return this->call_graph_; }
// Get the roots of each connection graph.
const std::set<Node*>&
connection_roots() const
{ return this->connection_roots_; }
// Get the nodes that escape globally.
const std::set<Node*>&
global_connections() const
{ return this->global_connections_; }
// Get the package name.
const std::string&
package_name() const;
@ -361,22 +345,6 @@ class Gogo
add_label_reference(const std::string&, Location,
bool issue_goto_errors);
// Add a FUNCTION to the call graph.
Node*
add_call_node(Named_object* function);
// Lookup the call node for FUNCTION.
Node*
lookup_call_node(Named_object* function) const;
// Add a connection node for OBJECT.
Node*
add_connection_node(Named_object* object);
// Lookup the connection node for OBJECT.
Node*
lookup_connection_node(Named_object* object) const;
// Return a snapshot of the current binding state.
Bindings_snapshot*
bindings_snapshot(Location);
@ -576,26 +544,6 @@ class Gogo
void
check_return_statements();
// Build call graph.
void
build_call_graph();
// Build connection graphs.
void
build_connection_graphs();
// Analyze reachability in the connection graphs.
void
analyze_reachability();
// Record escape information in function signatures for export data.
void
mark_escaping_signatures();
// Optimize variable allocation.
void
optimize_allocations(const char** filenames);
// Do all exports.
void
do_exports();
@ -730,10 +678,6 @@ class Gogo
// where they were defined.
typedef Unordered_map(std::string, Location) File_block_names;
// Type used to map named objects that refer to objects to the
// node that represent them in the escape analysis graphs.
typedef Unordered_map(Named_object*, Node*) Named_escape_nodes;
// Type used to queue writing a type specific function.
struct Specific_type_function
{
@ -766,20 +710,6 @@ class Gogo
// The global binding contour. This includes the builtin functions
// and the package we are compiling.
Bindings* globals_;
// The call graph for a program execution which represents the functions
// encountered and the caller-callee relationship between the functions.
std::set<Node*> call_graph_;
// The nodes that form the roots of the connection graphs for each called
// function and represent the connectivity relationship between all objects
// in the function.
std::set<Node*> connection_roots_;
// All connection nodes that have an escape state of ESCAPE_GLOBAL are a part
// of a special connection graph of only global variables.
std::set<Node*> global_connections_;
// Mapping from named objects to nodes in the call graph.
Named_escape_nodes named_call_nodes_;
// Mapping from named objects to nodes in a connection graph.
Named_escape_nodes named_connection_nodes_;
// The list of names we have seen in the file block.
File_block_names file_block_names_;
// Mapping from import file names to packages.
@ -1215,11 +1145,8 @@ class Function
// Import a function.
static void
import_func(Import*, std::string* pname, Typed_identifier** receiver,
Node::Escapement_lattice* rcvr_escape,
Typed_identifier_list** pparameters,
Node::Escape_states** pparam_escapes,
Typed_identifier_list** presults, bool* is_varargs,
bool* has_escape_info);
Typed_identifier_list** presults, bool* is_varargs);
private:
// Type for mapping from label names to Label objects.

View File

@ -502,28 +502,16 @@ Import::import_func(Package* package)
{
std::string name;
Typed_identifier* receiver;
Node::Escapement_lattice rcvr_escape;
Typed_identifier_list* parameters;
Node::Escape_states* param_escapes;
Typed_identifier_list* results;
bool is_varargs;
bool has_escape_info;
Function::import_func(this, &name, &receiver, &rcvr_escape, &parameters,
&param_escapes, &results, &is_varargs,
&has_escape_info);
Function::import_func(this, &name, &receiver,
&parameters, &results, &is_varargs);
Function_type *fntype = Type::make_function_type(receiver, parameters,
results, this->location_);
if (is_varargs)
fntype->set_is_varargs();
if (has_escape_info)
{
if (fntype->is_method())
fntype->set_receiver_escape_state(rcvr_escape);
fntype->set_parameter_escape_states(param_escapes);
fntype->set_has_escape_info();
}
Location loc = this->location_;
Named_object* no;
if (fntype->is_method())
@ -774,19 +762,6 @@ Import::read_type()
return type;
}
// Read escape info in the import stream.
Node::Escapement_lattice
Import::read_escape_info()
{
Stream* stream = this->stream_;
this->require_c_string("<escape ");
int escape_value = stream->get_char() - '0';
this->require_c_string(">");
return Node::Escapement_lattice(escape_value);
}
// Register the builtin types.
void

View File

@ -7,7 +7,6 @@
#ifndef GO_IMPORT_H
#define GO_IMPORT_H
#include "escape.h"
#include "export.h"
#include "go-linemap.h"
@ -198,10 +197,6 @@ class Import
Type*
read_type();
// Read escape information.
Node::Escapement_lattice
read_escape_info();
private:
static Stream*
try_package_in_directory(const std::string&, Location);

View File

@ -14,7 +14,6 @@
#include "backend.h"
#include "statements.h"
#include "ast-dump.h"
#include "dataflow.h"
// Class Statement.
@ -4821,22 +4820,6 @@ Select_clauses::Select_clause::check_types()
error_at(this->location(), "invalid receive on send-only channel");
}
// Analyze the dataflow across each case statement.
void
Select_clauses::Select_clause::analyze_dataflow(Dataflow* dataflow)
{
if (this->is_default_)
return;
// For a CommClause, the dataflow analysis should record a definition of
// VAR and CLOSEDVAR
if (this->var_ != NULL && !this->var_->is_sink())
dataflow->add_def(this->var_, this->channel_, NULL, false);
if (this->closedvar_ != NULL && !this->closedvar_->is_sink())
dataflow->add_def(this->closedvar_, this->channel_, NULL, false);
}
// Whether this clause may fall through to the statement which follows
// the overall select statement.
@ -4955,17 +4938,6 @@ Select_clauses::check_types()
p->check_types();
}
// Analyze the dataflow across each case statement.
void
Select_clauses::analyze_dataflow(Dataflow* dataflow)
{
for (Clauses::iterator p = this->clauses_.begin();
p != this->clauses_.end();
++p)
p->analyze_dataflow(dataflow);
}
// Return whether these select clauses fall through to the statement
// following the overall select statement.

View File

@ -47,7 +47,6 @@ class Bexpression;
class Bstatement;
class Bvariable;
class Ast_dump_context;
class Dataflow;
// This class is used to traverse assignments made by a statement
// which makes assignments.
@ -860,10 +859,6 @@ class Select_clauses
void
check_types();
// Analyze the dataflow across each case statement.
void
analyze_dataflow(Dataflow*);
// Whether the select clauses may fall through to the statement
// which follows the overall select statement.
bool
@ -920,10 +915,6 @@ class Select_clauses
void
check_types();
// Analyze the dataflow across each case statement.
void
analyze_dataflow(Dataflow*);
// Return true if this is the default clause.
bool
is_default() const
@ -1030,10 +1021,6 @@ class Select_statement : public Statement
Unnamed_label*
break_label();
void
analyze_dataflow(Dataflow* dataflow)
{ this->clauses_->analyze_dataflow(dataflow); }
protected:
int
do_traverse(Traverse* traverse)

View File

@ -8,7 +8,6 @@
#define GO_TYPES_H
#include "go-linemap.h"
#include "escape.h"
class Gogo;
class Package;
@ -1779,7 +1778,7 @@ class Function_type : public Type
: Type(TYPE_FUNCTION),
receiver_(receiver), parameters_(parameters), results_(results),
location_(location), is_varargs_(false), is_builtin_(false),
has_escape_info_(false), fnbtype_(NULL), parameter_escape_states_(NULL)
fnbtype_(NULL)
{ }
// Get the receiver.
@ -1787,16 +1786,6 @@ class Function_type : public Type
receiver() const
{ return this->receiver_; }
// Get the escape state of the receiver.
const Node::Escapement_lattice&
receiver_escape_state() const
{ return this->receiver_escape_state_; }
// Set the escape state of the receiver.
void
set_receiver_escape_state(const Node::Escapement_lattice& e)
{ this->receiver_escape_state_ = e; }
// Get the return names and types.
const Typed_identifier_list*
results() const
@ -1807,16 +1796,6 @@ class Function_type : public Type
parameters() const
{ return this->parameters_; }
// Get the escape states associated with each parameter.
const Node::Escape_states*
parameter_escape_states() const
{ return this->parameter_escape_states_; }
// Set the escape states of the parameters.
void
set_parameter_escape_states(Node::Escape_states* states)
{ this->parameter_escape_states_ = states; }
// Whether this is a varargs function.
bool
is_varargs() const
@ -1827,11 +1806,6 @@ class Function_type : public Type
is_builtin() const
{ return this->is_builtin_; }
// Whether this contains escape information.
bool
has_escape_info() const
{ return this->has_escape_info_; }
// The location where this type was defined.
Location
location() const
@ -1862,11 +1836,6 @@ class Function_type : public Type
set_is_builtin()
{ this->is_builtin_ = true; }
// Record that this has escape information.
void
set_has_escape_info()
{ this->has_escape_info_ = true; }
// Import a function type.
static Function_type*
do_import(Import*);
@ -1978,16 +1947,9 @@ class Function_type : public Type
// Whether this is a special builtin function which can not simply
// be called. This is used for len, cap, etc.
bool is_builtin_;
// Whether escape information for the receiver and parameters has been
// recorded.
bool has_escape_info_;
// The backend representation of this type for backend function
// declarations and definitions.
Btype* fnbtype_;
// The escape state of the receiver.
Node::Escapement_lattice receiver_escape_state_;
// The escape states of each parameter.
Node::Escape_states* parameter_escape_states_;
};
// The type of a function's backend representation.