Changes in src/SymTab/Validate.cc [6e50a6b:798a8b3]
- File:
-
- 1 edited
-
src/SymTab/Validate.cc (modified) (14 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/SymTab/Validate.cc
r6e50a6b r798a8b3 105 105 106 106 struct FixQualifiedTypes final : public WithIndexer { 107 FixQualifiedTypes() : WithIndexer(false) {}108 107 Type * postmutate( QualifiedType * ); 109 108 }; … … 175 174 }; 176 175 177 /// Does early resolution on the expressions that give enumeration constants their values178 struct ResolveEnumInitializers final : public WithIndexer, public WithGuards, public WithVisitorRef<ResolveEnumInitializers>, public WithShortCircuiting {179 ResolveEnumInitializers( const Indexer * indexer );180 void postvisit( EnumDecl * enumDecl );181 182 private:183 const Indexer * local_indexer;184 185 };186 187 176 /// Replaces array and function types in forall lists by appropriate pointer type and assigns each Object and Function declaration a unique ID. 188 177 struct ForallPointerDecay_old final { … … 271 260 void previsit( StructInstType * inst ); 272 261 void previsit( UnionInstType * inst ); 273 };274 275 /// desugar declarations and uses of dimension paramaters like [N],276 /// from type-system managed values, to tunnneling via ordinary types,277 /// as char[-] in and sizeof(-) out278 struct TranslateDimensionGenericParameters : public WithIndexer, public WithGuards {279 static void translateDimensions( std::list< Declaration * > &translationUnit );280 TranslateDimensionGenericParameters();281 282 bool nextVisitedNodeIsChildOfSUIT = false; // SUIT = Struct or Union -Inst Type283 bool visitingChildOfSUIT = false;284 void changeState_ChildOfSUIT( bool newVal );285 void premutate( StructInstType * sit );286 void premutate( UnionInstType * uit );287 void premutate( BaseSyntaxNode * node );288 289 TypeDecl * postmutate( TypeDecl * td );290 Expression * postmutate( DimensionExpr * de );291 Expression * postmutate( Expression * e );292 262 }; 293 263 … … 337 307 PassVisitor<EnumAndPointerDecay_old> epc; 338 308 PassVisitor<LinkReferenceToTypes_old> lrt( nullptr ); 339 PassVisitor<ResolveEnumInitializers> rei( nullptr );340 309 PassVisitor<ForallPointerDecay_old> fpd; 341 310 PassVisitor<CompoundLiteral> compoundliteral; … … 357 326 Stats::Heap::newPass("validate-B"); 358 327 Stats::Time::BlockGuard guard("validate-B"); 359 acceptAll( translationUnit, lrt ); // must happen before autogen, because sized flag needs to propagate to generated functions 360 mutateAll( translationUnit, fixQual ); // must happen after LinkReferenceToTypes_old, because aggregate members are accessed 361 HoistStruct::hoistStruct( translationUnit ); 362 EliminateTypedef::eliminateTypedef( translationUnit ); 328 Stats::Time::TimeBlock("Link Reference To Types", [&]() { 329 acceptAll( translationUnit, lrt ); // must happen before autogen, because sized flag needs to propagate to generated functions 330 }); 331 Stats::Time::TimeBlock("Fix Qualified Types", [&]() { 332 mutateAll( translationUnit, fixQual ); // must happen after LinkReferenceToTypes_old, because aggregate members are accessed 333 }); 334 Stats::Time::TimeBlock("Hoist Structs", [&]() { 335 HoistStruct::hoistStruct( translationUnit ); // must happen after EliminateTypedef, so that aggregate typedefs occur in the correct order 336 }); 337 Stats::Time::TimeBlock("Eliminate Typedefs", [&]() { 338 EliminateTypedef::eliminateTypedef( translationUnit ); // 339 }); 363 340 } 364 341 { 365 342 Stats::Heap::newPass("validate-C"); 366 343 Stats::Time::BlockGuard guard("validate-C"); 367 Stats::Time::TimeBlock("Validate Generic Parameters", [&]() { 368 acceptAll( translationUnit, genericParams ); // check as early as possible - can't happen before LinkReferenceToTypes_old; observed failing when attempted before eliminateTypedef 369 }); 370 Stats::Time::TimeBlock("Translate Dimensions", [&]() { 371 TranslateDimensionGenericParameters::translateDimensions( translationUnit ); 372 }); 373 Stats::Time::TimeBlock("Resolve Enum Initializers", [&]() { 374 acceptAll( translationUnit, rei ); // must happen after translateDimensions because rei needs identifier lookup, which needs name mangling 375 }); 376 Stats::Time::TimeBlock("Check Function Returns", [&]() { 377 ReturnChecker::checkFunctionReturns( translationUnit ); 378 }); 379 Stats::Time::TimeBlock("Fix Return Statements", [&]() { 380 InitTweak::fixReturnStatements( translationUnit ); // must happen before autogen 381 }); 344 acceptAll( translationUnit, genericParams ); // check as early as possible - can't happen before LinkReferenceToTypes_old 345 ReturnChecker::checkFunctionReturns( translationUnit ); 346 InitTweak::fixReturnStatements( translationUnit ); // must happen before autogen 382 347 } 383 348 { … … 679 644 } 680 645 681 LinkReferenceToTypes_old::LinkReferenceToTypes_old( const Indexer * other_indexer ) : WithIndexer( false ){646 LinkReferenceToTypes_old::LinkReferenceToTypes_old( const Indexer * other_indexer ) { 682 647 if ( other_indexer ) { 683 648 local_indexer = other_indexer; … … 699 664 } 700 665 666 void checkGenericParameters( ReferenceToType * inst ) { 667 for ( Expression * param : inst->parameters ) { 668 if ( ! dynamic_cast< TypeExpr * >( param ) ) { 669 SemanticError( inst, "Expression parameters for generic types are currently unsupported: " ); 670 } 671 } 672 } 673 701 674 void LinkReferenceToTypes_old::postvisit( StructInstType * structInst ) { 702 675 const StructDecl * st = local_indexer->lookupStruct( structInst->name ); … … 709 682 forwardStructs[ structInst->name ].push_back( structInst ); 710 683 } // if 684 checkGenericParameters( structInst ); 711 685 } 712 686 … … 721 695 forwardUnions[ unionInst->name ].push_back( unionInst ); 722 696 } // if 697 checkGenericParameters( unionInst ); 723 698 } 724 699 … … 832 807 forwardEnums.erase( fwds ); 833 808 } // if 809 810 for ( Declaration * member : enumDecl->members ) { 811 ObjectDecl * field = strict_dynamic_cast<ObjectDecl *>( member ); 812 if ( field->init ) { 813 // need to resolve enumerator initializers early so that other passes that determine if an expression is constexpr have the appropriate information. 814 SingleInit * init = strict_dynamic_cast<SingleInit *>( field->init ); 815 ResolvExpr::findSingleExpression( init->value, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), indexer ); 816 } 817 } 834 818 } // if 835 819 } … … 894 878 typeInst->set_isFtype( typeDecl->kind == TypeDecl::Ftype ); 895 879 } // if 896 } // if897 }898 899 ResolveEnumInitializers::ResolveEnumInitializers( const Indexer * other_indexer ) : WithIndexer( true ) {900 if ( other_indexer ) {901 local_indexer = other_indexer;902 } else {903 local_indexer = &indexer;904 } // if905 }906 907 void ResolveEnumInitializers::postvisit( EnumDecl * enumDecl ) {908 if ( enumDecl->body ) {909 for ( Declaration * member : enumDecl->members ) {910 ObjectDecl * field = strict_dynamic_cast<ObjectDecl *>( member );911 if ( field->init ) {912 // need to resolve enumerator initializers early so that other passes that determine if an expression is constexpr have the appropriate information.913 SingleInit * init = strict_dynamic_cast<SingleInit *>( field->init );914 ResolvExpr::findSingleExpression( init->value, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), indexer );915 }916 }917 880 } // if 918 881 } … … 1260 1223 } 1261 1224 1262 // Test for special name on a generic parameter. Special treatment for the1263 // special name is a bootstrapping hack. In most cases, the worlds of T's1264 // and of N's don't overlap (normal treamtemt). The foundations in1265 // array.hfa use tagging for both types and dimensions. Tagging treats1266 // its subject parameter even more opaquely than T&, which assumes it is1267 // possible to have a pointer/reference to such an object. Tagging only1268 // seeks to identify the type-system resident at compile time. Both N's1269 // and T's can make tags. The tag definition uses the special name, which1270 // is treated as "an N or a T." This feature is not inteded to be used1271 // outside of the definition and immediate uses of a tag.1272 static inline bool isReservedTysysIdOnlyName( const std::string & name ) {1273 // name's prefix was __CFA_tysys_id_only, before it got wrapped in __..._generic1274 int foundAt = name.find("__CFA_tysys_id_only");1275 if (foundAt == 0) return true;1276 if (foundAt == 2 && name[0] == '_' && name[1] == '_') return true;1277 return false;1278 }1279 1280 1225 template< typename Aggr > 1281 1226 void validateGeneric( Aggr * inst ) { … … 1294 1239 TypeSubstitution sub; 1295 1240 auto paramIter = params->begin(); 1296 auto argIter = args.begin(); 1297 for ( ; paramIter != params->end(); ++paramIter, ++argIter ) { 1298 if ( argIter != args.end() ) { 1299 TypeExpr * expr = dynamic_cast< TypeExpr * >( * argIter ); 1300 if ( expr ) { 1301 sub.add( (* paramIter)->get_name(), expr->get_type()->clone() ); 1302 } 1303 } else { 1241 for ( size_t i = 0; paramIter != params->end(); ++paramIter, ++i ) { 1242 if ( i < args.size() ) { 1243 TypeExpr * expr = strict_dynamic_cast< TypeExpr * >( * std::next( args.begin(), i ) ); 1244 sub.add( (* paramIter)->get_name(), expr->get_type()->clone() ); 1245 } else if ( i == args.size() ) { 1304 1246 Type * defaultType = (* paramIter)->get_init(); 1305 1247 if ( defaultType ) { 1306 1248 args.push_back( new TypeExpr( defaultType->clone() ) ); 1307 1249 sub.add( (* paramIter)->get_name(), defaultType->clone() ); 1308 argIter = std::prev(args.end());1309 } else {1310 SemanticError( inst, "Too few type arguments in generic type " );1311 1250 } 1312 1251 } 1313 assert( argIter != args.end() );1314 bool typeParamDeclared = (*paramIter)->kind != TypeDecl::Kind::Dimension;1315 bool typeArgGiven;1316 if ( isReservedTysysIdOnlyName( (*paramIter)->name ) ) {1317 // coerce a match when declaration is reserved name, which means "either"1318 typeArgGiven = typeParamDeclared;1319 } else {1320 typeArgGiven = dynamic_cast< TypeExpr * >( * argIter );1321 }1322 if ( ! typeParamDeclared && typeArgGiven ) SemanticError( inst, "Type argument given for value parameter: " );1323 if ( typeParamDeclared && ! typeArgGiven ) SemanticError( inst, "Expression argument given for type parameter: " );1324 1252 } 1325 1253 1326 1254 sub.apply( inst ); 1255 if ( args.size() < params->size() ) SemanticError( inst, "Too few type arguments in generic type " ); 1327 1256 if ( args.size() > params->size() ) SemanticError( inst, "Too many type arguments in generic type " ); 1328 1257 } … … 1335 1264 void ValidateGenericParameters::previsit( UnionInstType * inst ) { 1336 1265 validateGeneric( inst ); 1337 }1338 1339 void TranslateDimensionGenericParameters::translateDimensions( std::list< Declaration * > &translationUnit ) {1340 PassVisitor<TranslateDimensionGenericParameters> translator;1341 mutateAll( translationUnit, translator );1342 }1343 1344 TranslateDimensionGenericParameters::TranslateDimensionGenericParameters() : WithIndexer( false ) {}1345 1346 // Declaration of type variable: forall( [N] ) -> forall( N & | sized( N ) )1347 TypeDecl * TranslateDimensionGenericParameters::postmutate( TypeDecl * td ) {1348 if ( td->kind == TypeDecl::Dimension ) {1349 td->kind = TypeDecl::Dtype;1350 if ( ! isReservedTysysIdOnlyName( td->name ) ) {1351 td->sized = true;1352 }1353 }1354 return td;1355 }1356 1357 // Situational awareness:1358 // array( float, [[currentExpr]] ) has visitingChildOfSUIT == true1359 // array( float, [[currentExpr]] - 1 ) has visitingChildOfSUIT == false1360 // size_t x = [[currentExpr]] has visitingChildOfSUIT == false1361 void TranslateDimensionGenericParameters::changeState_ChildOfSUIT( bool newVal ) {1362 GuardValue( nextVisitedNodeIsChildOfSUIT );1363 GuardValue( visitingChildOfSUIT );1364 visitingChildOfSUIT = nextVisitedNodeIsChildOfSUIT;1365 nextVisitedNodeIsChildOfSUIT = newVal;1366 }1367 void TranslateDimensionGenericParameters::premutate( StructInstType * sit ) {1368 (void) sit;1369 changeState_ChildOfSUIT(true);1370 }1371 void TranslateDimensionGenericParameters::premutate( UnionInstType * uit ) {1372 (void) uit;1373 changeState_ChildOfSUIT(true);1374 }1375 void TranslateDimensionGenericParameters::premutate( BaseSyntaxNode * node ) {1376 (void) node;1377 changeState_ChildOfSUIT(false);1378 }1379 1380 // Passing values as dimension arguments: array( float, 7 ) -> array( float, char[ 7 ] )1381 // Consuming dimension parameters: size_t x = N - 1 ; -> size_t x = sizeof(N) - 1 ;1382 // Intertwined reality: array( float, N ) -> array( float, N )1383 // array( float, N - 1 ) -> array( float, char[ sizeof(N) - 1 ] )1384 // Intertwined case 1 is not just an optimization.1385 // Avoiding char[sizeof(-)] is necessary to enable the call of f to bind the value of N, in:1386 // forall([N]) void f( array(float, N) & );1387 // array(float, 7) a;1388 // f(a);1389 1390 Expression * TranslateDimensionGenericParameters::postmutate( DimensionExpr * de ) {1391 // Expression de is an occurrence of N in LHS of above examples.1392 // Look up the name that de references.1393 // If we are in a struct body, then this reference can be to an entry of the stuct's forall list.1394 // Whether or not we are in a struct body, this reference can be to an entry of a containing function's forall list.1395 // If we are in a struct body, then the stuct's forall declarations are innermost (functions don't occur in structs).1396 // Thus, a potential struct's declaration is highest priority.1397 // A struct's forall declarations are already renamed with _generic_ suffix. Try that name variant first.1398 1399 std::string useName = "__" + de->name + "_generic_";1400 TypeDecl * namedParamDecl = const_cast<TypeDecl *>( strict_dynamic_cast<const TypeDecl *, nullptr >( indexer.lookupType( useName ) ) );1401 1402 if ( ! namedParamDecl ) {1403 useName = de->name;1404 namedParamDecl = const_cast<TypeDecl *>( strict_dynamic_cast<const TypeDecl *, nullptr >( indexer.lookupType( useName ) ) );1405 }1406 1407 // Expect to find it always. A misspelled name would have been parsed as an identifier.1408 assert( namedParamDecl && "Type-system-managed value name not found in symbol table" );1409 1410 delete de;1411 1412 TypeInstType * refToDecl = new TypeInstType( 0, useName, namedParamDecl );1413 1414 if ( visitingChildOfSUIT ) {1415 // As in postmutate( Expression * ), topmost expression needs a TypeExpr wrapper1416 // But avoid ArrayType-Sizeof1417 return new TypeExpr( refToDecl );1418 } else {1419 // the N occurrence is being used directly as a runtime value,1420 // if we are in a type instantiation, then the N is within a bigger value computation1421 return new SizeofExpr( refToDecl );1422 }1423 }1424 1425 Expression * TranslateDimensionGenericParameters::postmutate( Expression * e ) {1426 if ( visitingChildOfSUIT ) {1427 // e is an expression used as an argument to instantiate a type1428 if (! dynamic_cast< TypeExpr * >( e ) ) {1429 // e is a value expression1430 // but not a DimensionExpr, which has a distinct postmutate1431 Type * typeExprContent = new ArrayType( 0, new BasicType( 0, BasicType::Char ), e, true, false );1432 TypeExpr * result = new TypeExpr( typeExprContent );1433 return result;1434 }1435 }1436 return e;1437 1266 } 1438 1267
Note:
See TracChangeset
for help on using the changeset viewer.