Changes in src/InitTweak/GenInit.cc [f0121d7:62e5546]
- File:
-
- 1 edited
-
src/InitTweak/GenInit.cc (modified) (14 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/InitTweak/GenInit.cc
rf0121d7 r62e5546 29 29 #include "GenPoly/DeclMutator.h" 30 30 #include "GenPoly/ScopedSet.h" 31 #include "ResolvExpr/typeops.h"32 31 33 32 namespace InitTweak { … … 37 36 } 38 37 39 class ReturnFixer : public GenPoly::PolyMutator {38 class ReturnFixer final : public GenPoly::PolyMutator { 40 39 public: 41 40 /// consistently allocates a temporary variable for the return value … … 46 45 ReturnFixer(); 47 46 48 virtual DeclarationWithType * mutate( FunctionDecl *functionDecl );49 50 virtual Statement * mutate( ReturnStmt * returnStmt ) ;47 using GenPoly::PolyMutator::mutate; 48 virtual DeclarationWithType * mutate( FunctionDecl *functionDecl ) override; 49 virtual Statement * mutate( ReturnStmt * returnStmt ) override; 51 50 52 51 protected: 53 FunctionType * ftype;52 std::list<DeclarationWithType*> returnVals; 54 53 UniqueName tempNamer; 55 54 std::string funcName; 56 55 }; 57 56 58 class CtorDtor : public GenPoly::PolyMutator {57 class CtorDtor final : public GenPoly::PolyMutator { 59 58 public: 60 59 typedef GenPoly::PolyMutator Parent; … … 66 65 static void generateCtorDtor( std::list< Declaration * > &translationUnit ); 67 66 68 virtual DeclarationWithType * mutate( ObjectDecl * ) ;69 virtual DeclarationWithType * mutate( FunctionDecl *functionDecl ) ;67 virtual DeclarationWithType * mutate( ObjectDecl * ) override; 68 virtual DeclarationWithType * mutate( FunctionDecl *functionDecl ) override; 70 69 // should not traverse into any of these declarations to find objects 71 70 // that need to be constructed or destructed 72 virtual Declaration* mutate( StructDecl *aggregateDecl ) ;73 virtual Declaration* mutate( UnionDecl *aggregateDecl ) { return aggregateDecl; }74 virtual Declaration* mutate( EnumDecl *aggregateDecl ) { return aggregateDecl; }75 virtual Declaration* mutate( TraitDecl *aggregateDecl ) { return aggregateDecl; }76 virtual TypeDecl* mutate( TypeDecl *typeDecl ) { return typeDecl; }77 virtual Declaration* mutate( TypedefDecl *typeDecl ) { return typeDecl; }78 79 virtual Type * mutate( FunctionType *funcType ) { return funcType; }80 81 virtual CompoundStmt * mutate( CompoundStmt * compoundStmt ) ;71 virtual Declaration* mutate( StructDecl *aggregateDecl ) override; 72 virtual Declaration* mutate( UnionDecl *aggregateDecl ) override { return aggregateDecl; } 73 virtual Declaration* mutate( EnumDecl *aggregateDecl ) override { return aggregateDecl; } 74 virtual Declaration* mutate( TraitDecl *aggregateDecl ) override { return aggregateDecl; } 75 virtual TypeDecl* mutate( TypeDecl *typeDecl ) override { return typeDecl; } 76 virtual Declaration* mutate( TypedefDecl *typeDecl ) override { return typeDecl; } 77 78 virtual Type * mutate( FunctionType *funcType ) override { return funcType; } 79 80 virtual CompoundStmt * mutate( CompoundStmt * compoundStmt ) override; 82 81 83 82 private: … … 87 86 88 87 bool isManaged( ObjectDecl * objDecl ) const ; // determine if object is managed 89 bool isManaged( Type * type ) const; // determine if type is managed90 88 void handleDWT( DeclarationWithType * dwt ); // add type to managed if ctor/dtor 91 89 GenPoly::ScopedSet< std::string > managedTypes; … … 93 91 }; 94 92 95 class HoistArrayDimension : public GenPoly::DeclMutator {93 class HoistArrayDimension final : public GenPoly::DeclMutator { 96 94 public: 97 95 typedef GenPoly::DeclMutator Parent; … … 103 101 104 102 private: 105 virtual DeclarationWithType * mutate( ObjectDecl * objectDecl ); 106 virtual DeclarationWithType * mutate( FunctionDecl *functionDecl ); 103 using Parent::mutate; 104 105 virtual DeclarationWithType * mutate( ObjectDecl * objectDecl ) override; 106 virtual DeclarationWithType * mutate( FunctionDecl *functionDecl ) override; 107 107 // should not traverse into any of these declarations to find objects 108 108 // that need to be constructed or destructed 109 virtual Declaration* mutate( StructDecl *aggregateDecl ) { return aggregateDecl; }110 virtual Declaration* mutate( UnionDecl *aggregateDecl ) { return aggregateDecl; }111 virtual Declaration* mutate( EnumDecl *aggregateDecl ) { return aggregateDecl; }112 virtual Declaration* mutate( TraitDecl *aggregateDecl ) { return aggregateDecl; }113 virtual TypeDecl* mutate( TypeDecl *typeDecl ) { return typeDecl; }114 virtual Declaration* mutate( TypedefDecl *typeDecl ) { return typeDecl; }115 116 virtual Type* mutate( FunctionType *funcType ) { return funcType; }109 virtual Declaration* mutate( StructDecl *aggregateDecl ) override { return aggregateDecl; } 110 virtual Declaration* mutate( UnionDecl *aggregateDecl ) override { return aggregateDecl; } 111 virtual Declaration* mutate( EnumDecl *aggregateDecl ) override { return aggregateDecl; } 112 virtual Declaration* mutate( TraitDecl *aggregateDecl ) override { return aggregateDecl; } 113 virtual TypeDecl* mutate( TypeDecl *typeDecl ) override { return typeDecl; } 114 virtual Declaration* mutate( TypedefDecl *typeDecl ) override { return typeDecl; } 115 116 virtual Type* mutate( FunctionType *funcType ) override { return funcType; } 117 117 118 118 void hoist( Type * type ); … … 136 136 137 137 Statement *ReturnFixer::mutate( ReturnStmt *returnStmt ) { 138 std::list< DeclarationWithType * > & returnVals = ftype->get_returnVals();138 // update for multiple return values 139 139 assert( returnVals.size() == 0 || returnVals.size() == 1 ); 140 140 // hands off if the function returns an lvalue - we don't want to allocate a temporary if a variable's address … … 158 158 159 159 DeclarationWithType* ReturnFixer::mutate( FunctionDecl *functionDecl ) { 160 // xxx - need to handle named return values - this pass may need to happen 161 // after resolution? the ordering is tricky because return statements must be 162 // constructed - the simplest way to do that (while also handling multiple 163 // returns) is to structure the returnVals into a tuple, as done here. 164 // however, if the tuple return value is structured before resolution, 165 // it's difficult to resolve named return values, since the name is lost 166 // in conversion to a tuple. this might be easiest to deal with 167 // after reference types are added, as it may then be possible to 168 // uniformly move named return values to the parameter list directly 169 ValueGuard< FunctionType * > oldFtype( ftype ); 160 ValueGuard< std::list<DeclarationWithType*> > oldReturnVals( returnVals ); 170 161 ValueGuard< std::string > oldFuncName( funcName ); 171 162 172 ftype = functionDecl->get_functionType(); 173 std::list< DeclarationWithType * > & retVals = ftype->get_returnVals(); 174 if ( retVals.size() > 1 ) { 175 TupleType * tupleType = safe_dynamic_cast< TupleType * >( ResolvExpr::extractResultType( ftype ) ); 176 ObjectDecl * newRet = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, tupleType, new ListInit( std::list<Initializer*>(), noDesignators, false ) ); 177 retVals.clear(); 178 retVals.push_back( newRet ); 179 } 163 FunctionType * type = functionDecl->get_functionType(); 164 returnVals = type->get_returnVals(); 180 165 funcName = functionDecl->get_name(); 181 166 DeclarationWithType * decl = Mutator::mutate( functionDecl ); … … 237 222 } 238 223 239 bool CtorDtor::isManaged( Type * type ) const {240 if ( TupleType * tupleType = dynamic_cast< TupleType * > ( type ) ) {241 // tuple is also managed if any of its components are managed242 if ( std::any_of( tupleType->get_types().begin(), tupleType->get_types().end(), [&](Type * type) { return isManaged( type ); }) ) {243 return true;244 }245 }246 return managedTypes.find( SymTab::Mangler::mangle( type ) ) != managedTypes.end();247 }248 249 224 bool CtorDtor::isManaged( ObjectDecl * objDecl ) const { 250 225 Type * type = objDecl->get_type(); … … 252 227 type = at->get_base(); 253 228 } 254 return isManaged( type);229 return managedTypes.find( SymTab::Mangler::mangle( type ) ) != managedTypes.end(); 255 230 } 256 231 … … 263 238 managedTypes.insert( SymTab::Mangler::mangle( type->get_base() ) ); 264 239 } 265 }266 267 ConstructorInit * genCtorInit( ObjectDecl * objDecl ) {268 // call into genImplicitCall from Autogen.h to generate calls to ctor/dtor269 // for each constructable object270 std::list< Statement * > ctor;271 std::list< Statement * > dtor;272 273 InitExpander srcParam( objDecl->get_init() );274 InitExpander nullParam( (Initializer *)NULL );275 SymTab::genImplicitCall( srcParam, new VariableExpr( objDecl ), "?{}", back_inserter( ctor ), objDecl );276 SymTab::genImplicitCall( nullParam, new VariableExpr( objDecl ), "^?{}", front_inserter( dtor ), objDecl, false );277 278 // Currently genImplicitCall produces a single Statement - a CompoundStmt279 // which wraps everything that needs to happen. As such, it's technically280 // possible to use a Statement ** in the above calls, but this is inherently281 // unsafe, so instead we take the slightly less efficient route, but will be282 // immediately informed if somehow the above assumption is broken. In this case,283 // we could always wrap the list of statements at this point with a CompoundStmt,284 // but it seems reasonable at the moment for this to be done by genImplicitCall285 // itself. It is possible that genImplicitCall produces no statements (e.g. if286 // an array type does not have a dimension). In this case, it's fine to ignore287 // the object for the purposes of construction.288 assert( ctor.size() == dtor.size() && ctor.size() <= 1 );289 if ( ctor.size() == 1 ) {290 // need to remember init expression, in case no ctors exist291 // if ctor does exist, want to use ctor expression instead of init292 // push this decision to the resolver293 assert( dynamic_cast< ImplicitCtorDtorStmt * > ( ctor.front() ) && dynamic_cast< ImplicitCtorDtorStmt * > ( dtor.front() ) );294 return new ConstructorInit( ctor.front(), dtor.front(), objDecl->get_init() );295 }296 return nullptr;297 240 } 298 241 … … 307 250 if ( ! checkInitDepth( objDecl ) ) throw SemanticError( "Managed object's initializer is too deep ", objDecl ); 308 251 309 objDecl->set_init( genCtorInit( objDecl ) ); 252 // call into genImplicitCall from Autogen.h to generate calls to ctor/dtor 253 // for each constructable object 254 std::list< Statement * > ctor; 255 std::list< Statement * > dtor; 256 257 InitExpander srcParam( objDecl->get_init() ); 258 InitExpander nullParam( (Initializer *)NULL ); 259 SymTab::genImplicitCall( srcParam, new VariableExpr( objDecl ), "?{}", back_inserter( ctor ), objDecl ); 260 SymTab::genImplicitCall( nullParam, new VariableExpr( objDecl ), "^?{}", front_inserter( dtor ), objDecl, false ); 261 262 // Currently genImplicitCall produces a single Statement - a CompoundStmt 263 // which wraps everything that needs to happen. As such, it's technically 264 // possible to use a Statement ** in the above calls, but this is inherently 265 // unsafe, so instead we take the slightly less efficient route, but will be 266 // immediately informed if somehow the above assumption is broken. In this case, 267 // we could always wrap the list of statements at this point with a CompoundStmt, 268 // but it seems reasonable at the moment for this to be done by genImplicitCall 269 // itself. It is possible that genImplicitCall produces no statements (e.g. if 270 // an array type does not have a dimension). In this case, it's fine to ignore 271 // the object for the purposes of construction. 272 assert( ctor.size() == dtor.size() && ctor.size() <= 1 ); 273 if ( ctor.size() == 1 ) { 274 // need to remember init expression, in case no ctors exist 275 // if ctor does exist, want to use ctor expression instead of init 276 // push this decision to the resolver 277 assert( dynamic_cast< ImplicitCtorDtorStmt * > ( ctor.front() ) && dynamic_cast< ImplicitCtorDtorStmt * > ( dtor.front() ) ); 278 objDecl->set_init( new ConstructorInit( ctor.front(), dtor.front(), objDecl->get_init() ) ); 279 } 310 280 } 311 281 return Parent::mutate( objDecl ); … … 320 290 managedTypes.beginScope(); 321 291 // go through assertions and recursively add seen ctor/dtors 322 for ( auto &tyDecl : functionDecl->get_functionType()->get_forall() ) {292 for ( TypeDecl * tyDecl : functionDecl->get_functionType()->get_forall() ) { 323 293 for ( DeclarationWithType *& assertion : tyDecl->get_assertions() ) { 324 294 assertion = assertion->acceptMutator( *this );
Note:
See TracChangeset
for help on using the changeset viewer.