Changeset d3e4d6c for src/Tuples
- Timestamp:
- Aug 23, 2017, 6:22:07 PM (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, stuck-waitfor-destruct, with_gc
- Children:
- 87e08e24, cb811ac
- Parents:
- 9f07232 (diff), bd37119 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)links above to see all the changes relative to each parent. - Location:
- src/Tuples
- Files:
-
- 5 edited
-
Explode.cc (modified) (2 diffs)
-
Explode.h (modified) (4 diffs)
-
TupleAssignment.cc (modified) (9 diffs)
-
TupleExpansion.cc (modified) (15 diffs)
-
Tuples.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
src/Tuples/Explode.cc
r9f07232 rd3e4d6c 15 15 16 16 #include "Explode.h" 17 #include <list> // for list 17 18 18 #include <list> // for list 19 20 #include "SynTree/Mutator.h" // for Mutator 19 #include "SynTree/Mutator.h" // for Mutator 20 #include "Common/PassVisitor.h" // for PassVisitor 21 21 22 22 namespace Tuples { 23 23 namespace { 24 struct AddrExploder : public Mutator { 24 // remove one level of reference from a reference type -- may be useful elsewhere. 25 Type * getReferenceBase( Type * t ) { 26 if ( ReferenceType * refType = dynamic_cast<ReferenceType *>( t ) ) { 27 return refType->get_base(); 28 } else { 29 // for the moment, I want to know immediately if a non-reference type is ever passed in here. 30 assertf( false, "getReferenceBase for non-ref: %s", toString( refType ).c_str() ); 31 return nullptr; 32 } 33 } 34 35 struct CastExploder { 36 bool castAdded = false; 25 37 bool foundUniqueExpr = false; 26 Expression * apply Addr( Expression * expr, bool first = true ) {38 Expression * applyCast( Expression * expr, bool first = true ) { 27 39 if ( TupleExpr * tupleExpr = dynamic_cast< TupleExpr * >( expr ) ){ 28 40 foundUniqueExpr = true; 29 41 std::list< Expression * > exprs; 30 42 for ( Expression *& expr : tupleExpr->get_exprs() ) { 31 // move &into tuple exprs32 exprs.push_back( apply Addr( expr, false ) );43 // move cast into tuple exprs 44 exprs.push_back( applyCast( expr, false ) ); 33 45 } 34 // want the top-level expression to be address-taken, but not nested46 // want the top-level expression to be cast to reference type, but not nested 35 47 // tuple expressions 36 48 if ( first ) { 37 return new AddressExpr( new TupleExpr( exprs ) ); 49 castAdded = true; 50 Expression * tupleExpr = new TupleExpr( exprs ); 51 return new CastExpr( tupleExpr, new ReferenceType( Type::Qualifiers(), tupleExpr->result->clone() ) ); 38 52 } else { 39 53 return new TupleExpr( exprs ); 40 54 } 41 55 } 42 // anything else should be address-taken as normal 43 return new AddressExpr( expr->clone() ); 56 if ( dynamic_cast<ReferenceType*>( expr->result ) ) { 57 // don't need to cast reference type to another reference type 58 return expr->clone(); 59 } else { 60 // anything else should be cast to reference as normal 61 castAdded = true; 62 return new CastExpr( expr->clone(), new ReferenceType( Type::Qualifiers(), expr->result->clone() ) ); 63 } 44 64 } 45 65 46 virtual Expression *mutate( UniqueExpr * uniqueExpr ) {47 // move & into unique expr so that the unique expr has type T*rather than66 Expression * postmutate( UniqueExpr * uniqueExpr ) { 67 // move cast into unique expr so that the unique expr has type T& rather than 48 68 // type T. In particular, this transformation helps with generating the 49 // correct code for address-takenmember tuple expressions, since the result50 // should now be a tuple of addresses rather than the address ofa tuple.69 // correct code for reference-cast member tuple expressions, since the result 70 // should now be a tuple of references rather than a reference to a tuple. 51 71 // Still, this code is a bit awkward, and could use some improvement. 52 if ( dynamic_cast< AddressExpr * > ( uniqueExpr->get_expr() ) ) { 53 // this unique expression has already been mutated or otherwise shouldn't be (can't take the address-of an address-of expression) 54 return uniqueExpr; 72 UniqueExpr * newUniqueExpr = new UniqueExpr( applyCast( uniqueExpr->get_expr() ), uniqueExpr->get_id() ); 73 delete uniqueExpr; 74 if ( castAdded ) { 75 // if a cast was added by applyCast, then unique expr now has one more layer of reference 76 // than it had coming into this function. To ensure types still match correctly, need to cast 77 // to reference base so that outer expressions are still correct. 78 castAdded = false; 79 Type * toType = getReferenceBase( newUniqueExpr->result ); 80 return new CastExpr( newUniqueExpr, toType->clone() ); 55 81 } 56 UniqueExpr * newUniqueExpr = new UniqueExpr( applyAddr( uniqueExpr->get_expr() ), uniqueExpr->get_id() ); 57 delete uniqueExpr; 58 UntypedExpr * deref = UntypedExpr::createDeref( Mutator::mutate( newUniqueExpr ) ); 59 return deref; 82 return newUniqueExpr; 60 83 } 61 84 62 virtual Expression * mutate( TupleIndexExpr * tupleExpr ) { 85 86 Expression * postmutate( TupleIndexExpr * tupleExpr ) { 63 87 // tuple index expr needs to be rebuilt to ensure that the type of the 64 88 // field is consistent with the type of the tuple expr, since the field 65 // may have changed from type T to T *.66 Expression * expr = tupleExpr->get_tuple() ->acceptMutator( *this );89 // may have changed from type T to T&. 90 Expression * expr = tupleExpr->get_tuple(); 67 91 tupleExpr->set_tuple( nullptr ); 68 92 TupleIndexExpr * ret = new TupleIndexExpr( expr, tupleExpr->get_index() ); … … 73 97 } // namespace 74 98 75 Expression * distributeAddr( Expression * expr ) { 76 AddrExploder addrExploder; 77 expr = expr->acceptMutator( addrExploder ); 78 if ( ! addrExploder.foundUniqueExpr ) { 79 expr = new AddressExpr( expr ); 99 Expression * distributeReference( Expression * expr ) { 100 PassVisitor<CastExploder> exploder; 101 expr = expr->acceptMutator( exploder ); 102 if ( ! exploder.pass.foundUniqueExpr ) { 103 // if a UniqueExpr was found, then the cast has already been added inside the UniqueExpr as appropriate 104 expr = new CastExpr( expr, new ReferenceType( Type::Qualifiers(), expr->result->clone() ) ); 80 105 } 81 106 return expr; -
src/Tuples/Explode.h
r9f07232 rd3e4d6c 28 28 29 29 namespace Tuples { 30 /// helper function used by explode to properly distribute 31 /// '&' across a tuple expression 32 Expression * distributeAddr( Expression * expr ); 30 Expression * distributeReference( Expression * ); 33 31 34 32 /// helper function used by explode … … 36 34 void explodeUnique( Expression * expr, const ResolvExpr::Alternative & alt, const SymTab::Indexer & indexer, OutputIterator out, bool isTupleAssign ) { 37 35 if ( isTupleAssign ) { 38 // tuple assignment needs AddressExprs to be recursively exploded to easily get at all of the components39 if ( AddressExpr * addrExpr = dynamic_cast< AddressExpr * >( expr ) ) {36 // tuple assignment needs CastExprs to be recursively exploded to easily get at all of the components 37 if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) { 40 38 ResolvExpr::AltList alts; 41 explodeUnique( addrExpr->get_arg(), alt, indexer, back_inserter( alts ), isTupleAssign );39 explodeUnique( castExpr->get_arg(), alt, indexer, back_inserter( alts ), isTupleAssign ); 42 40 for ( ResolvExpr::Alternative & alt : alts ) { 43 // distribute '&'over all components44 alt.expr = distribute Addr( alt.expr );41 // distribute reference cast over all components 42 alt.expr = distributeReference( alt.expr ); 45 43 *out++ = alt; 46 44 } … … 49 47 } 50 48 } 51 Type * res = expr->get_result() ;49 Type * res = expr->get_result()->stripReferences(); 52 50 if ( TupleType * tupleType = dynamic_cast< TupleType * > ( res ) ) { 53 51 if ( TupleExpr * tupleExpr = dynamic_cast< TupleExpr * >( expr ) ) { … … 57 55 } 58 56 } else { 59 // tuple type, but not tuple expr - recursively index into its components 57 // tuple type, but not tuple expr - recursively index into its components. 58 // if expr type is reference, convert to value type 60 59 Expression * arg = expr->clone(); 61 if ( Tuples::maybeImpure ( arg ) && ! dynamic_cast< UniqueExpr * >( arg ) ) {60 if ( Tuples::maybeImpureIgnoreUnique( arg ) ) { 62 61 // expressions which may contain side effects require a single unique instance of the expression. 63 62 arg = new UniqueExpr( arg ); 63 } 64 // cast reference to value type to facilitate further explosion 65 if ( dynamic_cast<ReferenceType *>( arg->get_result() ) ) { 66 arg = new CastExpr( arg, tupleType->clone() ); 64 67 } 65 68 for ( unsigned int i = 0; i < tupleType->size(); i++ ) { -
src/Tuples/TupleAssignment.cc
r9f07232 rd3e4d6c 21 21 #include <string> // for string 22 22 23 #include "CodeGen/OperatorTable.h" 23 24 #include "Common/UniqueName.h" // for UniqueName 24 25 #include "Common/utility.h" // for zipWith … … 84 85 if ( ! expr ) return false; 85 86 assert( expr->has_result() ); 86 return dynamic_cast< TupleType * >( expr->get_result() );87 return dynamic_cast< TupleType * >( expr->get_result()->stripReferences() ); 87 88 } 88 89 … … 96 97 } 97 98 98 bool pointsToTuple( Expression *expr ) { 99 bool refToTuple( Expression *expr ) { 100 assert( expr->get_result() ); 99 101 // also check for function returning tuple of reference types 100 102 if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) { 101 return pointsToTuple( castExpr->get_arg() );102 } else if ( AddressExpr *addr = dynamic_cast< AddressExpr * >( expr) ){103 return isTuple( addr->get_arg());103 return refToTuple( castExpr->get_arg() ); 104 } else { 105 return isTuple( expr ); 104 106 } 105 107 return false; … … 116 118 void TupleAssignSpotter::spot( UntypedExpr * expr, const std::list<ResolvExpr::AltList> &possibilities ) { 117 119 if ( NameExpr *op = dynamic_cast< NameExpr * >(expr->get_function()) ) { 118 if ( InitTweak::isCtorDtorAssign( op->get_name() ) ) {120 if ( CodeGen::isCtorDtorAssign( op->get_name() ) ) { 119 121 fname = op->get_name(); 120 122 for ( std::list<ResolvExpr::AltList>::const_iterator ali = possibilities.begin(); ali != possibilities.end(); ++ali ) { 121 123 if ( ali->size() == 0 ) continue; // AlternativeFinder will natrually handle this case, if it's legal 122 if ( ali->size() <= 1 && InitTweak::isAssignment( op->get_name() ) ) {124 if ( ali->size() <= 1 && CodeGen::isAssignment( op->get_name() ) ) { 123 125 // what does it mean if an assignment takes 1 argument? maybe someone defined such a function, in which case AlternativeFinder will naturally handle it 124 126 continue; … … 129 131 const ResolvExpr::Alternative & alt1 = ali->front(); 130 132 auto begin = std::next(ali->begin(), 1), end = ali->end(); 131 if ( pointsToTuple(alt1.expr) ) {133 if ( refToTuple(alt1.expr) ) { 132 134 if ( isMultAssign( begin, end ) ) { 133 135 matcher.reset( new MultipleAssignMatcher( *this, *ali ) ); … … 187 189 188 190 ResolvExpr::Alternative lhsAlt = alts.front(); 189 // peel off the cast that exists on ctor/dtor expressions 190 bool isCast = false; 191 if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( lhsAlt.expr ) ) { 192 lhsAlt.expr = castExpr->get_arg(); 193 castExpr->set_arg( nullptr ); 194 delete castExpr; 195 isCast = true; 191 // explode is aware of casts - ensure every LHS expression is sent into explode with a reference cast 192 if ( ! dynamic_cast< CastExpr * >( lhsAlt.expr ) ) { 193 lhsAlt.expr = new CastExpr( lhsAlt.expr, new ReferenceType( Type::Qualifiers(), lhsAlt.expr->get_result()->clone() ) ); 196 194 } 197 195 … … 199 197 explode( lhsAlt, spotter.currentFinder.get_indexer(), back_inserter(lhs), true ); 200 198 201 // and finally, re-add the cast to each lhs expr, so that qualified tuple fields can be constructed 202 if ( isCast ) { 203 for ( ResolvExpr::Alternative & alt : lhs ) { 204 Expression *& expr = alt.expr; 205 Type * castType = expr->get_result()->clone(); 206 Type * type = InitTweak::getPointerBase( castType ); 207 assert( type ); 208 type->get_qualifiers() -= Type::Qualifiers( Type::Const | Type::Volatile | Type::Restrict | Type::Atomic ); 209 type->set_lvalue( true ); // xxx - might not need this 210 expr = new CastExpr( expr, castType ); 199 for ( ResolvExpr::Alternative & alt : lhs ) { 200 // every LHS value must be a reference - some come in with a cast expression, if it doesn't just cast to reference here. 201 if ( ! dynamic_cast< ReferenceType * >( alt.expr->get_result() ) ) { 202 alt.expr = new CastExpr( alt.expr, new ReferenceType( Type::Qualifiers(), alt.expr->get_result()->clone() ) ); 211 203 } 212 204 } … … 228 220 assert( left ); 229 221 std::list< Expression * > args; 230 args.push_back( new AddressExpr( UntypedExpr::createDeref( new VariableExpr( left ) )) );222 args.push_back( new VariableExpr( left ) ); 231 223 // args.push_back( new AddressExpr( new VariableExpr( left ) ) ); 232 224 if ( right ) args.push_back( new VariableExpr( right ) ); … … 248 240 assert( expr->has_result() && ! expr->get_result()->isVoid() ); 249 241 ObjectDecl * ret = new ObjectDecl( namer.newName(), Type::StorageClasses(), LinkageSpec::Cforall, nullptr, expr->get_result()->clone(), new SingleInit( expr->clone() ) ); 250 ConstructorInit * ctorInit = InitTweak::genCtorInit( ret ); 251 ret->set_init( ctorInit ); 252 ResolvExpr::resolveCtorInit( ctorInit, spotter.currentFinder.get_indexer() ); // resolve ctor/dtors for the new object 253 EnvRemover rm; // remove environments from subexpressions of StmtExprs 254 ctorInit->accept( rm ); 242 // if expression type is a reference, don't need to construct anything, a simple initializer is sufficient. 243 if ( ! dynamic_cast< ReferenceType * >( expr->get_result() ) ) { 244 ConstructorInit * ctorInit = InitTweak::genCtorInit( ret ); 245 ret->set_init( ctorInit ); 246 ResolvExpr::resolveCtorInit( ctorInit, spotter.currentFinder.get_indexer() ); // resolve ctor/dtors for the new object 247 EnvRemover rm; // remove environments from subexpressions of StmtExprs 248 ctorInit->accept( rm ); 249 } 255 250 return ret; 256 251 } -
src/Tuples/TupleExpansion.cc
r9f07232 rd3e4d6c 37 37 namespace Tuples { 38 38 namespace { 39 class MemberTupleExpander final : public Mutator { 40 public: 39 struct MemberTupleExpander final : public Mutator { 41 40 typedef Mutator Parent; 42 41 using Parent::mutate; … … 45 44 }; 46 45 47 class UniqueExprExpander final : public GenPoly::DeclMutator { 48 public: 49 typedef GenPoly::DeclMutator Parent; 50 using Parent::mutate; 51 52 virtual Expression * mutate( UniqueExpr * unqExpr ) override; 46 struct UniqueExprExpander final : public WithDeclsToAdd { 47 Expression * postmutate( UniqueExpr * unqExpr ); 53 48 54 49 std::map< int, Expression * > decls; // not vector, because order added may not be increasing order … … 61 56 }; 62 57 63 class TupleAssignExpander : public Mutator { 64 public: 65 typedef Mutator Parent; 66 using Parent::mutate; 67 68 virtual Expression * mutate( TupleAssignExpr * tupleExpr ); 58 struct TupleAssignExpander { 59 Expression * postmutate( TupleAssignExpr * tupleExpr ); 69 60 }; 70 61 … … 79 70 }; 80 71 81 class TupleIndexExpander { 82 public: 72 struct TupleIndexExpander { 83 73 Expression * postmutate( TupleIndexExpr * tupleExpr ); 84 74 }; 85 75 86 class TupleExprExpander final : public Mutator { 87 public: 88 typedef Mutator Parent; 89 using Parent::mutate; 90 91 virtual Expression * mutate( TupleExpr * tupleExpr ) override; 76 struct TupleExprExpander final { 77 Expression * postmutate( TupleExpr * tupleExpr ); 92 78 }; 93 79 } … … 99 85 100 86 void expandUniqueExpr( std::list< Declaration * > & translationUnit ) { 101 UniqueExprExpanderunqExpander;102 unqExpander.mutateDeclarationList( translationUnit);87 PassVisitor<UniqueExprExpander> unqExpander; 88 mutateAll( translationUnit, unqExpander ); 103 89 } 104 90 105 91 void expandTuples( std::list< Declaration * > & translationUnit ) { 106 TupleAssignExpanderassnExpander;92 PassVisitor<TupleAssignExpander> assnExpander; 107 93 mutateAll( translationUnit, assnExpander ); 108 94 … … 113 99 mutateAll( translationUnit, idxExpander ); 114 100 115 TupleExprExpanderexprExpander;101 PassVisitor<TupleExprExpander> exprExpander; 116 102 mutateAll( translationUnit, exprExpander ); 117 103 } … … 146 132 // aggregate expressions which might be impure must be wrapped in unique expressions 147 133 // xxx - if there's a member-tuple expression nested in the aggregate, this currently generates the wrong code if a UniqueExpr is not used, and it's purely an optimization to remove the UniqueExpr 148 // if ( Tuples::maybeImpure ( memberExpr->get_aggregate() ) ) aggr = new UniqueExpr( aggr );134 // if ( Tuples::maybeImpureIgnoreUnique( memberExpr->get_aggregate() ) ) aggr = new UniqueExpr( aggr ); 149 135 aggr = new UniqueExpr( aggr ); 150 136 for ( Expression *& expr : tupleExpr->get_exprs() ) { … … 164 150 } 165 151 166 Expression * UniqueExprExpander::mutate( UniqueExpr * unqExpr ) { 167 unqExpr = safe_dynamic_cast< UniqueExpr * > ( Parent::mutate( unqExpr ) ); 152 Expression * UniqueExprExpander::postmutate( UniqueExpr * unqExpr ) { 168 153 const int id = unqExpr->get_id(); 169 154 … … 175 160 if ( unqExpr->get_object() ) { 176 161 // an object was generated to represent this unique expression -- it should be added to the list of declarations now 177 addDeclaration( unqExpr->get_object() );162 declsToAddBefore.push_back( unqExpr->get_object() ); 178 163 unqExpr->set_object( nullptr ); 179 164 // steal the expr from the unqExpr … … 189 174 ObjectDecl * finished = new ObjectDecl( toString( "_unq", id, "_finished_" ), Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new BasicType( Type::Qualifiers(), BasicType::Bool ), 190 175 new SingleInit( new ConstantExpr( Constant::from_int( 0 ) ) ) ); 191 addDeclaration( finished );176 declsToAddBefore.push_back( finished ); 192 177 // (finished ? _unq_expr_N : (_unq_expr_N = <unqExpr->get_expr()>, finished = 1, _unq_expr_N)) 193 178 // This pattern ensures that each unique expression is evaluated once, regardless of evaluation order of the generated C code. … … 203 188 } 204 189 205 Expression * TupleAssignExpander::mutate( TupleAssignExpr * assnExpr ) { 206 assnExpr = safe_dynamic_cast< TupleAssignExpr * >( Parent::mutate( assnExpr ) ); 190 Expression * TupleAssignExpander::postmutate( TupleAssignExpr * assnExpr ) { 207 191 StmtExpr * ret = assnExpr->get_stmtExpr(); 208 192 assnExpr->set_stmtExpr( nullptr ); … … 238 222 for ( auto p : group_iterate( tupleType->get_types(), decl->get_parameters() ) ) { 239 223 Type * t = std::get<0>(p); 240 TypeDecl * td = std::get<1>(p);241 224 newType->get_parameters().push_back( new TypeExpr( t->clone() ) ); 242 if ( env ) {243 // add bindings to the type environment.244 // xxx - This may not be sufficient, it may be necessary to rename type variables on StructInstType?245 env->add( td->get_name(), t->clone() );246 }247 225 } 248 226 delete tupleType; … … 293 271 } 294 272 295 Expression * TupleExprExpander::mutate( TupleExpr * tupleExpr ) { 296 // recursively expand sub-tuple-expressions 297 tupleExpr = safe_dynamic_cast<TupleExpr *>(Parent::mutate(tupleExpr)); 273 Expression * TupleExprExpander::postmutate( TupleExpr * tupleExpr ) { 298 274 Type * result = tupleExpr->get_result(); 299 275 std::list< Expression * > exprs = tupleExpr->get_exprs(); … … 342 318 class ImpurityDetector : public Visitor { 343 319 public: 320 ImpurityDetector( bool ignoreUnique ) : ignoreUnique( ignoreUnique ) {} 321 344 322 typedef Visitor Parent; 345 323 virtual void visit( ApplicationExpr * appExpr ) { … … 355 333 maybeImpure = true; 356 334 } 357 virtual void visit( __attribute__((unused)) UntypedExpr * untypedExpr ) { maybeImpure = true; } 335 virtual void visit( UntypedExpr * ) { maybeImpure = true; } 336 virtual void visit( UniqueExpr * unq ) { 337 if ( ignoreUnique ) { 338 // bottom out at unique expression. 339 // The existence of a unique expression doesn't change the purity of an expression. 340 // That is, even if the wrapped expression is impure, the wrapper protects the rest of the expression. 341 return; 342 } 343 maybeAccept( unq->expr, *this ); 344 } 345 358 346 bool maybeImpure = false; 347 bool ignoreUnique; 359 348 }; 360 349 } // namespace 361 350 362 351 bool maybeImpure( Expression * expr ) { 363 ImpurityDetector detector; 352 ImpurityDetector detector( false ); 353 expr->accept( detector ); 354 return detector.maybeImpure; 355 } 356 357 bool maybeImpureIgnoreUnique( Expression * expr ) { 358 ImpurityDetector detector( true ); 364 359 expr->accept( detector ); 365 360 return detector.maybeImpure; -
src/Tuples/Tuples.h
r9f07232 rd3e4d6c 46 46 /// returns true if the expression may contain side-effects. 47 47 bool maybeImpure( Expression * expr ); 48 49 /// returns true if the expression may contain side-effect, ignoring the presence of unique expressions. 50 bool maybeImpureIgnoreUnique( Expression * expr ); 48 51 } // namespace Tuples 49 52
Note:
See TracChangeset
for help on using the changeset viewer.