source: src/AST/Stmt.hpp @ c570806

arm-ehenumforall-pointer-decayjacob/cs343-translationnew-astnew-ast-unique-exprpthread-emulationqualifiedEnum
Last change on this file since c570806 was c570806, checked in by Michael Brooks <mlbrooks@…>, 3 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.