Changes in src/GenPoly/Lvalue.cc [a4d188f:a16764a6]
- File:
-
- 1 edited
-
src/GenPoly/Lvalue.cc (modified) (13 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/GenPoly/Lvalue.cc
ra4d188f ra16764a6 59 59 } 60 60 61 struct ReferenceConversions final : public WithStmtsToAdd{61 struct ReferenceConversions final { 62 62 Expression * postmutate( CastExpr * castExpr ); 63 63 Expression * postmutate( AddressExpr * addrExpr ); … … 114 114 } 115 115 116 void convertLvalue( std::list< Declaration* > & translationUnit ) {116 void convertLvalue( std::list< Declaration* >& translationUnit ) { 117 117 PassVisitor<ReferenceConversions> refCvt; 118 118 PassVisitor<ReferenceTypeElimination> elim; … … 150 150 // use type of return variable rather than expr result type, since it may have been changed to a pointer type 151 151 FunctionType * ftype = GenPoly::getFunctionType( func->get_type() ); 152 Type * ret = ftype-> returnVals.empty() ? nullptr : ftype->returnVals.front()->get_type();153 return func-> linkage== LinkageSpec::Intrinsic && dynamic_cast<ReferenceType *>( ret );152 Type * ret = ftype->get_returnVals().empty() ? nullptr : ftype->get_returnVals().front()->get_type(); 153 return func->get_linkage() == LinkageSpec::Intrinsic && dynamic_cast<ReferenceType *>( ret ); 154 154 } 155 155 } … … 160 160 if ( isIntrinsicReference( appExpr ) ) { 161 161 // eliminate reference types from intrinsic applications - now they return lvalues 162 Type * result = appExpr-> result;163 appExpr-> result = result->stripReferences()->clone();164 appExpr-> result->set_lvalue( true );162 Type * result = appExpr->get_result(); 163 appExpr->set_result( result->stripReferences()->clone() ); 164 appExpr->get_result()->set_lvalue( true ); 165 165 if ( ! inIntrinsic ) { 166 166 // when not in an intrinsic function, add a cast to 167 167 // don't add cast when in an intrinsic function, since they already have the cast 168 168 Expression * ret = new CastExpr( appExpr, result ); 169 std::swap( ret->env, appExpr->env ); 169 ret->set_env( appExpr->get_env() ); 170 appExpr->set_env( nullptr ); 170 171 return ret; 171 172 } … … 186 187 assertf( ftype, "Function declaration does not have function type." ); 187 188 // can be of differing lengths only when function is variadic 188 assertf( ftype-> parameters.size() == appExpr->args.size() || ftype->isVarArgs, "ApplicationExpr args do not match formal parameter type." );189 assertf( ftype->get_parameters().size() == appExpr->get_args().size() || ftype->get_isVarArgs(), "ApplicationExpr args do not match formal parameter type." ); 189 190 190 191 191 192 unsigned int i = 0; 192 const unsigned int end = ftype-> parameters.size();193 for ( auto p : unsafe_group_iterate( appExpr-> args, ftype->parameters) ) {193 const unsigned int end = ftype->get_parameters().size(); 194 for ( auto p : unsafe_group_iterate( appExpr->get_args(), ftype->get_parameters() ) ) { 194 195 if (i == end) break; 195 196 Expression *& arg = std::get<0>( p ); … … 211 212 // std::cerr << "===adding deref to arg" << std::endl; 212 213 // if the parameter is a reference, add a dereference to the reference-typed argument. 213 Type * baseType = InitTweak::getPointerBase( arg-> result);214 assertf( baseType, "parameter is reference, arg must be pointer or reference: %s", toString( arg-> result).c_str() );214 Type * baseType = InitTweak::getPointerBase( arg->get_result() ); 215 assertf( baseType, "parameter is reference, arg must be pointer or reference: %s", toString( arg->get_result() ).c_str() ); 215 216 PointerType * ptrType = new PointerType( Type::Qualifiers(), baseType->clone() ); 216 delete arg-> result;217 delete arg->get_result(); 217 218 arg->set_result( ptrType ); 218 219 arg = mkDeref( arg ); … … 248 249 Expression * AddrRef::postmutate( AddressExpr * addrExpr ) { 249 250 if ( refDepth == 0 ) { 250 if ( ! isIntrinsicReference( addrExpr-> arg) ) {251 if ( ! isIntrinsicReference( addrExpr->get_arg() ) ) { 251 252 // try to avoid ?[?] 252 refDepth = addrExpr-> arg->result->referenceDepth();253 refDepth = addrExpr->get_arg()->get_result()->referenceDepth(); 253 254 } 254 255 } … … 279 280 // pointer casts in the right places. 280 281 281 // Note: reference depth difference is the determining factor in what code is run, rather than whether something is 282 // reference type or not, since conversion still needs to occur when both types are references that differ in depth. 283 284 Type * destType = castExpr->result; 285 Type * srcType = castExpr->arg->result; 286 int depth1 = destType->referenceDepth(); 287 int depth2 = srcType->referenceDepth(); 288 int diff = depth1 - depth2; 289 290 if ( diff > 0 && ! srcType->get_lvalue() ) { 291 // rvalue to reference conversion -- introduce temporary 292 // know that reference depth of cast argument is 0, need to introduce n temporaries for reference depth of n, e.g. 293 // (int &&&)3; 294 // becomes 295 // int __ref_tmp_0 = 3; 296 // int & __ref_tmp_1 = _&_ref_tmp_0; 297 // int && __ref_tmp_2 = &__ref_tmp_1; 298 // &__ref_tmp_2; 299 // the last & comes from the remaining reference conversion code 300 SemanticWarning( castExpr->arg->location, Warning::RvalueToReferenceConversion, toCString( castExpr->arg ) ); 301 302 static UniqueName tempNamer( "__ref_tmp_" ); 303 ObjectDecl * temp = ObjectDecl::newObject( tempNamer.newName(), castExpr->arg->result->clone(), new SingleInit( castExpr->arg ) ); 304 PRINT( std::cerr << "made temp: " << temp << std::endl; ) 305 stmtsToAddBefore.push_back( new DeclStmt( temp ) ); 306 for ( int i = 0; i < depth1-1; i++ ) { // xxx - maybe this should be diff-1? check how this works with reference type for srcType 307 ObjectDecl * newTemp = ObjectDecl::newObject( tempNamer.newName(), new ReferenceType( Type::Qualifiers(), temp->type->clone() ), new SingleInit( new AddressExpr( new VariableExpr( temp ) ) ) ); 308 PRINT( std::cerr << "made temp" << i << ": " << newTemp << std::endl; ) 309 stmtsToAddBefore.push_back( new DeclStmt( newTemp ) ); 310 temp = newTemp; 311 } 312 // update diff so that remaining code works out correctly 313 castExpr->arg = new VariableExpr( temp ); 314 PRINT( std::cerr << "update cast to: " << castExpr << std::endl; ) 315 srcType = castExpr->arg->result; 316 depth2 = srcType->referenceDepth(); 317 diff = depth1 - depth2; 318 assert( diff == 1 ); 319 } 320 321 // handle conversion between different depths 322 PRINT ( 323 if ( depth1 || depth2 ) { 324 std::cerr << "destType: " << destType << " / srcType: " << srcType << std::endl; 325 std::cerr << "depth: " << depth1 << " / " << depth2 << std::endl; 326 } 327 ) 328 if ( diff > 0 ) { 329 // conversion to type with more depth (e.g. int & -> int &&): add address-of for each level of difference 282 // conversion to reference type 283 if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( castExpr->get_result() ) ) { 284 (void)refType; 285 if ( ReferenceType * otherRef = dynamic_cast< ReferenceType * >( castExpr->get_arg()->get_result() ) ) { 286 // nothing to do if casting from reference to reference. 287 (void)otherRef; 288 PRINT( std::cerr << "convert reference to reference -- nop" << std::endl; ) 289 if ( isIntrinsicReference( castExpr->get_arg() ) ) { 290 Expression * callExpr = castExpr->get_arg(); 291 PRINT( 292 std::cerr << "but arg is deref -- &" << std::endl; 293 std::cerr << callExpr << std::endl; 294 ) 295 callExpr = new AddressExpr( callExpr ); // this doesn't work properly for multiple casts 296 delete callExpr->get_result(); 297 callExpr->set_result( refType->clone() ); 298 // move environment out to new top-level 299 callExpr->set_env( castExpr->get_env() ); 300 castExpr->set_arg( nullptr ); 301 castExpr->set_env( nullptr ); 302 delete castExpr; 303 return callExpr; 304 } 305 int depth1 = refType->referenceDepth(); 306 int depth2 = otherRef->referenceDepth(); 307 int diff = depth1-depth2; 308 if ( diff == 0 ) { 309 // conversion between references of the same depth 310 assertf( depth1 == depth2, "non-intrinsic reference with cast of reference to reference not yet supported: %d %d %s", depth1, depth2, toString( castExpr ).c_str() ); 311 PRINT( std::cerr << castExpr << std::endl; ) 312 return castExpr; 313 } else if ( diff < 0 ) { 314 // conversion from reference to reference with less depth (e.g. int && -> int &): add dereferences 315 Expression * ret = castExpr->arg; 316 for ( int i = 0; i < diff; ++i ) { 317 ret = mkDeref( ret ); 318 } 319 ret->env = castExpr->env; 320 delete ret->result; 321 ret->result = castExpr->result; 322 ret->result->set_lvalue( true ); // ensure result is lvalue 323 castExpr->env = nullptr; 324 castExpr->arg = nullptr; 325 castExpr->result = nullptr; 326 delete castExpr; 327 return ret; 328 } else if ( diff > 0 ) { 329 // conversion from reference to reference with more depth (e.g. int & -> int &&): add address-of 330 Expression * ret = castExpr->arg; 331 for ( int i = 0; i < diff; ++i ) { 332 ret = new AddressExpr( ret ); 333 } 334 ret->env = castExpr->env; 335 delete ret->result; 336 ret->result = castExpr->result; 337 castExpr->env = nullptr; 338 castExpr->arg = nullptr; 339 castExpr->result = nullptr; 340 delete castExpr; 341 return ret; 342 } 343 344 assertf( depth1 == depth2, "non-intrinsic reference with cast of reference to reference not yet supported: %d %d %s", depth1, depth2, toString( castExpr ).c_str() ); 345 PRINT( std::cerr << castExpr << std::endl; ) 346 return castExpr; 347 } else if ( castExpr->arg->result->get_lvalue() ) { 348 // conversion from lvalue to reference 349 // xxx - keep cast, but turn into pointer cast?? 350 // xxx - memory 351 PRINT( 352 std::cerr << "convert lvalue to reference -- &" << std::endl; 353 std::cerr << castExpr->arg << std::endl; 354 ) 355 AddressExpr * ret = new AddressExpr( castExpr->arg ); 356 if ( refType->base->get_qualifiers() != castExpr->arg->result->get_qualifiers() ) { 357 // must keep cast if cast-to type is different from the actual type 358 castExpr->arg = ret; 359 return castExpr; 360 } 361 ret->env = castExpr->env; 362 delete ret->result; 363 ret->result = castExpr->result; 364 castExpr->env = nullptr; 365 castExpr->arg = nullptr; 366 castExpr->result = nullptr; 367 delete castExpr; 368 return ret; 369 } else { 370 // rvalue to reference conversion -- introduce temporary 371 } 372 assertf( false, "Only conversions to reference from lvalue are currently supported: %s", toString( castExpr ).c_str() ); 373 } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( castExpr->arg->result ) ) { 374 (void)refType; 375 // conversion from reference to rvalue 376 PRINT( 377 std::cerr << "convert reference to rvalue -- *" << std::endl; 378 std::cerr << "was = " << castExpr << std::endl; 379 ) 330 380 Expression * ret = castExpr->arg; 331 for ( int i = 0; i < diff; ++i ) { 332 ret = new AddressExpr( ret ); 333 } 334 if ( srcType->get_lvalue() && srcType->get_qualifiers() != strict_dynamic_cast<ReferenceType *>( destType )->base->get_qualifiers() ) { 335 // must keep cast if cast-to type is different from the actual type 336 castExpr->arg = ret; 337 return castExpr; 338 } 339 ret->env = castExpr->env; 340 delete ret->result; 341 ret->result = castExpr->result; 342 castExpr->env = nullptr; 343 castExpr->arg = nullptr; 344 castExpr->result = nullptr; 345 delete castExpr; 346 return ret; 347 } else if ( diff < 0 ) { 348 // conversion to type with less depth (e.g. int && -> int &): add dereferences for each level of difference 349 diff = -diff; // care only about magnitude now 350 Expression * ret = castExpr->arg; 351 for ( int i = 0; i < diff; ++i ) { 381 TypeSubstitution * env = castExpr->env; 382 castExpr->set_env( nullptr ); 383 if ( ! isIntrinsicReference( ret ) ) { 384 // dereference if not already dereferenced 352 385 ret = mkDeref( ret ); 353 386 } 354 if ( ! ResolvExpr::typesCompatibleIgnoreQualifiers( destType->stripReferences(), srcType->stripReferences(), SymTab::Indexer() ) ) { 387 if ( ResolvExpr::typesCompatibleIgnoreQualifiers( castExpr->result, castExpr->arg->result->stripReferences(), SymTab::Indexer() ) ) { 388 // can remove cast if types are compatible, changing expression type to value type 389 ret->result = castExpr->result->clone(); 390 ret->result->set_lvalue( true ); // ensure result is lvalue 391 castExpr->arg = nullptr; 392 delete castExpr; 393 } else { 355 394 // must keep cast if types are different 356 395 castExpr->arg = ret; 357 return castExpr; 358 } 359 ret->env = castExpr->env; 360 delete ret->result; 361 ret->result = castExpr->result; 362 ret->result->set_lvalue( true ); // ensure result is lvalue 363 castExpr->env = nullptr; 364 castExpr->arg = nullptr; 365 castExpr->result = nullptr; 366 delete castExpr; 396 ret = castExpr; 397 } 398 ret->set_env( env ); 399 PRINT( std::cerr << "now: " << ret << std::endl; ) 367 400 return ret; 368 } else { 369 assert( diff == 0 ); 370 // conversion between references of the same depth 371 return castExpr; 372 } 401 } 402 return castExpr; 373 403 } 374 404 375 405 Type * ReferenceTypeElimination::postmutate( ReferenceType * refType ) { 376 Type * base = refType-> base;406 Type * base = refType->get_base(); 377 407 Type::Qualifiers qualifiers = refType->get_qualifiers(); 378 refType-> base = nullptr;408 refType->set_base( nullptr ); 379 409 delete refType; 380 410 return new PointerType( qualifiers, base ); … … 384 414 Expression * GeneralizedLvalue::applyTransformation( Expression * expr, Expression * arg, Func mkExpr ) { 385 415 if ( CommaExpr * commaExpr = dynamic_cast< CommaExpr * >( arg ) ) { 386 Expression * arg1 = commaExpr-> arg1->clone();387 Expression * arg2 = commaExpr-> arg2->clone();416 Expression * arg1 = commaExpr->get_arg1()->clone(); 417 Expression * arg2 = commaExpr->get_arg2()->clone(); 388 418 Expression * ret = new CommaExpr( arg1, mkExpr( arg2 )->acceptMutator( *visitor ) ); 389 ret-> env = expr->env;390 expr-> env = nullptr;419 ret->set_env( expr->get_env() ); 420 expr->set_env( nullptr ); 391 421 delete expr; 392 422 return ret; 393 423 } else if ( ConditionalExpr * condExpr = dynamic_cast< ConditionalExpr * >( arg ) ) { 394 Expression * arg1 = condExpr-> arg1->clone();395 Expression * arg2 = condExpr-> arg2->clone();396 Expression * arg3 = condExpr-> arg3->clone();424 Expression * arg1 = condExpr->get_arg1()->clone(); 425 Expression * arg2 = condExpr->get_arg2()->clone(); 426 Expression * arg3 = condExpr->get_arg3()->clone(); 397 427 ConditionalExpr * ret = new ConditionalExpr( arg1, mkExpr( arg2 )->acceptMutator( *visitor ), mkExpr( arg3 )->acceptMutator( *visitor ) ); 398 ret-> env = expr->env;399 expr-> env = nullptr;428 ret->set_env( expr->get_env() ); 429 expr->set_env( nullptr ); 400 430 delete expr; 401 431 … … 406 436 AssertionSet needAssertions, haveAssertions; 407 437 OpenVarSet openVars; 408 unify( ret-> arg2->result, ret->arg3->result, newEnv, needAssertions, haveAssertions, openVars, SymTab::Indexer(), commonType );409 ret-> result = commonType ? commonType : ret->arg2->result->clone();438 unify( ret->get_arg2()->get_result(), ret->get_arg3()->get_result(), newEnv, needAssertions, haveAssertions, openVars, SymTab::Indexer(), commonType ); 439 ret->set_result( commonType ? commonType : ret->get_arg2()->get_result()->clone() ); 410 440 return ret; 411 441 } … … 414 444 415 445 Expression * GeneralizedLvalue::postmutate( MemberExpr * memExpr ) { 416 return applyTransformation( memExpr, memExpr-> aggregate, [=]( Expression * aggr ) { return new MemberExpr( memExpr->member, aggr ); } );446 return applyTransformation( memExpr, memExpr->get_aggregate(), [=]( Expression * aggr ) { return new MemberExpr( memExpr->get_member(), aggr ); } ); 417 447 } 418 448 419 449 Expression * GeneralizedLvalue::postmutate( AddressExpr * addrExpr ) { 420 return applyTransformation( addrExpr, addrExpr-> arg, []( Expression * arg ) { return new AddressExpr( arg ); } );450 return applyTransformation( addrExpr, addrExpr->get_arg(), []( Expression * arg ) { return new AddressExpr( arg ); } ); 421 451 } 422 452 423 453 Expression * CollapseAddrDeref::postmutate( AddressExpr * addrExpr ) { 424 Expression * arg = addrExpr-> arg;454 Expression * arg = addrExpr->get_arg(); 425 455 if ( isIntrinsicReference( arg ) ) { 426 456 std::string fname = InitTweak::getFunctionName( arg ); … … 428 458 Expression *& arg0 = InitTweak::getCallArg( arg, 0 ); 429 459 Expression * ret = arg0; 430 ret->set_env( addrExpr-> env);460 ret->set_env( addrExpr->get_env() ); 431 461 arg0 = nullptr; 432 addrExpr-> env = nullptr;462 addrExpr->set_env( nullptr ); 433 463 delete addrExpr; 434 464 return ret; … … 457 487 // } 458 488 if ( AddressExpr * addrExpr = dynamic_cast< AddressExpr * >( arg ) ) { 459 Expression * ret = addrExpr-> arg;460 ret-> env = appExpr->env;461 addrExpr-> arg = nullptr;462 appExpr-> env = nullptr;489 Expression * ret = addrExpr->get_arg(); 490 ret->set_env( appExpr->get_env() ); 491 addrExpr->set_arg( nullptr ); 492 appExpr->set_env( nullptr ); 463 493 delete appExpr; 464 494 return ret;
Note:
See TracChangeset
for help on using the changeset viewer.