Changeset b95fe40


Ignore:
Timestamp:
Nov 22, 2017, 3:40:12 PM (4 years ago)
Author:
Rob Schluntz <rschlunt@…>
Branches:
aaron-thesis, arm-eh, cleanup-dtors, deferred_resn, demangler, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, resolv-new, with_gc
Children:
7e4c4f4
Parents:
98a249f
Message:

Add casts to dtype-static member expressions to prevent loss of type information [fixes #42] [fixes #59]

Location:
src
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • src/GenPoly/InstantiateGeneric.cc

    r98a249f rb95fe40  
    2727#include "Common/utility.h"            // for deleteAll, cloneAll
    2828#include "GenPoly.h"                   // for isPolyType, typesPolyCompatible
     29#include "ResolvExpr/typeops.h"
    2930#include "ScopedSet.h"                 // for ScopedSet, ScopedSet<>::iterator
    3031#include "ScrubTyVars.h"               // for ScrubTyVars
     
    151152                return gt;
    152153        }
     154
     155        /// Add cast to dtype-static member expressions so that type information is not lost in GenericInstantiator
     156        struct FixDtypeStatic final {
     157                Expression * postmutate( MemberExpr * memberExpr );
     158
     159                template<typename AggrInst>
     160                Expression * fixMemberExpr( AggrInst * inst, MemberExpr * memberExpr );
     161        };
    153162
    154163        /// Mutator pass that replaces concrete instantiations of generic types with actual struct declarations, scoped appropriately
     
    198207
    199208        void instantiateGeneric( std::list< Declaration* > &translationUnit ) {
     209                PassVisitor<FixDtypeStatic> fixer;
    200210                PassVisitor<GenericInstantiator> instantiator;
     211
     212                mutateAll( translationUnit, fixer );
    201213                mutateAll( translationUnit, instantiator );
     214        }
     215
     216        bool isDtypeStatic( const std::list< TypeDecl* >& baseParams ) {
     217                return std::all_of( baseParams.begin(), baseParams.end(), []( TypeDecl * td ) { return ! td->isComplete(); } );
    202218        }
    203219
     
    479495        }
    480496
     497        template< typename AggrInst >
     498        Expression * FixDtypeStatic::fixMemberExpr( AggrInst * inst, MemberExpr * memberExpr ) {
     499                // need to cast dtype-static member expressions to their actual type before that type is erased.
     500                auto & baseParams = *inst->get_baseParameters();
     501                if ( isDtypeStatic( baseParams ) ) {
     502                        if ( ! ResolvExpr::typesCompatible( memberExpr->result, memberExpr->member->get_type(), SymTab::Indexer() ) ) {
     503                                // type of member and type of expression differ, so add cast to actual type
     504                                return new CastExpr( memberExpr, memberExpr->result->clone() );
     505                        }
     506                }
     507                return memberExpr;
     508        }
     509
     510        Expression * FixDtypeStatic::postmutate( MemberExpr * memberExpr ) {
     511                Type * aggrType = memberExpr->aggregate->result;
     512                if ( isGenericType( aggrType ) ) {
     513                        if ( StructInstType * inst = dynamic_cast< StructInstType * >( aggrType ) ) {
     514                                return fixMemberExpr( inst, memberExpr );
     515                        } else if ( UnionInstType * inst = dynamic_cast< UnionInstType * >( aggrType ) ) {
     516                                return fixMemberExpr( inst, memberExpr );
     517                        }
     518                }
     519                return memberExpr;
     520        }
     521
    481522} // namespace GenPoly
    482523
  • src/SymTab/Autogen.h

    r98a249f rb95fe40  
    5656        /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls.
    5757        template< typename OutputIterator >
    58         Statement * genCall( InitTweak::InitExpander & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, bool addCast = false, bool forward = true );
     58        Statement * genCall( InitTweak::InitExpander & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, Type * addCast = nullptr, bool forward = true );
    5959
    6060        /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Should only be called with non-array types.
    6161        /// optionally returns a statement which must be inserted prior to the containing loop, if there is one
    6262        template< typename OutputIterator >
    63         Statement * genScalarCall( InitTweak::InitExpander & srcParam, Expression * dstParam, std::string fname, OutputIterator out, Type * type, bool addCast = false ) {
     63        Statement * genScalarCall( InitTweak::InitExpander & srcParam, Expression * dstParam, std::string fname, OutputIterator out, Type * type, Type * addCast = nullptr ) {
    6464                bool isReferenceCtorDtor = false;
    6565                if ( dynamic_cast< ReferenceType * >( type ) && CodeGen::isCtorDtor( fname ) ) {
     
    6868                        fname = "?=?";
    6969                        dstParam = new AddressExpr( dstParam );
    70                         addCast = false;
     70                        addCast = nullptr;
    7171                        isReferenceCtorDtor = true;
    7272                }
     
    8383                        // remove lvalue as a qualifier, this can change to
    8484                        //   type->get_qualifiers() = Type::Qualifiers();
    85                         assert( type );
    86                         Type * castType = type->clone();
     85                        Type * castType = addCast->clone();
    8786                        castType->get_qualifiers() -= Type::Qualifiers( Type::Lvalue | Type::Const | Type::Volatile | Type::Restrict | Type::Atomic );
    8887                        // castType->set_lvalue( true ); // xxx - might not need this
     
    115114        /// If forward is true, loop goes from 0 to N-1, else N-1 to 0
    116115        template< typename OutputIterator >
    117         void genArrayCall( InitTweak::InitExpander & srcParam, Expression *dstParam, const std::string & fname, OutputIterator out, ArrayType *array, bool addCast = false, bool forward = true ) {
     116        void genArrayCall( InitTweak::InitExpander & srcParam, Expression *dstParam, const std::string & fname, OutputIterator out, ArrayType *array, Type * addCast = nullptr, bool forward = true ) {
    118117                static UniqueName indexName( "_index" );
    119118
    120119                // for a flexible array member nothing is done -- user must define own assignment
    121                 if ( ! array->get_dimension() ) return ;
     120                if ( ! array->get_dimension() ) return;
     121
     122                if ( addCast ) {
     123                        // peel off array layer from cast
     124                        ArrayType * at = strict_dynamic_cast< ArrayType * >( addCast );
     125                        addCast = at->base;
     126                }
    122127
    123128                Expression * begin, * end, * update, * cmp;
     
    171176
    172177        template< typename OutputIterator >
    173         Statement * genCall( InitTweak::InitExpander & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, bool addCast, bool forward ) {
     178        Statement * genCall( InitTweak::InitExpander & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, Type * addCast, bool forward ) {
    174179                if ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) {
    175180                        genArrayCall( srcParam, dstParam, fname, out, at, addCast, forward );
     
    191196                if ( isUnnamedBitfield( obj ) ) return;
    192197
    193                 bool addCast = (fname == "?{}" || fname == "^?{}") && ( !obj || ( obj && ! obj->get_bitfieldWidth() ) );
     198                Type * addCast = nullptr;
     199                if ( (fname == "?{}" || fname == "^?{}") && ( !obj || ( obj && ! obj->get_bitfieldWidth() ) ) ) {
     200                        assert( dstParam->result );
     201                        addCast = dstParam->result;
     202                }
    194203                std::list< Statement * > stmts;
    195204                genCall( srcParam, dstParam, fname, back_inserter( stmts ), obj->type, addCast, forward );
  • src/SymTab/Validate.cc

    r98a249f rb95fe40  
    124124
    125125        /// Associates forward declarations of aggregates with their definitions
    126         struct LinkReferenceToTypes final : public WithIndexer {
     126        struct LinkReferenceToTypes final : public WithIndexer, public WithGuards {
    127127                LinkReferenceToTypes( const Indexer *indexer );
    128128                void postvisit( TypeInstType *typeInst );
     
    137137                void postvisit( UnionDecl *unionDecl );
    138138                void postvisit( TraitDecl * traitDecl );
     139
     140                void previsit( StructDecl *structDecl );
     141                void previsit( UnionDecl *unionDecl );
     142
     143                void renameGenericParams( std::list< TypeDecl * > & params );
    139144
    140145          private:
     
    147152                ForwardStructsType forwardStructs;
    148153                ForwardUnionsType forwardUnions;
     154                /// true if currently in a generic type body, so that type parameter instances can be renamed appropriately
     155                bool inGeneric = false;
    149156        };
    150157
     
    561568        }
    562569
     570        void LinkReferenceToTypes::renameGenericParams( std::list< TypeDecl * > & params ) {
     571                // rename generic type parameters uniquely so that they do not conflict with user-defined function forall parameters, e.g.
     572                //   forall(otype T)
     573                //   struct Box {
     574                //     T x;
     575                //   };
     576                //   forall(otype T)
     577                //   void f(Box(T) b) {
     578                //     ...
     579                //   }
     580                // The T in Box and the T in f are different, so internally the naming must reflect that.
     581                GuardValue( inGeneric );
     582                inGeneric = ! params.empty();
     583                for ( TypeDecl * td : params ) {
     584                        td->name = "__" + td->name + "_generic_";
     585                }
     586        }
     587
     588        void LinkReferenceToTypes::previsit( StructDecl * structDecl ) {
     589                renameGenericParams( structDecl->parameters );
     590        }
     591
     592        void LinkReferenceToTypes::previsit( UnionDecl * unionDecl ) {
     593                renameGenericParams( unionDecl->parameters );
     594        }
     595
    563596        void LinkReferenceToTypes::postvisit( StructDecl *structDecl ) {
    564597                // visit struct members first so that the types of self-referencing members are updated properly
     
    588621
    589622        void LinkReferenceToTypes::postvisit( TypeInstType *typeInst ) {
     623                // ensure generic parameter instances are renamed like the base type
     624                if ( inGeneric && typeInst->baseType ) typeInst->name = typeInst->baseType->name;
    590625                if ( NamedTypeDecl *namedTypeDecl = local_indexer->lookupType( typeInst->get_name() ) ) {
    591626                        if ( TypeDecl *typeDecl = dynamic_cast< TypeDecl * >( namedTypeDecl ) ) {
Note: See TracChangeset for help on using the changeset viewer.