| [6eb8948] | 1 | // | 
|---|
|  | 2 | // Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo | 
|---|
|  | 3 | // | 
|---|
|  | 4 | // The contents of this file are covered under the licence agreement in the | 
|---|
|  | 5 | // file "LICENCE" distributed with Cforall. | 
|---|
|  | 6 | // | 
|---|
|  | 7 | // TupleAssignment.cc -- | 
|---|
|  | 8 | // | 
|---|
|  | 9 | // Author           : Rodolfo G. Esteves | 
|---|
|  | 10 | // Created On       : Mon May 18 07:44:20 2015 | 
|---|
|  | 11 | // Last Modified By : Peter A. Buhr | 
|---|
| [68fe077a] | 12 | // Last Modified On : Thu Mar 16 08:05:17 2017 | 
|---|
|  | 13 | // Update Count     : 15 | 
|---|
| [6eb8948] | 14 | // | 
|---|
|  | 15 |  | 
|---|
|  | 16 | #include <iterator> | 
|---|
|  | 17 | #include <iostream> | 
|---|
|  | 18 | #include <cassert> | 
|---|
|  | 19 | #include "Tuples.h" | 
|---|
| [f006f01] | 20 | #include "GenPoly/DeclMutator.h" | 
|---|
|  | 21 | #include "SynTree/Mutator.h" | 
|---|
| [6eb8948] | 22 | #include "SynTree/Statement.h" | 
|---|
| [f006f01] | 23 | #include "SynTree/Declaration.h" | 
|---|
|  | 24 | #include "SynTree/Type.h" | 
|---|
| [3c13c03] | 25 | #include "SynTree/Expression.h" | 
|---|
|  | 26 | #include "SynTree/Initializer.h" | 
|---|
| [f006f01] | 27 | #include "SymTab/Mangler.h" | 
|---|
|  | 28 | #include "Common/ScopedMap.h" | 
|---|
| [1132b62] | 29 | #include "ResolvExpr/typeops.h" | 
|---|
| [f0121d7] | 30 | #include "InitTweak/GenInit.h" | 
|---|
| [b7b8674] | 31 | #include "InitTweak/InitTweak.h" | 
|---|
| [6eb8948] | 32 |  | 
|---|
|  | 33 | namespace Tuples { | 
|---|
| [3c13c03] | 34 | namespace { | 
|---|
| [5f5083e] | 35 | class MemberTupleExpander final : public Mutator { | 
|---|
| [bf32bb8] | 36 | public: | 
|---|
|  | 37 | typedef Mutator Parent; | 
|---|
| [5f5083e] | 38 | using Parent::mutate; | 
|---|
|  | 39 |  | 
|---|
|  | 40 | virtual Expression * mutate( UntypedMemberExpr * memberExpr ) override; | 
|---|
| [bf32bb8] | 41 | }; | 
|---|
|  | 42 |  | 
|---|
| [5f5083e] | 43 | class UniqueExprExpander final : public GenPoly::DeclMutator { | 
|---|
| [3c13c03] | 44 | public: | 
|---|
|  | 45 | typedef GenPoly::DeclMutator Parent; | 
|---|
| [5f5083e] | 46 | using Parent::mutate; | 
|---|
| [141b786] | 47 |  | 
|---|
| [5f5083e] | 48 | virtual Expression * mutate( UniqueExpr * unqExpr ) override; | 
|---|
| [141b786] | 49 |  | 
|---|
|  | 50 | std::map< int, Expression * > decls; // not vector, because order added may not be increasing order | 
|---|
|  | 51 |  | 
|---|
|  | 52 | ~UniqueExprExpander() { | 
|---|
|  | 53 | for ( std::pair<const int, Expression *> & p : decls ) { | 
|---|
|  | 54 | delete p.second; | 
|---|
|  | 55 | } | 
|---|
|  | 56 | } | 
|---|
| [3c13c03] | 57 | }; | 
|---|
|  | 58 |  | 
|---|
|  | 59 | class TupleAssignExpander : public Mutator { | 
|---|
|  | 60 | public: | 
|---|
|  | 61 | typedef Mutator Parent; | 
|---|
| [5f5083e] | 62 | using Parent::mutate; | 
|---|
|  | 63 |  | 
|---|
| [3c13c03] | 64 | virtual Expression * mutate( TupleAssignExpr * tupleExpr ); | 
|---|
|  | 65 | }; | 
|---|
|  | 66 |  | 
|---|
|  | 67 | class TupleTypeReplacer : public GenPoly::DeclMutator { | 
|---|
|  | 68 | public: | 
|---|
|  | 69 | typedef GenPoly::DeclMutator Parent; | 
|---|
| [5f5083e] | 70 | using Parent::mutate; | 
|---|
| [3c13c03] | 71 |  | 
|---|
| [5f5083e] | 72 | virtual Type * mutate( TupleType * tupleType ) override; | 
|---|
| [3c13c03] | 73 |  | 
|---|
| [5f5083e] | 74 | virtual CompoundStmt * mutate( CompoundStmt * stmt ) override { | 
|---|
| [3c13c03] | 75 | typeMap.beginScope(); | 
|---|
|  | 76 | stmt = Parent::mutate( stmt ); | 
|---|
|  | 77 | typeMap.endScope(); | 
|---|
|  | 78 | return stmt; | 
|---|
|  | 79 | } | 
|---|
|  | 80 | private: | 
|---|
| [e6512c8] | 81 | ScopedMap< int, StructDecl * > typeMap; | 
|---|
| [3c13c03] | 82 | }; | 
|---|
|  | 83 |  | 
|---|
| [5f5083e] | 84 | class TupleIndexExpander final : public Mutator { | 
|---|
| [3c13c03] | 85 | public: | 
|---|
|  | 86 | typedef Mutator Parent; | 
|---|
| [5f5083e] | 87 | using Parent::mutate; | 
|---|
|  | 88 |  | 
|---|
|  | 89 | virtual Expression * mutate( TupleIndexExpr * tupleExpr ) override; | 
|---|
| [3c13c03] | 90 | }; | 
|---|
|  | 91 |  | 
|---|
| [5f5083e] | 92 | class TupleExprExpander final : public Mutator { | 
|---|
| [3c13c03] | 93 | public: | 
|---|
|  | 94 | typedef Mutator Parent; | 
|---|
| [5f5083e] | 95 | using Parent::mutate; | 
|---|
| [d9fa60a] | 96 |  | 
|---|
| [5f5083e] | 97 | virtual Expression * mutate( TupleExpr * tupleExpr ) override; | 
|---|
| [3c13c03] | 98 | }; | 
|---|
|  | 99 | } | 
|---|
| [f006f01] | 100 |  | 
|---|
| [bf32bb8] | 101 | void expandMemberTuples( std::list< Declaration * > & translationUnit ) { | 
|---|
|  | 102 | MemberTupleExpander expander; | 
|---|
|  | 103 | mutateAll( translationUnit, expander ); | 
|---|
|  | 104 | } | 
|---|
|  | 105 |  | 
|---|
| [aefcc3b] | 106 | void expandUniqueExpr( std::list< Declaration * > & translationUnit ) { | 
|---|
| [3c13c03] | 107 | UniqueExprExpander unqExpander; | 
|---|
|  | 108 | unqExpander.mutateDeclarationList( translationUnit ); | 
|---|
| [aefcc3b] | 109 | } | 
|---|
| [3c13c03] | 110 |  | 
|---|
| [aefcc3b] | 111 | void expandTuples( std::list< Declaration * > & translationUnit ) { | 
|---|
| [3c13c03] | 112 | TupleAssignExpander assnExpander; | 
|---|
|  | 113 | mutateAll( translationUnit, assnExpander ); | 
|---|
| [f006f01] | 114 |  | 
|---|
|  | 115 | TupleTypeReplacer replacer; | 
|---|
|  | 116 | replacer.mutateDeclarationList( translationUnit ); | 
|---|
| [3c13c03] | 117 |  | 
|---|
|  | 118 | TupleIndexExpander idxExpander; | 
|---|
|  | 119 | mutateAll( translationUnit, idxExpander ); | 
|---|
|  | 120 |  | 
|---|
|  | 121 | TupleExprExpander exprExpander; | 
|---|
|  | 122 | mutateAll( translationUnit, exprExpander ); | 
|---|
|  | 123 | } | 
|---|
|  | 124 |  | 
|---|
| [bf32bb8] | 125 | namespace { | 
|---|
|  | 126 | /// given a expression representing the member and an expression representing the aggregate, | 
|---|
|  | 127 | /// reconstructs a flattened UntypedMemberExpr with the right precedence | 
|---|
| [64ac636] | 128 | Expression * reconstructMemberExpr( Expression * member, Expression * aggr, CodeLocation & loc ) { | 
|---|
| [bf32bb8] | 129 | if ( UntypedMemberExpr * memberExpr = dynamic_cast< UntypedMemberExpr * >( member ) ) { | 
|---|
|  | 130 | // construct a new UntypedMemberExpr with the correct structure , and recursively | 
|---|
|  | 131 | // expand that member expression. | 
|---|
|  | 132 | MemberTupleExpander expander; | 
|---|
| [64ac636] | 133 | UntypedMemberExpr * inner = new UntypedMemberExpr( memberExpr->get_aggregate(), aggr->clone() ); | 
|---|
|  | 134 | UntypedMemberExpr * newMemberExpr = new UntypedMemberExpr( memberExpr->get_member(), inner ); | 
|---|
|  | 135 | inner->location = newMemberExpr->location = loc; | 
|---|
| [bf32bb8] | 136 | memberExpr->set_member(nullptr); | 
|---|
|  | 137 | memberExpr->set_aggregate(nullptr); | 
|---|
|  | 138 | delete memberExpr; | 
|---|
|  | 139 | return newMemberExpr->acceptMutator( expander ); | 
|---|
|  | 140 | } else { | 
|---|
|  | 141 | // not a member expression, so there is nothing to do but attach and return | 
|---|
| [64ac636] | 142 | UntypedMemberExpr * newMemberExpr = new UntypedMemberExpr( member, aggr->clone() ); | 
|---|
|  | 143 | newMemberExpr->location = loc; | 
|---|
|  | 144 | return newMemberExpr; | 
|---|
| [bf32bb8] | 145 | } | 
|---|
|  | 146 | } | 
|---|
|  | 147 | } | 
|---|
|  | 148 |  | 
|---|
|  | 149 | Expression * MemberTupleExpander::mutate( UntypedMemberExpr * memberExpr ) { | 
|---|
| [907eccb] | 150 | if ( UntypedTupleExpr * tupleExpr = dynamic_cast< UntypedTupleExpr * > ( memberExpr->get_member() ) ) { | 
|---|
| [141b786] | 151 | Expression * aggr = memberExpr->get_aggregate()->clone()->acceptMutator( *this ); | 
|---|
|  | 152 | // aggregate expressions which might be impure must be wrapped in unique expressions | 
|---|
|  | 153 | // 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 | 
|---|
|  | 154 | // if ( Tuples::maybeImpure( memberExpr->get_aggregate() ) ) aggr = new UniqueExpr( aggr ); | 
|---|
|  | 155 | aggr = new UniqueExpr( aggr ); | 
|---|
| [bf32bb8] | 156 | for ( Expression *& expr : tupleExpr->get_exprs() ) { | 
|---|
| [64ac636] | 157 | expr = reconstructMemberExpr( expr, aggr, memberExpr->location ); | 
|---|
|  | 158 | expr->location = memberExpr->location; | 
|---|
| [bf32bb8] | 159 | } | 
|---|
| [141b786] | 160 | delete aggr; | 
|---|
| [64ac636] | 161 | tupleExpr->location = memberExpr->location; | 
|---|
| [bf32bb8] | 162 | return tupleExpr; | 
|---|
|  | 163 | } else { | 
|---|
| [f0121d7] | 164 | // there may be a tuple expr buried in the aggregate | 
|---|
|  | 165 | // xxx - this is a memory leak | 
|---|
| [64ac636] | 166 | UntypedMemberExpr * newMemberExpr = new UntypedMemberExpr( memberExpr->get_member()->clone(), memberExpr->get_aggregate()->acceptMutator( *this ) ); | 
|---|
|  | 167 | newMemberExpr->location = memberExpr->location; | 
|---|
|  | 168 | return newMemberExpr; | 
|---|
| [bf32bb8] | 169 | } | 
|---|
|  | 170 | } | 
|---|
|  | 171 |  | 
|---|
| [3c13c03] | 172 | Expression * UniqueExprExpander::mutate( UniqueExpr * unqExpr ) { | 
|---|
|  | 173 | unqExpr = safe_dynamic_cast< UniqueExpr * > ( Parent::mutate( unqExpr ) ); | 
|---|
| [141b786] | 174 | const int id = unqExpr->get_id(); | 
|---|
|  | 175 |  | 
|---|
|  | 176 | // on first time visiting a unique expr with a particular ID, generate the expression that replaces all UniqueExprs with that ID, | 
|---|
|  | 177 | // and lookup on subsequent hits. This ensures that all unique exprs with the same ID reference the same variable. | 
|---|
|  | 178 | if ( ! decls.count( id ) ) { | 
|---|
|  | 179 | Expression * assignUnq; | 
|---|
|  | 180 | Expression * var = unqExpr->get_var(); | 
|---|
|  | 181 | if ( unqExpr->get_object() ) { | 
|---|
|  | 182 | // an object was generated to represent this unique expression -- it should be added to the list of declarations now | 
|---|
|  | 183 | addDeclaration( unqExpr->get_object() ); | 
|---|
|  | 184 | unqExpr->set_object( nullptr ); | 
|---|
|  | 185 | // steal the expr from the unqExpr | 
|---|
|  | 186 | assignUnq = UntypedExpr::createAssign( unqExpr->get_var()->clone(), unqExpr->get_expr() ); | 
|---|
|  | 187 | unqExpr->set_expr( nullptr ); | 
|---|
|  | 188 | } else { | 
|---|
|  | 189 | // steal the already generated assignment to var from the unqExpr - this has been generated by FixInit | 
|---|
|  | 190 | Expression * expr = unqExpr->get_expr(); | 
|---|
|  | 191 | CommaExpr * commaExpr = safe_dynamic_cast< CommaExpr * >( expr ); | 
|---|
|  | 192 | assignUnq = commaExpr->get_arg1(); | 
|---|
|  | 193 | commaExpr->set_arg1( nullptr ); | 
|---|
|  | 194 | } | 
|---|
|  | 195 | BasicType * boolType = new BasicType( Type::Qualifiers(), BasicType::Bool ); | 
|---|
| [14a33790] | 196 | ObjectDecl * finished = new ObjectDecl( toString( "_unq", id, "_finished_" ), Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new BasicType( Type::Qualifiers(), BasicType::Bool ), new SingleInit( new ConstantExpr( Constant( boolType->clone(), "0" ) ), noDesignators ) ); | 
|---|
| [141b786] | 197 | addDeclaration( finished ); | 
|---|
|  | 198 | // (finished ? _unq_expr_N : (_unq_expr_N = <unqExpr->get_expr()>, finished = 1, _unq_expr_N)) | 
|---|
|  | 199 | // This pattern ensures that each unique expression is evaluated once, regardless of evaluation order of the generated C code. | 
|---|
|  | 200 | Expression * assignFinished = UntypedExpr::createAssign( new VariableExpr(finished), new ConstantExpr( Constant( boolType->clone(), "1" ) ) ); | 
|---|
|  | 201 | ConditionalExpr * condExpr = new ConditionalExpr( new VariableExpr( finished ), var->clone(), | 
|---|
|  | 202 | new CommaExpr( new CommaExpr( assignUnq, assignFinished ), var->clone() ) ); | 
|---|
|  | 203 | condExpr->set_result( var->get_result()->clone() ); | 
|---|
| [d5556a3] | 204 | condExpr->set_env( maybeClone( unqExpr->get_env() ) ); | 
|---|
| [141b786] | 205 | decls[id] = condExpr; | 
|---|
| [3c13c03] | 206 | } | 
|---|
| [141b786] | 207 | delete unqExpr; | 
|---|
|  | 208 | return decls[id]->clone(); | 
|---|
| [6eb8948] | 209 | } | 
|---|
|  | 210 |  | 
|---|
| [3c13c03] | 211 | Expression * TupleAssignExpander::mutate( TupleAssignExpr * assnExpr ) { | 
|---|
| [141b786] | 212 | assnExpr = safe_dynamic_cast< TupleAssignExpr * >( Parent::mutate( assnExpr ) ); | 
|---|
| [d5556a3] | 213 | StmtExpr * ret = assnExpr->get_stmtExpr(); | 
|---|
|  | 214 | assnExpr->set_stmtExpr( nullptr ); | 
|---|
|  | 215 | // move env to StmtExpr | 
|---|
|  | 216 | ret->set_env( assnExpr->get_env() ); | 
|---|
|  | 217 | assnExpr->set_env( nullptr ); | 
|---|
| [3c13c03] | 218 | delete assnExpr; | 
|---|
| [d5556a3] | 219 | return ret; | 
|---|
| [6eb8948] | 220 | } | 
|---|
|  | 221 |  | 
|---|
| [f006f01] | 222 | Type * TupleTypeReplacer::mutate( TupleType * tupleType ) { | 
|---|
| [d9fa60a] | 223 | tupleType = safe_dynamic_cast< TupleType * > ( Parent::mutate( tupleType ) ); | 
|---|
| [e6512c8] | 224 | unsigned tupleSize = tupleType->size(); | 
|---|
|  | 225 | if ( ! typeMap.count( tupleSize ) ) { | 
|---|
|  | 226 | // generate struct type to replace tuple type based on the number of components in the tuple | 
|---|
| [94a8123] | 227 | StructDecl * decl = new StructDecl( toString( "_tuple", tupleSize, "_" ) ); | 
|---|
| [f006f01] | 228 | decl->set_body( true ); | 
|---|
| [e6512c8] | 229 | for ( size_t i = 0; i < tupleSize; ++i ) { | 
|---|
| [68fe077a] | 230 | TypeDecl * tyParam = new TypeDecl( toString( "tuple_param_", i ), Type::StorageClasses(), nullptr, TypeDecl::Any ); | 
|---|
|  | 231 | decl->get_members().push_back( new ObjectDecl( toString("field_", i ), Type::StorageClasses(), LinkageSpec::C, nullptr, new TypeInstType( Type::Qualifiers(), tyParam->get_name(), tyParam ), nullptr ) ); | 
|---|
| [d9fa60a] | 232 | decl->get_parameters().push_back( tyParam ); | 
|---|
| [f006f01] | 233 | } | 
|---|
| [e6512c8] | 234 | if ( tupleSize == 0 ) { | 
|---|
| [4c8621ac] | 235 | // empty structs are not standard C. Add a dummy field to empty tuples to silence warnings when a compound literal Tuple0 is created. | 
|---|
| [68fe077a] | 236 | decl->get_members().push_back( new ObjectDecl( "dummy", Type::StorageClasses(), LinkageSpec::C, nullptr, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), nullptr ) ); | 
|---|
| [4c8621ac] | 237 | } | 
|---|
| [e6512c8] | 238 | typeMap[tupleSize] = decl; | 
|---|
| [f006f01] | 239 | addDeclaration( decl ); | 
|---|
|  | 240 | } | 
|---|
| [d9fa60a] | 241 | Type::Qualifiers qualifiers = tupleType->get_qualifiers(); | 
|---|
|  | 242 |  | 
|---|
| [e6512c8] | 243 | StructDecl * decl = typeMap[tupleSize]; | 
|---|
| [d9fa60a] | 244 | StructInstType * newType = new StructInstType( qualifiers, decl ); | 
|---|
|  | 245 | for ( Type * t : *tupleType ) { | 
|---|
|  | 246 | newType->get_parameters().push_back( new TypeExpr( t->clone() ) ); | 
|---|
|  | 247 | } | 
|---|
|  | 248 | delete tupleType; | 
|---|
|  | 249 | return newType; | 
|---|
| [f006f01] | 250 | } | 
|---|
|  | 251 |  | 
|---|
| [3c13c03] | 252 | Expression * TupleIndexExpander::mutate( TupleIndexExpr * tupleExpr ) { | 
|---|
|  | 253 | Expression * tuple = maybeMutate( tupleExpr->get_tuple(), *this ); | 
|---|
|  | 254 | assert( tuple ); | 
|---|
|  | 255 | tupleExpr->set_tuple( nullptr ); | 
|---|
|  | 256 | unsigned int idx = tupleExpr->get_index(); | 
|---|
| [d5556a3] | 257 | TypeSubstitution * env = tupleExpr->get_env(); | 
|---|
|  | 258 | tupleExpr->set_env( nullptr ); | 
|---|
| [3c13c03] | 259 | delete tupleExpr; | 
|---|
|  | 260 |  | 
|---|
|  | 261 | StructInstType * type = safe_dynamic_cast< StructInstType * >( tuple->get_result() ); | 
|---|
|  | 262 | StructDecl * structDecl = type->get_baseStruct(); | 
|---|
|  | 263 | assert( structDecl->get_members().size() > idx ); | 
|---|
|  | 264 | Declaration * member = *std::next(structDecl->get_members().begin(), idx); | 
|---|
| [d5556a3] | 265 | MemberExpr * memExpr = new MemberExpr( safe_dynamic_cast< DeclarationWithType * >( member ), tuple ); | 
|---|
|  | 266 | memExpr->set_env( env ); | 
|---|
|  | 267 | return memExpr; | 
|---|
| [3c13c03] | 268 | } | 
|---|
|  | 269 |  | 
|---|
| [d5556a3] | 270 | Expression * replaceTupleExpr( Type * result, const std::list< Expression * > & exprs, TypeSubstitution * env ) { | 
|---|
| [65660bd] | 271 | if ( result->isVoid() ) { | 
|---|
|  | 272 | // void result - don't need to produce a value for cascading - just output a chain of comma exprs | 
|---|
|  | 273 | assert( ! exprs.empty() ); | 
|---|
|  | 274 | std::list< Expression * >::const_iterator iter = exprs.begin(); | 
|---|
| [d5556a3] | 275 | Expression * expr = new CastExpr( *iter++ ); | 
|---|
| [65660bd] | 276 | for ( ; iter != exprs.end(); ++iter ) { | 
|---|
| [d5556a3] | 277 | expr = new CommaExpr( expr, new CastExpr( *iter ) ); | 
|---|
| [65660bd] | 278 | } | 
|---|
| [d5556a3] | 279 | expr->set_env( env ); | 
|---|
| [65660bd] | 280 | return expr; | 
|---|
|  | 281 | } else { | 
|---|
|  | 282 | // typed tuple expression - produce a compound literal which performs each of the expressions | 
|---|
|  | 283 | // as a distinct part of its initializer - the produced compound literal may be used as part of | 
|---|
|  | 284 | // another expression | 
|---|
|  | 285 | std::list< Initializer * > inits; | 
|---|
|  | 286 | for ( Expression * expr : exprs ) { | 
|---|
|  | 287 | inits.push_back( new SingleInit( expr ) ); | 
|---|
|  | 288 | } | 
|---|
| [d5556a3] | 289 | Expression * expr = new CompoundLiteralExpr( result, new ListInit( inits ) ); | 
|---|
|  | 290 | expr->set_env( env ); | 
|---|
|  | 291 | return expr; | 
|---|
| [3c13c03] | 292 | } | 
|---|
|  | 293 | } | 
|---|
|  | 294 |  | 
|---|
| [65660bd] | 295 | Expression * TupleExprExpander::mutate( TupleExpr * tupleExpr ) { | 
|---|
| [bf32bb8] | 296 | // recursively expand sub-tuple-expressions | 
|---|
|  | 297 | tupleExpr = safe_dynamic_cast<TupleExpr *>(Parent::mutate(tupleExpr)); | 
|---|
| [65660bd] | 298 | Type * result = tupleExpr->get_result(); | 
|---|
|  | 299 | std::list< Expression * > exprs = tupleExpr->get_exprs(); | 
|---|
|  | 300 | assert( result ); | 
|---|
| [d5556a3] | 301 | TypeSubstitution * env = tupleExpr->get_env(); | 
|---|
| [65660bd] | 302 |  | 
|---|
| [bf32bb8] | 303 | // remove data from shell and delete it | 
|---|
| [65660bd] | 304 | tupleExpr->set_result( nullptr ); | 
|---|
|  | 305 | tupleExpr->get_exprs().clear(); | 
|---|
| [d5556a3] | 306 | tupleExpr->set_env( nullptr ); | 
|---|
| [65660bd] | 307 | delete tupleExpr; | 
|---|
|  | 308 |  | 
|---|
| [d5556a3] | 309 | return replaceTupleExpr( result, exprs, env ); | 
|---|
| [65660bd] | 310 | } | 
|---|
|  | 311 |  | 
|---|
|  | 312 | Type * makeTupleType( const std::list< Expression * > & exprs ) { | 
|---|
|  | 313 | // produce the TupleType which aggregates the types of the exprs | 
|---|
| [bf4ac09] | 314 | TupleType *tupleType = new TupleType( Type::Qualifiers( Type::Const | Type::Volatile | Type::Restrict | Type::Lvalue | Type::Atomic | Type::Mutex ) ); | 
|---|
| [3c13c03] | 315 | Type::Qualifiers &qualifiers = tupleType->get_qualifiers(); | 
|---|
|  | 316 | for ( Expression * expr : exprs ) { | 
|---|
|  | 317 | assert( expr->get_result() ); | 
|---|
| [65660bd] | 318 | if ( expr->get_result()->isVoid() ) { | 
|---|
|  | 319 | // if the type of any expr is void, the type of the entire tuple is void | 
|---|
|  | 320 | delete tupleType; | 
|---|
|  | 321 | return new VoidType( Type::Qualifiers() ); | 
|---|
|  | 322 | } | 
|---|
| [3c13c03] | 323 | Type * type = expr->get_result()->clone(); | 
|---|
|  | 324 | tupleType->get_types().push_back( type ); | 
|---|
| [65660bd] | 325 | // the qualifiers on the tuple type are the qualifiers that exist on all component types | 
|---|
| [3c13c03] | 326 | qualifiers &= type->get_qualifiers(); | 
|---|
|  | 327 | } // for | 
|---|
| [907eccb] | 328 | if ( exprs.empty() ) qualifiers = Type::Qualifiers(); | 
|---|
| [3c13c03] | 329 | return tupleType; | 
|---|
|  | 330 | } | 
|---|
| [65660bd] | 331 |  | 
|---|
| [8bf784a] | 332 | TypeInstType * isTtype( Type * type ) { | 
|---|
|  | 333 | if ( TypeInstType * inst = dynamic_cast< TypeInstType * >( type ) ) { | 
|---|
|  | 334 | if ( inst->get_baseType()->get_kind() == TypeDecl::Ttype ) { | 
|---|
|  | 335 | return inst; | 
|---|
|  | 336 | } | 
|---|
|  | 337 | } | 
|---|
|  | 338 | return nullptr; | 
|---|
|  | 339 | } | 
|---|
|  | 340 |  | 
|---|
| [65660bd] | 341 | namespace { | 
|---|
|  | 342 | /// 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 | 
|---|
|  | 343 | class ImpurityDetector : public Visitor { | 
|---|
|  | 344 | public: | 
|---|
|  | 345 | typedef Visitor Parent; | 
|---|
| [b7b8674] | 346 | virtual void visit( ApplicationExpr * appExpr ) { | 
|---|
|  | 347 | if ( DeclarationWithType * function = InitTweak::getFunction( appExpr ) ) { | 
|---|
|  | 348 | if ( function->get_linkage() == LinkageSpec::Intrinsic ) { | 
|---|
|  | 349 | if ( function->get_name() == "*?" || function->get_name() == "?[?]" ) { | 
|---|
|  | 350 | // intrinsic dereference, subscript are pure, but need to recursively look for impurity | 
|---|
|  | 351 | Parent::visit( appExpr ); | 
|---|
|  | 352 | return; | 
|---|
|  | 353 | } | 
|---|
|  | 354 | } | 
|---|
|  | 355 | } | 
|---|
|  | 356 | maybeImpure = true; | 
|---|
|  | 357 | } | 
|---|
| [65660bd] | 358 | virtual void visit( UntypedExpr * untypedExpr ) { maybeImpure = true; } | 
|---|
|  | 359 | bool maybeImpure = false; | 
|---|
|  | 360 | }; | 
|---|
|  | 361 | } // namespace | 
|---|
|  | 362 |  | 
|---|
|  | 363 | bool maybeImpure( Expression * expr ) { | 
|---|
|  | 364 | ImpurityDetector detector; | 
|---|
|  | 365 | expr->accept( detector ); | 
|---|
|  | 366 | return detector.maybeImpure; | 
|---|
|  | 367 | } | 
|---|
| [6eb8948] | 368 | } // namespace Tuples | 
|---|
|  | 369 |  | 
|---|
|  | 370 | // Local Variables: // | 
|---|
|  | 371 | // tab-width: 4 // | 
|---|
|  | 372 | // mode: c++ // | 
|---|
|  | 373 | // compile-command: "make install" // | 
|---|
|  | 374 | // End: // | 
|---|