Changeset 8a34677
- Timestamp:
- Apr 8, 2016, 10:38:28 AM (9 years ago)
- Branches:
- ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, ctor, deferred_resn, demangler, enum, forall-pointer-decay, gc_noraii, jacob/cs343-translation, jenkins-sandbox, master, memory, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, string, with_gc
- Children:
- 224e52f
- Parents:
- 78885b5
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/GenPoly/Box.cc
r78885b5 r8a34677 216 216 /// * Moves polymorphic returns in function types to pointer-type parameters 217 217 /// * adds type size and assertion parameters to parameter lists 218 /// * does dynamic calculation of type layouts219 218 class Pass2 : public PolyMutator { 220 219 public: … … 227 226 virtual Type *mutate( PointerType *pointerType ); 228 227 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 236 229 private: 237 230 void addAdapters( FunctionType *functionType ); 238 /// Makes a new variable in the current scope with the given name, type & optional initializer239 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 returns241 bool findGeneric( Type *ty );242 /// adds type parameters to the layout call; will generate the appropriate parameters if needed243 void addOtypeParamsToLayoutCall( UntypedExpr *layoutCall, const std::list< Type* > &otypeParams );244 231 245 232 std::map< UniqueId, std::string > adapterName; 246 ScopedSet< std::string > knownLayouts; ///< Set of generic type layouts known in the current scope, indexed by sizeofName247 ScopedSet< std::string > knownOffsets; ///< Set of non-generic types for which the offset array exists in the current scope, indexed by offsetofName248 233 }; 249 234 … … 276 261 }; 277 262 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: 282 269 template< typename DeclClass > 283 270 DeclClass *handleDecl( DeclClass *decl, Type *type ); … … 290 277 virtual Type *mutate( FunctionType *funcType ); 291 278 virtual Expression *mutate( MemberExpr *memberExpr ); 279 virtual Expression *mutate( SizeofExpr *sizeofExpr ); 280 virtual Expression *mutate( AlignofExpr *alignofExpr ); 292 281 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 293 297 }; 294 298 … … 340 344 Pass2 pass2; 341 345 GenericInstantiator instantiator; 342 MemberExprFixer memberFixer;346 PolyGenericCalculator polyCalculator; 343 347 Pass3 pass3; 344 348 … … 347 351 mutateTranslationUnit/*All*/( translationUnit, pass2 ); 348 352 instantiator.mutateDeclarationList( translationUnit ); 349 mutateTranslationUnit/*All*/( translationUnit, memberFixer );353 mutateTranslationUnit/*All*/( translationUnit, polyCalculator ); 350 354 mutateTranslationUnit/*All*/( translationUnit, pass3 ); 351 355 } … … 1617 1621 1618 1622 seenTypes.insert( sizeName ); 1619 knownLayouts.insert( sizeName ); // make sure that any type information passed into the function is accounted for1620 1623 } 1621 1624 } … … 1629 1632 scopeTyVars = oldtyVars; 1630 1633 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 back1643 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 list1653 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 parameters1660 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 scope1676 return true;1677 } else if ( StructInstType *structTy = dynamic_cast< StructInstType* >( ty ) ) {1678 // check if this type already has a layout generated for it1679 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) monomorphized1683 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 function1687 knownLayouts.insert( sizeName ); // done early so as not to interfere with the later addition of parameters to the layout call1688 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 11693 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 array1696 } 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 function1702 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 it1714 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) monomorphized1718 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 function1722 knownLayouts.insert( sizeName ); // done early so as not to interfere with the later addition of parameters to the layout call1723 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 function1729 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 information1773 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 type1778 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 array1786 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 it1798 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();1816 1634 } 1817 1635 … … 2008 1826 2009 1827 template< typename DeclClass > 2010 DeclClass * MemberExprFixer::handleDecl( DeclClass *decl, Type *type ) {1828 DeclClass * PolyGenericCalculator::handleDecl( DeclClass *decl, Type *type ) { 2011 1829 TyVarMap oldtyVars = scopeTyVars; 2012 1830 makeTyVarMap( type, scopeTyVars ); … … 2018 1836 } 2019 1837 2020 ObjectDecl * MemberExprFixer::mutate( ObjectDecl *objectDecl ) {1838 ObjectDecl * PolyGenericCalculator::mutate( ObjectDecl *objectDecl ) { 2021 1839 return handleDecl( objectDecl, objectDecl->get_type() ); 2022 1840 } 2023 1841 2024 DeclarationWithType * MemberExprFixer::mutate( FunctionDecl *functionDecl ) {1842 DeclarationWithType * PolyGenericCalculator::mutate( FunctionDecl *functionDecl ) { 2025 1843 return handleDecl( functionDecl, functionDecl->get_functionType() ); 2026 1844 } 2027 1845 2028 TypedefDecl * MemberExprFixer::mutate( TypedefDecl *typedefDecl ) {1846 TypedefDecl * PolyGenericCalculator::mutate( TypedefDecl *typedefDecl ) { 2029 1847 return handleDecl( typedefDecl, typedefDecl->get_base() ); 2030 1848 } 2031 1849 2032 TypeDecl * MemberExprFixer::mutate( TypeDecl *typeDecl ) {1850 TypeDecl * PolyGenericCalculator::mutate( TypeDecl *typeDecl ) { 2033 1851 scopeTyVars[ typeDecl->get_name() ] = typeDecl->get_kind(); 2034 1852 return Mutator::mutate( typeDecl ); 2035 1853 } 2036 1854 2037 Type * MemberExprFixer::mutate( PointerType *pointerType ) {1855 Type * PolyGenericCalculator::mutate( PointerType *pointerType ) { 2038 1856 TyVarMap oldtyVars = scopeTyVars; 2039 1857 makeTyVarMap( pointerType, scopeTyVars ); … … 2045 1863 } 2046 1864 2047 Type * MemberExprFixer::mutate( FunctionType *functionType ) {1865 Type * PolyGenericCalculator::mutate( FunctionType *funcType ) { 2048 1866 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 ); 2052 1879 2053 1880 scopeTyVars = oldtyVars; … … 2055 1882 } 2056 1883 2057 Statement * MemberExprFixer::mutate( DeclStmt *declStmt ) {1884 Statement *PolyGenericCalculator::mutate( DeclStmt *declStmt ) { 2058 1885 if ( ObjectDecl *objectDecl = dynamic_cast< ObjectDecl *>( declStmt->get_decl() ) ) { 2059 if ( isPolyType( objectDecl->get_type(), scopeTyVars) ) {1886 if ( findGeneric( objectDecl->get_type() ) ) { 2060 1887 // change initialization of a polymorphic value object 2061 1888 // to allocate storage with alloca … … 2109 1936 } 2110 1937 2111 Expression * MemberExprFixer::mutate( MemberExpr *memberExpr ) {1938 Expression *PolyGenericCalculator::mutate( MemberExpr *memberExpr ) { 2112 1939 // mutate, exiting early if no longer MemberExpr 2113 1940 Expression *expr = Mutator::mutate( memberExpr ); … … 2126 1953 Type *objectType = hasPolyBase( objectDecl->get_type(), scopeTyVars, &tyDepth ); 2127 1954 if ( ! objectType ) return memberExpr; 1955 findGeneric( objectType ); // ensure layout for this type is available 2128 1956 2129 1957 Expression *newMemberExpr = 0; … … 2157 1985 } 2158 1986 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 ) { 2160 2126 // mutate, exiting early if no longer OffsetofExpr 2161 2127 Expression *expr = Mutator::mutate( offsetofExpr ); … … 2164 2130 2165 2131 // 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 2169 2135 if ( StructInstType *structType = dynamic_cast< StructInstType* >( ty ) ) { 2170 2136 // replace offsetof expression by index into offset array … … 2182 2148 } 2183 2149 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 2184 2201 ////////////////////////////////////////// Pass3 //////////////////////////////////////////////////// 2185 2202
Note: See TracChangeset
for help on using the changeset viewer.