Changes in src/InitTweak/GenInit.cc [4d2434a:cad355a]
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/InitTweak/GenInit.cc
r4d2434a rcad355a 26 26 #include "SymTab/Autogen.h" 27 27 #include "GenPoly/PolyMutator.h" 28 #include "GenPoly/DeclMutator.h"29 28 30 29 namespace InitTweak { … … 56 55 public: 57 56 /// create constructor and destructor statements for object declarations. 58 /// the actual call statements will be added in after the resolver has run59 /// so that the initializer expression is only removed if a constructor is found60 /// and the same destructor call is inserted in all of the appropriate locations.57 /// Destructors are inserted directly into the code, whereas constructors 58 /// will be added in after the resolver has run so that the initializer expression 59 /// is only removed if a constructor is found 61 60 static void generateCtorDtor( std::list< Declaration * > &translationUnit ); 61 62 CtorDtor() : inFunction( false ) {} 62 63 63 64 virtual DeclarationWithType * mutate( ObjectDecl * ); 64 65 virtual DeclarationWithType * mutate( FunctionDecl *functionDecl ); 65 // should not traverse into any of these declarations to find objects 66 // that need to be constructed or destructed 67 virtual Declaration* mutate( StructDecl *aggregateDecl ) { return aggregateDecl; } 68 virtual Declaration* mutate( UnionDecl *aggregateDecl ) { return aggregateDecl; } 69 virtual Declaration* mutate( EnumDecl *aggregateDecl ) { return aggregateDecl; } 70 virtual Declaration* mutate( TraitDecl *aggregateDecl ) { return aggregateDecl; } 71 virtual TypeDecl* mutate( TypeDecl *typeDecl ) { return typeDecl; } 72 virtual Declaration* mutate( TypedefDecl *typeDecl ) { return typeDecl; } 73 74 virtual Type * mutate( FunctionType *funcType ) { return funcType; } 66 virtual Declaration* mutate( StructDecl *aggregateDecl ); 67 virtual Declaration* mutate( UnionDecl *aggregateDecl ); 68 virtual Declaration* mutate( EnumDecl *aggregateDecl ); 69 virtual Declaration* mutate( TraitDecl *aggregateDecl ); 70 virtual TypeDecl* mutate( TypeDecl *typeDecl ); 71 virtual Declaration* mutate( TypedefDecl *typeDecl ); 72 73 virtual Type * mutate( FunctionType *funcType ); 75 74 76 75 protected: 77 }; 78 79 class HoistArrayDimension : public GenPoly::DeclMutator { 80 public: 81 typedef GenPoly::DeclMutator Parent; 82 83 /// hoist dimension from array types in object declaration so that it uses a single 84 /// const variable of type size_t, so that side effecting array dimensions are only 85 /// computed once. 86 static void hoistArrayDimension( std::list< Declaration * > & translationUnit ); 87 88 private: 89 virtual DeclarationWithType * mutate( ObjectDecl * objectDecl ); 90 virtual DeclarationWithType * mutate( FunctionDecl *functionDecl ); 91 // should not traverse into any of these declarations to find objects 92 // that need to be constructed or destructed 93 virtual Declaration* mutate( StructDecl *aggregateDecl ) { return aggregateDecl; } 94 virtual Declaration* mutate( UnionDecl *aggregateDecl ) { return aggregateDecl; } 95 virtual Declaration* mutate( EnumDecl *aggregateDecl ) { return aggregateDecl; } 96 virtual Declaration* mutate( TraitDecl *aggregateDecl ) { return aggregateDecl; } 97 virtual TypeDecl* mutate( TypeDecl *typeDecl ) { return typeDecl; } 98 virtual Declaration* mutate( TypedefDecl *typeDecl ) { return typeDecl; } 99 100 virtual Type* mutate( FunctionType *funcType ) { return funcType; } 101 102 void hoist( Type * type ); 103 104 DeclarationNode::StorageClass storageclass = DeclarationNode::NoStorageClass; 105 bool inFunction = false; 76 bool inFunction; 106 77 }; 107 78 108 79 void genInit( std::list< Declaration * > & translationUnit ) { 109 80 ReturnFixer::makeReturnTemp( translationUnit ); 110 HoistArrayDimension::hoistArrayDimension( translationUnit );111 81 CtorDtor::generateCtorDtor( translationUnit ); 112 82 } … … 154 124 } 155 125 156 // precompute array dimension expression, because constructor generation may duplicate it,157 // which would be incorrect if it is a side-effecting computation.158 void HoistArrayDimension::hoistArrayDimension( std::list< Declaration * > & translationUnit ) {159 HoistArrayDimension hoister;160 hoister.mutateDeclarationList( translationUnit );161 }162 163 DeclarationWithType * HoistArrayDimension::mutate( ObjectDecl * objectDecl ) {164 storageclass = objectDecl->get_storageClass();165 DeclarationWithType * temp = Parent::mutate( objectDecl );166 hoist( objectDecl->get_type() );167 storageclass = DeclarationNode::NoStorageClass;168 return temp;169 }170 171 void HoistArrayDimension::hoist( Type * type ) {172 // if in function, generate const size_t var173 static UniqueName dimensionName( "_array_dim" );174 if ( ArrayType * arrayType = dynamic_cast< ArrayType * >( type ) ) {175 if ( ! inFunction ) return;176 177 if ( ! arrayType->get_dimension() ) return; // xxx - recursive call to hoist?178 179 // don't need to hoist dimension if it's a constexpr - only need to if there's potential180 // for side effects.181 if ( isConstExpr( arrayType->get_dimension() ) ) return;182 183 ObjectDecl * arrayDimension = new ObjectDecl( dimensionName.newName(), storageclass, LinkageSpec::C, 0, SymTab::SizeType->clone(), new SingleInit( arrayType->get_dimension() ) );184 arrayDimension->get_type()->set_isConst( true );185 186 arrayType->set_dimension( new VariableExpr( arrayDimension ) );187 addDeclaration( arrayDimension );188 189 hoist( arrayType->get_base() );190 return;191 }192 }193 194 DeclarationWithType * HoistArrayDimension::mutate( FunctionDecl *functionDecl ) {195 bool oldInFunc = inFunction;196 inFunction = true;197 DeclarationWithType * decl = Parent::mutate( functionDecl );198 inFunction = oldInFunc;199 return decl;200 }201 126 202 127 void CtorDtor::generateCtorDtor( std::list< Declaration * > & translationUnit ) { … … 215 140 216 141 DeclarationWithType * CtorDtor::mutate( ObjectDecl * objDecl ) { 217 // hands off if designated , if @=, or if extern142 // hands off if designated or if @= 218 143 if ( tryConstruct( objDecl ) ) { 219 // call into genImplicitCall from Autogen.h to generate calls to ctor/dtor 220 // for each constructable object 221 std::list< Statement * > ctor; 222 std::list< Statement * > dtor; 223 224 InitExpander srcParam( objDecl->get_init() ); 225 InitExpander nullParam( (Initializer *)NULL ); 226 SymTab::genImplicitCall( srcParam, new VariableExpr( objDecl ), "?{}", back_inserter( ctor ), objDecl ); 227 SymTab::genImplicitCall( nullParam, new VariableExpr( objDecl ), "^?{}", front_inserter( dtor ), objDecl, false ); 228 229 // Currently genImplicitCall produces a single Statement - a CompoundStmt 230 // which wraps everything that needs to happen. As such, it's technically 231 // possible to use a Statement ** in the above calls, but this is inherently 232 // unsafe, so instead we take the slightly less efficient route, but will be 233 // immediately informed if somehow the above assumption is broken. In this case, 234 // we could always wrap the list of statements at this point with a CompoundStmt, 235 // but it seems reasonable at the moment for this to be done by genImplicitCall 236 // itself. It is possible that genImplicitCall produces no statements (e.g. if 237 // an array type does not have a dimension). In this case, it's fine to ignore 238 // the object for the purposes of construction. 239 assert( ctor.size() == dtor.size() && ctor.size() <= 1 ); 240 if ( ctor.size() == 1 ) { 241 // need to remember init expression, in case no ctors exist 242 // if ctor does exist, want to use ctor expression instead of init 243 // push this decision to the resolver 244 assert( dynamic_cast< ImplicitCtorDtorStmt * > ( ctor.front() ) && dynamic_cast< ImplicitCtorDtorStmt * > ( dtor.front() ) ); 245 objDecl->set_init( new ConstructorInit( ctor.front(), dtor.front(), objDecl->get_init() ) ); 144 if ( inFunction ) { 145 if ( ArrayType * at = dynamic_cast< ArrayType * >( objDecl->get_type() ) ) { 146 // call into makeArrayFunction from validate.cc to generate calls to ctor/dtor for each element of array 147 // TODO: walk initializer and generate appropriate copy ctor if element has initializer 148 std::list< Expression * > args = makeInitList( objDecl->get_init() ); 149 if ( args.empty() ) { 150 std::list< Statement * > ctor; 151 std::list< Statement * > dtor; 152 153 SymTab::makeArrayFunction( NULL, new VariableExpr( objDecl ), at, "?{}", back_inserter( ctor ) ); 154 SymTab::makeArrayFunction( NULL, new VariableExpr( objDecl ), at, "^?{}", front_inserter( dtor ), false ); 155 156 // Currently makeArrayFunction produces a single Statement - a CompoundStmt 157 // which wraps everything that needs to happen. As such, it's technically 158 // possible to use a Statement ** in the above calls, but this is inherently 159 // unsafe, so instead we take the slightly less efficient route, but will be 160 // immediately informed if somehow the above assumption is broken. In this case, 161 // we could always wrap the list of statements at this point with a CompoundStmt, 162 // but it seems reasonable at the moment for this to be done by makeArrayFunction 163 // itself 164 assert( ctor.size() == 1 && dynamic_cast< ImplicitCtorDtorStmt * >( ctor.front() ) ); 165 assert( dtor.size() == 1 && dynamic_cast< ImplicitCtorDtorStmt * >( dtor.front() ) ); 166 objDecl->set_init( new ConstructorInit( ctor.front(), dtor.front(), objDecl->get_init() ) ); 167 } else { 168 // array came with an initializer list: initialize each element 169 // may have more initializers than elements in the array - need to check at each index that 170 // we haven't exceeded size. This requires precomputing the size because it might be a side-effecting 171 // computation. 172 // may have fewer initializers than eleemnts in the array - need to default construct 173 // remaining elements. 174 // might be able to merge this with the case above. 175 } 176 } else { 177 // it's sufficient to attempt to call the ctor/dtor for the given object and its initializer 178 Expression * ctor = makeCtorDtorExpr( "?{}", objDecl, makeInitList( objDecl->get_init() ) ); 179 Expression * dtor = makeCtorDtorExpr( "^?{}", objDecl, std::list< Expression * >() ); 180 181 // need to remember init expression, in case no ctors exist 182 // if ctor does exist, want to use ctor expression instead of init 183 // push this decision to the resolver 184 ExprStmt * ctorStmt = new ExprStmt( noLabels, ctor ); 185 ExprStmt * dtorStmt = new ExprStmt( noLabels, dtor ); 186 objDecl->set_init( new ConstructorInit( new ImplicitCtorDtorStmt( ctorStmt ), new ImplicitCtorDtorStmt( dtorStmt ), objDecl->get_init() ) ); 187 } 246 188 } 247 189 } … … 251 193 DeclarationWithType * CtorDtor::mutate( FunctionDecl *functionDecl ) { 252 194 // parameters should not be constructed and destructed, so don't mutate FunctionType 195 bool oldInFunc = inFunction; 253 196 mutateAll( functionDecl->get_oldDecls(), *this ); 197 inFunction = true; 254 198 functionDecl->set_statements( maybeMutate( functionDecl->get_statements(), *this ) ); 199 inFunction = oldInFunc; 255 200 return functionDecl; 256 201 } 202 203 // should not traverse into any of these declarations to find objects 204 // that need to be constructed or destructed 205 Declaration* CtorDtor::mutate( StructDecl *aggregateDecl ) { return aggregateDecl; } 206 Declaration* CtorDtor::mutate( UnionDecl *aggregateDecl ) { return aggregateDecl; } 207 Declaration* CtorDtor::mutate( EnumDecl *aggregateDecl ) { return aggregateDecl; } 208 Declaration* CtorDtor::mutate( TraitDecl *aggregateDecl ) { return aggregateDecl; } 209 TypeDecl* CtorDtor::mutate( TypeDecl *typeDecl ) { return typeDecl; } 210 Declaration* CtorDtor::mutate( TypedefDecl *typeDecl ) { return typeDecl; } 211 Type* CtorDtor::mutate( FunctionType *funcType ) { return funcType; } 212 257 213 } // namespace InitTweak 258 214
Note:
See TracChangeset
for help on using the changeset viewer.