Changeset 31cb252
- Timestamp:
- Mar 19, 2018, 2:07:37 PM (7 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, with_gc
- Children:
- 6470882
- Parents:
- b1ccdfd
- git-author:
- Rob Schluntz <rschlunt@…> (03/09/18 14:42:56)
- git-committer:
- Rob Schluntz <rschlunt@…> (03/19/18 14:07:37)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/GenPoly/Lvalue.cc
rb1ccdfd r31cb252 59 59 } 60 60 61 struct ReferenceConversions final {61 struct ReferenceConversions final : public WithStmtsToAdd { 62 62 Expression * postmutate( CastExpr * castExpr ); 63 63 Expression * postmutate( AddressExpr * addrExpr ); … … 279 279 // pointer casts in the right places. 280 280 281 // conversion to reference type 282 if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( castExpr->result ) ) { 283 (void)refType; 284 if ( ReferenceType * otherRef = dynamic_cast< ReferenceType * >( castExpr->arg->result ) ) { 285 // nothing to do if casting from reference to reference. 286 (void)otherRef; 287 PRINT( std::cerr << "convert reference to reference -- nop" << std::endl; ) 288 if ( isIntrinsicReference( castExpr->arg ) ) { 289 Expression * callExpr = castExpr->arg; 290 PRINT( 291 std::cerr << "but arg is deref -- &" << std::endl; 292 std::cerr << callExpr << std::endl; 293 ) 294 callExpr = new AddressExpr( callExpr ); // this doesn't work properly for multiple casts 295 delete callExpr->result; 296 callExpr->set_result( refType->clone() ); 297 // move environment out to new top-level 298 callExpr->env = castExpr->env; 299 castExpr->arg = nullptr; 300 castExpr->env = nullptr; 301 delete castExpr; 302 return callExpr; 303 } 304 int depth1 = refType->referenceDepth(); 305 int depth2 = otherRef->referenceDepth(); 306 int diff = depth1-depth2; 307 if ( diff == 0 ) { 308 // conversion between references of the same depth 309 assertf( depth1 == depth2, "non-intrinsic reference with cast of reference to reference not yet supported: %d %d %s", depth1, depth2, toString( castExpr ).c_str() ); 310 PRINT( std::cerr << castExpr << std::endl; ) 311 return castExpr; 312 } else if ( diff < 0 ) { 313 // conversion from reference to reference with less depth (e.g. int && -> int &): add dereferences 314 Expression * ret = castExpr->arg; 315 for ( int i = 0; i < diff; ++i ) { 316 ret = mkDeref( ret ); 317 } 318 ret->env = castExpr->env; 319 delete ret->result; 320 ret->result = castExpr->result; 321 ret->result->set_lvalue( true ); // ensure result is lvalue 322 castExpr->env = nullptr; 323 castExpr->arg = nullptr; 324 castExpr->result = nullptr; 325 delete castExpr; 326 return ret; 327 } else if ( diff > 0 ) { 328 // conversion from reference to reference with more depth (e.g. int & -> int &&): add address-of 329 Expression * ret = castExpr->arg; 330 for ( int i = 0; i < diff; ++i ) { 331 ret = new AddressExpr( ret ); 332 } 333 ret->env = castExpr->env; 334 delete ret->result; 335 ret->result = castExpr->result; 336 castExpr->env = nullptr; 337 castExpr->arg = nullptr; 338 castExpr->result = nullptr; 339 delete castExpr; 340 return ret; 341 } 342 343 assertf( depth1 == depth2, "non-intrinsic reference with cast of reference to reference not yet supported: %d %d %s", depth1, depth2, toString( castExpr ).c_str() ); 344 PRINT( std::cerr << castExpr << std::endl; ) 281 // need to reorganize this so that depth difference is the determining factor in what code is run, rather than whether something is reference type or not. 282 283 Type * destType = castExpr->result; 284 Type * srcType = castExpr->arg->result; 285 int depth1 = destType->referenceDepth(); 286 int depth2 = srcType->referenceDepth(); 287 int diff = depth1 - depth2; 288 289 if ( diff > 0 && ! srcType->get_lvalue() ) { 290 // rvalue to reference conversion -- introduce temporary 291 // know that reference depth of cast argument is 0, need to introduce n temporaries for reference depth of n, e.g. 292 // (int &&&)3; 293 // becomes 294 // int __ref_tmp_0 = 3; 295 // int & __ref_tmp_1 = _&_ref_tmp_0; 296 // int && __ref_tmp_2 = &__ref_tmp_1; 297 // &__ref_tmp_2; 298 299 static UniqueName tempNamer( "__ref_tmp_" ); 300 ObjectDecl * temp = ObjectDecl::newObject( tempNamer.newName(), castExpr->arg->result->clone(), new SingleInit( castExpr->arg ) ); 301 PRINT( std::cerr << "made temp: " << temp << std::endl; ) 302 stmtsToAddBefore.push_back( new DeclStmt( temp ) ); 303 for ( int i = 0; i < depth1-1; i++ ) { 304 ObjectDecl * newTemp = ObjectDecl::newObject( tempNamer.newName(), new ReferenceType( Type::Qualifiers(), temp->type->clone() ), new SingleInit( new AddressExpr( new VariableExpr( temp ) ) ) ); 305 PRINT( std::cerr << "made temp" << i << ": " << newTemp << std::endl; ) 306 stmtsToAddBefore.push_back( new DeclStmt( newTemp ) ); 307 temp = newTemp; 308 } 309 // update diff so that remaining code works out correctly 310 castExpr->arg = new VariableExpr( temp ); 311 PRINT( std::cerr << "update cast to: " << castExpr << std::endl; ) 312 srcType = castExpr->arg->result; 313 depth2 = srcType->referenceDepth(); 314 diff = depth1 - depth2; 315 assert( diff == 1 ); 316 } 317 318 PRINT ( 319 if ( depth1 || depth2 ) { 320 std::cerr << "destType: " << destType << " / srcType: " << srcType << std::endl; 321 std::cerr << "depth: " << depth1 << " / " << depth2 << std::endl; 322 } 323 ) 324 if ( diff > 0 ) { 325 // conversion to type with more depth (e.g. int & -> int &&): add address-of for each level of difference 326 Expression * ret = castExpr->arg; 327 for ( int i = 0; i < diff; ++i ) { 328 ret = new AddressExpr( ret ); 329 } 330 if ( srcType->get_lvalue() && srcType->get_qualifiers() != strict_dynamic_cast<ReferenceType *>( destType )->base->get_qualifiers() ) { 331 // must keep cast if cast-to type is different from the actual type 332 castExpr->arg = ret; 345 333 return castExpr; 346 } else if ( castExpr->arg->result->get_lvalue() ) { 347 // conversion from lvalue to reference 348 // xxx - keep cast, but turn into pointer cast?? 349 // xxx - memory 350 PRINT( 351 std::cerr << "convert lvalue to reference -- &" << std::endl; 352 std::cerr << castExpr->arg << std::endl; 353 ) 354 AddressExpr * ret = new AddressExpr( castExpr->arg ); 355 if ( refType->base->get_qualifiers() != castExpr->arg->result->get_qualifiers() ) { 356 // must keep cast if cast-to type is different from the actual type 357 castExpr->arg = ret; 358 return castExpr; 359 } 360 ret->env = castExpr->env; 361 delete ret->result; 362 ret->result = castExpr->result; 363 castExpr->env = nullptr; 364 castExpr->arg = nullptr; 365 castExpr->result = nullptr; 366 delete castExpr; 367 return ret; 368 } else { 369 // rvalue to reference conversion -- introduce temporary 370 } 371 assertf( false, "Only conversions to reference from lvalue are currently supported: %s", toString( castExpr ).c_str() ); 372 } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( castExpr->arg->result ) ) { 373 (void)refType; 374 // conversion from reference to rvalue 375 PRINT( 376 std::cerr << "convert reference to rvalue -- *" << std::endl; 377 std::cerr << "was = " << castExpr << std::endl; 378 ) 334 } 335 ret->env = castExpr->env; 336 delete ret->result; 337 ret->result = castExpr->result; 338 castExpr->env = nullptr; 339 castExpr->arg = nullptr; 340 castExpr->result = nullptr; 341 delete castExpr; 342 return ret; 343 } else if ( diff < 0 ) { 344 // conversion to type with less depth (e.g. int && -> int &): add dereferences for each level of difference 345 diff = -diff; // care only about magnitude now 379 346 Expression * ret = castExpr->arg; 380 TypeSubstitution * env = castExpr->env; 381 castExpr->set_env( nullptr ); 382 if ( ! isIntrinsicReference( ret ) ) { 383 // dereference if not already dereferenced 347 for ( int i = 0; i < diff; ++i ) { 384 348 ret = mkDeref( ret ); 385 349 } 386 if ( ResolvExpr::typesCompatibleIgnoreQualifiers( castExpr->result, castExpr->arg->result->stripReferences(), SymTab::Indexer() ) ) { 387 // can remove cast if types are compatible, changing expression type to value type 388 ret->result = castExpr->result->clone(); 389 ret->result->set_lvalue( true ); // ensure result is lvalue 390 castExpr->arg = nullptr; 391 delete castExpr; 392 } else { 350 if ( ! ResolvExpr::typesCompatibleIgnoreQualifiers( destType->stripReferences(), srcType->stripReferences(), SymTab::Indexer() ) ) { 393 351 // must keep cast if types are different 394 352 castExpr->arg = ret; 395 ret = castExpr; 396 } 397 ret->set_env( env ); 398 PRINT( std::cerr << "now: " << ret << std::endl; ) 353 return castExpr; 354 } 355 ret->env = castExpr->env; 356 delete ret->result; 357 ret->result = castExpr->result; 358 ret->result->set_lvalue( true ); // ensure result is lvalue 359 castExpr->env = nullptr; 360 castExpr->arg = nullptr; 361 castExpr->result = nullptr; 362 delete castExpr; 399 363 return ret; 400 } 401 return castExpr; 364 } else { 365 assert( diff == 0 ); 366 // conversion between references of the same depth 367 return castExpr; 368 } 369 370 // // conversion to reference type 371 // if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( castExpr->result ) ) { 372 // (void)refType; 373 // if ( ReferenceType * otherRef = dynamic_cast< ReferenceType * >( castExpr->arg->result ) ) { 374 // // nothing to do if casting from reference to reference. 375 // (void)otherRef; 376 // PRINT( std::cerr << "convert reference to reference -- nop" << std::endl; ) 377 // if ( isIntrinsicReference( castExpr->arg ) ) { 378 // Expression * callExpr = castExpr->arg; 379 // PRINT( 380 // std::cerr << "but arg is deref -- &" << std::endl; 381 // std::cerr << callExpr << std::endl; 382 // ) 383 // callExpr = new AddressExpr( callExpr ); // this doesn't work properly for multiple casts 384 // delete callExpr->result; 385 // callExpr->set_result( refType->clone() ); 386 // // move environment out to new top-level 387 // callExpr->env = castExpr->env; 388 // castExpr->arg = nullptr; 389 // castExpr->env = nullptr; 390 // delete castExpr; 391 // return callExpr; 392 // } 393 // int depth1 = refType->referenceDepth(); 394 // int depth2 = otherRef->referenceDepth(); 395 // int diff = depth1-depth2; 396 // if ( diff == 0 ) { 397 // // conversion between references of the same depth 398 // assertf( depth1 == depth2, "non-intrinsic reference with cast of reference to reference not yet supported: %d %d %s", depth1, depth2, toString( castExpr ).c_str() ); 399 // PRINT( std::cerr << castExpr << std::endl; ) 400 // return castExpr; 401 // } else if ( diff < 0 ) { 402 // // conversion from reference to reference with less depth (e.g. int && -> int &): add dereferences 403 // Expression * ret = castExpr->arg; 404 // for ( int i = 0; i < diff; ++i ) { 405 // ret = mkDeref( ret ); 406 // } 407 // ret->env = castExpr->env; 408 // delete ret->result; 409 // ret->result = castExpr->result; 410 // ret->result->set_lvalue( true ); // ensure result is lvalue 411 // castExpr->env = nullptr; 412 // castExpr->arg = nullptr; 413 // castExpr->result = nullptr; 414 // delete castExpr; 415 // return ret; 416 // } else if ( diff > 0 ) { 417 // // conversion from reference to reference with more depth (e.g. int & -> int &&): add address-of 418 // Expression * ret = castExpr->arg; 419 // for ( int i = 0; i < diff; ++i ) { 420 // ret = new AddressExpr( ret ); 421 // } 422 // ret->env = castExpr->env; 423 // delete ret->result; 424 // ret->result = castExpr->result; 425 // castExpr->env = nullptr; 426 // castExpr->arg = nullptr; 427 // castExpr->result = nullptr; 428 // delete castExpr; 429 // return ret; 430 // } 431 432 // assertf( depth1 == depth2, "non-intrinsic reference with cast of reference to reference not yet supported: %d %d %s", depth1, depth2, toString( castExpr ).c_str() ); 433 // PRINT( std::cerr << castExpr << std::endl; ) 434 // return castExpr; 435 // } else if ( castExpr->arg->result->get_lvalue() ) { 436 // // conversion from lvalue to reference 437 // // xxx - keep cast, but turn into pointer cast?? 438 // // xxx - memory 439 // PRINT( 440 // std::cerr << "convert lvalue to reference -- &" << std::endl; 441 // std::cerr << castExpr->arg << std::endl; 442 // ) 443 // AddressExpr * ret = new AddressExpr( castExpr->arg ); 444 // if ( refType->base->get_qualifiers() != castExpr->arg->result->get_qualifiers() ) { 445 // // must keep cast if cast-to type is different from the actual type 446 // castExpr->arg = ret; 447 // return castExpr; 448 // } 449 // ret->env = castExpr->env; 450 // delete ret->result; 451 // ret->result = castExpr->result; 452 // castExpr->env = nullptr; 453 // castExpr->arg = nullptr; 454 // castExpr->result = nullptr; 455 // delete castExpr; 456 // return ret; 457 // } else { 458 // // rvalue to reference conversion -- introduce temporary 459 // // know that reference depth of cast argument is 0, need to introduce n temporaries for reference depth of n, e.g. 460 // // (int &&&)3; 461 // // becomes 462 // // int __ref_tmp_0 = 3; 463 // // int & __ref_tmp_1 = _&_ref_tmp_0; 464 // // int && __ref_tmp_2 = &__ref_tmp_1; 465 // // &__ref_tmp_2; 466 467 // static UniqueName tempNamer( "__ref_tmp_" ); 468 // ObjectDecl * temp = ObjectDecl::newObject( tempNamer.newName(), castExpr->arg->result->clone(), new SingleInit( castExpr->arg ) ); 469 // stmtsToAddBefore.push_back( new DeclStmt( temp ) ); 470 // auto depth = castExpr->result->referenceDepth(); 471 // for ( int i = 0; i < depth-1; i++ ) { 472 // ObjectDecl * newTemp = ObjectDecl::newObject( tempNamer.newName(), new ReferenceType( Type::Qualifiers(), temp->type->clone() ), new SingleInit( new AddressExpr( new VariableExpr( temp ) ) ) ); 473 // stmtsToAddBefore.push_back( new DeclStmt( newTemp ) ); 474 // temp = newTemp; 475 // } 476 // Expression * ret = new AddressExpr( new VariableExpr( temp ) ); 477 // // for ( int i = 0; i < depth; ++i ) { 478 // // ret = mkDeref( ret ); 479 // // } 480 // ret->result = castExpr->result; 481 // ret->result->set_lvalue( true ); // ensure result is lvalue 482 // ret->env = castExpr->env; 483 // castExpr->arg = nullptr; 484 // castExpr->env = nullptr; 485 // castExpr->result = nullptr; 486 // delete castExpr; 487 // return ret; 488 // } 489 // } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( castExpr->arg->result ) ) { 490 // (void)refType; 491 // // conversion from reference to rvalue 492 // PRINT( 493 // std::cerr << "convert reference to rvalue -- *" << std::endl; 494 // std::cerr << "was = " << castExpr << std::endl; 495 // ) 496 // Expression * ret = castExpr->arg; 497 // TypeSubstitution * env = castExpr->env; 498 // castExpr->set_env( nullptr ); 499 // if ( ! isIntrinsicReference( ret ) ) { 500 // // dereference if not already dereferenced 501 // ret = mkDeref( ret ); 502 // } 503 // if ( ResolvExpr::typesCompatibleIgnoreQualifiers( castExpr->result, castExpr->arg->result->stripReferences(), SymTab::Indexer() ) ) { 504 // // can remove cast if types are compatible, changing expression type to value type 505 // ret->result = castExpr->result->clone(); 506 // ret->result->set_lvalue( true ); // ensure result is lvalue 507 // castExpr->arg = nullptr; 508 // delete castExpr; 509 // } else { 510 // // must keep cast if types are different 511 // castExpr->arg = ret; 512 // ret = castExpr; 513 // } 514 // ret->set_env( env ); 515 // PRINT( std::cerr << "now: " << ret << std::endl; ) 516 // return ret; 517 // } 518 // return castExpr; 402 519 } 403 520
Note: See TracChangeset
for help on using the changeset viewer.