Changeset 8a34677


Ignore:
Timestamp:
Apr 8, 2016, 10:38:28 AM (6 years ago)
Author:
Aaron Moss <a3moss@…>
Branches:
aaron-thesis, arm-eh, cleanup-dtors, ctor, deferred_resn, demangler, gc_noraii, jacob/cs343-translation, jenkins-sandbox, master, memory, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, resolv-new, string, with_gc
Children:
224e52f
Parents:
78885b5
Message:

Move layout function generation into renamed MemberExprFixer? pass

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/GenPoly/Box.cc

    r78885b5 r8a34677  
    216216                /// * Moves polymorphic returns in function types to pointer-type parameters
    217217                /// * adds type size and assertion parameters to parameter lists
    218                 /// * does dynamic calculation of type layouts
    219218                class Pass2 : public PolyMutator {
    220219                  public:
     
    227226                        virtual Type *mutate( PointerType *pointerType );
    228227                        virtual Type *mutate( FunctionType *funcType );
    229                         virtual Expression *mutate( SizeofExpr *sizeofExpr );
    230                         virtual Expression *mutate( AlignofExpr *alignofExpr );
    231                         virtual Expression *mutate( OffsetofExpr *offsetofExpr );
    232                         virtual Expression *mutate( OffsetPackExpr *offsetPackExpr );
    233 
    234                         virtual void doBeginScope();
    235                         virtual void doEndScope();
     228                       
    236229                  private:
    237230                        void addAdapters( FunctionType *functionType );
    238                         /// Makes a new variable in the current scope with the given name, type & optional initializer
    239                         ObjectDecl *makeVar( const std::string &name, Type *type, Initializer *init = 0 );
    240                         /// returns true if the type has a dynamic layout; such a layout will be stored in appropriately-named local variables when the function returns
    241                         bool findGeneric( Type *ty );
    242                         /// adds type parameters to the layout call; will generate the appropriate parameters if needed
    243                         void addOtypeParamsToLayoutCall( UntypedExpr *layoutCall, const std::list< Type* > &otypeParams );
    244231
    245232                        std::map< UniqueId, std::string > adapterName;
    246                         ScopedSet< std::string > knownLayouts;          ///< Set of generic type layouts known in the current scope, indexed by sizeofName
    247                         ScopedSet< std::string > knownOffsets;          ///< Set of non-generic types for which the offset array exists in the current scope, indexed by offsetofName
    248233                };
    249234
     
    276261                };
    277262
    278                 /// Replaces member expressions for polymorphic types with calculated add-field-offset-and-dereference;
    279                 /// also fixes offsetof expressions.
    280                 class MemberExprFixer : public PolyMutator {
    281                   public:
     263                /// Replaces member and size/align/offsetof expressions on polymorphic generic types with calculated expressions.
     264                /// * Replaces member expressions for polymorphic types with calculated add-field-offset-and-dereference
     265                /// * Calculates polymorphic offsetof expressions from offset array
     266                /// * Inserts dynamic calculation of polymorphic type layouts where needed
     267                class PolyGenericCalculator : public PolyMutator {
     268                public:
    282269                        template< typename DeclClass >
    283270                        DeclClass *handleDecl( DeclClass *decl, Type *type );
     
    290277                        virtual Type *mutate( FunctionType *funcType );
    291278                        virtual Expression *mutate( MemberExpr *memberExpr );
     279                        virtual Expression *mutate( SizeofExpr *sizeofExpr );
     280                        virtual Expression *mutate( AlignofExpr *alignofExpr );
    292281                        virtual Expression *mutate( OffsetofExpr *offsetofExpr );
     282                        virtual Expression *mutate( OffsetPackExpr *offsetPackExpr );
     283
     284                        virtual void doBeginScope();
     285                        virtual void doEndScope();
     286
     287                private:
     288                        /// Makes a new variable in the current scope with the given name, type & optional initializer
     289                        ObjectDecl *makeVar( const std::string &name, Type *type, Initializer *init = 0 );
     290                        /// returns true if the type has a dynamic layout; such a layout will be stored in appropriately-named local variables when the function returns
     291                        bool findGeneric( Type *ty );
     292                        /// adds type parameters to the layout call; will generate the appropriate parameters if needed
     293                        void addOtypeParamsToLayoutCall( UntypedExpr *layoutCall, const std::list< Type* > &otypeParams );
     294                       
     295                        ScopedSet< std::string > knownLayouts;          ///< Set of generic type layouts known in the current scope, indexed by sizeofName
     296                        ScopedSet< std::string > knownOffsets;          ///< Set of non-generic types for which the offset array exists in the current scope, indexed by offsetofName
    293297                };
    294298
     
    340344                Pass2 pass2;
    341345                GenericInstantiator instantiator;
    342                 MemberExprFixer memberFixer;
     346                PolyGenericCalculator polyCalculator;
    343347                Pass3 pass3;
    344348               
     
    347351                mutateTranslationUnit/*All*/( translationUnit, pass2 );
    348352                instantiator.mutateDeclarationList( translationUnit );
    349                 mutateTranslationUnit/*All*/( translationUnit, memberFixer );
     353                mutateTranslationUnit/*All*/( translationUnit, polyCalculator );
    350354                mutateTranslationUnit/*All*/( translationUnit, pass3 );
    351355        }
     
    16171621
    16181622                                        seenTypes.insert( sizeName );
    1619                                         knownLayouts.insert( sizeName );  // make sure that any type information passed into the function is accounted for
    16201623                                }
    16211624                        }
     
    16291632                        scopeTyVars = oldtyVars;
    16301633                        return funcType;
    1631                 }
    1632 
    1633                 ObjectDecl *Pass2::makeVar( const std::string &name, Type *type, Initializer *init ) {
    1634                         ObjectDecl *newObj = new ObjectDecl( name, DeclarationNode::NoStorageClass, LinkageSpec::C, 0, type, init );
    1635                         stmtsToAdd.push_back( new DeclStmt( noLabels, newObj ) );
    1636                         return newObj;
    1637                 }
    1638 
    1639                 void Pass2::addOtypeParamsToLayoutCall( UntypedExpr *layoutCall, const std::list< Type* > &otypeParams ) {
    1640                         for ( std::list< Type* >::const_iterator param = otypeParams.begin(); param != otypeParams.end(); ++param ) {
    1641                                 if ( findGeneric( *param ) ) {
    1642                                         // push size/align vars for a generic parameter back
    1643                                         layoutCall->get_args().push_back( new NameExpr( sizeofName( *param ) ) );
    1644                                         layoutCall->get_args().push_back( new NameExpr( alignofName( *param ) ) );
    1645                                 } else {
    1646                                         layoutCall->get_args().push_back( new SizeofExpr( (*param)->clone() ) );
    1647                                         layoutCall->get_args().push_back( new AlignofExpr( (*param)->clone() ) );
    1648                                 }
    1649                         }
    1650                 }
    1651 
    1652                 /// returns true if any of the otype parameters have a dynamic layout and puts all otype parameters in the output list
    1653                 bool findGenericParams( std::list< TypeDecl* > &baseParams, std::list< Expression* > &typeParams, std::list< Type* > &out ) {
    1654                         bool hasDynamicLayout = false;
    1655 
    1656                         std::list< TypeDecl* >::const_iterator baseParam = baseParams.begin();
    1657                         std::list< Expression* >::const_iterator typeParam = typeParams.begin();
    1658                         for ( ; baseParam != baseParams.end() && typeParam != typeParams.end(); ++baseParam, ++typeParam ) {
    1659                                 // skip non-otype parameters
    1660                                 if ( (*baseParam)->get_kind() != TypeDecl::Any ) continue;
    1661                                 TypeExpr *typeExpr = dynamic_cast< TypeExpr* >( *typeParam );
    1662                                 assert( typeExpr && "all otype parameters should be type expressions" );
    1663 
    1664                                 Type *type = typeExpr->get_type();
    1665                                 out.push_back( type );
    1666                                 if ( isPolyType( type ) ) hasDynamicLayout = true;
    1667                         }
    1668                         assert( baseParam == baseParams.end() && typeParam == typeParams.end() );
    1669 
    1670                         return hasDynamicLayout;
    1671                 }
    1672                
    1673                 bool Pass2::findGeneric( Type *ty ) {
    1674                         if ( dynamic_cast< TypeInstType* >( ty ) ) {
    1675                                 // NOTE this assumes that all type variables will be properly bound, and thus have their layouts in scope
    1676                                 return true;
    1677                         } else if ( StructInstType *structTy = dynamic_cast< StructInstType* >( ty ) ) {
    1678                                 // check if this type already has a layout generated for it
    1679                                 std::string sizeName = sizeofName( ty );
    1680                                 if ( knownLayouts.find( sizeName ) != knownLayouts.end() ) return true;
    1681                                
    1682                                 // check if any of the type parameters have dynamic layout; if none do, this type is (or will be) monomorphized
    1683                                 std::list< Type* > otypeParams;
    1684                                 if ( ! findGenericParams( *structTy->get_baseParameters(), structTy->get_parameters(), otypeParams ) ) return false;
    1685 
    1686                                 // insert local variables for layout and generate call to layout function
    1687                                 knownLayouts.insert( sizeName );  // done early so as not to interfere with the later addition of parameters to the layout call
    1688                                 Type *layoutType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
    1689 
    1690                                 int n_members = structTy->get_baseStruct()->get_members().size();
    1691                                 if ( n_members == 0 ) {
    1692                                         // all empty structs have the same layout - size 1, align 1
    1693                                         makeVar( sizeName, layoutType, new SingleInit( new ConstantExpr( Constant::from( (unsigned long)1 ) ) ) );
    1694                                         makeVar( alignofName( ty ), layoutType->clone(), new SingleInit( new ConstantExpr( Constant::from( (unsigned long)1 ) ) ) );
    1695                                         // NOTE zero-length arrays are forbidden in C, so empty structs have no offsetof array
    1696                                 } else {
    1697                                         ObjectDecl *sizeVar = makeVar( sizeName, layoutType );
    1698                                         ObjectDecl *alignVar = makeVar( alignofName( ty ), layoutType->clone() );
    1699                                         ObjectDecl *offsetVar = makeVar( offsetofName( ty ), new ArrayType( Type::Qualifiers(), layoutType->clone(), new ConstantExpr( Constant::from( n_members ) ), false, false ) );
    1700 
    1701                                         // generate call to layout function
    1702                                         UntypedExpr *layoutCall = new UntypedExpr( new NameExpr( "__layoutof_" + structTy->get_baseStruct()->get_name() ) );
    1703                                         layoutCall->get_args().push_back( new AddressExpr( new VariableExpr( sizeVar ) ) );
    1704                                         layoutCall->get_args().push_back( new AddressExpr( new VariableExpr( alignVar ) ) );
    1705                                         layoutCall->get_args().push_back( new VariableExpr( offsetVar ) );
    1706                                         addOtypeParamsToLayoutCall( layoutCall, otypeParams );
    1707 
    1708                                         stmtsToAdd.push_back( new ExprStmt( noLabels, layoutCall ) );
    1709                                 }
    1710                                
    1711                                 return true;
    1712                         } else if ( UnionInstType *unionTy = dynamic_cast< UnionInstType* >( ty ) ) {
    1713                                 // check if this type already has a layout generated for it
    1714                                 std::string sizeName = sizeofName( ty );
    1715                                 if ( knownLayouts.find( sizeName ) != knownLayouts.end() ) return true;
    1716                                
    1717                                 // check if any of the type parameters have dynamic layout; if none do, this type is (or will be) monomorphized
    1718                                 std::list< Type* > otypeParams;
    1719                                 if ( ! findGenericParams( *unionTy->get_baseParameters(), unionTy->get_parameters(), otypeParams ) ) return false;
    1720 
    1721                                 // insert local variables for layout and generate call to layout function
    1722                                 knownLayouts.insert( sizeName );  // done early so as not to interfere with the later addition of parameters to the layout call
    1723                                 Type *layoutType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
    1724 
    1725                                 ObjectDecl *sizeVar = makeVar( sizeName, layoutType );
    1726                                 ObjectDecl *alignVar = makeVar( alignofName( ty ), layoutType->clone() );
    1727                                
    1728                                 // generate call to layout function
    1729                                 UntypedExpr *layoutCall = new UntypedExpr( new NameExpr( "__layoutof_" + unionTy->get_baseUnion()->get_name() ) );
    1730                                 layoutCall->get_args().push_back( new AddressExpr( new VariableExpr( sizeVar ) ) );
    1731                                 layoutCall->get_args().push_back( new AddressExpr( new VariableExpr( alignVar ) ) );
    1732                                 addOtypeParamsToLayoutCall( layoutCall, otypeParams );
    1733 
    1734                                 stmtsToAdd.push_back( new ExprStmt( noLabels, layoutCall ) );
    1735 
    1736                                 return true;
    1737                         }
    1738                        
    1739                         return false;
    1740                 }
    1741                
    1742                 Expression *Pass2::mutate( SizeofExpr *sizeofExpr ) {
    1743                         Type *ty = sizeofExpr->get_type();
    1744                         if ( findGeneric( ty ) ) {
    1745                                 Expression *ret = new NameExpr( sizeofName( ty ) );
    1746                                 delete sizeofExpr;
    1747                                 return ret;
    1748                         }
    1749                         return sizeofExpr;
    1750                 }
    1751 
    1752                 Expression *Pass2::mutate( AlignofExpr *alignofExpr ) {
    1753                         Type *ty = alignofExpr->get_type();
    1754                         if ( findGeneric( ty ) ) {
    1755                                 Expression *ret = new NameExpr( alignofName( ty ) );
    1756                                 delete alignofExpr;
    1757                                 return ret;
    1758                         }
    1759                         return alignofExpr;
    1760                 }
    1761 
    1762                 Expression *Pass2::mutate( OffsetofExpr *offsetofExpr ) {
    1763                         findGeneric( offsetofExpr->get_type() );
    1764                         return offsetofExpr;
    1765                 }
    1766 
    1767                 Expression *Pass2::mutate( OffsetPackExpr *offsetPackExpr ) {
    1768                         StructInstType *ty = offsetPackExpr->get_type();
    1769 
    1770                         Expression *ret = 0;
    1771                         if ( findGeneric( ty ) ) {
    1772                                 // pull offset back from generated type information
    1773                                 ret = new NameExpr( offsetofName( ty ) );
    1774                         } else {
    1775                                 std::string offsetName = offsetofName( ty );
    1776                                 if ( knownOffsets.find( offsetName ) != knownOffsets.end() ) {
    1777                                         // use the already-generated offsets for this type
    1778                                         ret = new NameExpr( offsetName );
    1779                                 } else {
    1780                                         knownOffsets.insert( offsetName );
    1781                                        
    1782                                         std::list< Declaration* > &baseMembers = ty->get_baseStruct()->get_members();
    1783                                         Type *offsetType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
    1784 
    1785                                         // build initializer list for offset array
    1786                                         std::list< Initializer* > inits;
    1787                                         for ( std::list< Declaration* >::const_iterator member = baseMembers.begin(); member != baseMembers.end(); ++member ) {
    1788                                                 DeclarationWithType *memberDecl;
    1789                                                 if ( DeclarationWithType *origMember = dynamic_cast< DeclarationWithType* >( *member ) ) {
    1790                                                         memberDecl = origMember->clone();
    1791                                                 } else {
    1792                                                         memberDecl = new ObjectDecl( (*member)->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, offsetType->clone(), 0 );
    1793                                                 }
    1794                                                 inits.push_back( new SingleInit( new OffsetofExpr( ty->clone(), memberDecl ) ) );
    1795                                         }
    1796 
    1797                                         // build the offset array and replace the pack with a reference to it
    1798                                         ObjectDecl *offsetArray = makeVar( offsetName, new ArrayType( Type::Qualifiers(), offsetType, new ConstantExpr( Constant::from( baseMembers.size() ) ), false, false ),
    1799                                                         new ListInit( inits ) );
    1800                                         ret = new VariableExpr( offsetArray );
    1801                                 }
    1802                         }
    1803 
    1804                         delete offsetPackExpr;
    1805                         return ret;
    1806                 }
    1807 
    1808                 void Pass2::doBeginScope() {
    1809                         knownLayouts.beginScope();
    1810                         knownOffsets.beginScope();
    1811                 }
    1812                
    1813                 void Pass2::doEndScope() {
    1814                         knownLayouts.endScope();
    1815                         knownOffsets.beginScope();
    18161634                }
    18171635
     
    20081826
    20091827                template< typename DeclClass >
    2010                 DeclClass * MemberExprFixer::handleDecl( DeclClass *decl, Type *type ) {
     1828                DeclClass * PolyGenericCalculator::handleDecl( DeclClass *decl, Type *type ) {
    20111829                        TyVarMap oldtyVars = scopeTyVars;
    20121830                        makeTyVarMap( type, scopeTyVars );
     
    20181836                }
    20191837
    2020                 ObjectDecl * MemberExprFixer::mutate( ObjectDecl *objectDecl ) {
     1838                ObjectDecl * PolyGenericCalculator::mutate( ObjectDecl *objectDecl ) {
    20211839                        return handleDecl( objectDecl, objectDecl->get_type() );
    20221840                }
    20231841
    2024                 DeclarationWithType * MemberExprFixer::mutate( FunctionDecl *functionDecl ) {
     1842                DeclarationWithType * PolyGenericCalculator::mutate( FunctionDecl *functionDecl ) {
    20251843                        return handleDecl( functionDecl, functionDecl->get_functionType() );
    20261844                }
    20271845
    2028                 TypedefDecl * MemberExprFixer::mutate( TypedefDecl *typedefDecl ) {
     1846                TypedefDecl * PolyGenericCalculator::mutate( TypedefDecl *typedefDecl ) {
    20291847                        return handleDecl( typedefDecl, typedefDecl->get_base() );
    20301848                }
    20311849
    2032                 TypeDecl * MemberExprFixer::mutate( TypeDecl *typeDecl ) {
     1850                TypeDecl * PolyGenericCalculator::mutate( TypeDecl *typeDecl ) {
    20331851                        scopeTyVars[ typeDecl->get_name() ] = typeDecl->get_kind();
    20341852                        return Mutator::mutate( typeDecl );
    20351853                }
    20361854
    2037                 Type * MemberExprFixer::mutate( PointerType *pointerType ) {
     1855                Type * PolyGenericCalculator::mutate( PointerType *pointerType ) {
    20381856                        TyVarMap oldtyVars = scopeTyVars;
    20391857                        makeTyVarMap( pointerType, scopeTyVars );
     
    20451863                }
    20461864
    2047                 Type * MemberExprFixer::mutate( FunctionType *functionType ) {
     1865                Type * PolyGenericCalculator::mutate( FunctionType *funcType ) {
    20481866                        TyVarMap oldtyVars = scopeTyVars;
    2049                         makeTyVarMap( functionType, scopeTyVars );
    2050 
    2051                         Type *ret = Mutator::mutate( functionType );
     1867                        makeTyVarMap( funcType, scopeTyVars );
     1868
     1869                        // make sure that any type information passed into the function is accounted for
     1870                        for ( std::list< DeclarationWithType* >::const_iterator fnParm = funcType->get_parameters().begin(); fnParm != funcType->get_parameters().end(); ++fnParm ) {
     1871                                // condition here duplicates that in Pass2::mutate( FunctionType* )
     1872                                Type *polyBase = hasPolyBase( (*fnParm)->get_type(), scopeTyVars );
     1873                                if ( polyBase && ! dynamic_cast< TypeInstType* >( polyBase ) ) {
     1874                                        knownLayouts.insert( sizeofName( polyBase ) );
     1875                                }
     1876                        }
     1877                       
     1878                        Type *ret = Mutator::mutate( funcType );
    20521879
    20531880                        scopeTyVars = oldtyVars;
     
    20551882                }
    20561883
    2057                 Statement *MemberExprFixer::mutate( DeclStmt *declStmt ) {
     1884                Statement *PolyGenericCalculator::mutate( DeclStmt *declStmt ) {
    20581885                        if ( ObjectDecl *objectDecl = dynamic_cast< ObjectDecl *>( declStmt->get_decl() ) ) {
    2059                                 if ( isPolyType( objectDecl->get_type(), scopeTyVars ) ) {
     1886                                if ( findGeneric( objectDecl->get_type() ) ) {
    20601887                                        // change initialization of a polymorphic value object
    20611888                                        // to allocate storage with alloca
     
    21091936                }
    21101937               
    2111                 Expression *MemberExprFixer::mutate( MemberExpr *memberExpr ) {
     1938                Expression *PolyGenericCalculator::mutate( MemberExpr *memberExpr ) {
    21121939                        // mutate, exiting early if no longer MemberExpr
    21131940                        Expression *expr = Mutator::mutate( memberExpr );
     
    21261953                        Type *objectType = hasPolyBase( objectDecl->get_type(), scopeTyVars, &tyDepth );
    21271954                        if ( ! objectType ) return memberExpr;
     1955                        findGeneric( objectType ); // ensure layout for this type is available
    21281956
    21291957                        Expression *newMemberExpr = 0;
     
    21571985                }
    21581986
    2159                 Expression *MemberExprFixer::mutate( OffsetofExpr *offsetofExpr ) {
     1987                ObjectDecl *PolyGenericCalculator::makeVar( const std::string &name, Type *type, Initializer *init ) {
     1988                        ObjectDecl *newObj = new ObjectDecl( name, DeclarationNode::NoStorageClass, LinkageSpec::C, 0, type, init );
     1989                        stmtsToAdd.push_back( new DeclStmt( noLabels, newObj ) );
     1990                        return newObj;
     1991                }
     1992
     1993                void PolyGenericCalculator::addOtypeParamsToLayoutCall( UntypedExpr *layoutCall, const std::list< Type* > &otypeParams ) {
     1994                        for ( std::list< Type* >::const_iterator param = otypeParams.begin(); param != otypeParams.end(); ++param ) {
     1995                                if ( findGeneric( *param ) ) {
     1996                                        // push size/align vars for a generic parameter back
     1997                                        layoutCall->get_args().push_back( new NameExpr( sizeofName( *param ) ) );
     1998                                        layoutCall->get_args().push_back( new NameExpr( alignofName( *param ) ) );
     1999                                } else {
     2000                                        layoutCall->get_args().push_back( new SizeofExpr( (*param)->clone() ) );
     2001                                        layoutCall->get_args().push_back( new AlignofExpr( (*param)->clone() ) );
     2002                                }
     2003                        }
     2004                }
     2005
     2006                /// returns true if any of the otype parameters have a dynamic layout and puts all otype parameters in the output list
     2007                bool findGenericParams( std::list< TypeDecl* > &baseParams, std::list< Expression* > &typeParams, std::list< Type* > &out ) {
     2008                        bool hasDynamicLayout = false;
     2009
     2010                        std::list< TypeDecl* >::const_iterator baseParam = baseParams.begin();
     2011                        std::list< Expression* >::const_iterator typeParam = typeParams.begin();
     2012                        for ( ; baseParam != baseParams.end() && typeParam != typeParams.end(); ++baseParam, ++typeParam ) {
     2013                                // skip non-otype parameters
     2014                                if ( (*baseParam)->get_kind() != TypeDecl::Any ) continue;
     2015                                TypeExpr *typeExpr = dynamic_cast< TypeExpr* >( *typeParam );
     2016                                assert( typeExpr && "all otype parameters should be type expressions" );
     2017
     2018                                Type *type = typeExpr->get_type();
     2019                                out.push_back( type );
     2020                                if ( isPolyType( type ) ) hasDynamicLayout = true;
     2021                        }
     2022                        assert( baseParam == baseParams.end() && typeParam == typeParams.end() );
     2023
     2024                        return hasDynamicLayout;
     2025                }
     2026
     2027                bool PolyGenericCalculator::findGeneric( Type *ty ) {
     2028                        if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( ty ) ) {
     2029                                // duplicate logic from isPolyType()
     2030                                if ( env ) {
     2031                                        if ( Type *newType = env->lookup( typeInst->get_name() ) ) {
     2032                                                return findGeneric( newType );
     2033                                        } // if
     2034                                } // if
     2035                                if ( scopeTyVars.find( typeInst->get_name() ) != scopeTyVars.end() ) {
     2036                                        // NOTE assumes here that getting put in the scopeTyVars included having the layout variables set
     2037                                        return true;
     2038                                }
     2039                                return false;
     2040                        } else if ( StructInstType *structTy = dynamic_cast< StructInstType* >( ty ) ) {
     2041                                // check if this type already has a layout generated for it
     2042                                std::string sizeName = sizeofName( ty );
     2043                                if ( knownLayouts.find( sizeName ) != knownLayouts.end() ) return true;
     2044
     2045                                // check if any of the type parameters have dynamic layout; if none do, this type is (or will be) monomorphized
     2046                                std::list< Type* > otypeParams;
     2047                                if ( ! findGenericParams( *structTy->get_baseParameters(), structTy->get_parameters(), otypeParams ) ) return false;
     2048
     2049                                // insert local variables for layout and generate call to layout function
     2050                                knownLayouts.insert( sizeName );  // done early so as not to interfere with the later addition of parameters to the layout call
     2051                                Type *layoutType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
     2052
     2053                                int n_members = structTy->get_baseStruct()->get_members().size();
     2054                                if ( n_members == 0 ) {
     2055                                        // all empty structs have the same layout - size 1, align 1
     2056                                        makeVar( sizeName, layoutType, new SingleInit( new ConstantExpr( Constant::from( (unsigned long)1 ) ) ) );
     2057                                        makeVar( alignofName( ty ), layoutType->clone(), new SingleInit( new ConstantExpr( Constant::from( (unsigned long)1 ) ) ) );
     2058                                        // NOTE zero-length arrays are forbidden in C, so empty structs have no offsetof array
     2059                                } else {
     2060                                        ObjectDecl *sizeVar = makeVar( sizeName, layoutType );
     2061                                        ObjectDecl *alignVar = makeVar( alignofName( ty ), layoutType->clone() );
     2062                                        ObjectDecl *offsetVar = makeVar( offsetofName( ty ), new ArrayType( Type::Qualifiers(), layoutType->clone(), new ConstantExpr( Constant::from( n_members ) ), false, false ) );
     2063
     2064                                        // generate call to layout function
     2065                                        UntypedExpr *layoutCall = new UntypedExpr( new NameExpr( "__layoutof_" + structTy->get_baseStruct()->get_name() ) );
     2066                                        layoutCall->get_args().push_back( new AddressExpr( new VariableExpr( sizeVar ) ) );
     2067                                        layoutCall->get_args().push_back( new AddressExpr( new VariableExpr( alignVar ) ) );
     2068                                        layoutCall->get_args().push_back( new VariableExpr( offsetVar ) );
     2069                                        addOtypeParamsToLayoutCall( layoutCall, otypeParams );
     2070
     2071                                        stmtsToAdd.push_back( new ExprStmt( noLabels, layoutCall ) );
     2072                                }
     2073
     2074                                return true;
     2075                        } else if ( UnionInstType *unionTy = dynamic_cast< UnionInstType* >( ty ) ) {
     2076                                // check if this type already has a layout generated for it
     2077                                std::string sizeName = sizeofName( ty );
     2078                                if ( knownLayouts.find( sizeName ) != knownLayouts.end() ) return true;
     2079
     2080                                // check if any of the type parameters have dynamic layout; if none do, this type is (or will be) monomorphized
     2081                                std::list< Type* > otypeParams;
     2082                                if ( ! findGenericParams( *unionTy->get_baseParameters(), unionTy->get_parameters(), otypeParams ) ) return false;
     2083
     2084                                // insert local variables for layout and generate call to layout function
     2085                                knownLayouts.insert( sizeName );  // done early so as not to interfere with the later addition of parameters to the layout call
     2086                                Type *layoutType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
     2087
     2088                                ObjectDecl *sizeVar = makeVar( sizeName, layoutType );
     2089                                ObjectDecl *alignVar = makeVar( alignofName( ty ), layoutType->clone() );
     2090
     2091                                // generate call to layout function
     2092                                UntypedExpr *layoutCall = new UntypedExpr( new NameExpr( "__layoutof_" + unionTy->get_baseUnion()->get_name() ) );
     2093                                layoutCall->get_args().push_back( new AddressExpr( new VariableExpr( sizeVar ) ) );
     2094                                layoutCall->get_args().push_back( new AddressExpr( new VariableExpr( alignVar ) ) );
     2095                                addOtypeParamsToLayoutCall( layoutCall, otypeParams );
     2096
     2097                                stmtsToAdd.push_back( new ExprStmt( noLabels, layoutCall ) );
     2098
     2099                                return true;
     2100                        }
     2101
     2102                        return false;
     2103                }
     2104
     2105                Expression *PolyGenericCalculator::mutate( SizeofExpr *sizeofExpr ) {
     2106                        Type *ty = sizeofExpr->get_type();
     2107                        if ( findGeneric( ty ) ) {
     2108                                Expression *ret = new NameExpr( sizeofName( ty ) );
     2109                                delete sizeofExpr;
     2110                                return ret;
     2111                        }
     2112                        return sizeofExpr;
     2113                }
     2114
     2115                Expression *PolyGenericCalculator::mutate( AlignofExpr *alignofExpr ) {
     2116                        Type *ty = alignofExpr->get_type();
     2117                        if ( findGeneric( ty ) ) {
     2118                                Expression *ret = new NameExpr( alignofName( ty ) );
     2119                                delete alignofExpr;
     2120                                return ret;
     2121                        }
     2122                        return alignofExpr;
     2123                }
     2124
     2125                Expression *PolyGenericCalculator::mutate( OffsetofExpr *offsetofExpr ) {
    21602126                        // mutate, exiting early if no longer OffsetofExpr
    21612127                        Expression *expr = Mutator::mutate( offsetofExpr );
     
    21642130
    21652131                        // only mutate expressions for polymorphic structs/unions
    2166                         Type *ty = isPolyType( offsetofExpr->get_type(), scopeTyVars );
    2167                         if ( ! ty ) return offsetofExpr;
    2168 
     2132                        Type *ty = offsetofExpr->get_type();
     2133                        if ( ! findGeneric( ty ) ) return offsetofExpr;
     2134                       
    21692135                        if ( StructInstType *structType = dynamic_cast< StructInstType* >( ty ) ) {
    21702136                                // replace offsetof expression by index into offset array
     
    21822148                }
    21832149
     2150                Expression *PolyGenericCalculator::mutate( OffsetPackExpr *offsetPackExpr ) {
     2151                        StructInstType *ty = offsetPackExpr->get_type();
     2152
     2153                        Expression *ret = 0;
     2154                        if ( findGeneric( ty ) ) {
     2155                                // pull offset back from generated type information
     2156                                ret = new NameExpr( offsetofName( ty ) );
     2157                        } else {
     2158                                std::string offsetName = offsetofName( ty );
     2159                                if ( knownOffsets.find( offsetName ) != knownOffsets.end() ) {
     2160                                        // use the already-generated offsets for this type
     2161                                        ret = new NameExpr( offsetName );
     2162                                } else {
     2163                                        knownOffsets.insert( offsetName );
     2164
     2165                                        std::list< Declaration* > &baseMembers = ty->get_baseStruct()->get_members();
     2166                                        Type *offsetType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
     2167
     2168                                        // build initializer list for offset array
     2169                                        std::list< Initializer* > inits;
     2170                                        for ( std::list< Declaration* >::const_iterator member = baseMembers.begin(); member != baseMembers.end(); ++member ) {
     2171                                                DeclarationWithType *memberDecl;
     2172                                                if ( DeclarationWithType *origMember = dynamic_cast< DeclarationWithType* >( *member ) ) {
     2173                                                        memberDecl = origMember->clone();
     2174                                                } else {
     2175                                                        memberDecl = new ObjectDecl( (*member)->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, offsetType->clone(), 0 );
     2176                                                }
     2177                                                inits.push_back( new SingleInit( new OffsetofExpr( ty->clone(), memberDecl ) ) );
     2178                                        }
     2179
     2180                                        // build the offset array and replace the pack with a reference to it
     2181                                        ObjectDecl *offsetArray = makeVar( offsetName, new ArrayType( Type::Qualifiers(), offsetType, new ConstantExpr( Constant::from( baseMembers.size() ) ), false, false ),
     2182                                                        new ListInit( inits ) );
     2183                                        ret = new VariableExpr( offsetArray );
     2184                                }
     2185                        }
     2186
     2187                        delete offsetPackExpr;
     2188                        return ret;
     2189                }
     2190
     2191                void PolyGenericCalculator::doBeginScope() {
     2192                        knownLayouts.beginScope();
     2193                        knownOffsets.beginScope();
     2194                }
     2195
     2196                void PolyGenericCalculator::doEndScope() {
     2197                        knownLayouts.endScope();
     2198                        knownOffsets.beginScope();
     2199                }
     2200
    21842201////////////////////////////////////////// Pass3 ////////////////////////////////////////////////////
    21852202
Note: See TracChangeset for help on using the changeset viewer.