Changes in src/InitTweak/GenInit.cc [6cf27a07:cad355a]
- File:
-
- 1 edited
-
src/InitTweak/GenInit.cc (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/InitTweak/GenInit.cc
r6cf27a07 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 void HoistArrayDimension::hoistArrayDimension( std::list< Declaration * > & translationUnit ) {157 HoistArrayDimension hoister;158 hoister.mutateDeclarationList( translationUnit );159 }160 161 DeclarationWithType * HoistArrayDimension::mutate( ObjectDecl * objectDecl ) {162 storageclass = objectDecl->get_storageClass();163 DeclarationWithType * temp = Parent::mutate( objectDecl );164 hoist( objectDecl->get_type() );165 storageclass = DeclarationNode::NoStorageClass;166 return temp;167 }168 169 void HoistArrayDimension::hoist( Type * type ) {170 // if in function, generate const size_t var171 static UniqueName dimensionName( "_array_dim" );172 if ( ArrayType * arrayType = dynamic_cast< ArrayType * >( type ) ) {173 if ( ! inFunction ) return;174 175 if ( ! arrayType->get_dimension() ) return; // xxx - recursive call to hoist?176 177 // don't need to hoist dimension if it's a constexpr - only need to if there's potential178 // for side effects.179 if ( isConstExpr( arrayType->get_dimension() ) ) return;180 181 ObjectDecl * arrayDimension = new ObjectDecl( dimensionName.newName(), storageclass, LinkageSpec::C, 0, SymTab::SizeType->clone(), new SingleInit( arrayType->get_dimension() ) );182 arrayDimension->get_type()->set_isConst( true );183 184 arrayType->set_dimension( new VariableExpr( arrayDimension ) );185 addDeclaration( arrayDimension );186 187 hoist( arrayType->get_base() );188 return;189 }190 }191 192 DeclarationWithType * HoistArrayDimension::mutate( FunctionDecl *functionDecl ) {193 bool oldInFunc = inFunction;194 inFunction = true;195 DeclarationWithType * decl = Parent::mutate( functionDecl );196 inFunction = oldInFunc;197 return decl;198 }199 126 200 127 void CtorDtor::generateCtorDtor( std::list< Declaration * > & translationUnit ) { … … 213 140 214 141 DeclarationWithType * CtorDtor::mutate( ObjectDecl * objDecl ) { 215 // hands off if designated , if @=, or if extern142 // hands off if designated or if @= 216 143 if ( tryConstruct( objDecl ) ) { 217 if ( ArrayType * at = dynamic_cast< ArrayType * >( objDecl->get_type() ) ) { 218 // call into makeArrayFunction from validate.cc to generate calls to ctor/dtor for each element of array 219 // TODO: walk initializers and generate appropriate ctor if element has initializer. 220 // Initializer could be nested (depends on the depth of the array type on the object) 221 222 std::list< Expression * > args = makeInitList( objDecl->get_init() ); 223 if ( args.empty() ) { 224 std::list< Statement * > ctor; 225 std::list< Statement * > dtor; 226 227 SymTab::genImplicitCall( NULL, new VariableExpr( objDecl ), "?{}", back_inserter( ctor ), objDecl ); 228 SymTab::genImplicitCall( NULL, new VariableExpr( objDecl ), "^?{}", front_inserter( dtor ), objDecl, false ); 229 230 // Currently genImplicitCall produces a single Statement - a CompoundStmt 231 // which wraps everything that needs to happen. As such, it's technically 232 // possible to use a Statement ** in the above calls, but this is inherently 233 // unsafe, so instead we take the slightly less efficient route, but will be 234 // immediately informed if somehow the above assumption is broken. In this case, 235 // we could always wrap the list of statements at this point with a CompoundStmt, 236 // but it seems reasonable at the moment for this to be done by genImplicitCall 237 // itself. It is possible that genImplicitCall produces no statements (e.g. if 238 // an array type does not have a dimension). In this case, it's fine to ignore 239 // the object for the purposes of construction. 240 assert( ctor.size() == dtor.size() && ctor.size() <= 1 ); 241 if ( ctor.size() == 1 ) { 242 assert( dynamic_cast< ImplicitCtorDtorStmt * > ( ctor.front() ) && dynamic_cast< ImplicitCtorDtorStmt * > ( dtor.front() ) ); 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() ) ); 243 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. 244 175 } 245 176 } else { 246 // array came with an initializer list: initialize each element 247 // may have more initializers than elements in the array - need to check at each index that 248 // we haven't exceeded size. This requires precomputing the size because it might be a side-effecting 249 // computation. 250 // may have fewer initializers than elements in the array - need to default construct 251 // remaining elements. 252 // might be able to merge this with the case above. 253 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() ) ); 254 187 } 255 } else {256 // it's sufficient to attempt to call the ctor/dtor for the given object and its initializer257 Expression * ctor = makeCtorDtorExpr( "?{}", objDecl, makeInitList( objDecl->get_init() ) );258 Expression * dtor = makeCtorDtorExpr( "^?{}", objDecl, std::list< Expression * >() );259 260 // need to remember init expression, in case no ctors exist261 // if ctor does exist, want to use ctor expression instead of init262 // push this decision to the resolver263 ExprStmt * ctorStmt = new ExprStmt( noLabels, ctor );264 ExprStmt * dtorStmt = new ExprStmt( noLabels, dtor );265 objDecl->set_init( new ConstructorInit( new ImplicitCtorDtorStmt( ctorStmt ), new ImplicitCtorDtorStmt( dtorStmt ), objDecl->get_init() ) );266 188 } 267 189 } … … 271 193 DeclarationWithType * CtorDtor::mutate( FunctionDecl *functionDecl ) { 272 194 // parameters should not be constructed and destructed, so don't mutate FunctionType 195 bool oldInFunc = inFunction; 273 196 mutateAll( functionDecl->get_oldDecls(), *this ); 197 inFunction = true; 274 198 functionDecl->set_statements( maybeMutate( functionDecl->get_statements(), *this ) ); 199 inFunction = oldInFunc; 275 200 return functionDecl; 276 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 277 213 } // namespace InitTweak 278 214
Note:
See TracChangeset
for help on using the changeset viewer.