Changeset 58fe85a for src/InitTweak/GenInit.cc
- Timestamp:
- Jan 7, 2021, 3:27:00 PM (5 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- 2b4daf2, 64aeca0
- Parents:
- 3c64c668 (diff), eef8dfb (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/InitTweak/GenInit.cc
r3c64c668 r58fe85a 26 26 #include "AST/Node.hpp" 27 27 #include "AST/Stmt.hpp" 28 #include "CompilationState.h" 28 29 #include "CodeGen/OperatorTable.h" 29 30 #include "Common/PassVisitor.h" // for PassVisitor, WithGuards, WithShort... … … 121 122 }; 122 123 124 struct HoistArrayDimension_NoResolve final : public WithDeclsToAdd, public WithShortCircuiting, public WithGuards { 125 /// hoist dimension from array types in object declaration so that it uses a single 126 /// const variable of type size_t, so that side effecting array dimensions are only 127 /// computed once. 128 static void hoistArrayDimension( std::list< Declaration * > & translationUnit ); 129 130 void premutate( ObjectDecl * objectDecl ); 131 DeclarationWithType * postmutate( ObjectDecl * objectDecl ); 132 void premutate( FunctionDecl *functionDecl ); 133 // should not traverse into any of these declarations to find objects 134 // that need to be constructed or destructed 135 void premutate( AggregateDecl * ) { visit_children = false; } 136 void premutate( NamedTypeDecl * ) { visit_children = false; } 137 void premutate( FunctionType * ) { visit_children = false; } 138 139 void hoist( Type * type ); 140 141 Type::StorageClasses storageClasses; 142 bool inFunction = false; 143 }; 144 123 145 void genInit( std::list< Declaration * > & translationUnit ) { 146 if (!useNewAST) { 147 HoistArrayDimension::hoistArrayDimension( translationUnit ); 148 } 149 else { 150 HoistArrayDimension_NoResolve::hoistArrayDimension( translationUnit ); 151 } 124 152 fixReturnStatements( translationUnit ); 125 HoistArrayDimension::hoistArrayDimension( translationUnit ); 126 CtorDtor::generateCtorDtor( translationUnit ); 153 154 if (!useNewAST) { 155 CtorDtor::generateCtorDtor( translationUnit ); 156 } 127 157 } 128 158 … … 196 226 arrayType->isVarLen = ! isConstExpr( arrayType->dimension ); 197 227 // don't need to hoist dimension if it's definitely pure - only need to if there's potential for side effects. 228 // xxx - hoisting has no side effects anyways, so don't skip since we delay resolve 229 // still try to detect constant expressions 198 230 if ( ! Tuples::maybeImpure( arrayType->dimension ) ) return; 199 231 … … 210 242 211 243 void HoistArrayDimension::premutate( FunctionDecl * ) { 244 GuardValue( inFunction ); 245 inFunction = true; 246 } 247 248 // precompute array dimension expression, because constructor generation may duplicate it, 249 // which would be incorrect if it is a side-effecting computation. 250 void HoistArrayDimension_NoResolve::hoistArrayDimension( std::list< Declaration * > & translationUnit ) { 251 PassVisitor<HoistArrayDimension_NoResolve> hoister; 252 mutateAll( translationUnit, hoister ); 253 } 254 255 void HoistArrayDimension_NoResolve::premutate( ObjectDecl * objectDecl ) { 256 GuardValue( storageClasses ); 257 storageClasses = objectDecl->get_storageClasses(); 258 } 259 260 DeclarationWithType * HoistArrayDimension_NoResolve::postmutate( ObjectDecl * objectDecl ) { 261 hoist( objectDecl->get_type() ); 262 return objectDecl; 263 } 264 265 void HoistArrayDimension_NoResolve::hoist( Type * type ) { 266 // if in function, generate const size_t var 267 static UniqueName dimensionName( "_array_dim" ); 268 269 // C doesn't allow variable sized arrays at global scope or for static variables, so don't hoist dimension. 270 if ( ! inFunction ) return; 271 if ( storageClasses.is_static ) return; 272 273 if ( ArrayType * arrayType = dynamic_cast< ArrayType * >( type ) ) { 274 if ( ! arrayType->get_dimension() ) return; // xxx - recursive call to hoist? 275 // don't need to hoist dimension if it's definitely pure - only need to if there's potential for side effects. 276 // xxx - hoisting has no side effects anyways, so don't skip since we delay resolve 277 // still try to detect constant expressions 278 if ( ! Tuples::maybeImpure( arrayType->dimension ) ) return; 279 280 ObjectDecl * arrayDimension = new ObjectDecl( dimensionName.newName(), storageClasses, LinkageSpec::C, 0, Validate::SizeType->clone(), new SingleInit( arrayType->get_dimension() ) ); 281 arrayDimension->get_type()->set_const( true ); 282 283 arrayType->set_dimension( new VariableExpr( arrayDimension ) ); 284 declsToAddBefore.push_back( arrayDimension ); 285 286 hoist( arrayType->get_base() ); 287 return; 288 } 289 } 290 291 void HoistArrayDimension_NoResolve::premutate( FunctionDecl * ) { 212 292 GuardValue( inFunction ); 213 293 inFunction = true; … … 245 325 } 246 326 327 // why is this not just on FunctionDecl? 247 328 void ManagedTypes::handleDWT( DeclarationWithType * dwt ) { 248 329 // if this function is a user-defined constructor or destructor, mark down the type as "managed" … … 275 356 void ManagedTypes::endScope() { managedTypes.endScope(); } 276 357 358 bool ManagedTypes_new::isManaged( const ast::Type * type ) const { 359 // references are never constructed 360 if ( dynamic_cast< const ast::ReferenceType * >( type ) ) return false; 361 if ( auto tupleType = dynamic_cast< const ast::TupleType * > ( type ) ) { 362 // tuple is also managed if any of its components are managed 363 for (auto & component : tupleType->types) { 364 if (isManaged(component)) return true; 365 } 366 } 367 // need to clear and reset qualifiers when determining if a type is managed 368 // ValueGuard< Type::Qualifiers > qualifiers( type->get_qualifiers() ); 369 auto tmp = shallowCopy(type); 370 tmp->qualifiers = {}; 371 // delete tmp at return 372 ast::ptr<ast::Type> guard = tmp; 373 // 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) 374 return managedTypes.find( Mangle::mangle( tmp, {Mangle::NoOverrideable | Mangle::NoGenericParams | Mangle::Type} ) ) != managedTypes.end() || GenPoly::isPolyType( tmp ); 375 } 376 377 bool ManagedTypes_new::isManaged( const ast::ObjectDecl * objDecl ) const { 378 const ast::Type * type = objDecl->type; 379 while ( auto at = dynamic_cast< const ast::ArrayType * >( type ) ) { 380 // must always construct VLAs with an initializer, since this is an error in C 381 if ( at->isVarLen && objDecl->init ) return true; 382 type = at->base; 383 } 384 return isManaged( type ); 385 } 386 387 void ManagedTypes_new::handleDWT( const ast::DeclWithType * dwt ) { 388 // if this function is a user-defined constructor or destructor, mark down the type as "managed" 389 if ( ! dwt->linkage.is_overrideable && CodeGen::isCtorDtor( dwt->name ) ) { 390 auto & params = GenPoly::getFunctionType( dwt->get_type())->params; 391 assert( ! params.empty() ); 392 // Type * type = InitTweak::getPointerBase( params.front() ); 393 // assert( type ); 394 managedTypes.insert( Mangle::mangle( params.front(), {Mangle::NoOverrideable | Mangle::NoGenericParams | Mangle::Type} ) ); 395 } 396 } 397 398 void ManagedTypes_new::handleStruct( const ast::StructDecl * aggregateDecl ) { 399 // don't construct members, but need to take note if there is a managed member, 400 // because that means that this type is also managed 401 for ( auto & member : aggregateDecl->members ) { 402 if ( auto field = member.as<ast::ObjectDecl>() ) { 403 if ( isManaged( field ) ) { 404 // generic parameters should not play a role in determining whether a generic type is constructed - construct all generic types, so that 405 // polymorphic constructors make generic types managed types 406 ast::StructInstType inst( aggregateDecl ); 407 managedTypes.insert( Mangle::mangle( &inst, {Mangle::NoOverrideable | Mangle::NoGenericParams | Mangle::Type} ) ); 408 break; 409 } 410 } 411 } 412 } 413 414 void ManagedTypes_new::beginScope() { managedTypes.beginScope(); } 415 void ManagedTypes_new::endScope() { managedTypes.endScope(); } 416 277 417 ImplicitCtorDtorStmt * genCtorDtor( const std::string & fname, ObjectDecl * objDecl, Expression * arg ) { 278 418 // call into genImplicitCall from Autogen.h to generate calls to ctor/dtor … … 283 423 assert( stmts.size() <= 1 ); 284 424 return stmts.size() == 1 ? strict_dynamic_cast< ImplicitCtorDtorStmt * >( stmts.front() ) : nullptr; 425 426 } 427 428 ast::ptr<ast::Stmt> genCtorDtor (const CodeLocation & loc, const std::string & fname, const ast::ObjectDecl * objDecl, const ast::Expr * arg) { 429 assertf(objDecl, "genCtorDtor passed null objDecl"); 430 InitExpander_new srcParam(arg); 431 return SymTab::genImplicitCall(srcParam, new ast::VariableExpr(loc, objDecl), loc, fname, objDecl); 285 432 } 286 433 … … 363 510 // constructable object 364 511 InitExpander_new srcParam{ objDecl->init }, nullParam{ (const ast::Init *)nullptr }; 512 ast::ptr< ast::Expr > dstParam = new ast::VariableExpr(loc, objDecl); 365 513 366 514 ast::ptr< ast::Stmt > ctor = SymTab::genImplicitCall( 367 srcParam, new ast::VariableExpr{ loc, objDecl }, loc, "?{}", objDecl );515 srcParam, dstParam, loc, "?{}", objDecl ); 368 516 ast::ptr< ast::Stmt > dtor = SymTab::genImplicitCall( 369 nullParam, new ast::VariableExpr{ loc, objDecl }, loc, "^?{}", objDecl,517 nullParam, dstParam, loc, "^?{}", objDecl, 370 518 SymTab::LoopBackward ); 371 519
Note:
See TracChangeset
for help on using the changeset viewer.