Changeset fc134a48


Ignore:
Timestamp:
Jun 2, 2022, 4:12:53 AM (4 months ago)
Author:
JiadaL <j82liang@…>
Branches:
master, pthread-emulation, qualifiedEnum
Children:
1df492a, 90a8125, e5d9274
Parents:
01f6a06
Message:

Implement the struct enum

Files:
2 added
12 edited

Legend:

Unmodified
Added
Removed
  • src/CodeTools/ResolvProtoDump.cc

    r01f6a06 rfc134a48  
    304304
    305305                        // replace enums with int
    306                         void previsit( EnumInstType* ) { ss << (int)BasicType::SignedInt; }
     306                        void previsit( EnumInstType* ) {
     307                                // TODO: add the meaningful representation of typed int
     308                                ss << (int)BasicType::SignedInt;
     309                        }
    307310
    308311                        void previsit( TypeInstType* vt ) {
  • src/Common/ResolvProtoDump.cpp

    r01f6a06 rfc134a48  
    227227        }
    228228
    229         void previsit( const ast::EnumInstType * ) {
     229        void previsit( const ast::EnumInstType * enumInst) {
     230                // TODO: Add the meaningful text representation of typed enum
    230231                ss << (int)ast::BasicType::SignedInt;
    231232        }
  • src/InitTweak/GenInit.cc

    r01f6a06 rfc134a48  
    368368
    369369        struct ReturnFixer_New final :
    370                         public ast::WithStmtsToAdd<>, ast::WithGuards {
     370                        public ast::WithStmtsToAdd<>, ast::WithGuards, ast::WithShortCircuiting {
    371371                void previsit( const ast::FunctionDecl * decl );
    372372                const ast::ReturnStmt * previsit( const ast::ReturnStmt * stmt );
     
    376376
    377377        void ReturnFixer_New::previsit( const ast::FunctionDecl * decl ) {
     378                if (decl->linkage == ast::Linkage::Intrinsic) visit_children = false;
    378379                GuardValue( funcDecl ) = decl;
    379380        }
  • src/ResolvExpr/CandidateFinder.cpp

    r01f6a06 rfc134a48  
    899899
    900900                                                if (argType.as<ast::PointerType>()) funcFinder.otypeKeys.insert(Mangle::Encoding::pointer);
     901                                                else if (const ast::EnumInstType * enumInst = argType.as<ast::EnumInstType>()) {
     902                                                        const ast::EnumDecl * enumDecl = enumInst->base;
     903                                                        if ( const ast::Type* enumType = enumDecl->base ) {
     904                                                                // instance of enum (T) is a instance of type (T)
     905                                                                funcFinder.otypeKeys.insert(Mangle::mangle(enumType, Mangle::NoGenericParams | Mangle::Type));
     906                                                        } else {
     907                                                                // instance of an untyped enum is techically int
     908                                                                funcFinder.otypeKeys.insert(Mangle::mangle(enumDecl, Mangle::NoGenericParams | Mangle::Type));
     909                                                        }
     910                                                }
    901911                                                else funcFinder.otypeKeys.insert(Mangle::mangle(argType, Mangle::NoGenericParams | Mangle::Type));
    902912                                        }
     
    918928
    919929                        // find function operators
    920                         ast::ptr< ast::Expr > opExpr = new ast::NameExpr{ untypedExpr->location, "?()" };
     930                        ast::ptr< ast::Expr > opExpr = new ast::NameExpr{ untypedExpr->location, "?()" }; // ??? why not ?{}
    921931                        CandidateFinder opFinder( context, tenv );
    922932                        // okay if there aren't any function operations
  • src/ResolvExpr/CommonType.cc

    r01f6a06 rfc134a48  
    497497                                result = new BasicType( basicType->tq | otherBasic->tq, newType );
    498498                        } // if
    499                 } else if ( dynamic_cast< EnumInstType * > ( type2 ) || dynamic_cast< ZeroType * >( type2 ) || dynamic_cast< OneType * >( type2 ) ) {
     499                } else if ( dynamic_cast< ZeroType * >( type2 ) || dynamic_cast< OneType * >( type2 ) ) {
    500500                        // use signed int in lieu of the enum/zero/one type
    501501                        BasicType::Kind newType = commonTypes[ basicType->get_kind() ][ BasicType::SignedInt ];
     
    503503                                result = new BasicType( basicType->tq | type2->tq, newType );
    504504                        } // if
    505                 } // if
     505                } else if ( const EnumInstType * enumInst = dynamic_cast< const EnumInstType * > ( type2 ) ) {
     506                        const EnumDecl* enumDecl = enumInst->baseEnum;
     507                        if ( const Type* baseType = enumDecl->base ) {
     508                                result = baseType->clone();
     509                        } else {
     510                                BasicType::Kind newType = commonTypes[ basicType->get_kind() ][ BasicType::SignedInt ];
     511                                if ( ( ( newType == basicType->get_kind() && basicType->tq >= type2->tq ) || widenFirst ) && ( ( newType != basicType->get_kind() && basicType->tq <= type2->tq ) || widenSecond ) ) {
     512                                        result = new BasicType( basicType->tq | type2->tq, newType );
     513                                } // if
     514                        }
     515                }
    506516        }
    507517
     
    691701                                }
    692702                        } else if (
    693                                 dynamic_cast< const ast::EnumInstType * >( type2 )
    694                                 || dynamic_cast< const ast::ZeroType * >( type2 )
     703                                dynamic_cast< const ast::ZeroType * >( type2 )
    695704                                || dynamic_cast< const ast::OneType * >( type2 )
    696705                        ) {
     
    705714                                        result = new ast::BasicType{ kind, basic->qualifiers | type2->qualifiers };
    706715                                }
     716                        } else if ( const ast::EnumInstType * enumInst = dynamic_cast< const ast::EnumInstType * >( type2 ) ) {
     717                                #warning remove casts when `commonTypes` moved to new AST
     718                                const ast::EnumDecl* enumDecl = enumInst->base;
     719                                if ( enumDecl->base ) {
     720                                        result = enumDecl->base.get();
     721                                } else {
     722                                        ast::BasicType::Kind kind = (ast::BasicType::Kind)(int)commonTypes[ (BasicType::Kind)(int)basic->kind ][ (BasicType::Kind)(int)ast::BasicType::SignedInt ];
     723                                        if (
     724                                                ( ( kind == basic->kind && basic->qualifiers >= type2->qualifiers )
     725                                                        || widen.first )
     726                                                && ( ( kind != basic->kind && basic->qualifiers <= type2->qualifiers )
     727                                                        || widen.second )
     728                                        ) {
     729                                                result = new ast::BasicType{ kind, basic->qualifiers | type2->qualifiers };
     730                                        }
     731                                }
    707732                        }
    708733                }
     
    723748                        result = voidPtr;
    724749                        add_qualifiers( result, oPtr->qualifiers );
     750                }
     751
     752                // For a typed enum, we want to unify type1 with the base type of the enum
     753                bool tryResolveWithTypedEnum( const ast::Type * type1 ) {
     754                        if (auto enumInst = dynamic_cast<const ast::EnumInstType *> (type2) ) {
     755                                ast::AssertionSet have, need; // unused
     756                                ast::OpenVarSet newOpen{ open };
     757                                if (enumInst->base->base
     758                                && unifyExact(type1, enumInst->base->base, tenv, need, have, newOpen, widen, symtab)) {
     759                                        result = type1;
     760                                        return true;
     761                                }
     762                        }
     763                        return false;
    725764                }
    726765
     
    768807                                result = pointer;
    769808                                add_qualifiers( result, type2->qualifiers );
    770                         }
    771                 }
    772 
    773                 void postvisit( const ast::ArrayType * ) {}
     809                        } else {
     810                                tryResolveWithTypedEnum( pointer );
     811                        }
     812                }
     813
     814                void postvisit( const ast::ArrayType * arr ) {
     815                        // xxx - does it make sense?
     816                        tryResolveWithTypedEnum( arr );
     817                }
    774818
    775819                void postvisit( const ast::ReferenceType * ref ) {
     
    810854                                result = ref;
    811855                                add_qualifiers( result, type2->qualifiers );
    812                         }
    813                 }
    814 
    815                 void postvisit( const ast::FunctionType * ) {}
    816 
    817                 void postvisit( const ast::StructInstType * ) {}
    818 
    819                 void postvisit( const ast::UnionInstType * ) {}
     856                        } else {
     857                                // xxx - does unifying a ref with typed enumInst makes sense?
     858                                if (!dynamic_cast<const ast::EnumInstType *>(type2))
     859                                        result = commonType( type2, ref, widen, symtab, tenv, open );
     860                        }
     861                }
     862
     863                void postvisit( const ast::FunctionType * func) {
     864                        tryResolveWithTypedEnum( func );
     865                }
     866
     867                void postvisit( const ast::StructInstType * inst ) {
     868                        tryResolveWithTypedEnum( inst );
     869                }
     870
     871                void postvisit( const ast::UnionInstType * inst ) {
     872                        tryResolveWithTypedEnum( inst );
     873                }
    820874
    821875                void postvisit( const ast::EnumInstType * enumInst ) {
    822                         if (
    823                                 dynamic_cast< const ast::BasicType * >( type2 )
    824                                 || dynamic_cast< const ast::ZeroType * >( type2 )
    825                                 || dynamic_cast< const ast::OneType * >( type2 )
    826                         ) {
    827                                 // reuse BasicType/EnumInstType common type by swapping
     876                        // reuse BasicType/EnumInstType common type by swapping
     877                        // xxx - is this already handled by unify?
     878                        if (!dynamic_cast<const ast::EnumInstType *>(type2))
    828879                                result = commonType( type2, enumInst, widen, symtab, tenv, open );
    829                         }
    830880                }
    831881
     
    850900                                                result = type2;
    851901                                                reset_qualifiers( result, q1 | q2 );
     902                                        } else {
     903                                                tryResolveWithTypedEnum( t1 );
    852904                                        }
    853905                                }
     
    855907                }
    856908
    857                 void postvisit( const ast::TupleType * ) {}
     909                void postvisit( const ast::TupleType * tuple) {
     910                        tryResolveWithTypedEnum( tuple );
     911                }
    858912
    859913                void postvisit( const ast::VarArgsType * ) {}
     
    861915                void postvisit( const ast::ZeroType * zero ) {
    862916                        if ( ! widen.first ) return;
    863                         if (
    864                                 dynamic_cast< const ast::BasicType * >( type2 )
    865                                 || dynamic_cast< const ast::PointerType * >( type2 )
    866                                 || dynamic_cast< const ast::EnumInstType * >( type2 )
    867                         ) {
     917                        if ( dynamic_cast< const ast::BasicType * >( type2 )
     918                                || dynamic_cast< const ast::PointerType * >( type2 ) ) {
    868919                                if ( widen.second || zero->qualifiers <= type2->qualifiers ) {
    869920                                        result = type2;
     
    873924                                result = new ast::BasicType{
    874925                                        ast::BasicType::SignedInt, zero->qualifiers | type2->qualifiers };
     926                        } else if ( const ast::EnumInstType * enumInst = dynamic_cast< const ast::EnumInstType * >( type2 ) ) {
     927                                const ast::EnumDecl * enumDecl = enumInst->base;
     928                                if ( enumDecl->base ) {
     929                                        if ( tryResolveWithTypedEnum( zero ) )
     930                                                add_qualifiers( result, zero->qualifiers );
     931                                } else {
     932                                        if ( widen.second || zero->qualifiers <= type2->qualifiers ) {
     933                                                result = type2;
     934                                                add_qualifiers( result, zero->qualifiers );
     935                                        }
     936                                }
    875937                        }
    876938                }
     
    878940                void postvisit( const ast::OneType * one ) {
    879941                        if ( ! widen.first ) return;
    880                         if (
    881                                 dynamic_cast< const ast::BasicType * >( type2 )
    882                                 || dynamic_cast< const ast::EnumInstType * >( type2 )
    883                         ) {
     942                        if ( dynamic_cast< const ast::BasicType * >( type2 ) ) {
    884943                                if ( widen.second || one->qualifiers <= type2->qualifiers ) {
    885944                                        result = type2;
     
    889948                                result = new ast::BasicType{
    890949                                        ast::BasicType::SignedInt, one->qualifiers | type2->qualifiers };
     950                        } else if ( const ast::EnumInstType * enumInst = dynamic_cast< const ast::EnumInstType * >( type2 ) ) {
     951                                const ast::EnumDecl * enumBase = enumInst->base;
     952                                if ( enumBase->base ) {
     953                                        if ( tryResolveWithTypedEnum( one ))
     954                                                add_qualifiers( result, one->qualifiers );
     955                                } else {
     956                                        if ( widen.second || one->qualifiers <= type2->qualifiers ) {
     957                                                result = type2;
     958                                                add_qualifiers( result, one->qualifiers );
     959                                        }
     960                                }
    891961                        }
    892962                }
  • src/ResolvExpr/ConversionCost.cc

    r01f6a06 rfc134a48  
    321321        }
    322322
     323        // refactor for code resue
     324        void ConversionCost::conversionCostFromBasicToBasic(const BasicType * src, const BasicType * dest) {
     325                int tableResult = costMatrix[ src->kind ][ dest->kind ];
     326                if ( tableResult == -1 ) {
     327                        cost = Cost::unsafe;
     328                } else {
     329                        cost = Cost::zero;
     330                        cost.incSafe( tableResult );
     331                        cost.incSign( signMatrix[ src->kind ][ dest->kind ] );
     332                } // if
     333        } // ConversionCost::conversionCostFromBasicToBasic
     334
    323335        void ConversionCost::postvisit(const BasicType * basicType) {
    324336                if ( const BasicType * destAsBasic = dynamic_cast< const BasicType * >( dest ) ) {
    325                         int tableResult = costMatrix[ basicType->kind ][ destAsBasic->kind ];
    326                         if ( tableResult == -1 ) {
    327                                 cost = Cost::unsafe;
    328                         } else {
    329                                 cost = Cost::zero;
    330                                 cost.incSafe( tableResult );
    331                                 cost.incSign( signMatrix[ basicType->kind ][ destAsBasic->kind ] );
    332                         } // if
    333                 } else if ( dynamic_cast< const EnumInstType * >( dest ) ) {
    334                         // xxx - not positive this is correct, but appears to allow casting int => enum
    335                         // TODO
    336                         EnumDecl * decl = dynamic_cast< const EnumInstType * >( dest )->baseEnum;
    337                         if ( decl->base ) {
    338                                 cost = Cost::infinity;
     337                        conversionCostFromBasicToBasic(basicType, destAsBasic);
     338                } else if ( const EnumInstType * enumInst = dynamic_cast< const EnumInstType * >( dest ) ) {
     339                        const EnumDecl * base_enum = enumInst->baseEnum;
     340                        if ( const Type * base = base_enum->base ) { // if the base enum has a base (if it is typed)
     341                                if ( const BasicType * enumBaseAstBasic = dynamic_cast< const BasicType *> (base) ) {
     342                                        conversionCostFromBasicToBasic(basicType, enumBaseAstBasic);
     343                                } else {
     344                                        cost = Cost::infinity;
     345                                } // if
    339346                        } else {
    340347                                cost = Cost::unsafe;
     
    398405        void ConversionCost::postvisit( const FunctionType * ) {}
    399406
    400         void ConversionCost::postvisit( const EnumInstType * ) {
    401                 static Type::Qualifiers q;
    402                 static BasicType integer( q, BasicType::SignedInt );
    403                 cost = costFunc( &integer, dest, srcIsLvalue, indexer, env );  // safe if dest >= int
     407        void ConversionCost::postvisit( const EnumInstType * enumInst) {
     408                const EnumDecl * enumDecl = enumInst -> baseEnum;
     409                if ( const Type * enumType = enumDecl -> base ) { // if it is a typed enum
     410                        cost = costFunc( enumType, dest, srcIsLvalue, indexer, env );
     411                } else {
     412                        static Type::Qualifiers q;
     413                        static BasicType integer( q, BasicType::SignedInt );
     414                        cost = costFunc( &integer, dest, srcIsLvalue, indexer, env );  // safe if dest >= int
     415                } // if
    404416                if ( cost < Cost::unsafe ) {
    405                         cost.incSafe();
     417                                cost.incSafe();
    406418                } // if
    407419        }
     
    604616}
    605617
     618void ConversionCost_new::conversionCostFromBasicToBasic( const ast::BasicType * src, const ast::BasicType* dest ) {
     619        int tableResult = costMatrix[ src->kind ][ dest->kind ];
     620        if ( tableResult == -1 ) {
     621                cost = Cost::unsafe;
     622        } else {
     623                cost = Cost::zero;
     624                cost.incSafe( tableResult );
     625                cost.incSign( signMatrix[ src->kind ][ dest->kind ] );
     626        }
     627}
     628
    606629void ConversionCost_new::postvisit( const ast::BasicType * basicType ) {
    607630        if ( const ast::BasicType * dstAsBasic = dynamic_cast< const ast::BasicType * >( dst ) ) {
    608                 int tableResult = costMatrix[ basicType->kind ][ dstAsBasic->kind ];
    609                 if ( tableResult == -1 ) {
    610                         cost = Cost::unsafe;
    611                 } else {
    612                         cost = Cost::zero;
    613                         cost.incSafe( tableResult );
    614                         cost.incSign( signMatrix[ basicType->kind ][ dstAsBasic->kind ] );
    615                 }
    616         } else if ( dynamic_cast< const ast::EnumInstType * >( dst ) ) {
    617                 // xxx - not positive this is correct, but appears to allow casting int => enum
    618                 const ast::EnumDecl * decl = (dynamic_cast< const ast::EnumInstType * >( dst ))->base.get();
    619                 if ( decl->base ) {
    620                         cost = Cost::infinity;
    621                 } else {
    622                         cost = Cost::unsafe;
    623                 } // if
     631                conversionCostFromBasicToBasic( basicType, dstAsBasic );
     632        } else if ( const ast::EnumInstType * enumInst = dynamic_cast< const ast::EnumInstType * >( dst ) ) {
     633                const ast::EnumDecl * enumDecl = enumInst->base.get();
     634                if ( const ast::Type * enumType = enumDecl->base.get() ) {
     635                        if ( const ast::BasicType * enumTypeAsBasic = dynamic_cast<const ast::BasicType *>(enumType) ) {
     636                                conversionCostFromBasicToBasic( basicType, enumTypeAsBasic );
     637                        } else {
     638                                cost = Cost::infinity;
     639                        }
     640                } else {
     641            cost = Cost::unsafe;
     642                }
    624643        }
    625644}
     
    673692
    674693void ConversionCost_new::postvisit( const ast::EnumInstType * enumInstType ) {
    675         (void)enumInstType;
    676         static ast::ptr<ast::BasicType> integer = { new ast::BasicType( ast::BasicType::SignedInt ) };
    677         cost = costCalc( integer, dst, srcIsLvalue, symtab, env );
     694        const ast::EnumDecl * baseEnum = enumInstType->base;
     695        if ( const ast::Type * baseType = baseEnum->base ) {
     696                cost = costCalc( baseType, dst, srcIsLvalue, symtab, env );
     697        } else {
     698                (void)enumInstType;
     699                static ast::ptr<ast::BasicType> integer = { new ast::BasicType( ast::BasicType::SignedInt ) };
     700                cost = costCalc( integer, dst, srcIsLvalue, symtab, env );
     701        }
    678702        if ( cost < Cost::unsafe ) {
    679703                cost.incSafe();
  • src/ResolvExpr/ConversionCost.h

    r01f6a06 rfc134a48  
    6565                const TypeEnvironment &env;
    6666                CostFunction costFunc;
     67          private:
     68                // refactor for code resue
     69                void conversionCostFromBasicToBasic( const BasicType * src, const BasicType* dest );
    6770        };
    6871
     
    111114        void postvisit( const ast::ZeroType * zeroType );
    112115        void postvisit( const ast::OneType * oneType );
     116private:
     117        // refactor for code resue
     118        void conversionCostFromBasicToBasic( const ast::BasicType * src, const ast::BasicType* dest );
    113119};
    114120
  • src/Validate/Autogen.cpp

    r01f6a06 rfc134a48  
    402402        auto retval = srcParam();
    403403        retval->name = "_ret";
     404        // xxx - Adding this unused attribute can slience unused variable warning
     405        // However, some code might not be compiled as expected
     406        // Temporarily disabled
     407        // retval->attributes.push_back(new ast::Attribute("unused"));
    404408        return genProto( "?=?", { dstParam(), srcParam() }, { retval } );
    405409}
  • tests/.expect/attributes.nast.x64.txt

    r01f6a06 rfc134a48  
    13391339        }
    13401340
    1341         {
    1342             ((void)(_X4_retM12__anonymous4_2=(*_X4_dstM12__anonymous4_2)) /* ?{} */);
    1343         }
    1344 
    1345         return _X4_retM12__anonymous4_2;
     1341        return (*_X4_dstM12__anonymous4_2);
    13461342    }
    13471343    {
  • tests/.expect/attributes.nast.x86.txt

    r01f6a06 rfc134a48  
    13391339        }
    13401340
    1341         {
    1342             ((void)(_X4_retM12__anonymous4_2=(*_X4_dstM12__anonymous4_2)) /* ?{} */);
    1343         }
    1344 
    1345         return _X4_retM12__anonymous4_2;
     1341        return (*_X4_dstM12__anonymous4_2);
    13461342    }
    13471343    {
  • tests/.expect/attributes.oast.x64.txt

    r01f6a06 rfc134a48  
    13391339        }
    13401340
    1341         {
    1342             ((void)(_X4_retM12__anonymous4_2=(*_X4_dstM12__anonymous4_2)) /* ?{} */);
    1343         }
    1344 
    1345         return _X4_retM12__anonymous4_2;
     1341        return (*_X4_dstM12__anonymous4_2);
    13461342    }
    13471343    {
  • tests/.expect/attributes.oast.x86.txt

    r01f6a06 rfc134a48  
    13391339        }
    13401340
    1341         {
    1342             ((void)(_X4_retM12__anonymous4_2=(*_X4_dstM12__anonymous4_2)) /* ?{} */);
    1343         }
    1344 
    13451341        return _X4_retM12__anonymous4_2;
    13461342    }
Note: See TracChangeset for help on using the changeset viewer.