Changeset 65660bd
- Timestamp:
- Sep 22, 2016, 8:14:56 AM (9 years ago)
- Branches:
- ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, with_gc
- Children:
- ac9ca96
- Parents:
- 1132b62
- git-author:
- Rob Schluntz <rschlunt@…> (09/21/16 23:43:37)
- git-committer:
- Rob Schluntz <rschlunt@…> (09/22/16 08:14:56)
- Location:
- src
- Files:
-
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
TabularUnified src/InitTweak/FixInit.cc ¶
r1132b62 r65660bd 69 69 70 70 /// create and resolve ctor/dtor expression: fname(var, [cpArg]) 71 ApplicationExpr* makeCtorDtor( const std::string & fname, ObjectDecl * var, Expression * cpArg = NULL );72 ApplicationExpr* makeCtorDtor( const std::string & fname, Expression * thisArg, Expression * cpArg = NULL );71 Expression * makeCtorDtor( const std::string & fname, ObjectDecl * var, Expression * cpArg = NULL ); 72 Expression * makeCtorDtor( const std::string & fname, Expression * thisArg, Expression * cpArg = NULL ); 73 73 /// true if type does not need to be copy constructed to ensure correctness 74 74 bool skipCopyConstruct( Type * type ); … … 360 360 } 361 361 362 ApplicationExpr* ResolveCopyCtors::makeCtorDtor( const std::string & fname, ObjectDecl * var, Expression * cpArg ) {362 Expression * ResolveCopyCtors::makeCtorDtor( const std::string & fname, ObjectDecl * var, Expression * cpArg ) { 363 363 assert( var ); 364 364 return makeCtorDtor( fname, new AddressExpr( new VariableExpr( var ) ), cpArg ); 365 365 } 366 366 367 ApplicationExpr* ResolveCopyCtors::makeCtorDtor( const std::string & fname, Expression * thisArg, Expression * cpArg ) {367 Expression * ResolveCopyCtors::makeCtorDtor( const std::string & fname, Expression * thisArg, Expression * cpArg ) { 368 368 assert( thisArg ); 369 369 UntypedExpr * untyped = new UntypedExpr( new NameExpr( fname ) ); … … 375 375 // (VariableExpr and already resolved expression) 376 376 CP_CTOR_PRINT( std::cerr << "ResolvingCtorDtor " << untyped << std::endl; ) 377 ApplicationExpr * resolved = dynamic_cast< ApplicationExpr * >( ResolvExpr::findVoidExpression( untyped, *this ) ); 377 Expression * resolved = ResolvExpr::findVoidExpression( untyped, *this ); 378 assert( resolved ); 378 379 if ( resolved->get_env() ) { 379 380 env->add( *resolved->get_env() ); 380 381 } // if 381 382 382 assert( resolved );383 383 delete untyped; 384 384 return resolved; … … 392 392 if ( skipCopyConstruct( result ) ) return; // skip certain non-copyable types 393 393 394 if ( TupleExpr * tupleExpr = dynamic_cast< TupleExpr * >( arg ) ) {395 for ( Expression * & expr : tupleExpr->get_exprs() ) {396 copyConstructArg( expr, impCpCtorExpr );397 }398 return;399 }400 401 394 // type may involve type variables, so apply type substitution to get temporary variable's actual type 402 395 result = result->clone(); … … 407 400 // create and resolve copy constructor 408 401 CP_CTOR_PRINT( std::cerr << "makeCtorDtor for an argument" << std::endl; ) 409 ApplicationExpr * cpCtor = makeCtorDtor( "?{}", tmp, arg ); 410 411 // if the chosen constructor is intrinsic, the copy is unnecessary, so 412 // don't create the temporary and don't call the copy constructor 413 VariableExpr * function = dynamic_cast< VariableExpr * >( cpCtor->get_function() ); 414 assert( function ); 415 if ( function->get_var()->get_linkage() != LinkageSpec::Intrinsic ) { 416 // replace argument to function call with temporary 417 arg = new CommaExpr( cpCtor, new VariableExpr( tmp ) ); 418 impCpCtorExpr->get_tempDecls().push_back( tmp ); 419 impCpCtorExpr->get_dtors().push_front( makeCtorDtor( "^?{}", tmp ) ); 420 } // if 402 Expression * cpCtor = makeCtorDtor( "?{}", tmp, arg ); 403 404 if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( cpCtor ) ) { 405 // if the chosen constructor is intrinsic, the copy is unnecessary, so 406 // don't create the temporary and don't call the copy constructor 407 VariableExpr * function = dynamic_cast< VariableExpr * >( appExpr->get_function() ); 408 assert( function ); 409 if ( function->get_var()->get_linkage() == LinkageSpec::Intrinsic ) return; 410 } 411 412 // replace argument to function call with temporary 413 arg = new CommaExpr( cpCtor, new VariableExpr( tmp ) ); 414 impCpCtorExpr->get_tempDecls().push_back( tmp ); 415 impCpCtorExpr->get_dtors().push_front( makeCtorDtor( "^?{}", tmp ) ); 421 416 } 422 417 423 418 void ResolveCopyCtors::destructRet( Expression * ret, ImplicitCopyCtorExpr * impCpCtorExpr ) { 424 if ( TupleType * tupleType = dynamic_cast< TupleType * > ( ret->get_result() ) ) {425 int idx = 0;426 for ( Type *& t : tupleType->get_types() ) {427 (void)t;428 destructRet( new TupleIndexExpr( ret->clone(), idx++ ), impCpCtorExpr );429 }430 return;431 }432 419 impCpCtorExpr->get_dtors().push_front( makeCtorDtor( "^?{}", new AddressExpr( ret ) ) ); 433 420 } -
TabularUnified src/InitTweak/GenInit.cc ¶
r1132b62 r65660bd 29 29 #include "GenPoly/DeclMutator.h" 30 30 #include "GenPoly/ScopedSet.h" 31 #include "ResolvExpr/typeops.h" 31 32 32 33 namespace InitTweak { … … 50 51 51 52 protected: 52 std::list<DeclarationWithType*> returnVals;53 FunctionType * ftype; 53 54 UniqueName tempNamer; 54 55 std::string funcName; … … 86 87 87 88 bool isManaged( ObjectDecl * objDecl ) const ; // determine if object is managed 89 bool isManaged( Type * type ) const; // determine if type is managed 88 90 void handleDWT( DeclarationWithType * dwt ); // add type to managed if ctor/dtor 89 91 GenPoly::ScopedSet< std::string > managedTypes; … … 134 136 135 137 Statement *ReturnFixer::mutate( ReturnStmt *returnStmt ) { 136 // update for multiple return values138 std::list< DeclarationWithType * > & returnVals = ftype->get_returnVals(); 137 139 assert( returnVals.size() == 0 || returnVals.size() == 1 ); 138 140 // hands off if the function returns an lvalue - we don't want to allocate a temporary if a variable's address … … 156 158 157 159 DeclarationWithType* ReturnFixer::mutate( FunctionDecl *functionDecl ) { 158 ValueGuard< std::list<DeclarationWithType*> > oldReturnVals( returnVals ); 160 // xxx - need to handle named return values - this pass may need to happen 161 // after resolution? the ordering is tricky because return statements must be 162 // constructed - the simplest way to do that (while also handling multiple 163 // returns) is to structure the returnVals into a tuple, as done here. 164 // however, if the tuple return value is structured before resolution, 165 // it's difficult to resolve named return values, since the name is lost 166 // in conversion to a tuple. this might be easiest to deal with 167 // after reference types are added, as it may then be possible to 168 // uniformly move named return values to the parameter list directly 169 ValueGuard< FunctionType * > oldFtype( ftype ); 159 170 ValueGuard< std::string > oldFuncName( funcName ); 160 171 161 FunctionType * type = functionDecl->get_functionType(); 162 returnVals = type->get_returnVals(); 172 ftype = functionDecl->get_functionType(); 173 std::list< DeclarationWithType * > & retVals = ftype->get_returnVals(); 174 if ( retVals.size() > 1 ) { 175 TupleType * tupleType = safe_dynamic_cast< TupleType * >( ResolvExpr::extractResultType( ftype ) ); 176 ObjectDecl * newRet = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, tupleType, new ListInit( std::list<Initializer*>(), noDesignators, false ) ); 177 retVals.clear(); 178 retVals.push_back( newRet ); 179 } 163 180 funcName = functionDecl->get_name(); 164 181 DeclarationWithType * decl = Mutator::mutate( functionDecl ); … … 220 237 } 221 238 239 bool CtorDtor::isManaged( Type * type ) const { 240 return managedTypes.find( SymTab::Mangler::mangle( type ) ) != managedTypes.end(); 241 } 242 222 243 bool CtorDtor::isManaged( ObjectDecl * objDecl ) const { 223 244 Type * type = objDecl->get_type(); … … 225 246 type = at->get_base(); 226 247 } 227 return managedTypes.find( SymTab::Mangler::mangle( type ) ) != managedTypes.end(); 248 if ( TupleType * tupleType = dynamic_cast< TupleType * > ( type ) ) { 249 return std::any_of( tupleType->get_types().begin(), tupleType->get_types().end(), [&](Type * type) { return isManaged( type ); }); 250 } 251 return isManaged( type ); 228 252 } 229 253 -
TabularUnified src/ResolvExpr/Alternative.h ¶
r1132b62 r65660bd 45 45 TypeEnvironment env; 46 46 }; 47 48 /// helper function used by explode49 template< typename OutputIterator >50 void explodeUnique( Expression * expr, const Alternative & alt, OutputIterator out ) {51 Type * res = expr->get_result();52 if ( TupleType * tupleType = dynamic_cast< TupleType * > ( res ) ) {53 if ( TupleExpr * tupleExpr = dynamic_cast< TupleExpr * >( expr ) ) {54 // can open tuple expr and dump its exploded components55 for ( Expression * expr : tupleExpr->get_exprs() ) {56 explodeUnique( expr, alt, out );57 }58 } else {59 // tuple type, but not tuple expr - need to refer to single instance of the argument60 // expression and index into its components61 UniqueExpr * unq = new UniqueExpr( expr->clone() );62 for ( unsigned int i = 0; i < tupleType->size(); i++ ) {63 TupleIndexExpr * idx = new TupleIndexExpr( unq->clone(), i );64 explodeUnique( idx, alt, out );65 delete idx;66 }67 delete unq;68 }69 } else {70 // atomic (non-tuple) type - output a clone of the expression in a new alternative71 *out++ = Alternative( expr->clone(), alt.env, alt.cost, alt.cvtCost );72 }73 }74 75 /// expands a tuple-valued alternative into multiple alternatives, each with a non-tuple-type76 template< typename OutputIterator >77 void explode( const Alternative &alt, OutputIterator out ) {78 explodeUnique( alt.expr, alt, out );79 }80 81 // explode list of alternatives82 template< typename OutputIterator >83 void explode( const AltList & alts, OutputIterator out ) {84 for ( const Alternative & alt : alts ) {85 explode( alt, out );86 }87 }88 47 } // namespace ResolvExpr 89 48 -
TabularUnified src/ResolvExpr/AlternativeFinder.cc ¶
r1132b62 r65660bd 435 435 // flatten actuals so that each actual has an atomic (non-tuple) type 436 436 AltList exploded; 437 explode( actuals, back_inserter( exploded ) );437 Tuples::explode( actuals, back_inserter( exploded ) ); 438 438 439 439 AltList::iterator actualExpr = exploded.begin(); -
TabularUnified src/ResolvExpr/Resolver.cc ¶
r1132b62 r65660bd 38 38 39 39 virtual void visit( FunctionDecl *functionDecl ); 40 virtual void visit( ObjectDecl * functionDecl );40 virtual void visit( ObjectDecl *objectDecl ); 41 41 virtual void visit( TypeDecl *typeDecl ); 42 42 virtual void visit( EnumDecl * enumDecl ); … … 442 442 (*iter)->accept( *this ); 443 443 } // for 444 } else if ( TupleType * tt = dynamic_cast< TupleType * > ( initContext ) ) { 445 for ( Type * t : *tt ) { 446 if ( iter == end ) break; 447 initContext = t; 448 (*iter++)->accept( *this ); 449 } 444 450 } else if ( StructInstType * st = dynamic_cast< StructInstType * >( initContext ) ) { 445 451 resolveAggrInit( st->get_baseStruct(), iter, end ); -
TabularUnified src/SynTree/Expression.h ¶
r1132b62 r65660bd 696 696 }; 697 697 698 /// TupleAssignExpr represents a multiple assignment operation, where both sides of the assignment have tuple type, e.g. [a, b, c] = [d, e, f];, or a mass assignment operation, where the left hand side has tuple type and the right hand side does not, e.g. [a, b, c] = 5.0;698 /// TupleAssignExpr represents a multiple assignment operation, where both sides of the assignment have tuple type, e.g. [a, b, c] = [d, e, f];, a mass assignment operation, where the left hand side has tuple type and the right hand side does not, e.g. [a, b, c] = 5.0;, or a tuple ctor/dtor expression 699 699 class TupleAssignExpr : public Expression { 700 700 public: -
TabularUnified src/SynTree/TupleExpr.cc ¶
r1132b62 r65660bd 88 88 89 89 TupleAssignExpr::TupleAssignExpr( const std::list< Expression * > & assigns, const std::list< ObjectDecl * > & tempDecls, Expression * _aname ) : Expression( _aname ), assigns( assigns ), tempDecls( tempDecls ) { 90 TupleType * type = new TupleType( Type::Qualifiers() ); 91 for ( Expression * expr : assigns ) { 92 assert( expr->has_result() ); 93 type->get_types().push_back( expr->get_result()->clone() ); 94 } 95 set_result( type ); 90 set_result( Tuples::makeTupleType( assigns ) ); 96 91 } 97 92 -
TabularUnified src/Tuples/TupleAssignment.cc ¶
r1132b62 r65660bd 21 21 #include "Tuples.h" 22 22 #include "Common/SemanticError.h" 23 #include "InitTweak/InitTweak.h" 23 24 24 25 #include <functional> … … 35 36 // dispatcher for Tuple (multiple and mass) assignment operations 36 37 TupleAssignSpotter( ResolvExpr::AlternativeFinder & ); 37 void spot( UntypedExpr * expr, std::list<ResolvExpr::AltList> &possibilities );38 void spot( UntypedExpr * expr, const std::list<ResolvExpr::AltList> &possibilities ); 38 39 39 40 private: … … 42 43 struct Matcher { 43 44 public: 44 Matcher( TupleAssignSpotter &spotter, ResolvExpr::Alternative & lhs, ResolvExpr::Alternative & rhs );45 Matcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList & alts ); 45 46 virtual ~Matcher() {} 46 47 virtual void match( std::list< Expression * > &out ) = 0; … … 52 53 struct MassAssignMatcher : public Matcher { 53 54 public: 54 MassAssignMatcher( TupleAssignSpotter &spotter, ResolvExpr::Alternative & lhs, ResolvExpr::Alternative & rhs );55 MassAssignMatcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList & alts ); 55 56 virtual void match( std::list< Expression * > &out ); 56 57 }; … … 58 59 struct MultipleAssignMatcher : public Matcher { 59 60 public: 60 MultipleAssignMatcher( TupleAssignSpotter &spot, ResolvExpr::Alternative & lhs, ResolvExpr::Alternative & rhs );61 MultipleAssignMatcher( TupleAssignSpotter &spot, const ResolvExpr::AltList & alts ); 61 62 virtual void match( std::list< Expression * > &out ); 62 63 }; 63 64 64 65 ResolvExpr::AlternativeFinder ¤tFinder; 65 // Expression *rhs, *lhs;66 Matcher *matcher = nullptr;66 std::string fname; 67 std::unique_ptr< Matcher > matcher; 67 68 }; 68 69 … … 74 75 } 75 76 77 template< typename AltIter > 78 bool isMultAssign( AltIter begin, AltIter end ) { 79 // multiple assignment if more than one alternative in the range or if 80 // the alternative is a tuple 81 if ( begin == end ) return false; 82 if ( isTuple( begin->expr ) ) return true; 83 return ++begin != end; 84 } 85 76 86 bool pointsToTuple( Expression *expr ) { 77 87 // also check for function returning tuple of reference types 78 if ( AddressExpr *addr = dynamic_cast< AddressExpr * >( expr) ) { 88 if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) { 89 return pointsToTuple( castExpr->get_arg() ); 90 } else if ( AddressExpr *addr = dynamic_cast< AddressExpr * >( expr) ) { 79 91 return isTuple( addr->get_arg() ); 80 92 } … … 82 94 } 83 95 84 void handleTupleAssignment( ResolvExpr::AlternativeFinder & currentFinder, UntypedExpr * expr, std::list<ResolvExpr::AltList> &possibilities ) {96 void handleTupleAssignment( ResolvExpr::AlternativeFinder & currentFinder, UntypedExpr * expr, const std::list<ResolvExpr::AltList> &possibilities ) { 85 97 TupleAssignSpotter spotter( currentFinder ); 86 98 spotter.spot( expr, possibilities ); … … 90 102 : currentFinder(f) {} 91 103 92 void TupleAssignSpotter::spot( UntypedExpr * expr, std::list<ResolvExpr::AltList> &possibilities ) { 93 if ( NameExpr *assgnop = dynamic_cast< NameExpr * >(expr->get_function()) ) { 94 if ( assgnop->get_name() == "?=?" ) { 95 for ( std::list<ResolvExpr::AltList>::iterator ali = possibilities.begin(); ali != possibilities.end(); ++ali ) { 96 if ( ali->size() != 2 ) continue; // what does it mean if an assignment takes >2 arguments? grab args 2-N and group into a TupleExpr, then proceed? 97 ResolvExpr::Alternative & alt1 = ali->front(), & alt2 = ali->back(); 98 104 void TupleAssignSpotter::spot( UntypedExpr * expr, const std::list<ResolvExpr::AltList> &possibilities ) { 105 if ( NameExpr *op = dynamic_cast< NameExpr * >(expr->get_function()) ) { 106 if ( InitTweak::isCtorDtorAssign( op->get_name() ) ) { 107 fname = op->get_name(); 108 for ( std::list<ResolvExpr::AltList>::const_iterator ali = possibilities.begin(); ali != possibilities.end(); ++ali ) { 109 if ( ali->size() == 0 ) continue; // AlternativeFinder will natrually handle this case, if it's legal 110 if ( ali->size() <= 1 && InitTweak::isAssignment( op->get_name() ) ) { 111 // what does it mean if an assignment takes 1 argument? maybe someone defined such a function, in which case AlternativeFinder will naturally handle it 112 continue; 113 } 114 115 assert( ! ali->empty() ); 116 // grab args 2-N and group into a TupleExpr 117 const ResolvExpr::Alternative & alt1 = ali->front(); 118 auto begin = std::next(ali->begin(), 1), end = ali->end(); 99 119 if ( pointsToTuple(alt1.expr) ) { 100 MultipleAssignMatcher multiMatcher( *this, alt1, alt2 ); 101 MassAssignMatcher massMatcher( *this, alt1, alt2 ); 102 if ( isTuple( alt2.expr ) ) { 103 matcher = &multiMatcher; 120 if ( isMultAssign( begin, end ) ) { 121 matcher.reset( new MultipleAssignMatcher( *this, *ali ) ); 104 122 } else { 105 123 // mass assignment 106 matcher = &massMatcher;124 matcher.reset( new MassAssignMatcher( *this, *ali ) ); 107 125 } 108 126 match(); 109 } else if ( isTuple( alt2.expr ) ) {110 throw SemanticError("Cannot assign a tuple value into a non-tuple lvalue.", expr);111 127 } 112 128 } … … 146 162 } 147 163 148 TupleAssignSpotter::Matcher::Matcher( TupleAssignSpotter &spotter, ResolvExpr::Alternative & lhs, ResolvExpr::Alternative & rhs ) : spotter(spotter) { 149 if (AddressExpr *addr = dynamic_cast<AddressExpr *>(lhs.expr) ) { 150 // xxx - not every assignment NEEDS to have the first argument as address-taken, e.g. a manual call to assignment. What to do in this case? skip it as a possibility for TupleAssignment, since the type will always be T*, where T can never be a tuple? Is this true? 151 152 // explode the lhs so that each field of the tuple-valued-expr is assigned. 153 ResolvExpr::Alternative lhsAlt( addr->get_arg()->clone(), lhs.env, lhs.cost, lhs.cvtCost ); 154 explode( lhsAlt, back_inserter(this->lhs) ); 155 } 156 } 157 158 TupleAssignSpotter::MassAssignMatcher::MassAssignMatcher( TupleAssignSpotter &spotter, ResolvExpr::Alternative & lhs, ResolvExpr::Alternative & rhs ) : Matcher( spotter, lhs, rhs ) { 159 this->rhs.push_back( rhs ); 160 } 161 162 TupleAssignSpotter::MultipleAssignMatcher::MultipleAssignMatcher( TupleAssignSpotter &spotter, ResolvExpr::Alternative & lhs, ResolvExpr::Alternative & rhs ) : Matcher( spotter, lhs, rhs ) { 163 164 TupleAssignSpotter::Matcher::Matcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList &alts ) : spotter(spotter) { 165 assert( ! alts.empty() ); 166 ResolvExpr::Alternative lhsAlt = alts.front(); 167 // peel off the cast that exists on ctor/dtor expressions 168 bool isCast = false; 169 if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( lhsAlt.expr ) ) { 170 lhsAlt.expr = castExpr->get_arg(); 171 castExpr->set_arg( nullptr ); 172 delete castExpr; 173 isCast = true; 174 } 175 176 // explode the lhs so that each field of the tuple-valued-expr is assigned. 177 explode( lhsAlt, back_inserter(lhs) ); 178 // and finally, re-add the cast to each lhs expr, so that qualified tuple fields can be constructed 179 if ( isCast ) { 180 for ( ResolvExpr::Alternative & alt : lhs ) { 181 Expression *& expr = alt.expr; 182 Type * castType = expr->get_result()->clone(); 183 Type * type = InitTweak::getPointerBase( castType ); 184 assert( type ); 185 type->get_qualifiers() -= Type::Qualifiers(true, true, true, false, true, true); 186 type->set_isLvalue( true ); // xxx - might not need this 187 expr = new CastExpr( expr, castType ); 188 } 189 } 190 // } 191 } 192 193 TupleAssignSpotter::MassAssignMatcher::MassAssignMatcher( TupleAssignSpotter &spotter,const ResolvExpr::AltList & alts ) : Matcher( spotter, alts ) { 194 assert( alts.size() == 1 || alts.size() == 2 ); 195 if ( alts.size() == 2 ) { 196 rhs.push_back( alts.back() ); 197 } 198 } 199 200 TupleAssignSpotter::MultipleAssignMatcher::MultipleAssignMatcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList & alts ) : Matcher( spotter, alts ) { 164 201 // explode the rhs so that each field of the tuple-valued-expr is assigned. 165 explode( rhs, back_inserter(this->rhs) );166 } 167 168 UntypedExpr * create Assgn(ObjectDecl *left, ObjectDecl *right ) {169 assert( left && right);202 explode( std::next(alts.begin(), 1), alts.end(), back_inserter(rhs) ); 203 } 204 205 UntypedExpr * createFunc( const std::string &fname, ObjectDecl *left, ObjectDecl *right ) { 206 assert( left ); 170 207 std::list< Expression * > args; 171 208 args.push_back( new AddressExpr( new UntypedExpr( new NameExpr("*?"), std::list< Expression * >{ new VariableExpr( left ) } ) ) ); 172 args.push_back( new VariableExpr( right ) ); 173 return new UntypedExpr( new NameExpr( "?=?" ), args ); 209 // args.push_back( new AddressExpr( new VariableExpr( left ) ) ); 210 if ( right ) args.push_back( new VariableExpr( right ) ); 211 return new UntypedExpr( new NameExpr( fname ), args ); 174 212 } 175 213 … … 182 220 static UniqueName lhsNamer( "__massassign_L" ); 183 221 static UniqueName rhsNamer( "__massassign_R" ); 184 assert ( ! lhs.empty() && rhs.size() == 1);185 186 ObjectDecl * rtmp = newObject( rhsNamer, rhs.front().expr );222 assert ( ! lhs.empty() && rhs.size() <= 1); 223 224 ObjectDecl * rtmp = rhs.size() == 1 ? newObject( rhsNamer, rhs.front().expr ) : nullptr; 187 225 for ( ResolvExpr::Alternative & lhsAlt : lhs ) { 188 ObjectDecl * ltmp = newObject( lhsNamer, new AddressExpr( lhsAlt.expr ));189 out.push_back( create Assgn(ltmp, rtmp ) );226 ObjectDecl * ltmp = newObject( lhsNamer, lhsAlt.expr ); 227 out.push_back( createFunc( spotter.fname, ltmp, rtmp ) ); 190 228 tmpDecls.push_back( ltmp ); 191 229 } 192 tmpDecls.push_back( rtmp );230 if ( rtmp ) tmpDecls.push_back( rtmp ); 193 231 } 194 232 … … 201 239 std::list< ObjectDecl * > rtmp; 202 240 std::transform( lhs.begin(), lhs.end(), back_inserter( ltmp ), []( ResolvExpr::Alternative & alt ){ 203 return newObject( lhsNamer, new AddressExpr( alt.expr ));241 return newObject( lhsNamer, alt.expr ); 204 242 }); 205 243 std::transform( rhs.begin(), rhs.end(), back_inserter( rtmp ), []( ResolvExpr::Alternative & alt ){ 206 244 return newObject( rhsNamer, alt.expr ); 207 245 }); 208 zipWith( ltmp.begin(), ltmp.end(), rtmp.begin(), rtmp.end(), back_inserter(out), createAssgn);246 zipWith( ltmp.begin(), ltmp.end(), rtmp.begin(), rtmp.end(), back_inserter(out), [&](ObjectDecl * obj1, ObjectDecl * obj2 ) { return createFunc(spotter.fname, obj1, obj2); } ); 209 247 tmpDecls.splice( tmpDecls.end(), ltmp ); 210 248 tmpDecls.splice( tmpDecls.end(), rtmp ); -
TabularUnified src/Tuples/TupleExpansion.cc ¶
r1132b62 r65660bd 49 49 50 50 virtual Type * mutate( TupleType * tupleType ); 51 virtual Type * mutate( FunctionType * ftype );52 51 53 52 virtual CompoundStmt * mutate( CompoundStmt * stmt ) { … … 119 118 delete assnExpr; 120 119 return new StmtExpr( compoundStmt ); 121 }122 123 Type * TupleTypeReplacer::mutate( FunctionType * ftype ) {124 // replace multiple-returning functions with functions which return a tuple125 if ( ftype->get_returnVals().size() > 1 ) {126 TupleType * tupleType = safe_dynamic_cast<TupleType *>( ResolvExpr::extractResultType( ftype ) );127 ObjectDecl * retVal = new ObjectDecl( "__tuple_ret", DeclarationNode::NoStorageClass, LinkageSpec::C, nullptr, tupleType, nullptr );128 // xxx - replace all uses of return vals with appropriate tuple index expr129 deleteAll( ftype->get_returnVals() );130 ftype->get_returnVals().clear();131 ftype->get_returnVals().push_back( retVal );132 }133 return Parent::mutate( ftype );134 120 } 135 121 … … 167 153 } 168 154 155 Expression * replaceTupleExpr( Type * result, const std::list< Expression * > & exprs ) { 156 if ( result->isVoid() ) { 157 // void result - don't need to produce a value for cascading - just output a chain of comma exprs 158 assert( ! exprs.empty() ); 159 std::list< Expression * >::const_iterator iter = exprs.begin(); 160 Expression * expr = *iter++; 161 for ( ; iter != exprs.end(); ++iter ) { 162 expr = new CommaExpr( expr, *iter ); 163 } 164 return expr; 165 } else { 166 // typed tuple expression - produce a compound literal which performs each of the expressions 167 // as a distinct part of its initializer - the produced compound literal may be used as part of 168 // another expression 169 std::list< Initializer * > inits; 170 for ( Expression * expr : exprs ) { 171 inits.push_back( new SingleInit( expr ) ); 172 } 173 return new CompoundLiteralExpr( result, new ListInit( inits ) ); 174 } 175 } 176 169 177 Expression * TupleExprExpander::mutate( TupleExpr * tupleExpr ) { 170 assert( tupleExpr->get_result() ); 171 std::list< Initializer * > inits; 172 for ( Expression * expr : tupleExpr->get_exprs() ) { 173 inits.push_back( new SingleInit( expr ) ); 174 } 175 return new CompoundLiteralExpr( tupleExpr->get_result(), new ListInit( inits ) ); 176 } 177 178 TupleType * makeTupleType( const std::list< Expression * > & exprs ) { 178 Type * result = tupleExpr->get_result(); 179 std::list< Expression * > exprs = tupleExpr->get_exprs(); 180 assert( result ); 181 182 tupleExpr->set_result( nullptr ); 183 tupleExpr->get_exprs().clear(); 184 delete tupleExpr; 185 186 return replaceTupleExpr( result, exprs ); 187 } 188 189 Type * makeTupleType( const std::list< Expression * > & exprs ) { 190 // produce the TupleType which aggregates the types of the exprs 179 191 TupleType *tupleType = new TupleType( Type::Qualifiers(true, true, true, true, true, false) ); 180 192 Type::Qualifiers &qualifiers = tupleType->get_qualifiers(); 181 193 for ( Expression * expr : exprs ) { 182 194 assert( expr->get_result() ); 195 if ( expr->get_result()->isVoid() ) { 196 // if the type of any expr is void, the type of the entire tuple is void 197 delete tupleType; 198 return new VoidType( Type::Qualifiers() ); 199 } 183 200 Type * type = expr->get_result()->clone(); 184 201 tupleType->get_types().push_back( type ); 202 // the qualifiers on the tuple type are the qualifiers that exist on all component types 185 203 qualifiers &= type->get_qualifiers(); 186 204 } // for 187 205 return tupleType; 206 } 207 208 namespace { 209 /// determines if impurity (read: side-effects) may exist in a piece of code. Currently gives a very crude approximation, wherein any function call expression means the code may be impure 210 class ImpurityDetector : public Visitor { 211 public: 212 typedef Visitor Parent; 213 virtual void visit( ApplicationExpr * appExpr ) { maybeImpure = true; } 214 virtual void visit( UntypedExpr * untypedExpr ) { maybeImpure = true; } 215 bool maybeImpure = false; 216 }; 217 } // namespace 218 219 bool maybeImpure( Expression * expr ) { 220 ImpurityDetector detector; 221 expr->accept( detector ); 222 return detector.maybeImpure; 188 223 } 189 224 } // namespace Tuples -
TabularUnified src/Tuples/Tuples.h ¶
r1132b62 r65660bd 15 15 16 16 #ifndef _TUPLES_H_ 17 #define _TUPLE _H_17 #define _TUPLES_H_ 18 18 19 19 #include <string> … … 27 27 namespace Tuples { 28 28 // TupleAssignment.cc 29 void handleTupleAssignment( ResolvExpr::AlternativeFinder & currentFinder, UntypedExpr * assign, std::list<ResolvExpr::AltList> & possibilities );29 void handleTupleAssignment( ResolvExpr::AlternativeFinder & currentFinder, UntypedExpr * assign, const std::list<ResolvExpr::AltList> & possibilities ); 30 30 31 31 // TupleExpansion.cc … … 34 34 void expandUniqueExpr( std::list< Declaration * > & translationUnit ); 35 35 36 TupleType * makeTupleType( const std::list< Expression * > & exprs ); 36 /// returns VoidType if any of the expressions have Voidtype, otherwise TupleType of the Expression result types 37 Type * makeTupleType( const std::list< Expression * > & exprs ); 38 39 bool maybeImpure( Expression * expr ); 40 41 42 /// helper function used by explode 43 template< typename OutputIterator > 44 void explodeUnique( Expression * expr, const ResolvExpr::Alternative & alt, OutputIterator out ) { 45 Type * res = expr->get_result(); 46 if ( AddressExpr * addrExpr = dynamic_cast< AddressExpr * >( expr ) ) { 47 ResolvExpr::AltList alts; 48 explodeUnique( addrExpr->get_arg(), alt, back_inserter( alts ) ); 49 for ( ResolvExpr::Alternative & alt : alts ) { 50 // distribute '&' over all components 51 alt.expr = new AddressExpr( alt.expr ); 52 *out++ = alt; 53 } 54 } else if ( TupleType * tupleType = dynamic_cast< TupleType * > ( res ) ) { 55 if ( TupleExpr * tupleExpr = dynamic_cast< TupleExpr * >( expr ) ) { 56 // can open tuple expr and dump its exploded components 57 for ( Expression * expr : tupleExpr->get_exprs() ) { 58 explodeUnique( expr, alt, out ); 59 } 60 } else { 61 // tuple type, but not tuple expr - recursively index into its components 62 Expression * arg = expr->clone(); 63 if ( Tuples::maybeImpure( arg ) ) { 64 // expressions which may contain side effects require a single unique instance of the expression 65 arg = new UniqueExpr( arg ); 66 } 67 for ( unsigned int i = 0; i < tupleType->size(); i++ ) { 68 TupleIndexExpr * idx = new TupleIndexExpr( arg->clone(), i ); 69 explodeUnique( idx, alt, out ); 70 delete idx; 71 } 72 delete arg; 73 } 74 } else { 75 // atomic (non-tuple) type - output a clone of the expression in a new alternative 76 *out++ = ResolvExpr::Alternative( expr->clone(), alt.env, alt.cost, alt.cvtCost ); 77 } 78 } 79 80 /// expands a tuple-valued alternative into multiple alternatives, each with a non-tuple-type 81 template< typename OutputIterator > 82 void explode( const ResolvExpr::Alternative &alt, OutputIterator out ) { 83 explodeUnique( alt.expr, alt, out ); 84 } 85 86 // explode list of alternatives 87 template< typename AltIterator, typename OutputIterator > 88 void explode( AltIterator altBegin, AltIterator altEnd, OutputIterator out ) { 89 for ( ; altBegin != altEnd; ++altBegin ) { 90 explode( *altBegin, out ); 91 } 92 } 93 94 template< typename OutputIterator > 95 void explode( const ResolvExpr::AltList & alts, OutputIterator out ) { 96 explode( alts.begin(), alts.end(), out ); 97 } 37 98 } // namespace Tuples 38 99
Note: See TracChangeset
for help on using the changeset viewer.