Changes in src/InitTweak/GenInit.cc [f9cebb5:cad355a]
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/InitTweak/GenInit.cc
rf9cebb5 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 175 // C doesn't allow variable sized arrays at global scope or for static variables,176 // so don't hoist dimension.177 if ( ! inFunction ) return;178 if ( storageclass == DeclarationNode::Static ) return;179 180 if ( ArrayType * arrayType = dynamic_cast< ArrayType * >( type ) ) {181 if ( ! arrayType->get_dimension() ) return; // xxx - recursive call to hoist?182 183 // don't need to hoist dimension if it's a constexpr - only need to if there's potential184 // for side effects.185 if ( isConstExpr( arrayType->get_dimension() ) ) return;186 187 ObjectDecl * arrayDimension = new ObjectDecl( dimensionName.newName(), storageclass, LinkageSpec::C, 0, SymTab::SizeType->clone(), new SingleInit( arrayType->get_dimension() ) );188 arrayDimension->get_type()->set_isConst( true );189 190 arrayType->set_dimension( new VariableExpr( arrayDimension ) );191 addDeclaration( arrayDimension );192 193 hoist( arrayType->get_base() );194 return;195 }196 }197 198 DeclarationWithType * HoistArrayDimension::mutate( FunctionDecl *functionDecl ) {199 bool oldInFunc = inFunction;200 inFunction = true;201 DeclarationWithType * decl = Parent::mutate( functionDecl );202 inFunction = oldInFunc;203 return decl;204 }205 126 206 127 void CtorDtor::generateCtorDtor( std::list< Declaration * > & translationUnit ) { … … 209 130 } 210 131 132 namespace { 133 Expression * makeCtorDtorExpr( std::string name, ObjectDecl * objDecl, std::list< Expression * > args ) { 134 UntypedExpr * expr = new UntypedExpr( new NameExpr( name ) ); 135 expr->get_args().push_back( new AddressExpr( new VariableExpr( objDecl ) ) ); 136 expr->get_args().splice( expr->get_args().end(), args ); 137 return expr; 138 } 139 } 140 211 141 DeclarationWithType * CtorDtor::mutate( ObjectDecl * objDecl ) { 212 // hands off if designated , if @=, or if extern142 // hands off if designated or if @= 213 143 if ( tryConstruct( objDecl ) ) { 214 // call into genImplicitCall from Autogen.h to generate calls to ctor/dtor 215 // for each constructable object 216 std::list< Statement * > ctor; 217 std::list< Statement * > dtor; 218 219 InitExpander srcParam( objDecl->get_init() ); 220 InitExpander nullParam( (Initializer *)NULL ); 221 SymTab::genImplicitCall( srcParam, new VariableExpr( objDecl ), "?{}", back_inserter( ctor ), objDecl ); 222 SymTab::genImplicitCall( nullParam, new VariableExpr( objDecl ), "^?{}", front_inserter( dtor ), objDecl, false ); 223 224 // Currently genImplicitCall produces a single Statement - a CompoundStmt 225 // which wraps everything that needs to happen. As such, it's technically 226 // possible to use a Statement ** in the above calls, but this is inherently 227 // unsafe, so instead we take the slightly less efficient route, but will be 228 // immediately informed if somehow the above assumption is broken. In this case, 229 // we could always wrap the list of statements at this point with a CompoundStmt, 230 // but it seems reasonable at the moment for this to be done by genImplicitCall 231 // itself. It is possible that genImplicitCall produces no statements (e.g. if 232 // an array type does not have a dimension). In this case, it's fine to ignore 233 // the object for the purposes of construction. 234 assert( ctor.size() == dtor.size() && ctor.size() <= 1 ); 235 if ( ctor.size() == 1 ) { 236 // need to remember init expression, in case no ctors exist 237 // if ctor does exist, want to use ctor expression instead of init 238 // push this decision to the resolver 239 assert( dynamic_cast< ImplicitCtorDtorStmt * > ( ctor.front() ) && dynamic_cast< ImplicitCtorDtorStmt * > ( dtor.front() ) ); 240 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 } 241 188 } 242 189 } … … 246 193 DeclarationWithType * CtorDtor::mutate( FunctionDecl *functionDecl ) { 247 194 // parameters should not be constructed and destructed, so don't mutate FunctionType 195 bool oldInFunc = inFunction; 248 196 mutateAll( functionDecl->get_oldDecls(), *this ); 197 inFunction = true; 249 198 functionDecl->set_statements( maybeMutate( functionDecl->get_statements(), *this ) ); 199 inFunction = oldInFunc; 250 200 return functionDecl; 251 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 252 213 } // namespace InitTweak 253 214
Note:
See TracChangeset
for help on using the changeset viewer.