diff options
Diffstat (limited to 'gcc/go/gofrontend/dataflow.cc')
-rw-r--r-- | gcc/go/gofrontend/dataflow.cc | 299 |
1 files changed, 0 insertions, 299 deletions
diff --git a/gcc/go/gofrontend/dataflow.cc b/gcc/go/gofrontend/dataflow.cc deleted file mode 100644 index bf1d54ab26..0000000000 --- a/gcc/go/gofrontend/dataflow.cc +++ /dev/null @@ -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; -} |