Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(74)

Side by Side Diff: lib/Target/JSBackend/Relooper.h

Issue 1692803002: Remove Emscripten support (Closed) Base URL: https://chromium.googlesource.com/a/native_client/pnacl-llvm.git@master
Patch Set: Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « lib/Target/JSBackend/OptPasses.h ('k') | lib/Target/JSBackend/Relooper.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 This is an optimized C++ implemention of the Relooper algorithm originally
3 developed as part of Emscripten. This implementation includes optimizations
4 added since the original academic paper [1] was published about it, and is
5 written in an LLVM-friendly way with the goal of inclusion in upstream
6 LLVM.
7
8 [1] Alon Zakai. 2011. Emscripten: an LLVM-to-JavaScript compiler. In Proceedings of the ACM international conference companion on Object oriented programming sy stems languages and applications companion (SPLASH '11). ACM, New York, NY, USA, 301-312. DOI=10.1145/2048147.2048224 http://doi.acm.org/10.1145/2048147.2048224
9 */
10
11 #include <assert.h>
12 #include <stdio.h>
13 #include <stdarg.h>
14
15 #ifdef __cplusplus
16
17 #include <map>
18 #include <deque>
19 #include <set>
20
21 struct Block;
22 struct Shape;
23
24 // Info about a branching from one block to another
25 struct Branch {
26 enum FlowType {
27 Direct = 0, // We will directly reach the right location through other mea ns, no need for continue or break
28 Break = 1,
29 Continue = 2,
30 Nested = 3 // This code is directly reached, but we must be careful to en sure it is nested in an if - it is not reached
31 // unconditionally, other code paths exist alongside it that w e need to make sure do not intertwine
32 };
33 Shape *Ancestor; // If not NULL, this shape is the relevant one for purposes o f getting to the target block. We break or continue on it
34 Branch::FlowType Type; // If Ancestor is not NULL, this says whether to break or continue
35 bool Labeled; // If a break or continue, whether we need to use a label
36 const char *Condition; // The condition for which we branch. For example, "my_ var == 1". Conditions are checked one by one. One of the conditions should have NULL as the condition, in which case it is the default
37 const char *Code; // If provided, code that is run right before the branch is taken. This is useful for phis
38
39 Branch(const char *ConditionInit, const char *CodeInit=NULL);
40 ~Branch();
41
42 // Prints out the branch
43 void Render(Block *Target, bool SetLabel);
44 };
45
46 typedef std::set<Block*> BlockSet;
47 typedef std::map<Block*, Branch*> BlockBranchMap;
48
49 // Represents a basic block of code - some instructions that end with a
50 // control flow modifier (a branch, return or throw).
51 struct Block {
52 // Branches become processed after we finish the shape relevant to them. For e xample,
53 // when we recreate a loop, branches to the loop start become continues and ar e now
54 // processed. When we calculate what shape to generate from a set of blocks, w e ignore
55 // processed branches.
56 // Blocks own the Branch objects they use, and destroy them when done.
57 BlockBranchMap BranchesOut;
58 BlockSet BranchesIn;
59 BlockBranchMap ProcessedBranchesOut;
60 BlockSet ProcessedBranchesIn;
61 Shape *Parent; // The shape we are directly inside
62 int Id; // A unique identifier, defined when added to relooper. Note that this uniquely identifies a *logical* block - if we split it, the two instances have the same content *and* the same Id
63 const char *Code; // The string representation of the code in this block. Owni ng pointer (we copy the input)
64 const char *BranchVar; // A variable whose value determines where we go; if th is is not NULL, emit a switch on that variable
65 bool IsCheckedMultipleEntry; // If true, we are a multiple entry, so reaching us requires setting the label variable
66
67 Block(const char *CodeInit, const char *BranchVarInit);
68 ~Block();
69
70 void AddBranchTo(Block *Target, const char *Condition, const char *Code=NULL);
71
72 // Prints out the instructions code and branchings
73 void Render(bool InLoop);
74 };
75
76 // Represents a structured control flow shape, one of
77 //
78 // Simple: No control flow at all, just instructions. If several
79 // blocks, then
80 //
81 // Multiple: A shape with more than one entry. If the next block to
82 // be entered is among them, we run it and continue to
83 // the next shape, otherwise we continue immediately to the
84 // next shape.
85 //
86 // Loop: An infinite loop.
87 //
88 // Emulated: Control flow is managed by a switch in a loop. This
89 // is necessary in some cases, for example when control
90 // flow is not known until runtime (indirect branches,
91 // setjmp returns, etc.)
92 //
93
94 struct SimpleShape;
95 struct LabeledShape;
96 struct MultipleShape;
97 struct LoopShape;
98 struct EmulatedShape;
99
100 struct Shape {
101 int Id; // A unique identifier. Used to identify loops, labels are Lx where x is the Id. Defined when added to relooper
102 Shape *Next; // The shape that will appear in the code right after this one
103 Shape *Natural; // The shape that control flow gets to naturally (if there is Next, then this is Next)
104
105 enum ShapeType {
106 Simple,
107 Multiple,
108 Loop,
109 Emulated
110 };
111 ShapeType Type;
112
113 Shape(ShapeType TypeInit) : Id(-1), Next(NULL), Type(TypeInit) {}
114 virtual ~Shape() {}
115
116 virtual void Render(bool InLoop) = 0;
117
118 static SimpleShape *IsSimple(Shape *It) { return It && It->Type == Simple ? (S impleShape*)It : NULL; }
119 static MultipleShape *IsMultiple(Shape *It) { return It && It->Type == Multipl e ? (MultipleShape*)It : NULL; }
120 static LoopShape *IsLoop(Shape *It) { return It && It->Type == Loop ? (LoopSha pe*)It : NULL; }
121 static LabeledShape *IsLabeled(Shape *It) { return IsMultiple(It) || IsLoop(It ) ? (LabeledShape*)It : NULL; }
122 static EmulatedShape *IsEmulated(Shape *It) { return It && It->Type == Emulate d ? (EmulatedShape*)It : NULL; }
123 };
124
125 struct SimpleShape : public Shape {
126 Block *Inner;
127
128 SimpleShape() : Shape(Simple), Inner(NULL) {}
129 void Render(bool InLoop) {
130 Inner->Render(InLoop);
131 if (Next) Next->Render(InLoop);
132 }
133 };
134
135 // A shape that may be implemented with a labeled loop.
136 struct LabeledShape : public Shape {
137 bool Labeled; // If we have a loop, whether it needs to be labeled
138
139 LabeledShape(ShapeType TypeInit) : Shape(TypeInit), Labeled(false) {}
140 };
141
142 // Blocks with the same id were split and are identical, so we just care about i ds in Multiple entries
143 typedef std::map<int, Shape*> IdShapeMap;
144
145 struct MultipleShape : public LabeledShape {
146 IdShapeMap InnerMap; // entry block ID -> shape
147 int Breaks; // If we have branches on us, we need a loop (or a switch). This i s a counter of requirements,
148 // if we optimize it to 0, the loop is unneeded
149 bool UseSwitch; // Whether to switch on label as opposed to an if-else chain
150
151 MultipleShape() : LabeledShape(Multiple), Breaks(0), UseSwitch(false) {}
152
153 void RenderLoopPrefix();
154 void RenderLoopPostfix();
155
156 void Render(bool InLoop);
157 };
158
159 struct LoopShape : public LabeledShape {
160 Shape *Inner;
161
162 LoopShape() : LabeledShape(Loop), Inner(NULL) {}
163 void Render(bool InLoop);
164 };
165
166 // TODO EmulatedShape is only partially functional. Currently it can be used for the
167 // entire set of blocks being relooped, but not subsets.
168 struct EmulatedShape : public LabeledShape {
169 Block *Entry;
170 BlockSet Blocks;
171
172 EmulatedShape() : LabeledShape(Emulated) { Labeled = true; }
173 void Render(bool InLoop);
174 };
175
176 // Implements the relooper algorithm for a function's blocks.
177 //
178 // Usage:
179 // 1. Instantiate this struct.
180 // 2. Call AddBlock with the blocks you have. Each should already
181 // have its branchings in specified (the branchings out will
182 // be calculated by the relooper).
183 // 3. Call Render().
184 //
185 // Implementation details: The Relooper instance has
186 // ownership of the blocks and shapes, and frees them when done.
187 struct Relooper {
188 std::deque<Block*> Blocks;
189 std::deque<Shape*> Shapes;
190 Shape *Root;
191 bool Emulate;
192 bool MinSize;
193 int BlockIdCounter;
194 int ShapeIdCounter;
195
196 Relooper();
197 ~Relooper();
198
199 void AddBlock(Block *New, int Id=-1);
200
201 // Calculates the shapes
202 void Calculate(Block *Entry);
203
204 // Renders the result.
205 void Render();
206
207 // Sets the global buffer all printing goes to. Must call this or MakeOutputBu ffer.
208 // XXX: this is deprecated, see MakeOutputBuffer
209 static void SetOutputBuffer(char *Buffer, int Size);
210
211 // Creates an internal output buffer. Must call this or SetOutputBuffer. Size is
212 // a hint for the initial size of the buffer, it can be resized later one dema nd.
213 // For that reason this is more recommended than SetOutputBuffer.
214 static void MakeOutputBuffer(int Size);
215
216 static char *GetOutputBuffer();
217
218 // Sets asm.js mode on or off (default is off)
219 static void SetAsmJSMode(int On);
220
221 // Sets whether we must emulate everything with switch-loop code
222 void SetEmulate(int E) { Emulate = E; }
223
224 // Sets us to try to minimize size
225 void SetMinSize(bool MinSize_) { MinSize = MinSize_; }
226 };
227
228 typedef std::map<Block*, BlockSet> BlockBlockSetMap;
229
230 #if DEBUG
231 struct Debugging {
232 static void Dump(BlockSet &Blocks, const char *prefix=NULL);
233 static void Dump(Shape *S, const char *prefix=NULL);
234 };
235 #endif
236
237 #endif // __cplusplus
238
239 // C API - useful for binding to other languages
240
241 #ifdef _WIN32
242 #ifdef RELOOPERDLL_EXPORTS
243 #define RELOOPERDLL_API __declspec(dllexport)
244 #else
245 #define RELOOPERDLL_API __declspec(dllimport)
246 #endif
247 #else
248 #define RELOOPERDLL_API
249 #endif
250
251 #ifdef __cplusplus
252 extern "C" {
253 #endif
254
255 RELOOPERDLL_API void rl_set_output_buffer(char *buffer, int size);
256 RELOOPERDLL_API void rl_make_output_buffer(int size);
257 RELOOPERDLL_API void rl_set_asm_js_mode(int on);
258 RELOOPERDLL_API void *rl_new_block(const char *text, const char *branch_var);
259 RELOOPERDLL_API void rl_delete_block(void *block);
260 RELOOPERDLL_API void rl_block_add_branch_to(void *from, void *to, const char *c ondition, const char *code);
261 RELOOPERDLL_API void *rl_new_relooper();
262 RELOOPERDLL_API void rl_delete_relooper(void *relooper);
263 RELOOPERDLL_API void rl_relooper_add_block(void *relooper, void *block);
264 RELOOPERDLL_API void rl_relooper_calculate(void *relooper, void *entry);
265 RELOOPERDLL_API void rl_relooper_render(void *relooper);
266
267 #ifdef __cplusplus
268 }
269 #endif
270
OLDNEW
« no previous file with comments | « lib/Target/JSBackend/OptPasses.h ('k') | lib/Target/JSBackend/Relooper.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698