Changes in src/InitTweak/GenInit.cc [e3e16bc:e35f30a]
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/InitTweak/GenInit.cc
re3e16bc re35f30a 26 26 #include "Common/UniqueName.h" // for UniqueName 27 27 #include "Common/utility.h" // for ValueGuard, maybeClone 28 #include "GenPoly/DeclMutator.h" // for DeclMutator29 28 #include "GenPoly/GenPoly.h" // for getFunctionType, isPolyType 30 29 #include "GenPoly/ScopedSet.h" // for ScopedSet, ScopedSet<>::const_iter... … … 62 61 }; 63 62 64 struct CtorDtor : public WithGuards, public WithShortCircuiting {63 struct CtorDtor : public WithGuards, public WithShortCircuiting, public WithVisitorRef<CtorDtor> { 65 64 /// create constructor and destructor statements for object declarations. 66 65 /// the actual call statements will be added in after the resolver has run … … 75 74 // that need to be constructed or destructed 76 75 void previsit( StructDecl *aggregateDecl ); 77 void previsit( __attribute__((unused)) UnionDecl * aggregateDecl ) { visit_children = false; } 78 void previsit( __attribute__((unused)) EnumDecl * aggregateDecl ) { visit_children = false; } 79 void previsit( __attribute__((unused)) TraitDecl * aggregateDecl ) { visit_children = false; } 80 void previsit( __attribute__((unused)) TypeDecl * typeDecl ) { visit_children = false; } 81 void previsit( __attribute__((unused)) TypedefDecl * typeDecl ) { visit_children = false; } 82 void previsit( __attribute__((unused)) FunctionType * funcType ) { visit_children = false; } 76 void previsit( AggregateDecl * ) { visit_children = false; } 77 void previsit( NamedTypeDecl * ) { visit_children = false; } 78 void previsit( FunctionType * ) { visit_children = false; } 83 79 84 80 void previsit( CompoundStmt * compoundStmt ); … … 89 85 // should not have a ConstructorInit generated. 90 86 91 bool isManaged( ObjectDecl * objDecl ) const ; // determine if object is managed 92 bool isManaged( Type * type ) const; // determine if type is managed 93 void handleDWT( DeclarationWithType * dwt ); // add type to managed if ctor/dtor 94 GenPoly::ScopedSet< std::string > managedTypes; 87 ManagedTypes managedTypes; 95 88 bool inFunction = false; 96 89 }; 97 90 98 class HoistArrayDimension final : public GenPoly::DeclMutator { 99 public: 100 typedef GenPoly::DeclMutator Parent; 101 91 struct HoistArrayDimension final : public WithDeclsToAdd, public WithShortCircuiting, public WithGuards { 102 92 /// hoist dimension from array types in object declaration so that it uses a single 103 93 /// const variable of type size_t, so that side effecting array dimensions are only … … 105 95 static void hoistArrayDimension( std::list< Declaration * > & translationUnit ); 106 96 107 private: 108 using Parent::mutate; 109 110 virtual DeclarationWithType * mutate( ObjectDecl * objectDecl ) override; 111 virtual DeclarationWithType * mutate( FunctionDecl *functionDecl ) override; 97 void premutate( ObjectDecl * objectDecl ); 98 DeclarationWithType * postmutate( ObjectDecl * objectDecl ); 99 void premutate( FunctionDecl *functionDecl ); 112 100 // should not traverse into any of these declarations to find objects 113 101 // that need to be constructed or destructed 114 virtual Declaration* mutate( StructDecl *aggregateDecl ) override { return aggregateDecl; } 115 virtual Declaration* mutate( UnionDecl *aggregateDecl ) override { return aggregateDecl; } 116 virtual Declaration* mutate( EnumDecl *aggregateDecl ) override { return aggregateDecl; } 117 virtual Declaration* mutate( TraitDecl *aggregateDecl ) override { return aggregateDecl; } 118 virtual TypeDecl* mutate( TypeDecl *typeDecl ) override { return typeDecl; } 119 virtual Declaration* mutate( TypedefDecl *typeDecl ) override { return typeDecl; } 120 121 virtual Type* mutate( FunctionType *funcType ) override { return funcType; } 102 void premutate( AggregateDecl * ) { visit_children = false; } 103 void premutate( NamedTypeDecl * ) { visit_children = false; } 104 void premutate( FunctionType * ) { visit_children = false; } 122 105 123 106 void hoist( Type * type ); … … 128 111 129 112 void genInit( std::list< Declaration * > & translationUnit ) { 130 ReturnFixer::makeReturnTemp( translationUnit );113 fixReturnStatements( translationUnit ); 131 114 HoistArrayDimension::hoistArrayDimension( translationUnit ); 132 115 CtorDtor::generateCtorDtor( translationUnit ); 133 116 } 134 117 135 void ReturnFixer::makeReturnTemp( std::list< Declaration * > & translationUnit ) {118 void fixReturnStatements( std::list< Declaration * > & translationUnit ) { 136 119 PassVisitor<ReturnFixer> fixer; 137 120 mutateAll( translationUnit, fixer ); … … 143 126 // hands off if the function returns a reference - we don't want to allocate a temporary if a variable's address 144 127 // is being returned 145 if ( returnStmt-> get_expr() && returnVals.size() == 1 && ! dynamic_cast< ReferenceType * >( returnVals.front()->get_type() ) ) {128 if ( returnStmt->expr && returnVals.size() == 1 && isConstructable( returnVals.front()->get_type() ) ) { 146 129 // explicitly construct the return value using the return expression and the retVal object 147 assertf( returnVals.front()->get_name() != "", "Function %s has unnamed return value\n", funcName.c_str() ); 148 149 stmtsToAddBefore.push_back( genCtorDtor( "?{}", dynamic_cast< ObjectDecl *>( returnVals.front() ), returnStmt->get_expr() ) ); 130 assertf( returnVals.front()->name != "", "Function %s has unnamed return value\n", funcName.c_str() ); 131 132 ObjectDecl * retVal = strict_dynamic_cast< ObjectDecl * >( returnVals.front() ); 133 if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( returnStmt->expr ) ) { 134 // return statement has already been mutated - don't need to do it again 135 if ( varExpr->var == retVal ) return; 136 } 137 stmtsToAddBefore.push_back( genCtorDtor( "?{}", retVal, returnStmt->get_expr() ) ); 150 138 151 139 // return the retVal object 152 returnStmt-> set_expr( new VariableExpr( returnVals.front()) );140 returnStmt->expr = new VariableExpr( returnVals.front() ); 153 141 } // if 154 142 } … … 158 146 GuardValue( funcName ); 159 147 160 ftype = functionDecl-> get_functionType();161 funcName = functionDecl-> get_name();148 ftype = functionDecl->type; 149 funcName = functionDecl->name; 162 150 } 163 151 … … 165 153 // which would be incorrect if it is a side-effecting computation. 166 154 void HoistArrayDimension::hoistArrayDimension( std::list< Declaration * > & translationUnit ) { 167 HoistArrayDimension hoister; 168 hoister.mutateDeclarationList( translationUnit ); 169 } 170 171 DeclarationWithType * HoistArrayDimension::mutate( ObjectDecl * objectDecl ) { 155 PassVisitor<HoistArrayDimension> hoister; 156 mutateAll( translationUnit, hoister ); 157 } 158 159 void HoistArrayDimension::premutate( ObjectDecl * objectDecl ) { 160 GuardValue( storageClasses ); 172 161 storageClasses = objectDecl->get_storageClasses(); 173 DeclarationWithType * temp = Parent::mutate( objectDecl ); 162 } 163 164 DeclarationWithType * HoistArrayDimension::postmutate( ObjectDecl * objectDecl ) { 174 165 hoist( objectDecl->get_type() ); 175 return temp;166 return objectDecl; 176 167 } 177 168 … … 194 185 195 186 arrayType->set_dimension( new VariableExpr( arrayDimension ) ); 196 addDeclaration( arrayDimension );187 declsToAddBefore.push_back( arrayDimension ); 197 188 198 189 hoist( arrayType->get_base() ); … … 201 192 } 202 193 203 DeclarationWithType * HoistArrayDimension::mutate( FunctionDecl *functionDecl ) { 204 ValueGuard< bool > oldInFunc( inFunction ); 205 inFunction = true; 206 DeclarationWithType * decl = Parent::mutate( functionDecl ); 207 return decl; 194 void HoistArrayDimension::premutate( FunctionDecl * ) { 195 GuardValue( inFunction ); 208 196 } 209 197 … … 213 201 } 214 202 215 bool CtorDtor::isManaged( Type * type ) const {216 // at least for now,references are never constructed203 bool ManagedTypes::isManaged( Type * type ) const { 204 // references are never constructed 217 205 if ( dynamic_cast< ReferenceType * >( type ) ) return false; 218 206 // need to clear and reset qualifiers when determining if a type is managed … … 221 209 if ( TupleType * tupleType = dynamic_cast< TupleType * > ( type ) ) { 222 210 // tuple is also managed if any of its components are managed 223 if ( std::any_of( tupleType-> get_types().begin(), tupleType->get_types().end(), [&](Type * type) { return isManaged( type ); }) ) {211 if ( std::any_of( tupleType->types.begin(), tupleType->types.end(), [&](Type * type) { return isManaged( type ); }) ) { 224 212 return true; 225 213 } 226 214 } 227 215 // a type is managed if it appears in the map of known managed types, or if it contains any polymorphism (is a type variable or generic type containing a type variable) 228 return managedTypes.find( SymTab::Mangler::mangle ( type ) ) != managedTypes.end() || GenPoly::isPolyType( type );229 } 230 231 bool CtorDtor::isManaged( ObjectDecl * objDecl ) const {216 return managedTypes.find( SymTab::Mangler::mangleConcrete( type ) ) != managedTypes.end() || GenPoly::isPolyType( type ); 217 } 218 219 bool ManagedTypes::isManaged( ObjectDecl * objDecl ) const { 232 220 Type * type = objDecl->get_type(); 233 221 while ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) { … … 237 225 } 238 226 239 void CtorDtor::handleDWT( DeclarationWithType * dwt ) {227 void ManagedTypes::handleDWT( DeclarationWithType * dwt ) { 240 228 // if this function is a user-defined constructor or destructor, mark down the type as "managed" 241 229 if ( ! LinkageSpec::isOverridable( dwt->get_linkage() ) && CodeGen::isCtorDtor( dwt->get_name() ) ) { … … 244 232 Type * type = InitTweak::getPointerBase( params.front()->get_type() ); 245 233 assert( type ); 246 managedTypes.insert( SymTab::Mangler::mangle( type ) ); 247 } 248 } 234 managedTypes.insert( SymTab::Mangler::mangleConcrete( type ) ); 235 } 236 } 237 238 void ManagedTypes::handleStruct( StructDecl * aggregateDecl ) { 239 // don't construct members, but need to take note if there is a managed member, 240 // because that means that this type is also managed 241 for ( Declaration * member : aggregateDecl->get_members() ) { 242 if ( ObjectDecl * field = dynamic_cast< ObjectDecl * >( member ) ) { 243 if ( isManaged( field ) ) { 244 // generic parameters should not play a role in determining whether a generic type is constructed - construct all generic types, so that 245 // polymorphic constructors make generic types managed types 246 StructInstType inst( Type::Qualifiers(), aggregateDecl ); 247 managedTypes.insert( SymTab::Mangler::mangleConcrete( &inst ) ); 248 break; 249 } 250 } 251 } 252 } 253 254 void ManagedTypes::beginScope() { managedTypes.beginScope(); } 255 void ManagedTypes::endScope() { managedTypes.endScope(); } 249 256 250 257 ImplicitCtorDtorStmt * genCtorDtor( const std::string & fname, ObjectDecl * objDecl, Expression * arg ) { … … 291 298 292 299 void CtorDtor::previsit( ObjectDecl * objDecl ) { 293 handleDWT( objDecl );300 managedTypes.handleDWT( objDecl ); 294 301 // hands off if @=, extern, builtin, etc. 295 302 // even if unmanaged, try to construct global or static if initializer is not constexpr, since this is not legal C 296 if ( tryConstruct( objDecl ) && ( isManaged( objDecl ) || ((! inFunction || objDecl->get_storageClasses().is_static ) && ! isConstExpr( objDecl->get_init() ) ) ) ) {303 if ( tryConstruct( objDecl ) && ( managedTypes.isManaged( objDecl ) || ((! inFunction || objDecl->get_storageClasses().is_static ) && ! isConstExpr( objDecl->get_init() ) ) ) ) { 297 304 // constructed objects cannot be designated 298 305 if ( isDesignated( objDecl->get_init() ) ) throw SemanticError( "Cannot include designations in the initializer for a managed Object. If this is really what you want, then initialize with @=.\n", objDecl ); … … 305 312 306 313 void CtorDtor::previsit( FunctionDecl *functionDecl ) { 314 visit_children = false; // do not try and construct parameters or forall parameters 307 315 GuardValue( inFunction ); 308 316 inFunction = true; 309 317 310 handleDWT( functionDecl );318 managedTypes.handleDWT( functionDecl ); 311 319 312 320 GuardScope( managedTypes ); … … 314 322 for ( auto & tyDecl : functionDecl->get_functionType()->get_forall() ) { 315 323 for ( DeclarationWithType *& assertion : tyDecl->get_assertions() ) { 316 handleDWT( assertion );324 managedTypes.handleDWT( assertion ); 317 325 } 318 326 } 319 327 320 PassVisitor<CtorDtor> newCtorDtor; 321 newCtorDtor.pass = *this; 322 maybeAccept( functionDecl->get_statements(), newCtorDtor ); 323 visit_children = false; // do not try and construct parameters or forall parameters - must happen after maybeAccept 328 maybeAccept( functionDecl->get_statements(), *visitor ); 324 329 } 325 330 … … 327 332 visit_children = false; // do not try to construct and destruct aggregate members 328 333 329 // don't construct members, but need to take note if there is a managed member, 330 // because that means that this type is also managed 331 for ( Declaration * member : aggregateDecl->get_members() ) { 332 if ( ObjectDecl * field = dynamic_cast< ObjectDecl * >( member ) ) { 333 if ( isManaged( field ) ) { 334 StructInstType inst( Type::Qualifiers(), aggregateDecl ); 335 managedTypes.insert( SymTab::Mangler::mangle( &inst ) ); 336 break; 337 } 338 } 339 } 340 } 341 342 void CtorDtor::previsit( __attribute__((unused)) CompoundStmt * compoundStmt ) { 334 managedTypes.handleStruct( aggregateDecl ); 335 } 336 337 void CtorDtor::previsit( CompoundStmt * ) { 343 338 GuardScope( managedTypes ); 344 339 }
Note:
See TracChangeset
for help on using the changeset viewer.