-
Notifications
You must be signed in to change notification settings - Fork 139
/
Copy pathILWalk.hpp
384 lines (279 loc) · 11 KB
/
ILWalk.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
/*******************************************************************************
* Copyright IBM Corp. and others 2000
*
* This program and the accompanying materials are made available under
* the terms of the Eclipse Public License 2.0 which accompanies this
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
* or the Apache License, Version 2.0 which accompanies this distribution
* and is available at https://www.apache.org/licenses/LICENSE-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the
* Eclipse Public License, v. 2.0 are satisfied: GNU General Public License,
* version 2 with the GNU Classpath Exception [1] and GNU General Public
* License, version 2 with the OpenJDK Assembly Exception [2].
*
* [1] https://www.gnu.org/software/classpath/license.html
* [2] https://openjdk.org/legal/assembly-exception.html
*
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 OR GPL-2.0-only WITH OpenJDK-assembly-exception-1.0
*******************************************************************************/
#ifndef OMR_INFRA_ILWALK
#define OMR_INFRA_ILWALK
#include "infra/Checklist.hpp"
#include "infra/SideTable.hpp"
#include "infra/Stack.hpp"
namespace TR {
// "Imported" classes
//
class Block;
class CFG;
class Compilation;
class MethodSymbol;
class Node;
class Optimization;
class TreeTop;
// Classes declared here
//
class AllBlockIterator;
class PostorderNodeIterator;
class PostorderNodeOccurrenceIterator;
class PreorderNodeIterator;
class PreorderNodeOccurrenceIterator;
class ReversePostorderSnapshotBlockIterator;
class TreeTopIterator;
class TreeTopIteratorImpl
{
// This has essentially everything from TreeTopIterator except the actual
// decision about when to call logCurrentLocation. Different subclasses
// have different conventions about the meaning of the "current location",
// so they'll want to do this in different ways.
protected:
TR::TreeTop *_current;
// For logging
//
TR::Compilation *_comp;
const char *_name; // NULL means we don't want logging
TR::Compilation * comp() { return _comp; }
void logCurrentLocation();
void stepForward();
void stepBackward();
TreeTopIteratorImpl(TR::TreeTop *start, TR::Compilation *comp, const char *name=NULL);
public:
TR::TreeTop *currentTree() { return _current; }
TR::Node *currentNode();
bool isAt(TR::TreeTop *tt) { return _current == tt; }
void jumpTo(TR::TreeTop *tt){ _current = tt; }
bool isAt(TreeTopIteratorImpl &other) { return isAt(other.currentTree()); }
bool isAt(PreorderNodeIterator &other);
public: // operators
bool operator ==(TR::TreeTop *tt) { return isAt(tt); }
bool operator !=(TR::TreeTop *tt) { return !isAt(tt); }
void operator ++(){ stepForward(); }
void operator --(){ stepBackward(); }
};
class TreeTopIterator: public TreeTopIteratorImpl
{
typedef TreeTopIteratorImpl Super;
public:
TreeTopIterator(TR::TreeTop *start, TR::Compilation *comp, const char *name=NULL):
TreeTopIteratorImpl(start, comp, name){ logCurrentLocation(); }
void stepForward() { Super::stepForward(); logCurrentLocation(); }
void stepBackward() { Super::stepBackward(); logCurrentLocation(); }
};
class NodeIterator: protected TreeTopIteratorImpl // abstract
{
typedef TreeTopIteratorImpl Super;
protected:
struct WalkState
{
TR::Node *_node;
int32_t _child;
bool _isBetweenChildren; // Makes logging pretty
WalkState(TR::Node *node):_node(node),_child(0),_isBetweenChildren(false){}
bool equals(struct WalkState &other){ return _node == other._node && _child == other._child; }
bool operator==(struct WalkState &other){ return equals(other); }
bool operator!=(struct WalkState &other){ return !equals(other); }
};
TR_Stack<WalkState> _stack;
NodeChecklist _checklist;
NodeIterator(TR::TreeTop *start, TR::Compilation *comp, const char *name=NULL);
NodeIterator(TR::TreeTop *start, TR::Compilation *comp);
int32_t stackDepth()
{
// TODO: TR_Stack curently has an unsigned depth, which leads to all kinds
// of havoc and undefined behaviour near zero. It should have a signed
// depth. Until then, use this function instead of calling _stack.size()
// directly.
return (int32_t)_stack.size();
}
void logCurrentLocation();
public:
TR::TreeTop *currentTree() { return Super::currentTree(); }
TR::Node *currentNode() { return _stack.top()._node; }
bool isAt(TR::TreeTop *tt) { return Super::isAt(tt); }
bool isAt(TreeTopIterator &other) { return isAt(other.currentTree()); }
bool isAt(PreorderNodeIterator &other);
public: // operators
bool operator ==(TR::TreeTop *tt) { return isAt(tt); }
bool operator !=(TR::TreeTop *tt) { return !isAt(tt); }
};
// Returns each node once, in the order in which they appear in the log
//
class PreorderNodeIterator: public NodeIterator
{
typedef class NodeIterator Super;
bool alreadyBeenPushed(TR::Node *node);
void push(TR::Node *node);
public:
PreorderNodeIterator(TR::TreeTop *start, TR::Compilation *comp, const char *name=NULL);
void stepForward();
public: // operators
void operator ++() { stepForward(); }
};
// Returns each node once, in postorder.
//
// This is the order in which nodes will be evaluated, except more strict.
// (Actual evaluation does not specify the order that siblings are visited.)
//
class PostorderNodeIterator: public NodeIterator
{
typedef class NodeIterator Super;
bool alreadyBeenPushed(TR::Node *node);
void push(TR::Node *node);
void descend();
public:
PostorderNodeIterator(TR::TreeTop *start, TR::Compilation *comp, const char *name=NULL);
void stepForward();
public: // operators
void operator ++() { stepForward(); }
};
class NodeOccurrenceIterator: public NodeIterator
{
protected:
NodeOccurrenceIterator(TR::TreeTop *start, TR::Compilation *comp, const char *name=NULL):
NodeIterator(start, comp, name){}
void logCurrentLocation();
public:
TR::Node *currentNode();
};
// Returns each node each time it appears, visiting nodes before their
// children, and visiting siblings in order.
//
// This is the order in which the nodes are listed in the logs.
//
class PreorderNodeOccurrenceIterator: public NodeOccurrenceIterator
{
typedef class NodeOccurrenceIterator Super;
bool alreadyPushedChildren(TR::Node *node);
void push(TR::Node *node);
public:
PreorderNodeOccurrenceIterator(TR::TreeTop *start, TR::Compilation *comp, const char *name=NULL);
void stepForward();
public: // operators
void operator ++() { stepForward(); }
};
// Returns each node each time it appears, visiting children before parents,
// and visiting siblings in order.
//
// This is the order in which nodes will be evaluated, except more strict.
// (Actual evaluation does not specify the order that siblings are visited.)
//
class PostorderNodeOccurrenceIterator: public NodeOccurrenceIterator
{
typedef class NodeOccurrenceIterator Super;
bool alreadyPushedChildren(TR::Node *node);
void pushLeftmost(TR::Node *node);
public:
PostorderNodeOccurrenceIterator(TR::TreeTop *start, TR::Compilation *comp, const char *name=NULL);
void stepForward();
public: // operators
void operator ++() { stepForward(); }
};
class BlockIterator
{
protected:
TR::Compilation *_comp;
const char *_name;
bool isLoggingEnabled();
BlockIterator(TR::Compilation *comp, const char *name);
};
// Scans blocks in reverse postorder from a given starting point, building up a
// list of blocks to visit. Then returns each block in that order which is
// still part of the CFG at the time it is encountered. Any block returned by
// this iterator is guaranteed to be in the CFG at the time it is returned.
//
class ReversePostorderSnapshotBlockIterator: protected BlockIterator
{
TR_Array<TR::Block*> _postorder; // Note that this is opposite to the order we want, so we walk this array in reverse
int32_t _currentIndex; // can be 1 past the valid index range of _postorder: -1 or _postorder.lastIndex()+1
void takeSnapshot(TR::Block *start);
void visit(TR::Block *block, TR::BlockChecklist &alreadyVisited);
void logCurrentLocation();
bool isStepOperationFinished();
public:
ReversePostorderSnapshotBlockIterator(TR::Block *start, TR::Compilation *comp, const char *name=NULL);
ReversePostorderSnapshotBlockIterator(TR::CFG *cfg, TR::Compilation * comp, const char *name=NULL);
TR::Block *currentBlock();
bool isAt(TR::Block *block){ return currentBlock() == block; }
void stepForward();
void stepBackward();
public: // operators
void operator ++() { stepForward(); }
void operator --() { stepBackward(); }
};
// Scans blocks in arbitrary order. All blocks present in the CFG at the time
// the walk finishes will have been returned exactly once, and possibly some
// (but not necessarily all) blocks deleted during the walk. Any block
// returned by this iterator is guaranteed to be in the CFG at the time it is
// returned.
//
// This iterator relies on the fact that CFGNodes are in a linked list into
// which new nodes are only ever prepended at the front. Because of this, we
// can be guarantee that we will visit all nodes if we (1) start again at the
// front of the list whenever we reach the end, and (2) stop the first time we
// hit a block we've already visited.
//
class AllBlockIterator: protected BlockIterator
{
TR::CFG *_cfg;
TR::Block *_currentBlock;
TR::Block *_nextBlock;
BlockChecklist _alreadyVisited;
void logCurrentLocation();
public:
AllBlockIterator(TR::CFG *cfg, TR::Compilation *comp, const char *name=NULL);
TR::Block *currentBlock();
bool isAt(TR::Block *block){ return currentBlock() == block; }
void stepForward();
public: // operators
void operator ++() { stepForward(); }
};
/** \brief
* Iterates through extended basic block sequences in a treetop order, where treetop order means the order in
* which the extended basic blocks appear in a trace log file.
*/
class TreeTopOrderExtendedBlockIterator : protected BlockIterator
{
public:
TreeTopOrderExtendedBlockIterator(TR::Compilation* comp, const char* name = NULL);
/** \brief
* Returns the first basic block in the current iteration of the extended basic block sequence.
*/
TR::Block* getFirst();
/** \brief
* Returns the last basic block in the current iteration of the extended basic block sequence.
*/
TR::Block* getLast();
/** \brief
* Advances the iterator to the next extended basic block in TreeTop order.
*/
void operator ++();
private:
void logCurrentLocation();
private:
TR::Block* _currBlock;
TR::Block* _nextBlock;
};
}
#endif