Changes in src/GenPoly/Specialize.cc [dc0557d:68fe077a]
- File:
-
- 1 edited
-
src/GenPoly/Specialize.cc (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/GenPoly/Specialize.cc
rdc0557d r68fe077a 10 10 // Created On : Mon May 18 07:44:20 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Mar 6 23:13:00201713 // Update Count : 3 012 // Last Modified On : Thu Mar 16 07:53:59 2017 13 // Update Count : 31 14 14 // 15 15 … … 77 77 } 78 78 79 /// True if both types have the same structure, but not necessarily the same types.80 /// That is, either both types are tuple types with the same size (recursively), or81 /// both are not tuple types.82 bool matchingTupleStructure( Type * t1, Type * t2 ) {83 TupleType * tuple1 = dynamic_cast< TupleType * >( t1 );84 TupleType * tuple2 = dynamic_cast< TupleType * >( t2 );85 if ( tuple1 && tuple2 ) {86 if ( tuple1->size() != tuple2->size() ) return false;87 for ( auto types : group_iterate( tuple1->get_types(), tuple2->get_types() ) ) {88 if ( ! matchingTupleStructure( std::get<0>( types ), std::get<1>( types ) ) ) return false;89 }90 return true;91 } else if ( ! tuple1 && ! tuple2 ) return true;92 return false;93 }94 95 79 bool needsTupleSpecialization( Type *formalType, Type *actualType, TypeSubstitution *env ) { 96 // Needs tuple specialization if the structure of the formal type and actual type do not match. 97 // This is the case if the formal type has ttype polymorphism, or if the structure of tuple types 98 // between the function do not match exactly. 99 if ( FunctionType * fftype = getFunctionType( formalType ) ) { 100 if ( fftype->isTtype() ) return true; 101 FunctionType * aftype = getFunctionType( actualType ); 102 assertf( aftype, "formal type is a function type, but actual type is not." ); 103 if ( fftype->get_parameters().size() != aftype->get_parameters().size() ) return true; 104 for ( auto params : group_iterate( fftype->get_parameters(), aftype->get_parameters() ) ) { 105 DeclarationWithType * formal = std::get<0>(params); 106 DeclarationWithType * actual = std::get<1>(params); 107 if ( ! matchingTupleStructure( formal->get_type(), actual->get_type() ) ) return true; 108 } 80 if ( FunctionType * ftype = getFunctionType( formalType ) ) { 81 return ftype->isTtype(); 109 82 } 110 83 return false; … … 137 110 } 138 111 139 /// restructures the arguments to match the structure of the formal parameters of the actual function. 140 /// [begin, end) are the exploded arguments. 141 template< typename Iterator, typename OutIterator > 142 void structureArg( Type * type, Iterator & begin, Iterator end, OutIterator out ) { 143 if ( TupleType * tuple = dynamic_cast< TupleType * >( type ) ) { 112 /// restructures arg to match the structure of a single formal parameter. Assumes that atomic types are compatible (as the Resolver should have ensured this) 113 template< typename OutIterator > 114 void matchOneFormal( Expression * arg, unsigned & idx, Type * formal, OutIterator out ) { 115 if ( TupleType * tupleType = dynamic_cast< TupleType * >( formal ) ) { 144 116 std::list< Expression * > exprs; 145 for ( Type * t : *tuple ) {146 structureArg( t, begin, end, back_inserter( exprs ) );117 for ( Type * t : *tupleType ) { 118 matchOneFormal( arg, idx, t, back_inserter( exprs ) ); 147 119 } 148 120 *out++ = new TupleExpr( exprs ); 149 121 } else { 150 assertf( begin != end, "reached the end of the arguments while structuring" ); 151 *out++ = *begin++; 152 } 153 } 154 155 /// explode assuming simple cases: either type is pure tuple (but not tuple expr) or type is non-tuple. 156 template< typename OutputIterator > 157 void explodeSimple( Expression * expr, OutputIterator out ) { 158 if ( TupleType * tupleType = dynamic_cast< TupleType * > ( expr->get_result() ) ) { 159 // tuple type, recursively index into its components 160 for ( unsigned int i = 0; i < tupleType->size(); i++ ) { 161 explodeSimple( new TupleIndexExpr( expr->clone(), i ), out ); 122 *out++ = new TupleIndexExpr( arg->clone(), idx++ ); 123 } 124 } 125 126 /// restructures the ttype argument to match the structure of the formal parameters of the actual function. 127 /// [begin, end) are the formal parameters. 128 /// args is the list of arguments currently given to the actual function, the last of which needs to be restructured. 129 template< typename Iterator, typename OutIterator > 130 void fixLastArg( Expression * last, Iterator begin, Iterator end, OutIterator out ) { 131 if ( Tuples::isTtype( last->get_result() ) ) { 132 *out++ = last; 133 } else { 134 // safe_dynamic_cast for the assertion 135 safe_dynamic_cast< TupleType * >( last->get_result() ); 136 unsigned idx = 0; 137 for ( ; begin != end; ++begin ) { 138 DeclarationWithType * formal = *begin; 139 Type * formalType = formal->get_type(); 140 matchOneFormal( last, idx, formalType, out ); 162 141 } 163 delete expr; 164 } else { 165 // non-tuple type - output a clone of the expression 166 *out++ = expr; 142 delete last; 167 143 } 168 144 } … … 179 155 } // if 180 156 // create new thunk with same signature as formal type (C linkage, empty body) 181 FunctionDecl *thunkFunc = new FunctionDecl( thunkNamer.newName(), DeclarationNode::StorageClasses(), LinkageSpec::C, newType, new CompoundStmt( noLabels ) );157 FunctionDecl *thunkFunc = new FunctionDecl( thunkNamer.newName(), Type::StorageClasses(), LinkageSpec::C, newType, new CompoundStmt( noLabels ) ); 182 158 thunkFunc->fixUniqueId(); 183 159 … … 197 173 std::list< DeclarationWithType * >::iterator actualBegin = actualType->get_parameters().begin(); 198 174 std::list< DeclarationWithType * >::iterator actualEnd = actualType->get_parameters().end(); 199 200 std::list< Expression * > args; 175 std::list< DeclarationWithType * >::iterator formalBegin = funType->get_parameters().begin(); 176 std::list< DeclarationWithType * >::iterator formalEnd = funType->get_parameters().end(); 177 201 178 for ( DeclarationWithType* param : thunkFunc->get_functionType()->get_parameters() ) { 202 // name each thunk parameter and explode it - these are then threaded back into the actual function call.179 // walk the parameters to the actual function alongside the parameters to the thunk to find the location where the ttype parameter begins to satisfy parameters in the actual function. 203 180 param->set_name( paramNamer.newName() ); 204 explodeSimple( new VariableExpr( param ), back_inserter( args ) ); 205 } 206 207 // walk parameters to the actual function alongside the exploded thunk parameters and restructure the arguments to match the actual parameters. 208 std::list< Expression * >::iterator argBegin = args.begin(), argEnd = args.end(); 209 for ( ; actualBegin != actualEnd; ++actualBegin ) { 210 structureArg( (*actualBegin)->get_type(), argBegin, argEnd, back_inserter( appExpr->get_args() ) ); 211 } 212 181 assertf( formalBegin != formalEnd, "Reached end of formal parameters before finding ttype parameter" ); 182 if ( Tuples::isTtype((*formalBegin)->get_type()) ) { 183 fixLastArg( new VariableExpr( param ), actualBegin, actualEnd, back_inserter( appExpr->get_args() ) ); 184 break; 185 } 186 assertf( actualBegin != actualEnd, "reached end of actual function's arguments before finding ttype parameter" ); 187 ++actualBegin; 188 ++formalBegin; 189 190 appExpr->get_args().push_back( new VariableExpr( param ) ); 191 } // for 213 192 appExpr->set_env( maybeClone( env ) ); 214 193 if ( inferParams ) {
Note:
See TracChangeset
for help on using the changeset viewer.