Changes in src/InitTweak/RemoveInit.cc [5b2f5bb:cf16f94]
- File:
-
- 1 edited
-
src/InitTweak/RemoveInit.cc (modified) (8 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/InitTweak/RemoveInit.cc
r5b2f5bb rcf16f94 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // RemoveInit.cc -- 7 // RemoveInit.cc -- 8 8 // 9 9 // Author : Rob Schluntz 10 10 // Created On : Mon May 18 07:44:20 2015 11 // Last Modified By : Rob Schluntz12 // Last Modified On : Wed Mar 30 15:45:12 201613 // Update Count : 1 6611 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Tue Dec 15 15:37:26 2015 13 // Update Count : 15 14 14 // 15 15 16 #include <stack>17 #include <list>18 16 #include "RemoveInit.h" 19 17 #include "SynTree/Declaration.h" … … 23 21 #include "SynTree/Initializer.h" 24 22 #include "SynTree/Mutator.h" 25 #include "SymTab/Autogen.h"26 #include "GenPoly/PolyMutator.h"27 23 28 24 namespace InitTweak { 29 25 namespace { 30 26 const std::list<Label> noLabels; 31 const std::list<Expression *> noDesignators;32 27 } 33 34 class RemoveInit : public GenPoly::PolyMutator {28 29 class RemoveInit : public Mutator { 35 30 public: 36 /// removes and replaces initialization for polymorphic value objects37 /// with assignment (TODO: constructor) statements.38 /// also consistently allocates a temporary variable for the return value39 /// of a function so that anything which the resolver decides can be assigned40 /// into the return type of a function can be returned.41 static void removeInitializers( std::list< Declaration * > &translationUnit );42 43 31 RemoveInit(); 44 virtual ObjectDecl * mutate( ObjectDecl *objDecl);32 virtual ObjectDecl * mutate(ObjectDecl *objDecl); 45 33 virtual DeclarationWithType * mutate( FunctionDecl *functionDecl ); 46 34 47 35 virtual Statement * mutate( ReturnStmt * returnStmt ); 36 37 virtual CompoundStmt * mutate(CompoundStmt * compoundStmt); 38 39 protected: 40 std::list< Statement* > stmtsToAddBefore; 41 std::list< Statement* > stmtsToAddAfter; 42 void mutateStatementList( std::list< Statement* > &statements ); 48 43 49 protected:50 44 std::list<DeclarationWithType*> returnVals; 51 45 UniqueName tempNamer; … … 53 47 }; 54 48 55 class CtorDtor : public GenPoly::PolyMutator { 56 public: 57 /// create constructor and destructor statements for object declarations. 58 /// Destructors are inserted directly into the code, whereas constructors 59 /// will be added in after the resolver has run so that the initializer expression 60 /// is only removed if a constructor is found 61 static void generateCtorDtor( std::list< Declaration * > &translationUnit ); 62 63 CtorDtor() : inFunction( false ) {} 64 65 virtual ObjectDecl * mutate( ObjectDecl * ); 66 virtual DeclarationWithType * mutate( FunctionDecl *functionDecl ); 67 virtual Declaration* mutate( StructDecl *aggregateDecl ); 68 virtual Declaration* mutate( UnionDecl *aggregateDecl ); 69 virtual Declaration* mutate( EnumDecl *aggregateDecl ); 70 virtual Declaration* mutate( ContextDecl *aggregateDecl ); 71 virtual TypeDecl* mutate( TypeDecl *typeDecl ); 72 virtual Declaration* mutate( TypedefDecl *typeDecl ); 73 74 protected: 75 bool inFunction; 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 ) { 49 void tweak( std::list< Declaration * > translationUnit ) { 84 50 RemoveInit remover; 85 51 mutateAll( translationUnit, remover ); … … 87 53 88 54 RemoveInit::RemoveInit() : tempNamer( "_retVal" ) {} 55 56 void RemoveInit::mutateStatementList( std::list< Statement* > &statements ) { 57 for ( std::list< Statement* >::iterator i = statements.begin(); i != statements.end(); ++i ) { 58 if ( ! stmtsToAddAfter.empty() ) { 59 statements.splice( i, stmtsToAddAfter ); 60 } // if 61 *i = (*i)->acceptMutator( *this ); 62 if ( ! stmtsToAddBefore.empty() ) { 63 statements.splice( i, stmtsToAddBefore ); 64 } // if 65 } // for 66 if ( ! stmtsToAddAfter.empty() ) { 67 statements.splice( statements.end(), stmtsToAddAfter ); 68 } // if 69 } 70 71 CompoundStmt *RemoveInit::mutate(CompoundStmt *compoundStmt) { 72 mutateStatementList( compoundStmt->get_kids() ); 73 return compoundStmt; 74 } 89 75 90 76 // in the case where an object has an initializer and a polymorphic type, insert an assignment immediately after the … … 93 79 if (objDecl->get_init() && dynamic_cast<TypeInstType*>(objDecl->get_type())) { 94 80 if (SingleInit * single = dynamic_cast<SingleInit*>(objDecl->get_init())) { 95 // xxx this can be more complicated - consider ListInit 96 UntypedExpr *assign = new UntypedExpr( new NameExpr( "?{}" ) ); 81 UntypedExpr *assign = new UntypedExpr( new NameExpr( "?=?" ) ); 97 82 assign->get_args().push_back( new AddressExpr (new NameExpr( objDecl->get_name() ) ) ); 98 83 assign->get_args().push_back( single->get_value()->clone() ); … … 109 94 // is being returned 110 95 if ( returnStmt->get_expr() && returnVals.size() == 1 && funcName != "?=?" && ! returnVals.front()->get_type()->get_isLvalue() ) { 111 // ensure return value is not destructed by explicitly creating 112 // an empty SingleInit node wherein maybeConstruct is false 113 ObjectDecl *newObj = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, returnVals.front()->get_type()->clone(), new ListInit( std::list<Initializer*>(), noDesignators, false ) ); 114 stmtsToAdd.push_back( new DeclStmt( noLabels, newObj ) ); 115 116 // and explicitly create the constructor expression separately 117 UntypedExpr *construct = new UntypedExpr( new NameExpr( "?{}" ) ); 118 construct->get_args().push_back( new AddressExpr (new NameExpr( newObj->get_name() ) ) ); 119 construct->get_args().push_back( returnStmt->get_expr() ); 120 stmtsToAdd.push_back(new ExprStmt(noLabels, construct)); 96 ObjectDecl *newObj = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, returnVals.front()->get_type()->clone(), 0 ); 97 stmtsToAddBefore.push_back( new DeclStmt( noLabels, newObj ) ); 98 99 UntypedExpr *assign = new UntypedExpr( new NameExpr( "?=?" ) ); 100 assign->get_args().push_back( new AddressExpr (new NameExpr( newObj->get_name() ) ) ); 101 assign->get_args().push_back( returnStmt->get_expr() ); 102 stmtsToAddBefore.push_back(new ExprStmt(noLabels, assign)); 121 103 122 104 returnStmt->set_expr( new VariableExpr( newObj ) ); … … 128 110 std::list<DeclarationWithType*> oldReturnVals = returnVals; 129 111 std::string oldFuncName = funcName; 130 112 131 113 FunctionType * type = functionDecl->get_functionType(); 132 114 returnVals = type->get_returnVals(); … … 137 119 return decl; 138 120 } 139 140 141 void CtorDtor::generateCtorDtor( std::list< Declaration * > & translationUnit ) {142 CtorDtor ctordtor;143 mutateAll( translationUnit, ctordtor );144 }145 146 namespace {147 bool tryConstruct( ObjectDecl * objDecl ) {148 // xxx - handle designations149 return ! LinkageSpec::isBuiltin( objDecl->get_linkage() ) &&150 (objDecl->get_init() == NULL ||151 ( objDecl->get_init() != NULL && objDecl->get_init()->get_maybeConstructed() ));152 }153 154 Expression * makeCtorDtorExpr( std::string name, ObjectDecl * objDecl, std::list< Expression * > args ) {155 UntypedExpr * expr = new UntypedExpr( new NameExpr( name ) );156 expr->get_args().push_back( new AddressExpr( new VariableExpr( objDecl ) ) );157 expr->get_args().splice( expr->get_args().end(), args );158 return expr;159 }160 161 class InitExpander : public Visitor {162 public:163 InitExpander() {}164 // ~InitExpander() {}165 virtual void visit( SingleInit * singleInit );166 virtual void visit( ListInit * listInit );167 std::list< Expression * > argList;168 };169 170 void InitExpander::visit( SingleInit * singleInit ) {171 argList.push_back( singleInit->get_value()->clone() );172 }173 174 void InitExpander::visit( ListInit * listInit ) {175 // xxx - for now, assume no nested list inits176 std::list<Initializer*>::iterator it = listInit->begin_initializers();177 for ( ; it != listInit->end_initializers(); ++it ) {178 (*it)->accept( *this );179 }180 }181 182 std::list< Expression * > makeInitList( Initializer * init ) {183 InitExpander expander;184 maybeAccept( init, expander );185 return expander.argList;186 }187 }188 189 ObjectDecl * CtorDtor::mutate( ObjectDecl * objDecl ) {190 // hands off if designated or if @=191 if ( tryConstruct( objDecl ) ) {192 if ( inFunction ) {193 if ( ArrayType * at = dynamic_cast< ArrayType * >( objDecl->get_type() ) ) {194 // call into makeArrayFunction from validate.cc to generate calls to ctor/dtor for each element of array195 // TODO: walk initializer and generate appropriate copy ctor if element has initializer196 std::list< Statement * > ctor;197 std::list< Statement * > dtor;198 199 SymTab::makeArrayFunction( NULL, new VariableExpr( objDecl ), at, "?{}", back_inserter( ctor ) );200 SymTab::makeArrayFunction( NULL, new VariableExpr( objDecl ), at, "^?{}", front_inserter( dtor ), false );201 202 // Currently makeArrayFunction produces a single Statement - a CompoundStmt203 // which wraps everything that needs to happen. As such, it's technically204 // possible to use a Statement ** in the above calls, but this is inherently205 // unsafe, so instead we take the slightly less efficient route, but will be206 // immediately informed if somehow the above assumption is broken. In this case,207 // we could always wrap the list of statements at this point with a CompoundStmt,208 // but it seems reasonable at the moment for this to be done by makeArrayFunction209 // itself210 assert( ctor.size() == 1 );211 assert( dtor.size() == 1 );212 213 objDecl->set_init( new ConstructorInit( ctor.front(), dtor.front(), objDecl->get_init() ) );214 } else {215 // it's sufficient to attempt to call the ctor/dtor for the given object and its initializer216 Expression * ctor = makeCtorDtorExpr( "?{}", objDecl, makeInitList( objDecl->get_init() ) );217 Expression * dtor = makeCtorDtorExpr( "^?{}", objDecl, std::list< Expression * >() );218 219 // need to remember init expression, in case no ctors exist220 // if ctor does exist, want to use ctor expression instead of init221 // push this decision to the resolver222 ExprStmt * ctorStmt = new ExprStmt( noLabels, ctor );223 ExprStmt * dtorStmt = new ExprStmt( noLabels, dtor );224 objDecl->set_init( new ConstructorInit( ctorStmt, dtorStmt, objDecl->get_init() ) );225 }226 } else {227 // xxx - find a way to construct/destruct globals228 // hack: implicit "static" initialization routine for each struct type? or something similar?229 // --ties into module system230 // this can be done by mangling main and replacing it with our own main which calls each231 // module initialization routine in some decided order (order given in link command?)232 // and finally calls mangled main233 }234 }235 return objDecl;236 }237 238 DeclarationWithType * CtorDtor::mutate( FunctionDecl *functionDecl ) {239 // parameters should not be constructed and destructed, so don't mutate FunctionType240 bool oldInFunc = inFunction;241 mutateAll( functionDecl->get_oldDecls(), *this );242 inFunction = true;243 functionDecl->set_statements( maybeMutate( functionDecl->get_statements(), *this ) );244 inFunction = oldInFunc;245 return functionDecl;246 }247 248 // should not traverse into any of these declarations to find objects249 // that need to be constructed or destructed250 Declaration* CtorDtor::mutate( StructDecl *aggregateDecl ) { return aggregateDecl; }251 Declaration* CtorDtor::mutate( UnionDecl *aggregateDecl ) { return aggregateDecl; }252 Declaration* CtorDtor::mutate( EnumDecl *aggregateDecl ) { return aggregateDecl; }253 Declaration* CtorDtor::mutate( ContextDecl *aggregateDecl ) { return aggregateDecl; }254 TypeDecl* CtorDtor::mutate( TypeDecl *typeDecl ) { return typeDecl; }255 Declaration* CtorDtor::mutate( TypedefDecl *typeDecl ) { return typeDecl; }256 257 121 } // namespace InitTweak 258 122
Note:
See TracChangeset
for help on using the changeset viewer.