Changeset 89173242
- Timestamp:
- Mar 10, 2016, 4:56:53 PM (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:
- b3f9a0cb
- Parents:
- 0531b5d
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/GenPoly/Box.cc
r0531b5d r89173242 30 30 #include "FindFunction.h" 31 31 #include "ScopedMap.h" 32 #include "ScopedSet.h" 32 33 #include "ScrubTyVars.h" 33 34 … … 118 119 typedef std::vector< Instantiation > ValueList; 119 120 /// Underlying map type; maps keys to a linear list of corresponding TypeLists and values 120 typedef ScopedMap< Key*, std::vector< Instantiation >> InnerMap;121 typedef ScopedMap< Key*, ValueList > InnerMap; 121 122 122 123 InnerMap instantiations; ///< instantiations … … 178 179 virtual void doEndScope(); 179 180 private: 180 /// Makes a new temporary array holding the offsets of the fields of `type`, and returns a new variable expression referencing it181 Expression *makeOffsetArray( StructInstType *type );182 181 /// Pass the extra type parameters from polymorphic generic arguments or return types into a function application 183 182 void passArgTypeVars( ApplicationExpr *appExpr, Type *parmType, Type *argBaseType, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars, std::set< std::string > &seenTypes ); … … 206 205 ObjectDecl *makeTemporary( Type *type ); 207 206 208 std::map< std::string, DeclarationWithType *> assignOps; 209 ResolvExpr::TypeMap< DeclarationWithType > scopedAssignOps; 210 ScopedMap< std::string, DeclarationWithType* > adapters; 207 std::map< std::string, DeclarationWithType *> assignOps; ///< Currently known type variable assignment operators 208 ResolvExpr::TypeMap< DeclarationWithType > scopedAssignOps; ///< Currently known assignment operators 209 ScopedMap< std::string, DeclarationWithType* > adapters; ///< Set of adapter functions in the current scope 210 211 211 DeclarationWithType *retval; 212 212 bool useRetval; … … 214 214 }; 215 215 216 /// Moves polymorphic returns in function types to pointer-type parameters, adds type size and assertion parameters to parameter lists as well 216 class OffsetPackExpr; // forward declaration so that it can be mutated by Pass2 217 218 /// * Moves polymorphic returns in function types to pointer-type parameters 219 /// * adds type size and assertion parameters to parameter lists 220 /// * does dynamic calculation of type layouts 217 221 class Pass2 : public PolyMutator { 218 222 public: … … 225 229 virtual Type *mutate( PointerType *pointerType ); 226 230 virtual Type *mutate( FunctionType *funcType ); 231 virtual Expression *mutate( SizeofExpr *sizeofExpr ); 232 virtual Expression *mutate( AlignofExpr *alignofExpr ); 233 virtual Expression *mutate( OffsetofExpr *offsetofExpr ); 234 Expression *mutate( OffsetPackExpr *offsetPackExpr ); 235 236 virtual void doBeginScope(); 237 virtual void doEndScope(); 227 238 private: 228 239 void addAdapters( FunctionType *functionType ); 240 /// Makes a new variable in the current scope with the given name, type & optional initializer 241 ObjectDecl *makeVar( const std::string &name, Type *type, Initializer *init = 0 ); 242 /// returns true if the type has a dynamic layout; such a layout will be stored in appropriately-named local variables when the function returns 243 bool findGeneric( Type *ty ); 244 /// adds type parameters to the layout call; will generate the appropriate parameters if needed 245 void addOtypeParamsToLayoutCall( UntypedExpr *layoutCall, const std::list< Type* > &otypeParams ); 229 246 230 247 std::map< UniqueId, std::string > adapterName; 248 ScopedSet< std::string > knownLayouts; ///< Set of generic type layouts known in the current scope, indexed by sizeofName 249 ScopedSet< std::string > knownOffsets; ///< Set of non-generic types for which the offset array exists in the current scope, indexed by offsetofName 250 }; 251 252 /// Special internal expression for offset arrays inserted by Pass1 and replaced by Pass2 253 class OffsetPackExpr : public Expression { 254 public: 255 OffsetPackExpr( StructInstType *type_, Expression *aname_ = 0 ) : Expression( aname_ ), type( type_ ) { 256 add_result( new ArrayType( Type::Qualifiers(), new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), 0, false, false ) ); 257 } 258 259 OffsetPackExpr( const OffsetPackExpr &other ) : Expression( other ), type( maybeClone( other.type ) ) {} 260 virtual ~OffsetPackExpr() { delete type; } 261 262 StructInstType *get_type() const { return type; } 263 void set_type( StructInstType *newValue ) { type = newValue; } 264 265 virtual OffsetPackExpr *clone() const { return new OffsetPackExpr( *this ); } 266 virtual void accept( Visitor &v ) { /* do nothing */ } 267 virtual Expression *acceptMutator( Mutator &m ) { 268 // only act if the mutator is a Pass2, which knows about this class 269 if ( Pass2 *m2 = dynamic_cast< Pass2* >( &m ) ) { 270 return m2->mutate( this ); 271 } else { 272 return this; 273 } 274 } 275 276 virtual void print( std::ostream &os, int indent = 0 ) const { 277 os << std::string( indent, ' ' ) << "Offset pack expression on "; 278 279 if ( type ) { 280 type->print(os, indent + 2); 281 } else { 282 os << "<NULL>"; 283 } 284 285 os << std::endl; 286 Expression::print( os, indent ); 287 } 288 289 private: 290 StructInstType *type; 231 291 }; 232 292 … … 633 693 634 694 DeclarationWithType *Pass1::mutate( FunctionDecl *functionDecl ) { 635 // if this is a polymorphicassignment function, put it in the map for this scope695 // if this is a assignment function, put it in the map for this scope 636 696 if ( Type *assignedType = isAssignment( functionDecl ) ) { 637 697 if ( ! dynamic_cast< TypeInstType* >( assignedType ) ) { … … 723 783 } 724 784 725 Expression *Pass1::makeOffsetArray( StructInstType *ty ) {726 std::list< Declaration* > &baseMembers = ty->get_baseStruct()->get_members();727 728 // make a new temporary array729 Type *offsetType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );730 std::stringstream lenGen;731 lenGen << baseMembers.size();732 ConstantExpr *lenExpr = new ConstantExpr( Constant( offsetType->clone(), lenGen.str() ) );733 ObjectDecl *arrayTemp = makeTemporary( new ArrayType( Type::Qualifiers(), offsetType, lenExpr, false, false ) );734 735 // build initializer list for temporary736 std::list< Initializer* > inits;737 for ( std::list< Declaration* >::const_iterator member = baseMembers.begin(); member != baseMembers.end(); ++member ) {738 DeclarationWithType *memberDecl;739 if ( DeclarationWithType *origMember = dynamic_cast< DeclarationWithType* >( *member ) ) {740 memberDecl = origMember->clone();741 } else {742 memberDecl = new ObjectDecl( (*member)->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, offsetType->clone(), 0 );743 }744 inits.push_back( new SingleInit( new OffsetofExpr( ty->clone(), memberDecl ) ) );745 }746 arrayTemp->set_init( new ListInit( inits ) );747 748 // return variable pointing to temporary749 return new VariableExpr( arrayTemp );750 }751 752 785 void Pass1::passArgTypeVars( ApplicationExpr *appExpr, Type *parmType, Type *argBaseType, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars, std::set< std::string > &seenTypes ) { 753 786 Type *polyBase = hasPolyBase( parmType, exprTyVars ); … … 762 795 if ( dynamic_cast< StructInstType* >( polyBase ) ) { 763 796 if ( StructInstType *argBaseStructType = dynamic_cast< StructInstType* >( argBaseType ) ) { 764 arg = appExpr->get_args().insert( arg, makeOffsetArray( argBaseStructType ) ); 765 arg++; 797 // zero-length arrays are forbidden by C, so don't pass offset for empty struct 798 if ( ! argBaseStructType->get_baseStruct()->get_members().empty() ) { 799 arg = appExpr->get_args().insert( arg, new OffsetPackExpr( argBaseStructType ) ); 800 arg++; 801 } 766 802 } else { 767 803 throw SemanticError( "Cannot pass non-struct type for generic struct" ); … … 1610 1646 ++last; 1611 1647 1612 if ( dynamic_cast< StructInstType* >( polyBase ) ) { 1613 offsetParm = newPtr.clone(); 1614 offsetParm->set_name( offsetofName( polyBase ) ); 1615 last = funcType->get_parameters().insert( last, offsetParm ); 1616 ++last; 1648 if ( StructInstType *polyBaseStruct = dynamic_cast< StructInstType* >( polyBase ) ) { 1649 // NOTE zero-length arrays are illegal in C, so empty structs have no offset array 1650 if ( ! polyBaseStruct->get_baseStruct()->get_members().empty() ) { 1651 offsetParm = newPtr.clone(); 1652 offsetParm->set_name( offsetofName( polyBase ) ); 1653 last = funcType->get_parameters().insert( last, offsetParm ); 1654 ++last; 1655 } 1617 1656 } 1618 1657 1619 1658 seenTypes.insert( sizeName ); 1659 knownLayouts.insert( sizeName ); // make sure that any type information passed into the function is accounted for 1620 1660 } 1621 1661 } … … 1629 1669 scopeTyVars = oldtyVars; 1630 1670 return funcType; 1671 } 1672 1673 ObjectDecl *Pass2::makeVar( const std::string &name, Type *type, Initializer *init ) { 1674 ObjectDecl *newObj = new ObjectDecl( name, DeclarationNode::NoStorageClass, LinkageSpec::C, 0, type, init ); 1675 stmtsToAdd.push_back( new DeclStmt( noLabels, newObj ) ); 1676 return newObj; 1677 } 1678 1679 void Pass2::addOtypeParamsToLayoutCall( UntypedExpr *layoutCall, const std::list< Type* > &otypeParams ) { 1680 for ( std::list< Type* >::const_iterator param = otypeParams.begin(); param != otypeParams.end(); ++param ) { 1681 if ( findGeneric( *param ) ) { 1682 // push size/align vars for a generic parameter back 1683 layoutCall->get_args().push_back( new NameExpr( sizeofName( *param ) ) ); 1684 layoutCall->get_args().push_back( new NameExpr( alignofName( *param ) ) ); 1685 } else { 1686 layoutCall->get_args().push_back( new SizeofExpr( *param ) ); 1687 layoutCall->get_args().push_back( new AlignofExpr( *param ) ); 1688 } 1689 } 1690 } 1691 1692 /// returns true if any of the otype parameters have a dynamic layout and puts all otype parameters in the output list 1693 bool findGenericParams( std::list< TypeDecl* > &baseParams, std::list< Expression* > &typeParams, std::list< Type* > &out ) { 1694 bool hasDynamicLayout = false; 1695 1696 std::list< TypeDecl* >::const_iterator baseParam = baseParams.begin(); 1697 std::list< Expression* >::const_iterator typeParam = typeParams.begin(); 1698 for ( ; baseParam != baseParams.end() && typeParam != typeParams.end(); ++baseParam, ++typeParam ) { 1699 // skip non-otype parameters 1700 if ( (*baseParam)->get_kind() != TypeDecl::Any ) continue; 1701 TypeExpr *typeExpr = dynamic_cast< TypeExpr* >( *typeParam ); 1702 assert( typeExpr && "all otype parameters should be type expressions" ); 1703 1704 Type *type = typeExpr->get_type(); 1705 out.push_back( type ); 1706 if ( isPolyType( type ) ) hasDynamicLayout = true; 1707 } 1708 assert( baseParam == baseParams.end() && typeParam == typeParams.end() ); 1709 1710 return hasDynamicLayout; 1711 } 1712 1713 bool Pass2::findGeneric( Type *ty ) { 1714 if ( dynamic_cast< TypeInstType* >( ty ) ) { 1715 // NOTE this assumes that all type variables will be properly bound, and thus have their layouts in scope 1716 return true; 1717 } else if ( StructInstType *structTy = dynamic_cast< StructInstType* >( ty ) ) { 1718 // check if this type already has a layout generated for it 1719 std::string sizeName = sizeofName( ty ); 1720 if ( knownLayouts.find( sizeName ) != knownLayouts.end() ) return true; 1721 1722 // check if any of the type parameters have dynamic layout; if none do, this type is (or will be) monomorphized 1723 std::list< Type* > otypeParams; 1724 if ( ! findGenericParams( *structTy->get_baseParameters(), structTy->get_parameters(), otypeParams ) ) return false; 1725 1726 // insert local variables for layout and generate call to layout function 1727 knownLayouts.insert( sizeName ); // done early so as not to interfere with the later addition of parameters to the layout call 1728 Type *layoutType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ); 1729 1730 int n_members = structTy->get_baseStruct()->get_members().size(); 1731 if ( n_members == 0 ) { 1732 // all empty structs have the same layout - size 1, align 1 1733 makeVar( sizeName, layoutType, new SingleInit( new ConstantExpr( Constant::from( (unsigned long)1 ) ) ) ); 1734 makeVar( alignofName( ty ), layoutType->clone(), new SingleInit( new ConstantExpr( Constant::from( (unsigned long)1 ) ) ) ); 1735 // NOTE zero-length arrays are forbidden in C, so empty structs have no offsetof array 1736 } else { 1737 ObjectDecl *sizeVar = makeVar( sizeName, layoutType ); 1738 ObjectDecl *alignVar = makeVar( alignofName( ty ), layoutType->clone() ); 1739 ObjectDecl *offsetVar = makeVar( offsetofName( ty ), new ArrayType( Type::Qualifiers(), layoutType->clone(), new ConstantExpr( Constant::from( n_members ) ), false, false ) ); 1740 1741 // generate call to layout function 1742 UntypedExpr *layoutCall = new UntypedExpr( new NameExpr( "__layoutof_" + structTy->get_baseStruct()->get_name() ) ); 1743 layoutCall->get_args().push_back( new AddressExpr( new VariableExpr( sizeVar ) ) ); 1744 layoutCall->get_args().push_back( new AddressExpr( new VariableExpr( alignVar ) ) ); 1745 layoutCall->get_args().push_back( new VariableExpr( offsetVar ) ); 1746 addOtypeParamsToLayoutCall( layoutCall, otypeParams ); 1747 1748 stmtsToAdd.push_back( new ExprStmt( noLabels, layoutCall ) ); 1749 } 1750 1751 return true; 1752 } else if ( UnionInstType *unionTy = dynamic_cast< UnionInstType* >( ty ) ) { 1753 // check if this type already has a layout generated for it 1754 std::string sizeName = sizeofName( ty ); 1755 if ( knownLayouts.find( sizeName ) != knownLayouts.end() ) return true; 1756 1757 // check if any of the type parameters have dynamic layout; if none do, this type is (or will be) monomorphized 1758 std::list< Type* > otypeParams; 1759 if ( ! findGenericParams( *unionTy->get_baseParameters(), unionTy->get_parameters(), otypeParams ) ) return false; 1760 1761 // insert local variables for layout and generate call to layout function 1762 knownLayouts.insert( sizeName ); // done early so as not to interfere with the later addition of parameters to the layout call 1763 Type *layoutType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ); 1764 1765 ObjectDecl *sizeVar = makeVar( sizeName, layoutType ); 1766 ObjectDecl *alignVar = makeVar( alignofName( ty ), layoutType->clone() ); 1767 1768 // generate call to layout function 1769 UntypedExpr *layoutCall = new UntypedExpr( new NameExpr( "__layoutof_" + unionTy->get_baseUnion()->get_name() ) ); 1770 layoutCall->get_args().push_back( new AddressExpr( new VariableExpr( sizeVar ) ) ); 1771 layoutCall->get_args().push_back( new AddressExpr( new VariableExpr( alignVar ) ) ); 1772 addOtypeParamsToLayoutCall( layoutCall, otypeParams ); 1773 1774 stmtsToAdd.push_back( new ExprStmt( noLabels, layoutCall ) ); 1775 1776 return true; 1777 } 1778 1779 return false; 1780 } 1781 1782 Expression *Pass2::mutate( SizeofExpr *sizeofExpr ) { 1783 Type *ty = sizeofExpr->get_type(); 1784 if ( findGeneric( ty ) ) { 1785 Expression *ret = new NameExpr( sizeofName( ty ) ); 1786 delete sizeofExpr; 1787 return ret; 1788 } 1789 return sizeofExpr; 1790 } 1791 1792 Expression *Pass2::mutate( AlignofExpr *alignofExpr ) { 1793 Type *ty = alignofExpr->get_type(); 1794 if ( findGeneric( ty ) ) { 1795 Expression *ret = new NameExpr( alignofName( ty ) ); 1796 delete alignofExpr; 1797 return ret; 1798 } 1799 return alignofExpr; 1800 } 1801 1802 Expression *Pass2::mutate( OffsetofExpr *offsetofExpr ) { 1803 findGeneric( offsetofExpr->get_type() ); 1804 return offsetofExpr; 1805 } 1806 1807 Expression *Pass2::mutate( OffsetPackExpr *offsetPackExpr ) { 1808 StructInstType *ty = offsetPackExpr->get_type(); 1809 1810 Expression *ret = 0; 1811 if ( findGeneric( ty ) ) { 1812 // pull offset back from generated type information 1813 ret = new NameExpr( offsetofName( ty ) ); 1814 } else { 1815 std::string offsetName = offsetofName( ty ); 1816 if ( knownOffsets.find( offsetName ) != knownOffsets.end() ) { 1817 // use the already-generated offsets for this type 1818 ret = new NameExpr( offsetName ); 1819 } else { 1820 std::list< Declaration* > &baseMembers = ty->get_baseStruct()->get_members(); 1821 Type *offsetType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ); 1822 1823 // build initializer list for offset array 1824 std::list< Initializer* > inits; 1825 for ( std::list< Declaration* >::const_iterator member = baseMembers.begin(); member != baseMembers.end(); ++member ) { 1826 DeclarationWithType *memberDecl; 1827 if ( DeclarationWithType *origMember = dynamic_cast< DeclarationWithType* >( *member ) ) { 1828 memberDecl = origMember->clone(); 1829 } else { 1830 memberDecl = new ObjectDecl( (*member)->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, offsetType->clone(), 0 ); 1831 } 1832 inits.push_back( new SingleInit( new OffsetofExpr( ty->clone(), memberDecl ) ) ); 1833 } 1834 1835 // build the offset array and replace the pack with a reference to it 1836 ObjectDecl *offsetArray = makeVar( offsetName, new ArrayType( Type::Qualifiers(), offsetType, new ConstantExpr( Constant::from( baseMembers.size() ) ), false, false ), 1837 new ListInit( inits ) ); 1838 ret = new VariableExpr( offsetArray ); 1839 } 1840 } 1841 1842 delete offsetPackExpr; 1843 return ret; 1844 } 1845 1846 void Pass2::doBeginScope() { 1847 knownLayouts.beginScope(); 1848 knownOffsets.beginScope(); 1849 } 1850 1851 void Pass2::doEndScope() { 1852 knownLayouts.endScope(); 1853 knownOffsets.beginScope(); 1631 1854 } 1632 1855
Note: See TracChangeset
for help on using the changeset viewer.