Changeset 16ba4a6f for src/InitTweak
- Timestamp:
- Nov 10, 2020, 12:20:37 AM (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:
- 18f0b70
- Parents:
- 3febb2d
- Location:
- src/InitTweak
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
src/InitTweak/GenInit.cc
r3febb2d r16ba4a6f 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... … … 122 123 123 124 void genInit( std::list< Declaration * > & translationUnit ) { 125 HoistArrayDimension::hoistArrayDimension( translationUnit ); 124 126 fixReturnStatements( translationUnit ); 125 HoistArrayDimension::hoistArrayDimension( translationUnit ); 126 CtorDtor::generateCtorDtor( translationUnit ); 127 128 if (!useNewAST) { 129 CtorDtor::generateCtorDtor( translationUnit ); 130 } 127 131 } 128 132 … … 192 196 193 197 // need to resolve array dimensions in order to accurately determine if constexpr 194 ResolvExpr::findSingleExpression( arrayType->dimension, Validate::SizeType->clone(), indexer ); 195 // array is variable-length when the dimension is not constexpr 196 arrayType->isVarLen = ! isConstExpr( arrayType->dimension ); 198 if (!useNewAST) { 199 ResolvExpr::findSingleExpression( arrayType->dimension, Validate::SizeType->clone(), indexer ); 200 // array is variable-length when the dimension is not constexpr 201 arrayType->isVarLen = ! isConstExpr( arrayType->dimension ); 202 } 197 203 // don't need to hoist dimension if it's definitely pure - only need to if there's potential for side effects. 198 if ( ! Tuples::maybeImpure( arrayType->dimension ) ) return; 204 // xxx - hoisting has no side effects anyways, so don't skip since we delay resolve 205 // only skip in the most trivial case, which does not require resolve 206 if (dynamic_cast<ConstantExpr *>(arrayType->dimension)) return; 207 // if ( ! Tuples::maybeImpure( arrayType->dimension ) ) return; 199 208 200 209 ObjectDecl * arrayDimension = new ObjectDecl( dimensionName.newName(), storageClasses, LinkageSpec::C, 0, Validate::SizeType->clone(), new SingleInit( arrayType->get_dimension() ) ); … … 245 254 } 246 255 256 // why is this not just on FunctionDecl? 247 257 void ManagedTypes::handleDWT( DeclarationWithType * dwt ) { 248 258 // if this function is a user-defined constructor or destructor, mark down the type as "managed" … … 274 284 void ManagedTypes::beginScope() { managedTypes.beginScope(); } 275 285 void ManagedTypes::endScope() { managedTypes.endScope(); } 286 287 bool ManagedTypes_new::isManaged( const ast::Type * type ) const { 288 // references are never constructed 289 if ( dynamic_cast< const ast::ReferenceType * >( type ) ) return false; 290 if ( auto tupleType = dynamic_cast< const ast::TupleType * > ( type ) ) { 291 // tuple is also managed if any of its components are managed 292 for (auto & component : tupleType->types) { 293 if (isManaged(component)) return true; 294 } 295 } 296 // need to clear and reset qualifiers when determining if a type is managed 297 // ValueGuard< Type::Qualifiers > qualifiers( type->get_qualifiers() ); 298 auto tmp = shallowCopy(type); 299 tmp->qualifiers = {}; 300 // delete tmp at return 301 ast::ptr<ast::Type> guard = tmp; 302 // 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) 303 return managedTypes.find( Mangle::mangle( tmp, {Mangle::NoOverrideable | Mangle::NoGenericParams | Mangle::Type} ) ) != managedTypes.end() || GenPoly::isPolyType( tmp ); 304 } 305 306 bool ManagedTypes_new::isManaged( const ast::ObjectDecl * objDecl ) const { 307 const ast::Type * type = objDecl->type; 308 while ( auto at = dynamic_cast< const ast::ArrayType * >( type ) ) { 309 // must always construct VLAs with an initializer, since this is an error in C 310 if ( at->isVarLen && objDecl->init ) return true; 311 type = at->base; 312 } 313 return isManaged( type ); 314 } 315 316 void ManagedTypes_new::handleDWT( const ast::DeclWithType * dwt ) { 317 // if this function is a user-defined constructor or destructor, mark down the type as "managed" 318 if ( ! dwt->linkage.is_overrideable && CodeGen::isCtorDtor( dwt->name ) ) { 319 auto & params = GenPoly::getFunctionType( dwt->get_type())->params; 320 assert( ! params.empty() ); 321 // Type * type = InitTweak::getPointerBase( params.front() ); 322 // assert( type ); 323 managedTypes.insert( Mangle::mangle( params.front(), {Mangle::NoOverrideable | Mangle::NoGenericParams | Mangle::Type} ) ); 324 } 325 } 326 327 void ManagedTypes_new::handleStruct( const ast::StructDecl * aggregateDecl ) { 328 // don't construct members, but need to take note if there is a managed member, 329 // because that means that this type is also managed 330 for ( auto & member : aggregateDecl->members ) { 331 if ( auto field = member.as<ast::ObjectDecl>() ) { 332 if ( isManaged( field ) ) { 333 // generic parameters should not play a role in determining whether a generic type is constructed - construct all generic types, so that 334 // polymorphic constructors make generic types managed types 335 ast::StructInstType inst( aggregateDecl ); 336 managedTypes.insert( Mangle::mangle( &inst, {Mangle::NoOverrideable | Mangle::NoGenericParams | Mangle::Type} ) ); 337 break; 338 } 339 } 340 } 341 } 342 343 void ManagedTypes_new::beginScope() { managedTypes.beginScope(); } 344 void ManagedTypes_new::endScope() { managedTypes.endScope(); } 276 345 277 346 ImplicitCtorDtorStmt * genCtorDtor( const std::string & fname, ObjectDecl * objDecl, Expression * arg ) { … … 370 439 // constructable object 371 440 InitExpander_new srcParam{ objDecl->init }, nullParam{ (const ast::Init *)nullptr }; 441 ast::ptr< ast::Expr > dstParam = new ast::VariableExpr(loc, objDecl); 372 442 373 443 ast::ptr< ast::Stmt > ctor = SymTab::genImplicitCall( 374 srcParam, new ast::VariableExpr{ loc, objDecl }, loc, "?{}", objDecl );444 srcParam, dstParam, loc, "?{}", objDecl ); 375 445 ast::ptr< ast::Stmt > dtor = SymTab::genImplicitCall( 376 nullParam, new ast::VariableExpr{ loc, objDecl }, loc, "^?{}", objDecl,446 nullParam, dstParam, loc, "^?{}", objDecl, 377 447 SymTab::LoopBackward ); 378 448 -
src/InitTweak/GenInit.h
r3febb2d r16ba4a6f 52 52 GenPoly::ScopedSet< std::string > managedTypes; 53 53 }; 54 55 class ManagedTypes_new { 56 public: 57 bool isManaged( const ast::ObjectDecl * objDecl ) const ; // determine if object is managed 58 bool isManaged( const ast::Type * type ) const; // determine if type is managed 59 60 void handleDWT( const ast::DeclWithType * dwt ); // add type to managed if ctor/dtor 61 void handleStruct( const ast::StructDecl * aggregateDecl ); // add type to managed if child is managed 62 63 void beginScope(); 64 void endScope(); 65 private: 66 GenPoly::ScopedSet< std::string > managedTypes; 67 }; 54 68 } // namespace 55 69 -
src/InitTweak/InitTweak.cc
r3febb2d r16ba4a6f 87 87 }; 88 88 89 struct HasDesignations_new : public ast::WithShortCircuiting { 90 bool result = false; 91 92 void previsit( const ast::Node * ) { 93 // short circuit if we already know there are designations 94 if ( result ) visit_children = false; 95 } 96 97 void previsit( const ast::Designation * des ) { 98 // short circuit if we already know there are designations 99 if ( result ) visit_children = false; 100 else if ( ! des->designators.empty() ) { 101 result = true; 102 visit_children = false; 103 } 104 } 105 }; 106 107 struct InitDepthChecker_new : public ast::WithGuards { 108 bool result = true; 109 const ast::Type * type; 110 int curDepth = 0, maxDepth = 0; 111 InitDepthChecker_new( const ast::Type * type ) : type( type ) { 112 const ast::Type * t = type; 113 while ( auto at = dynamic_cast< const ast::ArrayType * >( t ) ) { 114 maxDepth++; 115 t = at->base; 116 } 117 maxDepth++; 118 } 119 void previsit( ListInit * ) { 120 curDepth++; 121 GuardAction( [this]() { curDepth--; } ); 122 if ( curDepth > maxDepth ) result = false; 123 } 124 }; 125 89 126 struct InitFlattener_old : public WithShortCircuiting { 90 127 void previsit( SingleInit * singleInit ) { … … 122 159 maybeAccept( objDecl->init, checker ); 123 160 return checker.pass.depthOkay; 161 } 162 163 bool isDesignated( const ast::Init * init ) { 164 ast::Pass<HasDesignations_new> finder; 165 maybe_accept( init, finder ); 166 return finder.core.result; 167 } 168 169 bool checkInitDepth( const ast::ObjectDecl * objDecl ) { 170 ast::Pass<InitDepthChecker_new> checker( objDecl->type ); 171 maybe_accept( objDecl->init.get(), checker ); 172 return checker.core.result; 124 173 } 125 174 … … 358 407 if ( auto listInit = dynamic_cast< const ast::ListInit * >( init ) ) { 359 408 for ( const ast::Init * init : *listInit ) { 360 buildCallExpr( callExpr, index, dimension, init, out );409 buildCallExpr( shallowCopy(callExpr), index, dimension, init, out ); 361 410 } 362 411 } else { 363 buildCallExpr( callExpr, index, dimension, init, out );412 buildCallExpr( shallowCopy(callExpr), index, dimension, init, out ); 364 413 } 365 414 } else { … … 1027 1076 }; 1028 1077 1078 struct ConstExprChecker_new : public ast::WithShortCircuiting { 1079 // most expressions are not const expr 1080 void previsit( const ast::Expr * ) { result = false; visit_children = false; } 1081 1082 void previsit( const ast::AddressExpr *addressExpr ) { 1083 visit_children = false; 1084 const ast::Expr * arg = addressExpr->arg; 1085 1086 // address of a variable or member expression is constexpr 1087 if ( ! dynamic_cast< const ast::NameExpr * >( arg ) 1088 && ! dynamic_cast< const ast::VariableExpr * >( arg ) 1089 && ! dynamic_cast< const ast::MemberExpr * >( arg ) 1090 && ! dynamic_cast< const ast::UntypedMemberExpr * >( arg ) ) result = false; 1091 } 1092 1093 // these expressions may be const expr, depending on their children 1094 void previsit( const ast::SizeofExpr * ) {} 1095 void previsit( const ast::AlignofExpr * ) {} 1096 void previsit( const ast::UntypedOffsetofExpr * ) {} 1097 void previsit( const ast::OffsetofExpr * ) {} 1098 void previsit( const ast::OffsetPackExpr * ) {} 1099 void previsit( const ast::CommaExpr * ) {} 1100 void previsit( const ast::LogicalExpr * ) {} 1101 void previsit( const ast::ConditionalExpr * ) {} 1102 void previsit( const ast::CastExpr * ) {} 1103 void previsit( const ast::ConstantExpr * ) {} 1104 1105 void previsit( const ast::VariableExpr * varExpr ) { 1106 visit_children = false; 1107 1108 if ( auto inst = varExpr->result.as<ast::EnumInstType>() ) { 1109 long long int value; 1110 if ( inst->base->valueOf( varExpr->var, value ) ) { 1111 // enumerators are const expr 1112 return; 1113 } 1114 } 1115 result = false; 1116 } 1117 1118 bool result = true; 1119 }; 1120 1029 1121 bool isConstExpr( Expression * expr ) { 1030 1122 if ( expr ) { … … 1046 1138 } 1047 1139 1140 bool isConstExpr( const ast::Expr * expr ) { 1141 if ( expr ) { 1142 ast::Pass<ConstExprChecker_new> checker; 1143 expr->accept( checker ); 1144 return checker.core.result; 1145 } 1146 return true; 1147 } 1148 1149 bool isConstExpr( const ast::Init * init ) { 1150 if ( init ) { 1151 ast::Pass<ConstExprChecker_new> checker; 1152 init->accept( checker ); 1153 return checker.core.result; 1154 } // if 1155 // for all intents and purposes, no initializer means const expr 1156 return true; 1157 } 1158 1048 1159 bool isConstructor( const std::string & str ) { return str == "?{}"; } 1049 1160 bool isDestructor( const std::string & str ) { return str == "^?{}"; } -
src/InitTweak/InitTweak.h
r3febb2d r16ba4a6f 59 59 /// True if the Initializer contains designations 60 60 bool isDesignated( Initializer * init ); 61 bool isDesignated( const ast::Init * init ); 61 62 62 63 /// True if the ObjectDecl's Initializer nesting level is not deeper than the depth of its 63 64 /// type, where the depth of its type is the number of nested ArrayTypes + 1 64 65 bool checkInitDepth( ObjectDecl * objDecl ); 66 bool checkInitDepth( const ast::ObjectDecl * objDecl ); 65 67 66 68 /// returns the declaration of the function called by the expr (must be ApplicationExpr or UntypedExpr) … … 107 109 bool isConstExpr( Expression * expr ); 108 110 bool isConstExpr( Initializer * init ); 111 112 bool isConstExpr( const ast::Expr * expr ); 113 bool isConstExpr( const ast::Init * init ); 109 114 110 115 /// Modifies objDecl to have:
Note:
See TracChangeset
for help on using the changeset viewer.