Changeset fc1a3e2 for src/Virtual/VirtualDtor.cpp
- Timestamp:
- Apr 19, 2024, 2:36:52 PM (3 months ago)
- Branches:
- master
- Children:
- ba97ebf
- Parents:
- b9b6efb
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Virtual/VirtualDtor.cpp
rb9b6efb rfc1a3e2 28 28 29 29 struct CtorDtor { 30 31 32 33 34 30 FunctionDecl * dtorSetup; // dtor init routine to add after last dtor for a struct 31 FunctionDecl * deleteFn; 32 FunctionDecl * lastDtor; // pointer to last occurence of dtor to know where to insert after 33 34 CtorDtor() : dtorSetup(nullptr), deleteFn(nullptr), lastDtor(nullptr) {} 35 35 }; 36 36 37 37 class CtorDtorTable { 38 unordered_map<const StructDecl *, CtorDtor> & structMap; 38 unordered_map<const StructDecl *, CtorDtor> & structMap; 39 40 public: 41 // if dtor is last dtor for this decl return the routine to add afterwards 42 // otherwise return nullptr 43 FunctionDecl * getToAddLater( const StructDecl * decl, FunctionDecl * dtor, FunctionDecl ** retDeleteFn ) { 44 auto iter = structMap.find( decl ); 45 if ( iter == structMap.end() || iter->second.lastDtor != dtor ) return nullptr; // check if this is needed 46 *retDeleteFn = iter->second.deleteFn; 47 return iter->second.dtorSetup; 48 } 49 50 // return if the dtorSetup field has been defined for this decl 51 bool inTable( const StructDecl * decl ) { 52 auto iter = structMap.find( decl ); 53 return iter->second.dtorSetup != nullptr; 54 } 55 56 void addLater( const StructDecl * decl, FunctionDecl * dtorSetup, FunctionDecl * deleteFn ) { 57 auto iter = structMap.find( decl ); 58 iter->second.dtorSetup = dtorSetup; 59 iter->second.deleteFn = deleteFn; 60 } 61 62 void addDtor( const StructDecl * decl, FunctionDecl * dtor ) { 63 auto iter = structMap.find( decl ); 64 iter->second.lastDtor = dtor; 65 } 66 67 CtorDtorTable( unordered_map<const StructDecl *, CtorDtor> & structMap ) : structMap(structMap) {} 68 }; 69 70 struct CollectStructDecls : public ast::WithGuards { 71 unordered_map<const StructDecl *, CtorDtor> & structDecls; 72 StructDecl * parentDecl; 73 bool insideStruct = false; 74 bool namedDecl = false; 75 76 const StructDecl ** virtualDtor; 77 78 // finds and sets a ptr to the actor, message, and request structs, which are needed in the next pass 79 void previsit( const StructDecl * decl ) { 80 if ( !decl->body ) return; 81 if( decl->name == "virtual_dtor" ) { 82 structDecls.emplace( make_pair( decl, CtorDtor() ) ); 83 *virtualDtor = decl; 84 } else { 85 GuardValue(insideStruct); 86 insideStruct = true; 87 parentDecl = mutate( decl ); 88 } 89 } 90 91 // this catches structs of the form: 92 // struct derived_type { virtual_dtor a; }; 93 // since they should be: 94 // struct derived_type { inline virtual_dtor; }; 95 void previsit ( const ObjectDecl * decl ) { 96 if ( insideStruct && ! decl->name.empty() ) { 97 GuardValue(namedDecl); 98 namedDecl = true; 99 } 100 } 101 102 // this collects the derived actor and message struct decl ptrs 103 void postvisit( const StructInstType * node ) { 104 if ( ! *virtualDtor ) return; 105 if ( insideStruct && !namedDecl ) { 106 auto structIter = structDecls.find( node->aggr() ); 107 if ( structIter != structDecls.end() ) 108 structDecls.emplace( make_pair( parentDecl, CtorDtor() ) ); 109 } 110 } 39 111 40 112 public: 41 // if dtor is last dtor for this decl return the routine to add afterwards 42 // otherwise return nullptr 43 FunctionDecl * getToAddLater( const StructDecl * decl, FunctionDecl * dtor, FunctionDecl ** retDeleteFn ) { 44 auto iter = structMap.find( decl ); 45 if ( iter == structMap.end() || iter->second.lastDtor != dtor ) return nullptr; // check if this is needed 46 *retDeleteFn = iter->second.deleteFn; 47 return iter->second.dtorSetup; 48 } 49 50 // return if the dtorSetup field has been defined for this decl 51 bool inTable( const StructDecl * decl ) { 52 auto iter = structMap.find( decl ); 53 return iter->second.dtorSetup != nullptr; 54 } 55 56 void addLater( const StructDecl * decl, FunctionDecl * dtorSetup, FunctionDecl * deleteFn ) { 57 auto iter = structMap.find( decl ); 58 iter->second.dtorSetup = dtorSetup; 59 iter->second.deleteFn = deleteFn; 60 } 61 62 void addDtor( const StructDecl * decl, FunctionDecl * dtor ) { 63 auto iter = structMap.find( decl ); 64 iter->second.lastDtor = dtor; 65 } 66 67 CtorDtorTable( unordered_map<const StructDecl *, CtorDtor> & structMap ) : structMap(structMap) {} 68 }; 69 70 struct CollectStructDecls : public ast::WithGuards { 71 unordered_map<const StructDecl *, CtorDtor> & structDecls; 72 StructDecl * parentDecl; 73 bool insideStruct = false; 74 bool namedDecl = false; 75 76 const StructDecl ** virtualDtor; 77 78 // finds and sets a ptr to the actor, message, and request structs, which are needed in the next pass 79 void previsit( const StructDecl * decl ) { 80 if ( !decl->body ) return; 81 if( decl->name == "virtual_dtor" ) { 82 structDecls.emplace( make_pair( decl, CtorDtor() ) ); 83 *virtualDtor = decl; 84 } else { 85 GuardValue(insideStruct); 86 insideStruct = true; 87 parentDecl = mutate( decl ); 88 } 89 } 90 91 // this catches structs of the form: 92 // struct derived_type { virtual_dtor a; }; 93 // since they should be: 94 // struct derived_type { inline virtual_dtor; }; 95 void previsit ( const ObjectDecl * decl ) { 96 if ( insideStruct && ! decl->name.empty() ) { 97 GuardValue(namedDecl); 98 namedDecl = true; 99 } 100 } 101 102 // this collects the derived actor and message struct decl ptrs 103 void postvisit( const StructInstType * node ) { 104 if ( ! *virtualDtor ) return; 105 if ( insideStruct && !namedDecl ) { 106 auto structIter = structDecls.find( node->aggr() ); 107 if ( structIter != structDecls.end() ) 108 structDecls.emplace( make_pair( parentDecl, CtorDtor() ) ); 109 } 110 } 111 112 public: 113 CollectStructDecls( unordered_map<const StructDecl *, CtorDtor> & structDecls, const StructDecl ** virtualDtor ): 114 structDecls( structDecls ), virtualDtor(virtualDtor) {} 113 CollectStructDecls( unordered_map<const StructDecl *, CtorDtor> & structDecls, const StructDecl ** virtualDtor ): 114 structDecls( structDecls ), virtualDtor(virtualDtor) {} 115 115 }; 116 116 117 117 // generates the forward decl of virtual dtor setting routine and delete routine 118 118 // generates the call to the virtual dtor routine in each appropriate ctor 119 // collects data needed for next pass that does the circular defn resolution 119 // collects data needed for next pass that does the circular defn resolution 120 120 // for dtor setters and delete fns (via table above) 121 121 struct GenFuncsCreateTables : public ast::WithDeclsToAdd<> { 122 123 124 125 126 127 128 129 if ( (decl->name != "?{}" && decl->name != "^?{}") || decl->params.size() == 0 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 dtorBody->push_front( 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 decl->location, 234 235 236 237 238 decl->location, 239 new AddressExpr( decl->location, new NameExpr( decl->location, "this" )), 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 UntypedExpr::createCall( 294 decl->location, 295 296 297 298 299 300 301 302 303 304 305 306 307 308 UntypedExpr::createCall( 309 decl->location, 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 122 unordered_map<const StructDecl *, CtorDtor> & structDecls; 123 CtorDtorTable & torDecls; 124 const StructDecl ** virtualDtor; 125 126 // collects the dtor info for actors/messages 127 // gens the dtor fwd decl and dtor call in ctor 128 void previsit( const FunctionDecl * decl ) { 129 if ( (decl->name != "?{}" && decl->name != "^?{}") || decl->params.size() == 0 130 || !decl->stmts || (decl->name == "^?{}" && decl->params.size() != 1)) return; 131 132 // the first param should be a reference 133 const ReferenceType * ref = dynamic_cast<const ReferenceType *>(decl->params.at(0)->get_type()); 134 if ( !ref ) return; 135 136 // the reference should be to a struct instance 137 const StructInstType * instType = dynamic_cast<const StructInstType *>(ref->base.get()); 138 if ( !instType ) return; 139 140 // return if not ctor/dtor for an actor or message 141 auto structIter = structDecls.find( instType->aggr() ); 142 if ( structIter == structDecls.end() ) return; 143 144 // If first param not named we need to name it to use it 145 if ( decl->params.at(0)->name == "" ) 146 mutate( decl->params.at(0).get() )->name = "__CFA_Virt_Dtor_param"; 147 148 if ( decl->name == "^?{}") { 149 torDecls.addDtor( structIter->first, mutate( decl ) ); 150 151 CompoundStmt * dtorBody = mutate( decl->stmts.get() ); 152 // Adds the following to the start of any actor/message dtor: 153 // __CFA_dtor_shutdown( this ); 154 dtorBody->push_front( 155 new IfStmt( decl->location, 156 new UntypedExpr ( 157 decl->location, 158 new NameExpr( decl->location, "__CFA_dtor_shutdown" ), 159 { 160 new NameExpr( decl->location, decl->params.at(0)->name ) 161 } 162 ), 163 new ReturnStmt( decl->location, nullptr ) 164 ) 165 ); 166 return; 167 } 168 169 // not dtor by this point so must be ctor 170 CompoundStmt * ctorBody = mutate( decl->stmts.get() ); 171 // Adds the following to the end of any actor/message ctor: 172 // __CFA_set_dtor( this ); 173 ctorBody->push_back( new ExprStmt( 174 decl->location, 175 new UntypedExpr ( 176 decl->location, 177 new NameExpr( decl->location, "__CFA_set_dtor" ), 178 { 179 new NameExpr( decl->location, decl->params.at(0)->name ) 180 } 181 ) 182 )); 183 184 if ( torDecls.inTable( structIter->first ) ) return; 185 186 // Generates the following: 187 // void __CFA_set_dtor( Derived_type & this ){ 188 // void (*__my_dtor)( Derived_type & ) = ^?{}; 189 // this.__virtual_dtor = (void (*)( Base_type & ))__my_dtor; 190 // this.__virtual_obj_start = (void *)(&this); 191 // } 192 CompoundStmt * setDtorBody = new CompoundStmt( decl->location ); 193 194 // Function type is: (void (*)(Derived_type &)) 195 FunctionType * derivedDtor = new FunctionType(); 196 derivedDtor->params.push_back( ast::deepCopy( ref ) ); 197 198 // Generates: 199 // void (*__my_dtor)( Derived_type & ) = ^?{}; 200 setDtorBody->push_back( new DeclStmt( 201 decl->location, 202 new ObjectDecl( 203 decl->location, 204 "__my_dtor", 205 new PointerType( derivedDtor ), 206 new SingleInit( decl->location, new NameExpr( decl->location, "^?{}" ) ) 207 ) 208 )); 209 210 // Function type is: (void (*)( Base_type & )) 211 FunctionType * baseDtor = new FunctionType(); 212 baseDtor->params.push_back( new ReferenceType( new StructInstType( *virtualDtor ) ) ); 213 214 // Generates: 215 // __CFA_set_virt_dtor( this, (void (*)( Base_type & ))__my_dtor ) 216 setDtorBody->push_back( new ExprStmt( 217 decl->location, 218 new UntypedExpr ( 219 decl->location, 220 new NameExpr( decl->location, "__CFA_set_virt_dtor" ), 221 { 222 new NameExpr( decl->location, "this" ), 223 new CastExpr( decl->location, new NameExpr( decl->location, "__my_dtor" ), new PointerType( baseDtor ), ExplicitCast ) 224 } 225 ) 226 )); 227 228 // Generates: 229 // __CFA_set_virt_start( (void *)(&this) ); 230 setDtorBody->push_back( new ExprStmt( 231 decl->location, 232 new UntypedExpr ( 233 decl->location, 234 new NameExpr( decl->location, "__CFA_set_virt_start" ), 235 { 236 new NameExpr( decl->location, "this" ), 237 new CastExpr( 238 decl->location, 239 new AddressExpr( decl->location, new NameExpr( decl->location, "this" )), 240 new PointerType( new ast::VoidType() ), ExplicitCast 241 ) 242 } 243 ) 244 )); 245 246 // put it all together into the complete function decl from above 247 FunctionDecl * setDtorFunction = new FunctionDecl( 248 decl->location, 249 "__CFA_set_dtor", 250 { 251 new ObjectDecl( 252 decl->location, 253 "this", 254 ast::deepCopy( ref ) 255 ), 256 }, // params 257 {}, 258 nullptr, // body 259 { Storage::Static }, // storage 260 Linkage::Cforall, // linkage 261 {}, // attributes 262 { Function::Inline } 263 ); 264 265 declsToAddBefore.push_back( ast::deepCopy( setDtorFunction ) ); 266 267 setDtorFunction->stmts = setDtorBody; 268 269 // The following generates the following specialized delete routine: 270 // static inline void delete( derived_type * ptr ) { 271 // if ( ptr ) 272 // ^(*ptr){}; 273 // __CFA_virt_free( *ptr ); 274 // } 275 CompoundStmt * deleteFnBody = new CompoundStmt( decl->location ); 276 277 // Generates: 278 // if ( ptr ) 279 // ^(*ptr){}; 280 deleteFnBody->push_back( 281 new IfStmt( 282 decl->location, 283 UntypedExpr::createCall( 284 decl->location, 285 "?!=?", 286 { 287 new NameExpr( decl->location, "ptr" ), 288 ConstantExpr::null( decl->location, new PointerType( ast::deepCopy( instType ) ) ) 289 } 290 ), 291 new ExprStmt( 292 decl->location, 293 UntypedExpr::createCall( 294 decl->location, 295 "^?{}", 296 { 297 UntypedExpr::createDeref( decl->location, new NameExpr( decl->location, "ptr" )) 298 } 299 ) 300 ) 301 ) 302 ); 303 304 // Generates: 305 // __CFA_virt_free( *ptr ); 306 deleteFnBody->push_back( new ExprStmt( 307 decl->location, 308 UntypedExpr::createCall( 309 decl->location, 310 "__CFA_virt_free", 311 { 312 UntypedExpr::createDeref( decl->location, new NameExpr( decl->location, "ptr" )) 313 } 314 ) 315 ) 316 ); 317 318 FunctionDecl * deleteFn = new FunctionDecl( 319 decl->location, 320 "delete", 321 { 322 new ObjectDecl( 323 decl->location, 324 "ptr", 325 new PointerType( ast::deepCopy( instType ) ) 326 ), 327 }, // params 328 {}, 329 nullptr, // body 330 { Storage::Static }, // storage 331 Linkage::Cforall, // linkage 332 {}, // attributes 333 { Function::Inline } 334 ); 335 336 declsToAddBefore.push_back( ast::deepCopy( deleteFn ) ); 337 338 deleteFn->stmts = deleteFnBody; 339 340 torDecls.addLater( structIter->first, setDtorFunction, deleteFn ); 341 } 342 342 343 343 public: 344 345 344 GenFuncsCreateTables( unordered_map<const StructDecl *, CtorDtor> & structDecls, CtorDtorTable & torDecls, const StructDecl ** virtualDtor ): 345 structDecls(structDecls), torDecls(torDecls), virtualDtor(virtualDtor) {} 346 346 }; 347 347 … … 349 349 // generates the trailing definitions of dtor setting routines for virtual dtors on messages and actors 350 350 // generates the function defns of __CFA_set_dtor 351 // separate pass is needed since __CFA_set_dtor needs to be defined after 351 // separate pass is needed since __CFA_set_dtor needs to be defined after 352 352 // the last dtor defn which is found in prior pass 353 353 struct GenSetDtor : public ast::WithDeclsToAdd<> { 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 354 unordered_map<const StructDecl *, CtorDtor> & structDecls; // set of decls that inherit from virt dtor 355 CtorDtorTable & torDecls; 356 357 // handles adding the declaration of the dtor init routine after the last dtor detected 358 void postvisit( const FunctionDecl * decl ) { 359 if ( decl->name != "^?{}" || !decl->stmts || decl->params.size() != 1 ) return; 360 361 // the one param should be a reference 362 const ReferenceType * ref = dynamic_cast<const ReferenceType *>(decl->params.at(0)->get_type()); 363 if ( !ref ) return; 364 365 // the reference should be to a struct instance 366 const StructInstType * instType = dynamic_cast<const StructInstType *>(ref->base.get()); 367 if ( !instType ) return; 368 369 FunctionDecl * deleteRtn; 370 371 // returns nullptr if not in table 372 FunctionDecl * maybeAdd = torDecls.getToAddLater( instType->aggr(), mutate( decl ), &deleteRtn ); 373 if ( maybeAdd ) { 374 declsToAddAfter.push_back( maybeAdd ); 375 declsToAddAfter.push_back( deleteRtn ); 376 } 377 } 378 379 public: 380 GenSetDtor( unordered_map<const StructDecl *, CtorDtor> & structDecls, CtorDtorTable & torDecls ): 381 structDecls(structDecls), torDecls(torDecls) {} 382 382 }; 383 383 384 384 void implementVirtDtors( TranslationUnit & translationUnit ) { 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 385 // unordered_map to collect all derived types and associated data 386 unordered_map<const StructDecl *, CtorDtor> structDecls; 387 CtorDtorTable torDecls( structDecls ); 388 389 const StructDecl * virtualDtorPtr = nullptr; 390 const StructDecl ** virtualDtor = &virtualDtorPtr; 391 392 // first pass collects all structs that inherit from virtual_dtor 393 Pass<CollectStructDecls>::run( translationUnit, structDecls, virtualDtor ); 394 395 // second pass locates all dtor/ctor routines that need modifying or need fns inserted before/after 396 Pass<GenFuncsCreateTables>::run( translationUnit, structDecls, torDecls, virtualDtor ); 397 398 // The third pass adds the forward decls needed to resolve circular defn problems 399 Pass<GenSetDtor>::run( translationUnit, structDecls, torDecls ); 400 400 } 401 402 401 403 402 } // namespace Virtual
Note: See TracChangeset
for help on using the changeset viewer.