source: src/InitTweak/RemoveInit.cc@ ca1c11f

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 ca1c11f was f1e012b, checked in by Rob Schluntz <rschlunt@…>, 10 years ago

added intrinsic ctor/dtors to prelude, modified MakeLibCfa to build prelude ctor/dtors, added ctor/dtor to polymorphic object type constraints, rudimentary fallback on initializer nodes if chosen ctor is intrinsic, remove intrinsic destructor statements to reduce output pollution

  • Property mode set to 100644
File size: 9.1 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 Jan 19 11:12:49 2016
13// Update Count : 165
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 Expression * ctor = makeCtorDtorExpr( "?{}", objDecl, makeInitList( objDecl->get_init() ) );
195 Expression * dtor = makeCtorDtorExpr( "^?{}", objDecl, std::list< Expression * >() );
196
197 // need to remember init expression, in case no ctors exist
198 // if ctor does exist, want to use ctor expression instead of init
199 // push this decision to the resolver
200 objDecl->set_init( new ConstructorInit( ctor, objDecl->get_init() ) );
201 destructorStmts.push_front( new ExprStmt( noLabels, dtor ) );
202 } else {
203 // xxx - find a way to construct/destruct globals
204 // hack: implicit "static" initialization routine for each struct type? or something similar?
205 // --ties into module system
206 }
207 }
208 return objDecl;
209 }
210
211 DeclarationWithType * CtorDtor::mutate( FunctionDecl *functionDecl ) {
212 // parameters should not be constructed and destructed, so don't mutate FunctionType
213 bool oldInFunc = inFunction;
214 mutateAll( functionDecl->get_oldDecls(), *this );
215 inFunction = true;
216 functionDecl->set_statements( maybeMutate( functionDecl->get_statements(), *this ) );
217 inFunction = oldInFunc;
218 return functionDecl;
219 }
220
221 CompoundStmt * CtorDtor::mutate( CompoundStmt * compoundStmt ) {
222 CompoundStmt * ret = PolyMutator::mutate( compoundStmt );
223 std::list< Statement * > &statements = ret->get_kids();
224 if ( ! destructorStmts.empty() ) {
225 statements.splice( statements.end(), destructorStmts );
226 } // if
227 return ret;
228 }
229
230 // should not traverse into any of these declarations to find objects
231 // that need to be constructed or destructed
232 Declaration* CtorDtor::mutate( StructDecl *aggregateDecl ) { return aggregateDecl; }
233 Declaration* CtorDtor::mutate( UnionDecl *aggregateDecl ) { return aggregateDecl; }
234 Declaration* CtorDtor::mutate( EnumDecl *aggregateDecl ) { return aggregateDecl; }
235 Declaration* CtorDtor::mutate( ContextDecl *aggregateDecl ) { return aggregateDecl; }
236 TypeDecl* CtorDtor::mutate( TypeDecl *typeDecl ) { return typeDecl; }
237 Declaration* CtorDtor::mutate( TypedefDecl *typeDecl ) { return typeDecl; }
238
239} // namespace InitTweak
240
241// Local Variables: //
242// tab-width: 4 //
243// mode: c++ //
244// compile-command: "make install" //
245// End: //
Note: See TracBrowser for help on using the repository browser.