Changes in src/InitTweak/InitTweak.cc [cad355a:f9cebb5]
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/InitTweak/InitTweak.cc
rcad355a rf9cebb5 1 #include <algorithm> 1 2 #include "InitTweak.h" 2 3 #include "SynTree/Visitor.h" … … 4 5 #include "SynTree/Initializer.h" 5 6 #include "SynTree/Expression.h" 7 #include "SynTree/Attribute.h" 6 8 #include "GenPoly/GenPoly.h" 7 9 … … 20 22 }; 21 23 22 class Init Expander : public Visitor {24 class InitFlattener : public Visitor { 23 25 public: 24 InitExpander() {}25 26 virtual void visit( SingleInit * singleInit ); 26 27 virtual void visit( ListInit * listInit ); … … 28 29 }; 29 30 30 void Init Expander::visit( SingleInit * singleInit ) {31 void InitFlattener::visit( SingleInit * singleInit ) { 31 32 argList.push_back( singleInit->get_value()->clone() ); 32 33 } 33 34 34 void Init Expander::visit( ListInit * listInit ) {35 // xxx - for now, assume nonested list inits36 std::list<Initializer*>::iterator it = listInit->begin _initializers();37 for ( ; it != listInit->end _initializers(); ++it ) {35 void InitFlattener::visit( ListInit * listInit ) { 36 // flatten nested list inits 37 std::list<Initializer*>::iterator it = listInit->begin(); 38 for ( ; it != listInit->end(); ++it ) { 38 39 (*it)->accept( *this ); 39 40 } … … 42 43 43 44 std::list< Expression * > makeInitList( Initializer * init ) { 44 Init Expander expander;45 maybeAccept( init, expander );46 return expander.argList;45 InitFlattener flattener; 46 maybeAccept( init, flattener ); 47 return flattener.argList; 47 48 } 48 49 … … 53 54 } 54 55 56 class InitExpander::ExpanderImpl { 57 public: 58 virtual std::list< Expression * > next( std::list< Expression * > & indices ) = 0; 59 virtual Statement * buildListInit( UntypedExpr * callExpr, std::list< Expression * > & indices ) = 0; 60 }; 61 62 class InitImpl : public InitExpander::ExpanderImpl { 63 public: 64 InitImpl( Initializer * init ) : init( init ) {} 65 66 virtual std::list< Expression * > next( std::list< Expression * > & indices ) { 67 // this is wrong, but just a placeholder for now 68 // if ( ! flattened ) flatten( indices ); 69 // return ! inits.empty() ? makeInitList( inits.front() ) : std::list< Expression * >(); 70 return makeInitList( init ); 71 } 72 73 virtual Statement * buildListInit( UntypedExpr * callExpr, std::list< Expression * > & indices ); 74 private: 75 Initializer * init; 76 }; 77 78 class ExprImpl : public InitExpander::ExpanderImpl { 79 public: 80 ExprImpl( Expression * expr ) : arg( expr ) {} 81 82 virtual std::list< Expression * > next( std::list< Expression * > & indices ) { 83 std::list< Expression * > ret; 84 Expression * expr = maybeClone( arg ); 85 if ( expr ) { 86 for ( std::list< Expression * >::reverse_iterator it = indices.rbegin(); it != indices.rend(); ++it ) { 87 // go through indices and layer on subscript exprs ?[?] 88 ++it; 89 UntypedExpr * subscriptExpr = new UntypedExpr( new NameExpr( "?[?]") ); 90 subscriptExpr->get_args().push_back( expr ); 91 subscriptExpr->get_args().push_back( (*it)->clone() ); 92 expr = subscriptExpr; 93 } 94 ret.push_back( expr ); 95 } 96 return ret; 97 } 98 99 virtual Statement * buildListInit( UntypedExpr * callExpr, std::list< Expression * > & indices ); 100 private: 101 Expression * arg; 102 }; 103 104 InitExpander::InitExpander( Initializer * init ) : expander( new InitImpl( init ) ) {} 105 106 InitExpander::InitExpander( Expression * expr ) : expander( new ExprImpl( expr ) ) {} 107 108 std::list< Expression * > InitExpander::operator*() { 109 return cur; 110 } 111 112 InitExpander & InitExpander::operator++() { 113 cur = expander->next( indices ); 114 return *this; 115 } 116 117 // use array indices list to build switch statement 118 void InitExpander::addArrayIndex( Expression * index, Expression * dimension ) { 119 indices.push_back( index ); 120 indices.push_back( dimension ); 121 } 122 123 void InitExpander::clearArrayIndices() { 124 indices.clear(); 125 } 126 127 namespace { 128 /// given index i, dimension d, initializer init, and callExpr f, generates 129 /// if (i < d) f(..., init) 130 /// ++i; 131 /// so that only elements within the range of the array are constructed 132 template< typename OutIterator > 133 void buildCallExpr( UntypedExpr * callExpr, Expression * index, Expression * dimension, Initializer * init, OutIterator out ) { 134 UntypedExpr * cond = new UntypedExpr( new NameExpr( "?<?") ); 135 cond->get_args().push_back( index->clone() ); 136 cond->get_args().push_back( dimension->clone() ); 137 138 std::list< Expression * > args = makeInitList( init ); 139 callExpr->get_args().splice( callExpr->get_args().end(), args ); 140 141 *out++ = new IfStmt( noLabels, cond, new ExprStmt( noLabels, callExpr ), NULL ); 142 143 UntypedExpr * increment = new UntypedExpr( new NameExpr( "++?" ) ); 144 increment->get_args().push_back( new AddressExpr( index->clone() ) ); 145 *out++ = new ExprStmt( noLabels, increment ); 146 } 147 148 template< typename OutIterator > 149 void build( UntypedExpr * callExpr, InitExpander::IndexList::iterator idx, InitExpander::IndexList::iterator idxEnd, Initializer * init, OutIterator out ) { 150 if ( idx == idxEnd ) return; 151 Expression * index = *idx++; 152 assert( idx != idxEnd ); 153 Expression * dimension = *idx++; 154 155 // xxx - may want to eventually issue a warning here if we can detect 156 // that the number of elements exceeds to dimension of the array 157 if ( idx == idxEnd ) { 158 if ( ListInit * listInit = dynamic_cast< ListInit * >( init ) ) { 159 for ( Initializer * init : *listInit ) { 160 buildCallExpr( callExpr->clone(), index, dimension, init, out ); 161 } 162 } else { 163 buildCallExpr( callExpr->clone(), index, dimension, init, out ); 164 } 165 } else { 166 std::list< Statement * > branches; 167 168 unsigned long cond = 0; 169 ListInit * listInit = dynamic_cast< ListInit * >( init ); 170 if ( ! listInit ) { 171 // xxx - this shouldn't be an error, but need a way to 172 // terminate without creating output, so should catch this error 173 throw SemanticError( "unbalanced list initializers" ); 174 } 175 176 static UniqueName targetLabel( "L__autogen__" ); 177 Label switchLabel( targetLabel.newName(), 0, std::list< Attribute * >{ new Attribute("unused") } ); 178 for ( Initializer * init : *listInit ) { 179 Expression * condition; 180 // check for designations 181 // if ( init-> ) { 182 condition = new ConstantExpr( Constant::from_ulong( cond ) ); 183 ++cond; 184 // } else { 185 // condition = // ... take designation 186 // cond = // ... take designation+1 187 // } 188 std::list< Statement * > stmts; 189 build( callExpr, idx, idxEnd, init, back_inserter( stmts ) ); 190 stmts.push_back( new BranchStmt( noLabels, switchLabel, BranchStmt::Break ) ); 191 CaseStmt * caseStmt = new CaseStmt( noLabels, condition, stmts ); 192 branches.push_back( caseStmt ); 193 } 194 *out++ = new SwitchStmt( noLabels, index->clone(), branches ); 195 *out++ = new NullStmt( std::list<Label>{ switchLabel } ); 196 } 197 } 198 } 199 200 // if array came with an initializer list: initialize each element 201 // may have more initializers than elements in the array - need to check at each index that 202 // we haven't exceeded size. 203 // may have fewer initializers than elements in the array - need to default construct 204 // remaining elements. 205 // To accomplish this, generate switch statement, consuming all of expander's elements 206 Statement * InitImpl::buildListInit( UntypedExpr * dst, std::list< Expression * > & indices ) { 207 if ( ! init ) return NULL; 208 CompoundStmt * block = new CompoundStmt( noLabels ); 209 build( dst, indices.begin(), indices.end(), init, back_inserter( block->get_kids() ) ); 210 if ( block->get_kids().empty() ) { 211 delete block; 212 return NULL; 213 } else { 214 init = NULL; // init was consumed in creating the list init 215 return block; 216 } 217 } 218 219 Statement * ExprImpl::buildListInit( UntypedExpr * dst, std::list< Expression * > & indices ) { 220 return NULL; 221 } 222 223 Statement * InitExpander::buildListInit( UntypedExpr * dst ) { 224 return expander->buildListInit( dst, indices ); 225 } 226 55 227 bool tryConstruct( ObjectDecl * objDecl ) { 56 228 return ! LinkageSpec::isBuiltin( objDecl->get_linkage() ) && 57 229 (objDecl->get_init() == NULL || 58 230 ( objDecl->get_init() != NULL && objDecl->get_init()->get_maybeConstructed() )) && 59 ! isDesignated( objDecl->get_init() ); 231 ! isDesignated( objDecl->get_init() ) 232 && objDecl->get_storageClass() != DeclarationNode::Extern; 233 } 234 235 class CallFinder : public Visitor { 236 public: 237 typedef Visitor Parent; 238 CallFinder( const std::list< std::string > & names ) : names( names ) {} 239 240 virtual void visit( ApplicationExpr * appExpr ) { 241 handleCallExpr( appExpr ); 242 } 243 244 virtual void visit( UntypedExpr * untypedExpr ) { 245 handleCallExpr( untypedExpr ); 246 } 247 248 std::list< Expression * > * matches; 249 private: 250 const std::list< std::string > names; 251 252 template< typename CallExpr > 253 void handleCallExpr( CallExpr * expr ) { 254 Parent::visit( expr ); 255 std::string fname = getFunctionName( expr ); 256 if ( std::find( names.begin(), names.end(), fname ) != names.end() ) { 257 matches->push_back( expr ); 258 } 259 } 260 }; 261 262 void collectCtorDtorCalls( Statement * stmt, std::list< Expression * > & matches ) { 263 static CallFinder finder( std::list< std::string >{ "?{}", "^?{}" } ); 264 finder.matches = &matches; 265 maybeAccept( stmt, finder ); 60 266 } 61 267 62 268 Expression * getCtorDtorCall( Statement * stmt ) { 63 if ( stmt == NULL ) return NULL; 64 if ( ExprStmt * exprStmt = dynamic_cast< ExprStmt * >( stmt ) ) { 65 return exprStmt->get_expr(); 66 } else if ( CompoundStmt * compoundStmt = dynamic_cast< CompoundStmt * >( stmt ) ) { 67 // could also be a compound statement with a loop, in the case of an array 68 if( compoundStmt->get_kids().size() == 2 ) { 69 // loop variable and loop 70 ForStmt * forStmt = dynamic_cast< ForStmt * >( compoundStmt->get_kids().back() ); 71 assert( forStmt && forStmt->get_body() ); 72 return getCtorDtorCall( forStmt->get_body() ); 73 } else if ( compoundStmt->get_kids().size() == 1 ) { 74 // should be the call statement, but in any case there's only one option 75 return getCtorDtorCall( compoundStmt->get_kids().front() ); 76 } else { 77 assert( false && "too many statements in compoundStmt for getCtorDtorCall" ); 78 } 79 } if ( ImplicitCtorDtorStmt * impCtorDtorStmt = dynamic_cast< ImplicitCtorDtorStmt * > ( stmt ) ) { 80 return getCtorDtorCall( impCtorDtorStmt->get_callStmt() ); 81 } else { 82 // should never get here 83 assert( false && "encountered unknown call statement" ); 84 } 85 } 86 87 bool isInstrinsicSingleArgCallStmt( Statement * stmt ) { 88 Expression * callExpr = getCtorDtorCall( stmt ); 89 if ( ! callExpr ) return false; 90 ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( callExpr ); 91 assert( appExpr ); 92 VariableExpr * function = dynamic_cast< VariableExpr * >( appExpr->get_function() ); 269 std::list< Expression * > matches; 270 collectCtorDtorCalls( stmt, matches ); 271 assert( matches.size() <= 1 ); 272 return matches.size() == 1 ? matches.front() : NULL; 273 } 274 275 namespace { 276 VariableExpr * getCalledFunction( ApplicationExpr * appExpr ) { 277 assert( appExpr ); 278 // xxx - it's possible this can be other things, e.g. MemberExpr, so this is insufficient 279 return dynamic_cast< VariableExpr * >( appExpr->get_function() ); 280 } 281 } 282 283 ApplicationExpr * isIntrinsicCallExpr( Expression * expr ) { 284 ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( expr ); 285 if ( ! appExpr ) return NULL; 286 VariableExpr * function = getCalledFunction( appExpr ); 93 287 assert( function ); 94 288 // check for Intrinsic only - don't want to remove all overridable ctor/dtors because autogenerated ctor/dtor 95 289 // will call all member dtors, and some members may have a user defined dtor. 96 FunctionType * funcType = GenPoly::getFunctionType( function->get_var()->get_type() ); 97 assert( funcType ); 98 return function->get_var()->get_linkage() == LinkageSpec::Intrinsic && funcType->get_parameters().size() == 1; 290 return function->get_var()->get_linkage() == LinkageSpec::Intrinsic ? appExpr : NULL; 291 } 292 293 bool isIntrinsicSingleArgCallStmt( Statement * stmt ) { 294 std::list< Expression * > callExprs; 295 collectCtorDtorCalls( stmt, callExprs ); 296 // if ( callExprs.empty() ) return false; // xxx - do I still need this check? 297 return std::all_of( callExprs.begin(), callExprs.end(), []( Expression * callExpr ){ 298 if ( ApplicationExpr * appExpr = isIntrinsicCallExpr( callExpr ) ) { 299 assert( ! appExpr->get_function()->get_results().empty() ); 300 FunctionType *funcType = GenPoly::getFunctionType( appExpr->get_function()->get_results().front() ); 301 assert( funcType ); 302 return funcType->get_parameters().size() == 1; 303 } 304 return false; 305 }); 99 306 } 100 307 … … 160 367 else return NULL; 161 368 } 369 370 class ConstExprChecker : public Visitor { 371 public: 372 ConstExprChecker() : isConstExpr( true ) {} 373 374 virtual void visit( ApplicationExpr *applicationExpr ) { isConstExpr = false; } 375 virtual void visit( UntypedExpr *untypedExpr ) { isConstExpr = false; } 376 virtual void visit( NameExpr *nameExpr ) { isConstExpr = false; } 377 virtual void visit( CastExpr *castExpr ) { isConstExpr = false; } 378 virtual void visit( LabelAddressExpr *labAddressExpr ) { isConstExpr = false; } 379 virtual void visit( UntypedMemberExpr *memberExpr ) { isConstExpr = false; } 380 virtual void visit( MemberExpr *memberExpr ) { isConstExpr = false; } 381 virtual void visit( VariableExpr *variableExpr ) { isConstExpr = false; } 382 virtual void visit( ConstantExpr *constantExpr ) { /* bottom out */ } 383 // these might be okay? 384 // virtual void visit( SizeofExpr *sizeofExpr ); 385 // virtual void visit( AlignofExpr *alignofExpr ); 386 // virtual void visit( UntypedOffsetofExpr *offsetofExpr ); 387 // virtual void visit( OffsetofExpr *offsetofExpr ); 388 // virtual void visit( OffsetPackExpr *offsetPackExpr ); 389 // virtual void visit( AttrExpr *attrExpr ); 390 // virtual void visit( CommaExpr *commaExpr ); 391 // virtual void visit( LogicalExpr *logicalExpr ); 392 // virtual void visit( ConditionalExpr *conditionalExpr ); 393 virtual void visit( TupleExpr *tupleExpr ) { isConstExpr = false; } 394 virtual void visit( SolvedTupleExpr *tupleExpr ) { isConstExpr = false; } 395 virtual void visit( TypeExpr *typeExpr ) { isConstExpr = false; } 396 virtual void visit( AsmExpr *asmExpr ) { isConstExpr = false; } 397 virtual void visit( UntypedValofExpr *valofExpr ) { isConstExpr = false; } 398 virtual void visit( CompoundLiteralExpr *compLitExpr ) { isConstExpr = false; } 399 400 bool isConstExpr; 401 }; 402 403 bool isConstExpr( Expression * expr ) { 404 if ( expr ) { 405 ConstExprChecker checker; 406 expr->accept( checker ); 407 return checker.isConstExpr; 408 } 409 return true; 410 } 411 412 bool isConstExpr( Initializer * init ) { 413 if ( init ) { 414 ConstExprChecker checker; 415 init->accept( checker ); 416 return checker.isConstExpr; 417 } // if 418 // for all intents and purposes, no initializer means const expr 419 return true; 420 } 421 162 422 }
Note:
See TracChangeset
for help on using the changeset viewer.