Changes in src/GenPoly/Box.cc [bc1ab61:4e284ea6]
- File:
-
- 1 edited
-
src/GenPoly/Box.cc (modified) (21 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/GenPoly/Box.cc
rbc1ab61 r4e284ea6 30 30 #include "FindFunction.h" 31 31 #include "ScopedMap.h" 32 #include "ScopedSet.h"33 32 #include "ScrubTyVars.h" 34 33 … … 63 62 FunctionType *makeAdapterType( FunctionType *adaptee, const TyVarMap &tyVars ); 64 63 65 /// Abstracts type equality for a list of parameter types 66 struct TypeList { 67 TypeList() : params() {} 68 TypeList( const std::list< Type* > &_params ) : params() { cloneAll(_params, params); } 69 TypeList( std::list< Type* > &&_params ) : params( _params ) {} 70 71 TypeList( const TypeList &that ) : params() { cloneAll(that.params, params); } 72 TypeList( TypeList &&that ) : params( std::move( that.params ) ) {} 64 /// Key for a unique concrete type; generic base type paired with type parameter list 65 struct ConcreteType { 66 ConcreteType() : base(NULL), params() {} 67 68 ConcreteType(AggregateDecl *_base, const std::list< Type* >& _params) : base(_base), params() { cloneAll(_params, params); } 69 70 ConcreteType(const ConcreteType& that) : base(that.base), params() { cloneAll(that.params, params); } 73 71 74 72 /// Extracts types from a list of TypeExpr* 75 TypeList( const std::list< TypeExpr* >& _params ) :params() {73 ConcreteType(AggregateDecl *_base, const std::list< TypeExpr* >& _params) : base(_base), params() { 76 74 for ( std::list< TypeExpr* >::const_iterator param = _params.begin(); param != _params.end(); ++param ) { 77 75 params.push_back( (*param)->get_type()->clone() ); … … 79 77 } 80 78 81 TypeList& operator= ( const TypeList &that) {79 ConcreteType& operator= (const ConcreteType& that) { 82 80 deleteAll( params ); 83 84 81 params.clear(); 82 83 base = that.base; 85 84 cloneAll( that.params, params ); 86 85 … … 88 87 } 89 88 90 TypeList& operator= ( TypeList &&that ) { 91 deleteAll( params ); 92 93 params = std::move( that.params ); 94 95 return *this; 96 } 97 98 ~TypeList() { deleteAll( params ); } 99 100 bool operator== ( const TypeList& that ) const { 89 ~ConcreteType() { deleteAll( params ); } 90 91 bool operator== (const ConcreteType& that) const { 92 if ( base != that.base ) return false; 93 94 SymTab::Indexer dummy; 101 95 if ( params.size() != that.params.size() ) return false; 102 103 SymTab::Indexer dummy;104 96 for ( std::list< Type* >::const_iterator it = params.begin(), jt = that.params.begin(); it != params.end(); ++it, ++jt ) { 105 97 if ( ! ResolvExpr::typesCompatible( *it, *jt, dummy ) ) return false; … … 108 100 } 109 101 102 AggregateDecl *base; ///< Base generic type 110 103 std::list< Type* > params; ///< Instantiation parameters 111 104 }; 112 105 113 /// Maps a key and a TypeListto the some value, accounting for scope114 template< typename Key, typenameValue >106 /// Maps a concrete type to the some value, accounting for scope 107 template< typename Value > 115 108 class InstantiationMap { 116 /// Wraps value for a specific (Key, TypeList) combination 117 typedef std::pair< TypeList, Value* > Instantiation; 118 /// List of TypeLists paired with their appropriate values 119 typedef std::vector< Instantiation > ValueList; 120 /// Underlying map type; maps keys to a linear list of corresponding TypeLists and values 121 typedef ScopedMap< Key*, ValueList > InnerMap; 122 123 InnerMap instantiations; ///< instantiations 109 /// Information about a specific instantiation of a generic type 110 struct Instantiation { 111 ConcreteType key; ///< Instantiation parameters for this type 112 Value *value; ///< Value for this instantiation 113 114 Instantiation() : key(), value(0) {} 115 Instantiation(const ConcreteType &_key, Value *_value) : key(_key), value(_value) {} 116 }; 117 /// Map of generic types to instantiations of them 118 typedef std::map< AggregateDecl*, std::vector< Instantiation > > Scope; 119 120 std::vector< Scope > scopes; ///< list of scopes, from outermost to innermost 124 121 125 122 public: 126 123 /// Starts a new scope 127 void beginScope() { instantiations.beginScope(); } 124 void beginScope() { 125 Scope scope; 126 scopes.push_back(scope); 127 } 128 128 129 129 /// Ends a scope 130 void endScope() { instantiations.endScope(); } 131 132 /// Gets the value for the (key, typeList) pair, returns NULL on none such. 133 Value *lookup( Key *key, const std::list< TypeExpr* >& params ) const { 134 TypeList typeList( params ); 135 136 // scan scopes for matches to the key 137 for ( typename InnerMap::const_iterator insts = instantiations.find( key ); insts != instantiations.end(); insts = instantiations.findNext( insts, key ) ) { 138 for ( typename ValueList::const_reverse_iterator inst = insts->second.rbegin(); inst != insts->second.rend(); ++inst ) { 139 if ( inst->first == typeList ) return inst->second; 130 void endScope() { 131 scopes.pop_back(); 132 } 133 134 /// Default constructor initializes with one scope 135 InstantiationMap() { beginScope(); } 136 137 // private: 138 /// Gets the value for the concrete instantiation of this type, assuming it has already been instantiated in the current scope. 139 /// Returns NULL on none such. 140 Value *lookup( AggregateDecl *generic, const std::list< TypeExpr* >& params ) { 141 ConcreteType key(generic, params); 142 // scan scopes from innermost out 143 for ( typename std::vector< Scope >::const_reverse_iterator scope = scopes.rbegin(); scope != scopes.rend(); ++scope ) { 144 // skip scope if no instantiations of this generic type 145 typename Scope::const_iterator insts = scope->find( generic ); 146 if ( insts == scope->end() ) continue; 147 // look through instantiations for matches to concrete type 148 for ( typename std::vector< Instantiation >::const_iterator inst = insts->second.begin(); inst != insts->second.end(); ++inst ) { 149 if ( inst->key == key ) return inst->value; 140 150 } 141 151 } 142 // no matching instantiation sfound152 // no matching instantiation found 143 153 return 0; 144 154 } 145 146 /// Adds a value for a (key, typeList) pair to the current scope 147 void insert( Key *key, const std::list< TypeExpr* > ¶ms, Value *value ) { 148 instantiations[ key ].push_back( Instantiation( TypeList( params ), value ) ); 149 } 155 public: 156 // StructDecl* lookup( StructInstType *inst, const std::list< TypeExpr* > &typeSubs ) { return (StructDecl*)lookup( inst->get_baseStruct(), typeSubs ); } 157 // UnionDecl* lookup( UnionInstType *inst, const std::list< TypeExpr* > &typeSubs ) { return (UnionDecl*)lookup( inst->get_baseUnion(), typeSubs ); } 158 159 // private: 160 /// Adds a value for a concrete type to the current scope 161 void insert( AggregateDecl *generic, const std::list< TypeExpr* > ¶ms, Value *value ) { 162 ConcreteType key(generic, params); 163 scopes.back()[generic].push_back( Instantiation( key, value ) ); 164 } 165 // public: 166 // void insert( StructInstType *inst, const std::list< TypeExpr* > &typeSubs, StructDecl *decl ) { insert( inst->get_baseStruct(), typeSubs, decl ); } 167 // void insert( UnionInstType *inst, const std::list< TypeExpr* > &typeSubs, UnionDecl *decl ) { insert( inst->get_baseUnion(), typeSubs, decl ); } 150 168 }; 151 169 … … 179 197 virtual void doEndScope(); 180 198 private: 199 /// Makes a new temporary array holding the offsets of the fields of `type`, and returns a new variable expression referencing it 200 Expression *makeOffsetArray( StructInstType *type ); 181 201 /// Pass the extra type parameters from polymorphic generic arguments or return types into a function application 182 202 void passArgTypeVars( ApplicationExpr *appExpr, Type *parmType, Type *argBaseType, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars, std::set< std::string > &seenTypes ); … … 205 225 ObjectDecl *makeTemporary( Type *type ); 206 226 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 227 std::map< std::string, DeclarationWithType *> assignOps; 228 ResolvExpr::TypeMap< DeclarationWithType > scopedAssignOps; 229 ScopedMap< std::string, DeclarationWithType* > adapters; 211 230 DeclarationWithType *retval; 212 231 bool useRetval; … … 214 233 }; 215 234 216 /// * Moves polymorphic returns in function types to pointer-type parameters 217 /// * adds type size and assertion parameters to parameter lists 218 /// * does dynamic calculation of type layouts 235 /// Moves polymorphic returns in function types to pointer-type parameters, adds type size and assertion parameters to parameter lists as well 219 236 class Pass2 : public PolyMutator { 220 237 public: … … 227 244 virtual Type *mutate( PointerType *pointerType ); 228 245 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();236 246 private: 237 247 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 248 245 249 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 250 }; 249 251 … … 251 253 class GenericInstantiator : public DeclMutator { 252 254 /// Map of (generic type, parameter list) pairs to concrete type instantiations 253 InstantiationMap< AggregateDecl , AggregateDecl> instantiations;255 InstantiationMap< AggregateDecl > instantiations; 254 256 /// Namer for concrete types 255 257 UniqueName typeNamer; … … 346 348 mutateTranslationUnit/*All*/( translationUnit, pass1 ); 347 349 mutateTranslationUnit/*All*/( translationUnit, pass2 ); 350 // instantiateGeneric( translationUnit ); 348 351 instantiator.mutateDeclarationList( translationUnit ); 349 352 mutateTranslationUnit/*All*/( translationUnit, memberFixer ); … … 650 653 651 654 DeclarationWithType *Pass1::mutate( FunctionDecl *functionDecl ) { 652 // if this is a assignment function, put it in the map for this scope655 // if this is a polymorphic assignment function, put it in the map for this scope 653 656 if ( Type *assignedType = isAssignment( functionDecl ) ) { 654 657 if ( ! dynamic_cast< TypeInstType* >( assignedType ) ) { … … 740 743 } 741 744 745 Expression *Pass1::makeOffsetArray( StructInstType *ty ) { 746 std::list< Declaration* > &baseMembers = ty->get_baseStruct()->get_members(); 747 748 // make a new temporary array 749 Type *offsetType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ); 750 std::stringstream lenGen; 751 lenGen << baseMembers.size(); 752 ConstantExpr *lenExpr = new ConstantExpr( Constant( offsetType->clone(), lenGen.str() ) ); 753 ObjectDecl *arrayTemp = makeTemporary( new ArrayType( Type::Qualifiers(), offsetType, lenExpr, false, false ) ); 754 755 // build initializer list for temporary 756 std::list< Initializer* > inits; 757 for ( std::list< Declaration* >::const_iterator member = baseMembers.begin(); member != baseMembers.end(); ++member ) { 758 DeclarationWithType *memberDecl; 759 if ( DeclarationWithType *origMember = dynamic_cast< DeclarationWithType* >( *member ) ) { 760 memberDecl = origMember->clone(); 761 } else { 762 memberDecl = new ObjectDecl( (*member)->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, offsetType->clone(), 0 ); 763 } 764 inits.push_back( new SingleInit( new OffsetofExpr( ty->clone(), memberDecl ) ) ); 765 } 766 arrayTemp->set_init( new ListInit( inits ) ); 767 768 // return variable pointing to temporary 769 return new VariableExpr( arrayTemp ); 770 } 771 742 772 void Pass1::passArgTypeVars( ApplicationExpr *appExpr, Type *parmType, Type *argBaseType, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars, std::set< std::string > &seenTypes ) { 743 773 Type *polyBase = hasPolyBase( parmType, exprTyVars ); … … 752 782 if ( dynamic_cast< StructInstType* >( polyBase ) ) { 753 783 if ( StructInstType *argBaseStructType = dynamic_cast< StructInstType* >( argBaseType ) ) { 754 // zero-length arrays are forbidden by C, so don't pass offset for empty struct 755 if ( ! argBaseStructType->get_baseStruct()->get_members().empty() ) { 756 arg = appExpr->get_args().insert( arg, new OffsetPackExpr( argBaseStructType->clone() ) ); 757 arg++; 758 } 784 arg = appExpr->get_args().insert( arg, makeOffsetArray( argBaseStructType ) ); 785 arg++; 759 786 } else { 760 787 throw SemanticError( "Cannot pass non-struct type for generic struct" ); … … 904 931 return; 905 932 } else if ( arg->get_results().front()->get_isLvalue() ) { 906 // VariableExpr and MemberExpr are lvalues; need to check this isn't coming from the second arg of a comma expression though (not an lvalue) 907 if ( CommaExpr *commaArg = dynamic_cast< CommaExpr* >( arg ) ) { 908 commaArg->set_arg2( new AddressExpr( commaArg->get_arg2() ) ); 909 } else { 910 arg = new AddressExpr( arg ); 911 } 933 // VariableExpr and MemberExpr are lvalues 934 arg = new AddressExpr( arg ); 912 935 } else { 913 936 // use type computed in unification to declare boxed variables … … 1004 1027 } // for 1005 1028 } 1029 1030 1006 1031 1007 1032 FunctionDecl *Pass1::makeAdapter( FunctionType *adaptee, FunctionType *realType, const std::string &mangleName, const TyVarMap &tyVars ) { … … 1403 1428 std::list< TypeDecl* >::const_iterator forallIt = forallParams.begin(); 1404 1429 for ( ; tyIt != tyParams.end() && forallIt != forallParams.end(); ++tyIt, ++forallIt ) { 1405 // Add appropriate mapping to assignment expression environment 1430 if ( (*forallIt)->get_kind() != TypeDecl::Any ) continue; // skip types with no assign op (ftype/dtype) 1431 1432 std::list< DeclarationWithType* > &asserts = (*forallIt)->get_assertions(); 1433 assert( ! asserts.empty() && "Type param needs assignment operator assertion" ); 1434 DeclarationWithType *actualDecl = asserts.front(); 1435 TypeInstType *actualType = isTypeInstAssignment( actualDecl ); 1436 assert( actualType && "First assertion of type with assertions should be assignment operator" ); 1406 1437 TypeExpr *formalTypeExpr = dynamic_cast< TypeExpr* >( *tyIt ); 1407 1438 assert( formalTypeExpr && "type parameters must be type expressions" ); 1408 1439 Type *formalType = formalTypeExpr->get_type(); 1409 assignExpr->get_env()->add( (*forallIt)->get_name(), formalType ); 1410 1411 // skip types with no assign op (ftype/dtype) 1412 if ( (*forallIt)->get_kind() != TypeDecl::Any ) continue; 1413 1414 // find assignment operator for formal type 1440 assignExpr->get_env()->add( actualType->get_name(), formalType ); 1441 1415 1442 DeclarationWithType *assertAssign = 0; 1416 1443 if ( TypeInstType *formalTypeInstType = dynamic_cast< TypeInstType* >( formalType ) ) { … … 1426 1453 } 1427 1454 } 1428 1429 // add inferred parameter for field assignment operator to assignment expression 1430 std::list< DeclarationWithType* > &asserts = (*forallIt)->get_assertions(); 1431 assert( ! asserts.empty() && "Type param needs assignment operator assertion" ); 1432 DeclarationWithType *actualDecl = asserts.front(); 1455 1456 1433 1457 assignExpr->get_inferParams()[ actualDecl->get_uniqueId() ] 1434 1458 = ParamEntry( assertAssign->get_uniqueId(), assertAssign->get_type()->clone(), actualDecl->get_type()->clone(), wrapFunctionDecl( assertAssign ) ); … … 1563 1587 ObjectDecl newPtr( "", DeclarationNode::NoStorageClass, LinkageSpec::C, 0, 1564 1588 new PointerType( Type::Qualifiers(), new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) ), 0 ); 1589 // ObjectDecl *newFunPtr = new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), new FunctionType( Type::Qualifiers(), true ) ), 0 ); 1565 1590 for ( std::list< TypeDecl *>::const_iterator tyParm = funcType->get_forall().begin(); tyParm != funcType->get_forall().end(); ++tyParm ) { 1566 1591 ObjectDecl *sizeParm, *alignParm; … … 1606 1631 ++last; 1607 1632 1608 if ( StructInstType *polyBaseStruct = dynamic_cast< StructInstType* >( polyBase ) ) { 1609 // NOTE zero-length arrays are illegal in C, so empty structs have no offset array 1610 if ( ! polyBaseStruct->get_baseStruct()->get_members().empty() ) { 1611 offsetParm = newPtr.clone(); 1612 offsetParm->set_name( offsetofName( polyBase ) ); 1613 last = funcType->get_parameters().insert( last, offsetParm ); 1614 ++last; 1615 } 1633 if ( dynamic_cast< StructInstType* >( polyBase ) ) { 1634 offsetParm = newPtr.clone(); 1635 offsetParm->set_name( offsetofName( polyBase ) ); 1636 last = funcType->get_parameters().insert( last, offsetParm ); 1637 ++last; 1616 1638 } 1617 1639 1618 1640 seenTypes.insert( sizeName ); 1619 knownLayouts.insert( sizeName ); // make sure that any type information passed into the function is accounted for1620 1641 } 1621 1642 } … … 1629 1650 scopeTyVars = oldtyVars; 1630 1651 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 1652 } 1817 1653
Note:
See TracChangeset
for help on using the changeset viewer.