Rebase.
[official-gcc.git] / gcc / go / gofrontend / dataflow.cc
blob572ab3631cd5f579b6850918becbec498636b231
1 // dataflow.cc -- Go frontend dataflow.
3 // Copyright 2009 The Go Authors. All rights reserved.
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file.
7 #include "go-system.h"
9 #include "gogo.h"
10 #include "expressions.h"
11 #include "statements.h"
12 #include "dataflow.h"
14 // This class is used to traverse the tree to look for uses of
15 // variables.
17 class Dataflow_traverse_expressions : public Traverse
19 public:
20 Dataflow_traverse_expressions(Dataflow* dataflow, Statement* statement)
21 : Traverse(traverse_blocks | traverse_expressions),
22 dataflow_(dataflow), statement_(statement)
23 { }
25 protected:
26 // Only look at top-level expressions: do not descend into blocks.
27 // They will be examined via Dataflow_traverse_statements.
28 int
29 block(Block*)
30 { return TRAVERSE_SKIP_COMPONENTS; }
32 int
33 expression(Expression**);
35 private:
36 // The dataflow information.
37 Dataflow* dataflow_;
38 // The Statement in which we are looking.
39 Statement* statement_;
42 // Given an expression, return the Named_object that it refers to, if
43 // it is a local variable.
45 static Named_object*
46 get_var(Expression* expr)
48 Var_expression* ve = expr->var_expression();
49 if (ve == NULL)
50 return NULL;
51 Named_object* no = ve->named_object();
52 go_assert(no->is_variable() || no->is_result_variable());
53 if (no->is_variable() && no->var_value()->is_global())
54 return NULL;
55 return no;
58 // Look for a reference to a variable in an expression.
60 int
61 Dataflow_traverse_expressions::expression(Expression** expr)
63 Named_object* no = get_var(*expr);
64 if (no != NULL)
65 this->dataflow_->add_ref(no, this->statement_);
66 return TRAVERSE_CONTINUE;
69 // This class is used to handle an assignment statement.
71 class Dataflow_traverse_assignment : public Traverse_assignments
73 public:
74 Dataflow_traverse_assignment(Dataflow* dataflow, Statement* statement)
75 : dataflow_(dataflow), statement_(statement)
76 { }
78 protected:
79 void
80 initialize_variable(Named_object*);
82 void
83 assignment(Expression** lhs, Expression** rhs);
85 void
86 value(Expression**, bool, bool);
88 private:
89 // The dataflow information.
90 Dataflow* dataflow_;
91 // The Statement in which we are looking.
92 Statement* statement_;
95 // Handle a variable initialization.
97 void
98 Dataflow_traverse_assignment::initialize_variable(Named_object* var)
100 Expression* init = var->var_value()->init();
101 this->dataflow_->add_def(var, init, this->statement_, true);
102 if (init != NULL)
104 Expression* e = init;
105 this->value(&e, true, true);
106 go_assert(e == init);
110 // Handle an assignment in a statement.
112 void
113 Dataflow_traverse_assignment::assignment(Expression** plhs, Expression** prhs)
115 Named_object* no = get_var(*plhs);
116 if (no != NULL)
118 Expression* rhs = prhs == NULL ? NULL : *prhs;
119 this->dataflow_->add_def(no, rhs, this->statement_, false);
121 else
123 // If this is not a variable it may be some computed lvalue, and
124 // we want to look for references to variables in that lvalue.
125 this->value(plhs, false, false);
127 if (prhs != NULL)
128 this->value(prhs, true, false);
131 // Handle a value in a statement.
133 void
134 Dataflow_traverse_assignment::value(Expression** pexpr, bool, bool)
136 Named_object* no = get_var(*pexpr);
137 if (no != NULL)
138 this->dataflow_->add_ref(no, this->statement_);
139 else
141 Dataflow_traverse_expressions dte(this->dataflow_, this->statement_);
142 Expression::traverse(pexpr, &dte);
146 // This class is used to traverse the tree to look for statements.
148 class Dataflow_traverse_statements : public Traverse
150 public:
151 Dataflow_traverse_statements(Dataflow* dataflow)
152 : Traverse(traverse_statements),
153 dataflow_(dataflow)
156 protected:
158 statement(Block*, size_t* pindex, Statement*);
160 private:
161 // The dataflow information.
162 Dataflow* dataflow_;
165 // For each Statement, we look for expressions.
168 Dataflow_traverse_statements::statement(Block* block, size_t* pindex,
169 Statement *statement)
171 Dataflow_traverse_assignment dta(this->dataflow_, statement);
172 if (!statement->traverse_assignments(&dta))
174 Dataflow_traverse_expressions dte(this->dataflow_, statement);
175 statement->traverse(block, pindex, &dte);
177 return TRAVERSE_CONTINUE;
180 // Compare variables.
182 bool
183 Dataflow::Compare_vars::operator()(const Named_object* no1,
184 const Named_object* no2) const
186 if (no1->name() < no2->name())
187 return true;
188 if (no1->name() > no2->name())
189 return false;
191 // We can have two different variables with the same name.
192 Location loc1 = no1->location();
193 Location loc2 = no2->location();
194 if (loc1 < loc2)
195 return false;
196 if (loc1 > loc2)
197 return true;
199 if (no1 == no2)
200 return false;
202 // We can't have two variables with the same name in the same
203 // location.
204 go_unreachable();
207 // Class Dataflow.
209 Dataflow::Dataflow()
210 : defs_(), refs_()
214 // Build the dataflow information.
216 void
217 Dataflow::initialize(Gogo* gogo)
219 Dataflow_traverse_statements dts(this);
220 gogo->traverse(&dts);
223 // Add a definition of a variable.
225 void
226 Dataflow::add_def(Named_object* var, Expression* val, Statement* statement,
227 bool is_init)
229 Defs* defnull = NULL;
230 std::pair<Defmap::iterator, bool> ins =
231 this->defs_.insert(std::make_pair(var, defnull));
232 if (ins.second)
233 ins.first->second = new Defs;
234 Def def;
235 def.statement = statement;
236 def.val = val;
237 def.is_init = is_init;
238 ins.first->second->push_back(def);
241 // Add a reference to a variable.
243 void
244 Dataflow::add_ref(Named_object* var, Statement* statement)
246 Refs* refnull = NULL;
247 std::pair<Refmap::iterator, bool> ins =
248 this->refs_.insert(std::make_pair(var, refnull));
249 if (ins.second)
250 ins.first->second = new Refs;
251 Ref ref;
252 ref.statement = statement;
253 ins.first->second->push_back(ref);
256 // Return the definitions of a variable.
258 const Dataflow::Defs*
259 Dataflow::find_defs(Named_object* var) const
261 Defmap::const_iterator p = this->defs_.find(var);
262 if (p == this->defs_.end())
263 return NULL;
264 else
265 return p->second;
268 // Return the references of a variable.
270 const Dataflow::Refs*
271 Dataflow::find_refs(Named_object* var) const
273 Refmap::const_iterator p = this->refs_.find(var);
274 if (p == this->refs_.end())
275 return NULL;
276 else
277 return p->second;