Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/SymTab/Validate.cc

    r6e50a6b r798a8b3  
    105105
    106106        struct FixQualifiedTypes final : public WithIndexer {
    107                 FixQualifiedTypes() : WithIndexer(false) {}
    108107                Type * postmutate( QualifiedType * );
    109108        };
     
    175174        };
    176175
    177         /// Does early resolution on the expressions that give enumeration constants their values
    178         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 
    187176        /// Replaces array and function types in forall lists by appropriate pointer type and assigns each Object and Function declaration a unique ID.
    188177        struct ForallPointerDecay_old final {
     
    271260                void previsit( StructInstType * inst );
    272261                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(-) out
    278         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 Type
    283                 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 );
    292262        };
    293263
     
    337307                PassVisitor<EnumAndPointerDecay_old> epc;
    338308                PassVisitor<LinkReferenceToTypes_old> lrt( nullptr );
    339                 PassVisitor<ResolveEnumInitializers> rei( nullptr );
    340309                PassVisitor<ForallPointerDecay_old> fpd;
    341310                PassVisitor<CompoundLiteral> compoundliteral;
     
    357326                        Stats::Heap::newPass("validate-B");
    358327                        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                        });
    363340                }
    364341                {
    365342                        Stats::Heap::newPass("validate-C");
    366343                        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
    382347                }
    383348                {
     
    679644        }
    680645
    681         LinkReferenceToTypes_old::LinkReferenceToTypes_old( const Indexer * other_indexer ) : WithIndexer( false ) {
     646        LinkReferenceToTypes_old::LinkReferenceToTypes_old( const Indexer * other_indexer ) {
    682647                if ( other_indexer ) {
    683648                        local_indexer = other_indexer;
     
    699664        }
    700665
     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
    701674        void LinkReferenceToTypes_old::postvisit( StructInstType * structInst ) {
    702675                const StructDecl * st = local_indexer->lookupStruct( structInst->name );
     
    709682                        forwardStructs[ structInst->name ].push_back( structInst );
    710683                } // if
     684                checkGenericParameters( structInst );
    711685        }
    712686
     
    721695                        forwardUnions[ unionInst->name ].push_back( unionInst );
    722696                } // if
     697                checkGenericParameters( unionInst );
    723698        }
    724699
     
    832807                                forwardEnums.erase( fwds );
    833808                        } // 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                        }
    834818                } // if
    835819        }
     
    894878                                typeInst->set_isFtype( typeDecl->kind == TypeDecl::Ftype );
    895879                        } // if
    896                 } // if
    897         }
    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                 } // if
    905         }
    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                         }
    917880                } // if
    918881        }
     
    12601223        }
    12611224
    1262         // Test for special name on a generic parameter.  Special treatment for the
    1263         // special name is a bootstrapping hack.  In most cases, the worlds of T's
    1264         // and of N's don't overlap (normal treamtemt).  The foundations in
    1265         // array.hfa use tagging for both types and dimensions.  Tagging treats
    1266         // its subject parameter even more opaquely than T&, which assumes it is
    1267         // possible to have a pointer/reference to such an object.  Tagging only
    1268         // seeks to identify the type-system resident at compile time.  Both N's
    1269         // and T's can make tags.  The tag definition uses the special name, which
    1270         // is treated as "an N or a T."  This feature is not inteded to be used
    1271         // 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 __..._generic
    1274                 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 
    12801225        template< typename Aggr >
    12811226        void validateGeneric( Aggr * inst ) {
     
    12941239                        TypeSubstitution sub;
    12951240                        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() ) {
    13041246                                        Type * defaultType = (* paramIter)->get_init();
    13051247                                        if ( defaultType ) {
    13061248                                                args.push_back( new TypeExpr( defaultType->clone() ) );
    13071249                                                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 " );
    13111250                                        }
    13121251                                }
    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: " );
    13241252                        }
    13251253
    13261254                        sub.apply( inst );
     1255                        if ( args.size() < params->size() ) SemanticError( inst, "Too few type arguments in generic type " );
    13271256                        if ( args.size() > params->size() ) SemanticError( inst, "Too many type arguments in generic type " );
    13281257                }
     
    13351264        void ValidateGenericParameters::previsit( UnionInstType * inst ) {
    13361265                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 == true
    1359         // array( float, [[currentExpr]] - 1 )  has  visitingChildOfSUIT == false
    1360         // size_t x =    [[currentExpr]]        has  visitingChildOfSUIT == false
    1361         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 wrapper
    1416                         // But avoid ArrayType-Sizeof
    1417                         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 computation
    1421                         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 type
    1428                         if (! dynamic_cast< TypeExpr * >( e ) ) {
    1429                                 // e is a value expression
    1430                                 // but not a DimensionExpr, which has a distinct postmutate
    1431                                 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;
    14371266        }
    14381267
Note: See TracChangeset for help on using the changeset viewer.