Changeset 31cb252


Ignore:
Timestamp:
Mar 19, 2018, 2:07:37 PM (4 years ago)
Author:
Rob Schluntz <rschlunt@…>
Branches:
aaron-thesis, arm-eh, cleanup-dtors, deferred_resn, demangler, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, 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)
Message:

Work on reorganizing ReferenceConversions? pass to be simpler and more general

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/GenPoly/Lvalue.cc

    rb1ccdfd r31cb252  
    5959                }
    6060
    61                 struct ReferenceConversions final {
     61                struct ReferenceConversions final : public WithStmtsToAdd {
    6262                        Expression * postmutate( CastExpr * castExpr );
    6363                        Expression * postmutate( AddressExpr * addrExpr );
     
    279279                        // pointer casts in the right places.
    280280
    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;
    345333                                        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
    379346                                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 ) {
    384348                                        ret = mkDeref( ret );
    385349                                }
    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() ) ) {
    393351                                        // must keep cast if types are different
    394352                                        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;
    399363                                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;
    402519                }
    403520
Note: See TracChangeset for help on using the changeset viewer.