source: src/InitTweak/RemoveInit.cc@ 02c7d04

ADT aaron-thesis arm-eh ast-experimental cleanup-dtors ctor deferred_resn demangler enum forall-pointer-decay gc_noraii jacob/cs343-translation jenkins-sandbox memory new-ast new-ast-unique-expr new-env no_list persistent-indexer pthread-emulation qualifiedEnum resolv-new with_gc
Last change on this file since 02c7d04 was 02c7d04, checked in by Rob Schluntz <rschlunt@…>, 10 years ago

inserts constructor and destructor statements for object declarations - to be resolved

  • Property mode set to 100644
File size: 8.6 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 : Mon Jan 11 16:10:45 2016
13// Update Count : 150
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 virtual ObjectDecl * mutate( ObjectDecl * );
62 virtual DeclarationWithType * mutate( FunctionDecl *functionDecl );
63 virtual Declaration* mutate( StructDecl *aggregateDecl );
64 virtual Declaration* mutate( UnionDecl *aggregateDecl );
65 virtual Declaration* mutate( EnumDecl *aggregateDecl );
66 virtual Declaration* mutate( ContextDecl *aggregateDecl );
67 virtual TypeDecl* mutate( TypeDecl *typeDecl );
68 virtual Declaration* mutate( TypedefDecl *typeDecl );
69
70 virtual CompoundStmt * mutate( CompoundStmt * compoundStmt );
71
72 protected:
73
74 // to be added before block ends - use push_front so order is correct
75 std::list< Statement * > destructorStmts;
76 };
77
78 void tweak( std::list< Declaration * > & translationUnit ) {
79 RemoveInit::removeInitializers( translationUnit );
80 CtorDtor::generateCtorDtor( translationUnit );
81 }
82
83 void RemoveInit::removeInitializers( std::list< Declaration * > & translationUnit ) {
84 RemoveInit remover;
85 mutateAll( translationUnit, remover );
86 }
87
88 RemoveInit::RemoveInit() : tempNamer( "_retVal" ) {}
89
90 // in the case where an object has an initializer and a polymorphic type, insert an assignment immediately after the
91 // declaration. This will (seemingly) cause the later phases to do the right thing with the assignment
92 ObjectDecl *RemoveInit::mutate( ObjectDecl *objDecl ) {
93 if (objDecl->get_init() && dynamic_cast<TypeInstType*>(objDecl->get_type())) {
94 if (SingleInit * single = dynamic_cast<SingleInit*>(objDecl->get_init())) {
95 UntypedExpr *assign = new UntypedExpr( new NameExpr( "?=?" ) );
96 assign->get_args().push_back( new AddressExpr (new NameExpr( objDecl->get_name() ) ) );
97 assign->get_args().push_back( single->get_value()->clone() );
98 stmtsToAddAfter.push_back(new ExprStmt(noLabels, assign));
99 } // if
100 } // if
101 return objDecl;
102 }
103
104 Statement *RemoveInit::mutate( ReturnStmt *returnStmt ) {
105 // update for multiple return values
106 assert( returnVals.size() == 0 || returnVals.size() == 1 );
107 // hands off if the function returns an lvalue - we don't want to allocate a temporary if a variable's address
108 // is being returned
109 if ( returnStmt->get_expr() && returnVals.size() == 1 && funcName != "?=?" && ! returnVals.front()->get_type()->get_isLvalue() ) {
110 ObjectDecl *newObj = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, returnVals.front()->get_type()->clone(), 0 );
111 stmtsToAdd.push_back( new DeclStmt( noLabels, newObj ) );
112
113 UntypedExpr *assign = new UntypedExpr( new NameExpr( "?=?" ) );
114 assign->get_args().push_back( new AddressExpr (new NameExpr( newObj->get_name() ) ) );
115 assign->get_args().push_back( returnStmt->get_expr() );
116 stmtsToAdd.push_back(new ExprStmt(noLabels, assign));
117
118 returnStmt->set_expr( new VariableExpr( newObj ) );
119 } // if
120 return returnStmt;
121 }
122
123 DeclarationWithType* RemoveInit::mutate( FunctionDecl *functionDecl ) {
124 std::list<DeclarationWithType*> oldReturnVals = returnVals;
125 std::string oldFuncName = funcName;
126
127 FunctionType * type = functionDecl->get_functionType();
128 returnVals = type->get_returnVals();
129 funcName = functionDecl->get_name();
130 DeclarationWithType * decl = Mutator::mutate( functionDecl );
131 returnVals = oldReturnVals;
132 funcName = oldFuncName;
133 return decl;
134 }
135
136
137 void CtorDtor::generateCtorDtor( std::list< Declaration * > & translationUnit ) {
138 CtorDtor ctordtor;
139 mutateAll( translationUnit, ctordtor );
140 }
141
142 namespace {
143 bool tryConstruct( ObjectDecl * objDecl ) {
144 // xxx - handle designations
145 return ! LinkageSpec::isBuiltin( objDecl->get_linkage() ) &&
146 (objDecl->get_init() == NULL ||
147 ( objDecl->get_init() != NULL && objDecl->get_init()->get_maybeConstructed() ));
148 }
149
150 ExprStmt * makeCtorDtorStmt( std::string name, ObjectDecl * objDecl, std::list< Expression * > args ) {
151 UntypedExpr * expr = new UntypedExpr( new NameExpr( name ) );
152 expr->get_args().push_back( new AddressExpr( new VariableExpr( objDecl ) ) );
153 expr->get_args().splice( expr->get_args().end(), args );
154 return new ExprStmt( noLabels, expr );
155 }
156
157 class InitExpander : public Visitor {
158 public:
159 InitExpander() {}
160 // ~InitExpander() {}
161 virtual void visit( SingleInit * singleInit );
162 virtual void visit( ListInit * listInit );
163 std::list< Expression * > argList;
164 };
165
166 void InitExpander::visit( SingleInit * singleInit ) {
167 argList.push_back( singleInit->get_value()->clone() );
168 }
169
170 void InitExpander::visit( ListInit * listInit ) {
171 // xxx - for now, assume no nested list inits
172 std::list<Initializer*>::iterator it = listInit->begin_initializers();
173 for ( ; it != listInit->end_initializers(); ++it ) {
174 (*it)->accept( *this );
175 }
176 }
177
178 std::list< Expression * > makeInitList( Initializer * init ) {
179 InitExpander expander;
180 maybeAccept( init, expander );
181 return expander.argList;
182 }
183 }
184
185 ObjectDecl * CtorDtor::mutate( ObjectDecl * objDecl ) {
186 // hands off if designated or if @=
187 if ( tryConstruct( objDecl ) ) {
188 ExprStmt * ctor = makeCtorDtorStmt( "?{}", objDecl, makeInitList( objDecl->get_init() ) );
189 ExprStmt * dtor = makeCtorDtorStmt( "^?{}", objDecl, std::list< Expression * >() );
190
191 // set_ctor...
192 // need to remember init expression, in case no ctors exist
193 // if ctor does exist, want to use ctor stmt instead of init
194 objDecl->set_ctor( ctor );
195 destructorStmts.push_front( dtor );
196 }
197 return objDecl;
198 }
199
200 DeclarationWithType * CtorDtor::mutate( FunctionDecl *functionDecl ) {
201 // parameters should not be constructed and destructed, so don't mutate FunctionType
202 mutateAll( functionDecl->get_oldDecls(), *this );
203 functionDecl->set_statements( maybeMutate( functionDecl->get_statements(), *this ) );
204 return functionDecl;
205 }
206
207 CompoundStmt * CtorDtor::mutate( CompoundStmt * compoundStmt ) {
208 CompoundStmt * ret = PolyMutator::mutate( compoundStmt );
209 std::list< Statement * > &statements = ret->get_kids();
210 if ( ! destructorStmts.empty() ) {
211 statements.splice( statements.end(), destructorStmts );
212 } // if
213 return ret;
214 }
215
216 // should not traverse into any of these declarations to find objects
217 // that need to be constructed or destructed
218 Declaration* CtorDtor::mutate( StructDecl *aggregateDecl ) { return aggregateDecl; }
219 Declaration* CtorDtor::mutate( UnionDecl *aggregateDecl ) { return aggregateDecl; }
220 Declaration* CtorDtor::mutate( EnumDecl *aggregateDecl ) { return aggregateDecl; }
221 Declaration* CtorDtor::mutate( ContextDecl *aggregateDecl ) { return aggregateDecl; }
222 TypeDecl* CtorDtor::mutate( TypeDecl *typeDecl ) { return typeDecl; }
223 Declaration* CtorDtor::mutate( TypedefDecl *typeDecl ) { return typeDecl; }
224
225} // namespace InitTweak
226
227// Local Variables: //
228// tab-width: 4 //
229// mode: c++ //
230// compile-command: "make install" //
231// End: //
Note: See TracBrowser for help on using the repository browser.