Changeset 6e50a6b for src/SymTab


Ignore:
Timestamp:
Jun 18, 2021, 12:20:59 PM (3 years ago)
Author:
Michael Brooks <mlbrooks@…>
Branches:
ADT, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
c7d8696a
Parents:
dcbfcbc
Message:

Implementing language-provided syntax for (array) dimensions.

Former z(i) and Z(N) macros are eliminated.

Location:
src/SymTab
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • src/SymTab/Indexer.cc

    rdcbfcbc r6e50a6b  
    7474        }
    7575
    76         Indexer::Indexer()
     76        Indexer::Indexer( bool trackIdentifiers )
    7777        : idTable(), typeTable(), structTable(), enumTable(), unionTable(), traitTable(),
    78           prevScope(), scope( 0 ), repScope( 0 ) { ++* stats().count; }
     78          prevScope(), scope( 0 ), repScope( 0 ), trackIdentifiers( trackIdentifiers ) { ++* stats().count; }
    7979
    8080        Indexer::~Indexer() {
     
    110110
    111111        void Indexer::lookupId( const std::string & id, std::list< IdData > &out ) const {
     112                assert( trackIdentifiers );
     113
    112114                ++* stats().lookup_calls;
    113115                if ( ! idTable ) return;
     
    434436                        const Declaration * deleteStmt ) {
    435437                ++* stats().add_calls;
     438                if ( ! trackIdentifiers ) return;
    436439                const std::string &name = decl->name;
    437440                if ( name == "" ) return;
  • src/SymTab/Indexer.h

    rdcbfcbc r6e50a6b  
    3131        class Indexer : public std::enable_shared_from_this<SymTab::Indexer> {
    3232        public:
    33                 explicit Indexer();
     33                explicit Indexer( bool trackIdentifiers = true );
    3434                virtual ~Indexer();
    3535
     
    180180                /// returns true if there exists a declaration with C linkage and the given name with a different mangled name
    181181                bool hasIncompatibleCDecl( const std::string & id, const std::string & mangleName ) const;
     182
     183            bool trackIdentifiers;
    182184        };
    183185} // namespace SymTab
  • src/SymTab/Validate.cc

    rdcbfcbc r6e50a6b  
    105105
    106106        struct FixQualifiedTypes final : public WithIndexer {
     107                FixQualifiedTypes() : WithIndexer(false) {}
    107108                Type * postmutate( QualifiedType * );
    108109        };
     
    174175        };
    175176
     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
    176187        /// Replaces array and function types in forall lists by appropriate pointer type and assigns each Object and Function declaration a unique ID.
    177188        struct ForallPointerDecay_old final {
     
    260271                void previsit( StructInstType * inst );
    261272                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 );
    262292        };
    263293
     
    307337                PassVisitor<EnumAndPointerDecay_old> epc;
    308338                PassVisitor<LinkReferenceToTypes_old> lrt( nullptr );
     339                PassVisitor<ResolveEnumInitializers> rei( nullptr );
    309340                PassVisitor<ForallPointerDecay_old> fpd;
    310341                PassVisitor<CompoundLiteral> compoundliteral;
     
    326357                        Stats::Heap::newPass("validate-B");
    327358                        Stats::Time::BlockGuard guard("validate-B");
    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                         });
     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 );
    340363                }
    341364                {
    342365                        Stats::Heap::newPass("validate-C");
    343366                        Stats::Time::BlockGuard guard("validate-C");
    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
     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                        });
    347382                }
    348383                {
     
    644679        }
    645680
    646         LinkReferenceToTypes_old::LinkReferenceToTypes_old( const Indexer * other_indexer ) {
     681        LinkReferenceToTypes_old::LinkReferenceToTypes_old( const Indexer * other_indexer ) : WithIndexer( false ) {
    647682                if ( other_indexer ) {
    648683                        local_indexer = other_indexer;
     
    664699        }
    665700
    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 
    674701        void LinkReferenceToTypes_old::postvisit( StructInstType * structInst ) {
    675702                const StructDecl * st = local_indexer->lookupStruct( structInst->name );
     
    682709                        forwardStructs[ structInst->name ].push_back( structInst );
    683710                } // if
    684                 checkGenericParameters( structInst );
    685711        }
    686712
     
    695721                        forwardUnions[ unionInst->name ].push_back( unionInst );
    696722                } // if
    697                 checkGenericParameters( unionInst );
    698723        }
    699724
     
    807832                                forwardEnums.erase( fwds );
    808833                        } // 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                         }
    818834                } // if
    819835        }
     
    878894                                typeInst->set_isFtype( typeDecl->kind == TypeDecl::Ftype );
    879895                        } // 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                        }
    880917                } // if
    881918        }
     
    12231260        }
    12241261
     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
    12251280        template< typename Aggr >
    12261281        void validateGeneric( Aggr * inst ) {
     
    12391294                        TypeSubstitution sub;
    12401295                        auto paramIter = params->begin();
    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() ) {
     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 {
    12461304                                        Type * defaultType = (* paramIter)->get_init();
    12471305                                        if ( defaultType ) {
    12481306                                                args.push_back( new TypeExpr( defaultType->clone() ) );
    12491307                                                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 " );
    12501311                                        }
    12511312                                }
     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: " );
    12521324                        }
    12531325
    12541326                        sub.apply( inst );
    1255                         if ( args.size() < params->size() ) SemanticError( inst, "Too few type arguments in generic type " );
    12561327                        if ( args.size() > params->size() ) SemanticError( inst, "Too many type arguments in generic type " );
    12571328                }
     
    12641335        void ValidateGenericParameters::previsit( UnionInstType * inst ) {
    12651336                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;
    12661437        }
    12671438
Note: See TracChangeset for help on using the changeset viewer.