source: src/InitTweak/RemoveInit.cc @ 071a31a

aaron-thesisarm-ehcleanup-dtorsctordeferred_resndemanglergc_noraiijacob/cs343-translationjenkins-sandboxmemorynew-astnew-ast-unique-exprnew-envno_listpersistent-indexerresolv-newwith_gc
Last change on this file since 071a31a was 071a31a, checked in by Rob Schluntz <rschlunt@…>, 6 years ago

removed array ctor/dtors from prelude, generalized struct routine generation, fix fall back on initializer if ctor not found, begin special casing array ctor/dtor

  • Property mode set to 100644
File size: 9.8 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// RemoveInit.cc --
8//
9// Author           : Rob Schluntz
10// Created On       : Mon May 18 07:44:20 2015
11// Last Modified By : Rob Schluntz
12// Last Modified On : Tue Feb 09 15:12:29 2016
13// Update Count     : 166
14//
15
16#include <stack>
17#include <list>
18#include "RemoveInit.h"
19#include "SynTree/Declaration.h"
20#include "SynTree/Type.h"
21#include "SynTree/Expression.h"
22#include "SynTree/Statement.h"
23#include "SynTree/Initializer.h"
24#include "SynTree/Mutator.h"
25#include "GenPoly/PolyMutator.h"
26
27namespace InitTweak {
28        namespace {
29                const std::list<Label> noLabels;
30        }
31
32        class RemoveInit : public GenPoly::PolyMutator {
33          public:
34                /// removes and replaces initialization for polymorphic value objects
35                /// with assignment (TODO: constructor) statements.
36                /// also consistently allocates a temporary variable for the return value
37                /// of a function so that anything which the resolver decides can be assigned
38                /// into the return type of a function can be returned.
39                static void removeInitializers( std::list< Declaration * > &translationUnit );
40
41                RemoveInit();
42                virtual ObjectDecl * mutate( ObjectDecl *objDecl );
43                virtual DeclarationWithType * mutate( FunctionDecl *functionDecl );
44
45                virtual Statement * mutate( ReturnStmt * returnStmt );
46
47          protected:
48                std::list<DeclarationWithType*> returnVals;
49                UniqueName tempNamer;
50                std::string funcName;
51        };
52
53        class CtorDtor : public GenPoly::PolyMutator {
54          public:
55                /// create constructor and destructor statements for object declarations.
56                /// Destructors are inserted directly into the code, whereas constructors
57                /// will be added in after the resolver has run so that the initializer expression
58                /// is only removed if a constructor is found
59                static void generateCtorDtor( std::list< Declaration * > &translationUnit );
60
61                CtorDtor() : inFunction( false ) {}
62
63                virtual ObjectDecl * mutate( ObjectDecl * );
64                virtual DeclarationWithType * mutate( FunctionDecl *functionDecl );
65                virtual Declaration* mutate( StructDecl *aggregateDecl );
66                virtual Declaration* mutate( UnionDecl *aggregateDecl );
67                virtual Declaration* mutate( EnumDecl *aggregateDecl );
68                virtual Declaration* mutate( ContextDecl *aggregateDecl );
69                virtual TypeDecl* mutate( TypeDecl *typeDecl );
70                virtual Declaration* mutate( TypedefDecl *typeDecl );
71
72                virtual CompoundStmt * mutate( CompoundStmt * compoundStmt );
73
74          protected:
75                bool inFunction;
76
77                // to be added before block ends - use push_front so order is correct
78                std::list< Statement * > destructorStmts;
79        };
80
81        void tweak( std::list< Declaration * > & translationUnit ) {
82                RemoveInit::removeInitializers( translationUnit );
83                CtorDtor::generateCtorDtor( translationUnit );
84        }
85
86        void RemoveInit::removeInitializers( std::list< Declaration * > & translationUnit ) {
87                RemoveInit remover;
88                mutateAll( translationUnit, remover );
89        }
90
91        RemoveInit::RemoveInit() : tempNamer( "_retVal" ) {}
92
93        // in the case where an object has an initializer and a polymorphic type, insert an assignment immediately after the
94        // declaration. This will (seemingly) cause the later phases to do the right thing with the assignment
95        ObjectDecl *RemoveInit::mutate( ObjectDecl *objDecl ) {
96                if (objDecl->get_init() && dynamic_cast<TypeInstType*>(objDecl->get_type())) {
97                        if (SingleInit * single = dynamic_cast<SingleInit*>(objDecl->get_init())) {
98                                // xxx this can be more complicated - consider ListInit
99                                UntypedExpr *assign = new UntypedExpr( new NameExpr( "?{}" ) );
100                                assign->get_args().push_back( new AddressExpr (new NameExpr( objDecl->get_name() ) ) );
101                                assign->get_args().push_back( single->get_value()->clone() );
102                                stmtsToAddAfter.push_back(new ExprStmt(noLabels, assign));
103                        } // if
104                } // if
105                return objDecl;
106        }
107
108        Statement *RemoveInit::mutate( ReturnStmt *returnStmt ) {
109                // update for multiple return values
110                assert( returnVals.size() == 0 || returnVals.size() == 1 );
111                // hands off if the function returns an lvalue - we don't want to allocate a temporary if a variable's address
112                // is being returned
113                // xxx - this should construct rather than assign
114                if ( returnStmt->get_expr() && returnVals.size() == 1 && funcName != "?=?" && ! returnVals.front()->get_type()->get_isLvalue()  ) {
115                        ObjectDecl *newObj = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, returnVals.front()->get_type()->clone(), 0 );
116                        stmtsToAdd.push_back( new DeclStmt( noLabels, newObj ) );
117
118                        UntypedExpr *assign = new UntypedExpr( new NameExpr( "?=?" ) );
119                        assign->get_args().push_back( new AddressExpr (new NameExpr( newObj->get_name() ) ) );
120                        assign->get_args().push_back( returnStmt->get_expr() );
121                        stmtsToAdd.push_back(new ExprStmt(noLabels, assign));
122
123                        returnStmt->set_expr( new VariableExpr( newObj ) );
124                } // if
125                return returnStmt;
126        }
127
128        DeclarationWithType* RemoveInit::mutate( FunctionDecl *functionDecl ) {
129                std::list<DeclarationWithType*> oldReturnVals = returnVals;
130                std::string oldFuncName = funcName;
131
132                FunctionType * type = functionDecl->get_functionType();
133                returnVals = type->get_returnVals();
134                funcName = functionDecl->get_name();
135                DeclarationWithType * decl = Mutator::mutate( functionDecl );
136                returnVals = oldReturnVals;
137                funcName = oldFuncName;
138                return decl;
139        }
140
141
142        void CtorDtor::generateCtorDtor( std::list< Declaration * > & translationUnit ) {
143                CtorDtor ctordtor;
144                mutateAll( translationUnit, ctordtor );
145        }
146
147        namespace {
148                bool tryConstruct( ObjectDecl * objDecl ) {
149                        // xxx - handle designations
150                        return ! LinkageSpec::isBuiltin( objDecl->get_linkage() ) &&
151                                (objDecl->get_init() == NULL ||
152                                ( objDecl->get_init() != NULL && objDecl->get_init()->get_maybeConstructed() ));
153                }
154
155                Expression * makeCtorDtorExpr( std::string name, ObjectDecl * objDecl, std::list< Expression * > args ) {
156                        UntypedExpr * expr = new UntypedExpr( new NameExpr( name ) );
157                        expr->get_args().push_back( new AddressExpr( new VariableExpr( objDecl ) ) );
158                        expr->get_args().splice( expr->get_args().end(), args );
159                        return expr;
160                }
161
162                class InitExpander : public Visitor {
163                  public:
164                  InitExpander() {}
165                  // ~InitExpander() {}
166                        virtual void visit( SingleInit * singleInit );
167                        virtual void visit( ListInit * listInit );
168                        std::list< Expression * > argList;
169                };
170
171                void InitExpander::visit( SingleInit * singleInit ) {
172                        argList.push_back( singleInit->get_value()->clone() );
173                }
174
175                void InitExpander::visit( ListInit * listInit ) {
176                        // xxx - for now, assume no nested list inits
177                        std::list<Initializer*>::iterator it = listInit->begin_initializers();
178                        for ( ; it != listInit->end_initializers(); ++it ) {
179                                (*it)->accept( *this );
180                        }
181                }
182
183                std::list< Expression * > makeInitList( Initializer * init ) {
184                        InitExpander expander;
185                        maybeAccept( init, expander );
186                        return expander.argList;
187                }
188        }
189
190        ObjectDecl * CtorDtor::mutate( ObjectDecl * objDecl ) {
191                // hands off if designated or if @=
192                if ( tryConstruct( objDecl ) ) {
193                        if ( inFunction ) {
194                                if ( ArrayType * at = dynamic_cast< ArrayType * >( objDecl->get_type() ) ) {
195                                        // call into makeArrayFunction from validate.cc to generate calls to ctor/dtor for each element of array
196                                } else {
197                                        // it's sufficient to attempt to call the ctor/dtor for the given object and its initializer
198                                        Expression * ctor = makeCtorDtorExpr( "?{}", objDecl, makeInitList( objDecl->get_init() ) );
199                                        Expression * dtor = makeCtorDtorExpr( "^?{}", objDecl, std::list< Expression * >() );
200
201                                        // need to remember init expression, in case no ctors exist
202                                        // if ctor does exist, want to use ctor expression instead of init
203                                        // push this decision to the resolver
204                                        objDecl->set_init( new ConstructorInit( ctor, objDecl->get_init() ) );
205                                        destructorStmts.push_front( new ExprStmt( noLabels, dtor ) );
206                                }
207                        } else {
208                                // xxx - find a way to construct/destruct globals
209                                // hack: implicit "static" initialization routine for each struct type? or something similar?
210                                // --ties into module system
211                                // this can be done by mangling main and replacing it with our own main which calls each
212                                // module initialization routine in some decided order (order given in link command?)
213                                // and finally calls mangled main
214                        }
215                }
216                return objDecl;
217        }
218
219        DeclarationWithType * CtorDtor::mutate( FunctionDecl *functionDecl ) {
220                // parameters should not be constructed and destructed, so don't mutate FunctionType
221                bool oldInFunc = inFunction;
222                mutateAll( functionDecl->get_oldDecls(), *this );
223                inFunction = true;
224                functionDecl->set_statements( maybeMutate( functionDecl->get_statements(), *this ) );
225                inFunction = oldInFunc;
226                return functionDecl;
227        }
228
229        CompoundStmt * CtorDtor::mutate( CompoundStmt * compoundStmt ) {
230                CompoundStmt * ret = PolyMutator::mutate( compoundStmt );
231                std::list< Statement * > &statements = ret->get_kids();
232                if ( ! destructorStmts.empty() ) {
233                        // TODO: adding to the end of a block isn't sufficient, since
234                        // return/break/goto should trigger destructor when block is left.
235                        statements.splice( statements.end(), destructorStmts );
236                } // if
237                return ret;
238        }
239
240        // should not traverse into any of these declarations to find objects
241        // that need to be constructed or destructed
242        Declaration* CtorDtor::mutate( StructDecl *aggregateDecl ) { return aggregateDecl; }
243        Declaration* CtorDtor::mutate( UnionDecl *aggregateDecl ) { return aggregateDecl; }
244        Declaration* CtorDtor::mutate( EnumDecl *aggregateDecl ) { return aggregateDecl; }
245        Declaration* CtorDtor::mutate( ContextDecl *aggregateDecl ) { return aggregateDecl; }
246        TypeDecl* CtorDtor::mutate( TypeDecl *typeDecl ) { return typeDecl; }
247        Declaration* CtorDtor::mutate( TypedefDecl *typeDecl ) { return typeDecl; }
248
249} // namespace InitTweak
250
251// Local Variables: //
252// tab-width: 4 //
253// mode: c++ //
254// compile-command: "make install" //
255// End: //
Note: See TracBrowser for help on using the repository browser.