Changes in src/GenPoly/Lvalue.cc [a9b1b0c:a16764a6]
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/GenPoly/Lvalue.cc
ra9b1b0c ra16764a6 45 45 Expression * mkDeref( Expression * arg ) { 46 46 if ( SymTab::dereferenceOperator ) { 47 // note: reference depth can be arbitrarily deep here, so peel off the outermost pointer/reference, not just pointer because they are effecitvely equivalent in this pass48 47 VariableExpr * deref = new VariableExpr( SymTab::dereferenceOperator ); 49 48 deref->result = new PointerType( Type::Qualifiers(), deref->result ); … … 60 59 } 61 60 62 struct ReferenceConversions final : public WithStmtsToAdd{61 struct ReferenceConversions final { 63 62 Expression * postmutate( CastExpr * castExpr ); 64 63 Expression * postmutate( AddressExpr * addrExpr ); … … 115 114 } 116 115 117 void convertLvalue( std::list< Declaration* > 116 void convertLvalue( std::list< Declaration* >& translationUnit ) { 118 117 PassVisitor<ReferenceConversions> refCvt; 119 118 PassVisitor<ReferenceTypeElimination> elim; … … 151 150 // use type of return variable rather than expr result type, since it may have been changed to a pointer type 152 151 FunctionType * ftype = GenPoly::getFunctionType( func->get_type() ); 153 Type * ret = ftype-> returnVals.empty() ? nullptr : ftype->returnVals.front()->get_type();154 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 ); 155 154 } 156 155 } … … 161 160 if ( isIntrinsicReference( appExpr ) ) { 162 161 // eliminate reference types from intrinsic applications - now they return lvalues 163 Type * result = appExpr-> result;164 appExpr-> result = result->stripReferences()->clone();165 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 ); 166 165 if ( ! inIntrinsic ) { 167 166 // when not in an intrinsic function, add a cast to 168 167 // don't add cast when in an intrinsic function, since they already have the cast 169 168 Expression * ret = new CastExpr( appExpr, result ); 170 std::swap( ret->env, appExpr->env ); 169 ret->set_env( appExpr->get_env() ); 170 appExpr->set_env( nullptr ); 171 171 return ret; 172 172 } … … 187 187 assertf( ftype, "Function declaration does not have function type." ); 188 188 // can be of differing lengths only when function is variadic 189 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." ); 190 190 191 191 192 192 unsigned int i = 0; 193 const unsigned int end = ftype-> parameters.size();194 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() ) ) { 195 195 if (i == end) break; 196 196 Expression *& arg = std::get<0>( p ); … … 198 198 PRINT( 199 199 std::cerr << "pair<0>: " << arg << std::endl; 200 std::cerr << " -- " << arg->result << std::endl;201 200 std::cerr << "pair<1>: " << formal << std::endl; 202 201 ) 203 202 if ( dynamic_cast<ReferenceType*>( formal ) ) { 204 PRINT( 205 std::cerr << "===formal is reference" << std::endl; 206 ) 207 // TODO: it's likely that the second condition should be ... && ! isIntrinsicReference( arg ), but this requires investigation. 208 if ( function->get_linkage() != LinkageSpec::Intrinsic && isIntrinsicReference( arg ) ) { 209 // if argument is dereference or array subscript, the result isn't REALLY a reference, but non-intrinsic functions expect a reference: take address 210 PRINT( 211 std::cerr << "===is intrinsic arg in non-intrinsic call - adding address" << std::endl; 212 ) 213 arg = new AddressExpr( arg ); 214 } else if ( function->get_linkage() == LinkageSpec::Intrinsic && arg->result->referenceDepth() != 0 ) { 215 // argument is a 'real' reference, but function expects a C lvalue: add a dereference to the reference-typed argument 216 PRINT( 217 std::cerr << "===is non-intrinsic arg in intrinsic call - adding deref to arg" << std::endl; 218 ) 219 Type * baseType = InitTweak::getPointerBase( arg->result ); 220 assertf( baseType, "parameter is reference, arg must be pointer or reference: %s", toString( arg->result ).c_str() ); 203 if ( isIntrinsicReference( arg ) ) { // do not combine conditions, because that changes the meaning of the else if 204 if ( function->get_linkage() != LinkageSpec::Intrinsic ) { // intrinsic functions that turn pointers into references 205 // if argument is dereference or array subscript, the result isn't REALLY a reference, so it's not necessary to fix the argument 206 PRINT( 207 std::cerr << "===is intrinsic arg in non-intrinsic call - adding address" << std::endl; 208 ) 209 arg = new AddressExpr( arg ); 210 } 211 } else if ( function->get_linkage() == LinkageSpec::Intrinsic ) { 212 // std::cerr << "===adding deref to arg" << std::endl; 213 // if the parameter is a reference, add a dereference to the reference-typed argument. 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() ); 221 216 PointerType * ptrType = new PointerType( Type::Qualifiers(), baseType->clone() ); 222 delete arg-> result;217 delete arg->get_result(); 223 218 arg->set_result( ptrType ); 224 219 arg = mkDeref( arg ); 225 assertf( arg->result->referenceDepth() == 0, "Reference types should have been eliminated from intrinsic function calls, but weren't: %s", toCString( arg->result ) );226 220 } 227 221 } … … 255 249 Expression * AddrRef::postmutate( AddressExpr * addrExpr ) { 256 250 if ( refDepth == 0 ) { 257 if ( ! isIntrinsicReference( addrExpr-> arg) ) {251 if ( ! isIntrinsicReference( addrExpr->get_arg() ) ) { 258 252 // try to avoid ?[?] 259 refDepth = addrExpr-> arg->result->referenceDepth();253 refDepth = addrExpr->get_arg()->get_result()->referenceDepth(); 260 254 } 261 255 } … … 286 280 // pointer casts in the right places. 287 281 288 // Note: reference depth difference is the determining factor in what code is run, rather than whether something is 289 // reference type or not, since conversion still needs to occur when both types are references that differ in depth. 290 291 Type * destType = castExpr->result; 292 Type * srcType = castExpr->arg->result; 293 int depth1 = destType->referenceDepth(); 294 int depth2 = srcType->referenceDepth(); 295 int diff = depth1 - depth2; 296 297 if ( diff > 0 && ! srcType->get_lvalue() ) { 298 // rvalue to reference conversion -- introduce temporary 299 // know that reference depth of cast argument is 0, need to introduce n temporaries for reference depth of n, e.g. 300 // (int &&&)3; 301 // becomes 302 // int __ref_tmp_0 = 3; 303 // int & __ref_tmp_1 = _&_ref_tmp_0; 304 // int && __ref_tmp_2 = &__ref_tmp_1; 305 // &__ref_tmp_2; 306 // the last & comes from the remaining reference conversion code 307 SemanticWarning( castExpr->arg->location, Warning::RvalueToReferenceConversion, toCString( castExpr->arg ) ); 308 309 static UniqueName tempNamer( "__ref_tmp_" ); 310 ObjectDecl * temp = ObjectDecl::newObject( tempNamer.newName(), castExpr->arg->result->clone(), new SingleInit( castExpr->arg ) ); 311 PRINT( std::cerr << "made temp: " << temp << std::endl; ) 312 stmtsToAddBefore.push_back( new DeclStmt( temp ) ); 313 for ( int i = 0; i < depth1-1; i++ ) { // xxx - maybe this should be diff-1? check how this works with reference type for srcType 314 ObjectDecl * newTemp = ObjectDecl::newObject( tempNamer.newName(), new ReferenceType( Type::Qualifiers(), temp->type->clone() ), new SingleInit( new AddressExpr( new VariableExpr( temp ) ) ) ); 315 PRINT( std::cerr << "made temp" << i << ": " << newTemp << std::endl; ) 316 stmtsToAddBefore.push_back( new DeclStmt( newTemp ) ); 317 temp = newTemp; 318 } 319 // update diff so that remaining code works out correctly 320 castExpr->arg = new VariableExpr( temp ); 321 PRINT( std::cerr << "update cast to: " << castExpr << std::endl; ) 322 srcType = castExpr->arg->result; 323 depth2 = srcType->referenceDepth(); 324 diff = depth1 - depth2; 325 assert( diff == 1 ); 326 } 327 328 // handle conversion between different depths 329 PRINT ( 330 if ( depth1 || depth2 ) { 331 std::cerr << "destType: " << destType << " / srcType: " << srcType << std::endl; 332 std::cerr << "depth: " << depth1 << " / " << depth2 << std::endl; 333 } 334 ) 335 if ( diff > 0 ) { 336 // 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 ) 337 380 Expression * ret = castExpr->arg; 338 for ( int i = 0; i < diff; ++i ) { 339 ret = new AddressExpr( ret ); 340 } 341 if ( srcType->get_lvalue() && srcType->get_qualifiers() != strict_dynamic_cast<ReferenceType *>( destType )->base->get_qualifiers() ) { 342 // must keep cast if cast-to type is different from the actual type 343 castExpr->arg = ret; 344 return castExpr; 345 } 346 ret->env = castExpr->env; 347 delete ret->result; 348 ret->result = castExpr->result; 349 castExpr->env = nullptr; 350 castExpr->arg = nullptr; 351 castExpr->result = nullptr; 352 delete castExpr; 353 return ret; 354 } else if ( diff < 0 ) { 355 // conversion to type with less depth (e.g. int && -> int &): add dereferences for each level of difference 356 diff = -diff; // care only about magnitude now 357 Expression * ret = castExpr->arg; 358 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 359 385 ret = mkDeref( ret ); 360 386 } 361 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 { 362 394 // must keep cast if types are different 363 395 castExpr->arg = ret; 364 return castExpr; 365 } 366 ret->env = castExpr->env; 367 delete ret->result; 368 ret->result = castExpr->result; 369 ret->result->set_lvalue( true ); // ensure result is lvalue 370 castExpr->env = nullptr; 371 castExpr->arg = nullptr; 372 castExpr->result = nullptr; 373 delete castExpr; 396 ret = castExpr; 397 } 398 ret->set_env( env ); 399 PRINT( std::cerr << "now: " << ret << std::endl; ) 374 400 return ret; 375 } else { 376 assert( diff == 0 ); 377 // conversion between references of the same depth 378 return castExpr; 379 } 401 } 402 return castExpr; 380 403 } 381 404 382 405 Type * ReferenceTypeElimination::postmutate( ReferenceType * refType ) { 383 Type * base = refType-> base;406 Type * base = refType->get_base(); 384 407 Type::Qualifiers qualifiers = refType->get_qualifiers(); 385 refType-> base = nullptr;408 refType->set_base( nullptr ); 386 409 delete refType; 387 410 return new PointerType( qualifiers, base ); … … 391 414 Expression * GeneralizedLvalue::applyTransformation( Expression * expr, Expression * arg, Func mkExpr ) { 392 415 if ( CommaExpr * commaExpr = dynamic_cast< CommaExpr * >( arg ) ) { 393 Expression * arg1 = commaExpr-> arg1->clone();394 Expression * arg2 = commaExpr-> arg2->clone();416 Expression * arg1 = commaExpr->get_arg1()->clone(); 417 Expression * arg2 = commaExpr->get_arg2()->clone(); 395 418 Expression * ret = new CommaExpr( arg1, mkExpr( arg2 )->acceptMutator( *visitor ) ); 396 ret-> env = expr->env;397 expr-> env = nullptr;419 ret->set_env( expr->get_env() ); 420 expr->set_env( nullptr ); 398 421 delete expr; 399 422 return ret; 400 423 } else if ( ConditionalExpr * condExpr = dynamic_cast< ConditionalExpr * >( arg ) ) { 401 Expression * arg1 = condExpr-> arg1->clone();402 Expression * arg2 = condExpr-> arg2->clone();403 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(); 404 427 ConditionalExpr * ret = new ConditionalExpr( arg1, mkExpr( arg2 )->acceptMutator( *visitor ), mkExpr( arg3 )->acceptMutator( *visitor ) ); 405 ret-> env = expr->env;406 expr-> env = nullptr;428 ret->set_env( expr->get_env() ); 429 expr->set_env( nullptr ); 407 430 delete expr; 408 431 … … 413 436 AssertionSet needAssertions, haveAssertions; 414 437 OpenVarSet openVars; 415 unify( ret-> arg2->result, ret->arg3->result, newEnv, needAssertions, haveAssertions, openVars, SymTab::Indexer(), commonType );416 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() ); 417 440 return ret; 418 441 } … … 421 444 422 445 Expression * GeneralizedLvalue::postmutate( MemberExpr * memExpr ) { 423 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 ); } ); 424 447 } 425 448 426 449 Expression * GeneralizedLvalue::postmutate( AddressExpr * addrExpr ) { 427 return applyTransformation( addrExpr, addrExpr-> arg, []( Expression * arg ) { return new AddressExpr( arg ); } );450 return applyTransformation( addrExpr, addrExpr->get_arg(), []( Expression * arg ) { return new AddressExpr( arg ); } ); 428 451 } 429 452 430 453 Expression * CollapseAddrDeref::postmutate( AddressExpr * addrExpr ) { 431 Expression * arg = addrExpr-> arg;454 Expression * arg = addrExpr->get_arg(); 432 455 if ( isIntrinsicReference( arg ) ) { 433 456 std::string fname = InitTweak::getFunctionName( arg ); … … 435 458 Expression *& arg0 = InitTweak::getCallArg( arg, 0 ); 436 459 Expression * ret = arg0; 437 ret->set_env( addrExpr-> env);460 ret->set_env( addrExpr->get_env() ); 438 461 arg0 = nullptr; 439 addrExpr-> env = nullptr;462 addrExpr->set_env( nullptr ); 440 463 delete addrExpr; 441 464 return ret; … … 464 487 // } 465 488 if ( AddressExpr * addrExpr = dynamic_cast< AddressExpr * >( arg ) ) { 466 Expression * ret = addrExpr-> arg;467 ret-> env = appExpr->env;468 addrExpr-> arg = nullptr;469 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 ); 470 493 delete appExpr; 471 494 return ret;
Note:
See TracChangeset
for help on using the changeset viewer.