source: src/AST/Stmt.hpp@ 4e13e2a

ADT arm-eh ast-experimental enum forall-pointer-decay jacob/cs343-translation new-ast new-ast-unique-expr pthread-emulation qualifiedEnum
Last change on this file since 4e13e2a was c570806, checked in by Michael Brooks <mlbrooks@…>, 6 years ago

Changing new AST's ImplicitCtorDtorStatement to _own_ its reference to the underlying ctor/dtor call statement.

This change fixes a new-AST-resolver bug in which bootloader output lacks constructor/destructor calls surrounding overt declarations. (Constructor/destructor calls on temporaries were already working.)

This fix addresses the last bootloader output difference: now new-AST's bootloader output equals old AST's.

ImplicitCtorDtorStatement's reference to the underlying ctor/dtor call statement changes from readonly<...> to ptr<...>. Accordingly, the visitor framework changes, now proceeding across this reference. Old-AST deletes across this reference on ~ImplicitCtorDtorStatement and old-AST's visitor framework proceeds across this reference. Old AST's declaration of this reference had an incorrect comment saying the reference was non-owning; adjusting this comment.

Future issues with the ownership details of this reference may occur, e.g. when trying to port FixInit to new-AST. In the new-AST modeling, we need to ensure that re-parenting works properly, i.e. we don't delete in a transition state where the ref count falls to zero. The lifecycle of the underlying ctor/dtor statement is only partially understood. I believe, but have only partly tested, that for overt declarations:

This change has been tested for a clean convert-convert difference (vs no new-AST at all), for convert-convert at: pre-resolve, post-resolve, post-parse.

This change has been tested for, and causes a small regression of, cfa-cpp speed of compiling bootloader. Old AST = 4.72 s, New AST before this change = 3.74 s, New ast after this change 3.79 s. All numbers are mean of middle 3, among 5 samples, with 5-sample SDs <= 0.16 sec and mid-3 SDs <= 0.012 sec. New-AST improvement before this fix = 20.8%, new-AST improvement after this fix = 19.7%, a loss of 5.3% of the improvement.

The performance loss makes sense because more constructor calls are being exposed to the resolver. Constructor calls are generally most expensive to resolve, because of their high number of function-name matches.

  • Property mode set to 100644
File size: 12.3 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
7// Stmt.hpp --
8//
9// Author : Aaron B. Moss
10// Created On : Wed May 8 13:00:00 2019
11// Last Modified By : Andrew Beach
12// Last Modified On : Fri May 17 12:45:00 2019
13// Update Count : 5
14//
15
16#pragma once
17
18#include <list>
19#include <utility> // for move
20#include <vector>
21
22#include "Label.hpp"
23#include "Node.hpp" // for node, ptr
24#include "ParseNode.hpp"
25#include "Visitor.hpp"
26#include "Common/CodeLocation.h"
27
28// Must be included in *all* AST classes; should be #undef'd at the end of the file
29#define MUTATE_FRIEND \
30 template<typename node_t> friend node_t * mutate(const node_t * node); \
31 template<typename node_t> friend node_t * shallowCopy(const node_t * node);
32
33namespace ast {
34
35class Expr;
36
37/// Base statement node
38class Stmt : public ParseNode {
39public:
40 std::vector<Label> labels;
41
42 Stmt( const CodeLocation & loc, std::vector<Label> && labels = {} )
43 : ParseNode(loc), labels(std::move(labels)) {}
44
45 Stmt(const Stmt& o) : ParseNode(o), labels(o.labels) {}
46
47 const Stmt * accept( Visitor & v ) const override = 0;
48private:
49 Stmt * clone() const override = 0;
50 MUTATE_FRIEND
51};
52
53/// Compound statement `{ ... }`
54class CompoundStmt final : public Stmt {
55public:
56 std::list<ptr<Stmt>> kids;
57
58 CompoundStmt(const CodeLocation & loc, std::list<ptr<Stmt>> && ks = {},
59 std::vector<Label>&& labels = {} )
60 : Stmt(loc, std::move(labels)), kids(std::move(ks)) {}
61
62 CompoundStmt( const CompoundStmt& o );
63 CompoundStmt( CompoundStmt&& o ) = default;
64
65 void push_back( const Stmt * s ) { kids.emplace_back( s ); }
66 void push_front( const Stmt * s ) { kids.emplace_front( s ); }
67
68 const CompoundStmt * accept( Visitor & v ) const override { return v.visit( this ); }
69private:
70 CompoundStmt * clone() const override { return new CompoundStmt{ *this }; }
71 MUTATE_FRIEND
72};
73
74/// Empty statment `;`
75class NullStmt final : public Stmt {
76public:
77 NullStmt( const CodeLocation & loc, std::vector<Label> && labels = {} )
78 : Stmt(loc, std::move(labels)) {}
79
80 const NullStmt * accept( Visitor & v ) const override { return v.visit( this ); }
81private:
82 NullStmt * clone() const override { return new NullStmt{ *this }; }
83 MUTATE_FRIEND
84};
85
86/// Expression wrapped by statement
87class ExprStmt final : public Stmt {
88public:
89 ptr<Expr> expr;
90
91 ExprStmt( const CodeLocation& loc, const Expr* e, std::vector<Label>&& labels = {} )
92 : Stmt(loc, std::move(labels)), expr(e) {}
93
94 const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
95private:
96 ExprStmt * clone() const override { return new ExprStmt{ *this }; }
97 MUTATE_FRIEND
98};
99
100/// Assembly statement `asm ... ( "..." : ... )`
101class AsmStmt final : public Stmt {
102public:
103 bool isVolatile;
104 ptr<Expr> instruction;
105 std::vector<ptr<Expr>> output, input;
106 std::vector<ptr<ConstantExpr>> clobber;
107 std::vector<Label> gotoLabels;
108
109 AsmStmt( const CodeLocation & loc, bool isVolatile, const Expr * instruction,
110 std::vector<ptr<Expr>> && output, std::vector<ptr<Expr>> && input,
111 std::vector<ptr<ConstantExpr>> && clobber, std::vector<Label> && gotoLabels,
112 std::vector<Label> && labels = {})
113 : Stmt(loc, std::move(labels)), isVolatile(isVolatile), instruction(instruction),
114 output(std::move(output)), input(std::move(input)), clobber(std::move(clobber)),
115 gotoLabels(std::move(gotoLabels)) {}
116
117 const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
118private:
119 AsmStmt * clone() const override { return new AsmStmt{ *this }; }
120 MUTATE_FRIEND
121};
122
123/// C-preprocessor directive `#...`
124class DirectiveStmt final : public Stmt {
125public:
126 std::string directive;
127
128 DirectiveStmt( const CodeLocation & loc, const std::string & directive,
129 std::vector<Label> && labels = {} )
130 : Stmt(loc, std::move(labels)), directive(directive) {}
131
132 const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
133private:
134 DirectiveStmt * clone() const override { return new DirectiveStmt{ *this }; }
135 MUTATE_FRIEND
136};
137
138/// If conditional statement `if (...) ... else ...`
139class IfStmt final : public Stmt {
140public:
141 ptr<Expr> cond;
142 ptr<Stmt> thenPart;
143 ptr<Stmt> elsePart;
144 std::vector<ptr<Stmt>> inits;
145
146 IfStmt( const CodeLocation & loc, const Expr * cond, const Stmt * thenPart,
147 const Stmt * elsePart = nullptr, std::vector<ptr<Stmt>> && inits = {},
148 std::vector<Label> && labels = {} )
149 : Stmt(loc, std::move(labels)), cond(cond), thenPart(thenPart), elsePart(elsePart),
150 inits(std::move(inits)) {}
151
152 const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
153private:
154 IfStmt * clone() const override { return new IfStmt{ *this }; }
155 MUTATE_FRIEND
156};
157
158/// Switch or choose conditional statement `switch (...) { ... }`
159class SwitchStmt final : public Stmt {
160public:
161 ptr<Expr> cond;
162 std::vector<ptr<Stmt>> stmts;
163
164 SwitchStmt( const CodeLocation & loc, const Expr * cond, std::vector<ptr<Stmt>> && stmts,
165 std::vector<Label> && labels = {} )
166 : Stmt(loc, std::move(labels)), cond(cond), stmts(std::move(stmts)) {}
167
168 const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
169private:
170 SwitchStmt * clone() const override { return new SwitchStmt{ *this }; }
171 MUTATE_FRIEND
172};
173
174/// Case label `case ...:` `default:`
175class CaseStmt final : public Stmt {
176public:
177 ptr<Expr> cond;
178 std::vector<ptr<Stmt>> stmts;
179
180 CaseStmt( const CodeLocation & loc, const Expr * cond, std::vector<ptr<Stmt>> && stmts,
181 std::vector<Label> && labels = {} )
182 : Stmt(loc, std::move(labels)), cond(cond), stmts(std::move(stmts)) {}
183
184 bool isDefault() const { return !cond; }
185
186 const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
187private:
188 CaseStmt * clone() const override { return new CaseStmt{ *this }; }
189 MUTATE_FRIEND
190};
191
192/// While loop `while (...) ...` `do ... while (...);
193class WhileStmt final : public Stmt {
194public:
195 ptr<Expr> cond;
196 ptr<Stmt> body;
197 std::vector<ptr<Stmt>> inits;
198 bool isDoWhile;
199
200 WhileStmt( const CodeLocation & loc, const Expr * cond, const Stmt * body,
201 std::vector<ptr<Stmt>> && inits, bool isDoWhile = false, std::vector<Label> && labels = {} )
202 : Stmt(loc, std::move(labels)), cond(cond), body(body), inits(std::move(inits)),
203 isDoWhile(isDoWhile) {}
204
205 const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
206private:
207 WhileStmt * clone() const override { return new WhileStmt{ *this }; }
208 MUTATE_FRIEND
209};
210
211/// For loop `for (... ; ... ; ...) ...`
212class ForStmt final : public Stmt {
213public:
214 std::vector<ptr<Stmt>> inits;
215 ptr<Expr> cond;
216 ptr<Expr> inc;
217 ptr<Stmt> body;
218
219 ForStmt( const CodeLocation & loc, std::vector<ptr<Stmt>> && inits, const Expr * cond,
220 const Expr * inc, const Stmt * body, std::vector<Label> && labels = {} )
221 : Stmt(loc, std::move(labels)), inits(std::move(inits)), cond(cond), inc(inc),
222 body(body) {}
223
224 const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
225private:
226 ForStmt * clone() const override { return new ForStmt{ *this }; }
227 MUTATE_FRIEND
228};
229
230/// Branch control flow statement `goto ...` `break` `continue` `fallthru`
231class BranchStmt final : public Stmt {
232public:
233 enum Kind { Goto, Break, Continue, FallThrough, FallThroughDefault };
234 static constexpr size_t kindEnd = 1 + (size_t)FallThroughDefault;
235
236 const Label originalTarget;
237 Label target;
238 ptr<Expr> computedTarget;
239 Kind kind;
240
241 BranchStmt( const CodeLocation & loc, Kind kind, Label target,
242 std::vector<Label> && labels = {} );
243 BranchStmt( const CodeLocation & loc, const Expr * computedTarget,
244 std::vector<Label> && labels = {} )
245 : Stmt(loc, std::move(labels)), originalTarget(loc), target(loc),
246 computedTarget(computedTarget), kind(Goto) {}
247
248 const char * kindName() const { return kindNames[kind]; }
249
250 const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
251private:
252 BranchStmt * clone() const override { return new BranchStmt{ *this }; }
253 MUTATE_FRIEND
254
255 static const char * kindNames[kindEnd];
256};
257
258/// Return statement `return ...`
259class ReturnStmt final : public Stmt {
260public:
261 ptr<Expr> expr;
262
263 ReturnStmt( const CodeLocation & loc, const Expr * expr, std::vector<Label> && labels = {} )
264 : Stmt(loc, std::move(labels)), expr(expr) {}
265
266 const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
267private:
268 ReturnStmt * clone() const override { return new ReturnStmt{ *this }; }
269 MUTATE_FRIEND
270};
271
272/// Kind of exception
273enum ExceptionKind { Terminate, Resume };
274
275/// Throw statement `throw ...`
276class ThrowStmt final : public Stmt {
277public:
278 ptr<Expr> expr;
279 ptr<Expr> target;
280 ExceptionKind kind;
281
282 ThrowStmt(
283 const CodeLocation & loc, ExceptionKind kind, const Expr * expr, const Expr * target,
284 std::vector<Label> && labels = {} )
285 : Stmt(loc, std::move(labels)), expr(expr), target(target), kind(kind) {}
286
287 const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
288private:
289 ThrowStmt * clone() const override { return new ThrowStmt{ *this }; }
290 MUTATE_FRIEND
291};
292
293/// Try statement `try { ... } ...`
294class TryStmt final : public Stmt {
295public:
296 ptr<CompoundStmt> body;
297 std::vector<ptr<CatchStmt>> handlers;
298 ptr<FinallyStmt> finally;
299
300 TryStmt(
301 const CodeLocation & loc, const CompoundStmt * body,
302 std::vector<ptr<CatchStmt>> && handlers, const FinallyStmt * finally,
303 std::vector<Label> && labels = {} )
304 : Stmt(loc, std::move(labels)), body(body), handlers(std::move(handlers)), finally(finally) {}
305
306 const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
307private:
308 TryStmt * clone() const override { return new TryStmt{ *this }; }
309 MUTATE_FRIEND
310};
311
312/// Catch clause of try statement
313class CatchStmt final : public Stmt {
314public:
315 ptr<Decl> decl;
316 ptr<Expr> cond;
317 ptr<Stmt> body;
318 ExceptionKind kind;
319
320 CatchStmt(
321 const CodeLocation & loc, ExceptionKind kind, const Decl * decl, const Expr * cond,
322 const Stmt * body, std::vector<Label> && labels = {} )
323 : Stmt(loc, std::move(labels)), decl(decl), cond(cond), body(body), kind(kind) {}
324
325 const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
326private:
327 CatchStmt * clone() const override { return new CatchStmt{ *this }; }
328 MUTATE_FRIEND
329};
330
331/// Finally clause of try statement
332class FinallyStmt final : public Stmt {
333public:
334 ptr<CompoundStmt> body;
335
336 FinallyStmt( const CodeLocation & loc, const CompoundStmt * body,
337 std::vector<Label> && labels = {} )
338 : Stmt(loc, std::move(labels)), body(body) {}
339
340 const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
341private:
342 FinallyStmt * clone() const override { return new FinallyStmt{ *this }; }
343 MUTATE_FRIEND
344};
345
346/// Wait for concurrency statement `when (...) waitfor (... , ...) ... timeout(...) ... else ...`
347class WaitForStmt final : public Stmt {
348public:
349 struct Target {
350 ptr<Expr> func;
351 std::vector<ptr<Expr>> args;
352 };
353
354 struct Clause {
355 Target target;
356 ptr<Stmt> stmt;
357 ptr<Expr> cond;
358 };
359
360 struct Timeout {
361 ptr<Expr> time;
362 ptr<Stmt> stmt;
363 ptr<Expr> cond;
364 };
365
366 struct OrElse {
367 ptr<Stmt> stmt;
368 ptr<Expr> cond;
369 };
370
371 std::vector<Clause> clauses;
372 Timeout timeout;
373 OrElse orElse;
374
375 WaitForStmt( const CodeLocation & loc, std::vector<Label> && labels = {} )
376 : Stmt(loc, std::move(labels)) {}
377
378 const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
379private:
380 WaitForStmt * clone() const override { return new WaitForStmt{ *this }; }
381 MUTATE_FRIEND
382};
383
384/// Any declaration in a (compound) statement.
385class DeclStmt final : public Stmt {
386public:
387 ptr<Decl> decl;
388
389 DeclStmt( const CodeLocation & loc, const Decl * decl, std::vector<Label> && labels = {} )
390 : Stmt(loc, std::move(labels)), decl(decl) {}
391
392 const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
393private:
394 DeclStmt * clone() const override { return new DeclStmt{ *this }; }
395 MUTATE_FRIEND
396};
397
398/// Represents an implicit application of a constructor or destructor.
399class ImplicitCtorDtorStmt final : public Stmt {
400public:
401 ptr<Stmt> callStmt;
402
403 ImplicitCtorDtorStmt( const CodeLocation & loc, const Stmt * callStmt,
404 std::vector<Label> && labels = {} )
405 : Stmt(loc, std::move(labels)), callStmt(callStmt) {}
406
407 const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
408private:
409 ImplicitCtorDtorStmt * clone() const override { return new ImplicitCtorDtorStmt{ *this }; }
410 MUTATE_FRIEND
411};
412
413}
414
415#undef MUTATE_FRIEND
416
417// Local Variables: //
418// tab-width: 4 //
419// mode: c++ //
420// compile-command: "make install" //
421// End: //
Note: See TracBrowser for help on using the repository browser.