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.
10 #include "expressions.h"
11 #include "statements.h"
14 // This class is used to traverse the tree to look for uses of
17 class Dataflow_traverse_expressions
: public Traverse
20 Dataflow_traverse_expressions(Dataflow
* dataflow
, Statement
* statement
)
21 : Traverse(traverse_blocks
| traverse_expressions
),
22 dataflow_(dataflow
), statement_(statement
)
26 // Only look at top-level expressions: do not descend into blocks.
27 // They will be examined via Dataflow_traverse_statements.
30 { return TRAVERSE_SKIP_COMPONENTS
; }
33 expression(Expression
**);
36 // The dataflow information.
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.
46 get_var(Expression
* expr
)
48 Var_expression
* ve
= expr
->var_expression();
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())
58 // Look for a reference to a variable in an expression.
61 Dataflow_traverse_expressions::expression(Expression
** expr
)
63 Named_object
* no
= get_var(*expr
);
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
74 Dataflow_traverse_assignment(Dataflow
* dataflow
, Statement
* statement
)
75 : dataflow_(dataflow
), statement_(statement
)
80 initialize_variable(Named_object
*);
83 assignment(Expression
** lhs
, Expression
** rhs
);
86 value(Expression
**, bool, bool);
89 // The dataflow information.
91 // The Statement in which we are looking.
92 Statement
* statement_
;
95 // Handle a variable initialization.
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);
104 Expression
* e
= init
;
105 this->value(&e
, true, true);
106 go_assert(e
== init
);
110 // Handle an assignment in a statement.
113 Dataflow_traverse_assignment::assignment(Expression
** plhs
, Expression
** prhs
)
115 Named_object
* no
= get_var(*plhs
);
118 Expression
* rhs
= prhs
== NULL
? NULL
: *prhs
;
119 this->dataflow_
->add_def(no
, rhs
, this->statement_
, false);
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);
128 this->value(prhs
, true, false);
131 // Handle a value in a statement.
134 Dataflow_traverse_assignment::value(Expression
** pexpr
, bool, bool)
136 Named_object
* no
= get_var(*pexpr
);
138 this->dataflow_
->add_ref(no
, this->statement_
);
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
151 Dataflow_traverse_statements(Dataflow
* dataflow
)
152 : Traverse(traverse_statements
),
158 statement(Block
*, size_t* pindex
, Statement
*);
161 // The dataflow information.
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.
183 Dataflow::Compare_vars::operator()(const Named_object
* no1
,
184 const Named_object
* no2
) const
186 if (no1
->name() < no2
->name())
188 if (no1
->name() > no2
->name())
191 // We can have two different variables with the same name.
192 Location loc1
= no1
->location();
193 Location loc2
= no2
->location();
202 // We can't have two variables with the same name in the same
214 // Build the dataflow information.
217 Dataflow::initialize(Gogo
* gogo
)
219 Dataflow_traverse_statements
dts(this);
220 gogo
->traverse(&dts
);
223 // Add a definition of a variable.
226 Dataflow::add_def(Named_object
* var
, Expression
* val
, Statement
* statement
,
229 Defs
* defnull
= NULL
;
230 std::pair
<Defmap::iterator
, bool> ins
=
231 this->defs_
.insert(std::make_pair(var
, defnull
));
233 ins
.first
->second
= new Defs
;
235 def
.statement
= statement
;
237 def
.is_init
= is_init
;
238 ins
.first
->second
->push_back(def
);
241 // Add a reference to a variable.
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
));
250 ins
.first
->second
= new Refs
;
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())
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())