Changeset 32cab5b for src/GenPoly
- Timestamp:
- Apr 17, 2018, 12:01:09 PM (8 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:
- 3265399
- Parents:
- b2fe1c9 (diff), 81bb114 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)links above to see all the changes relative to each parent. - Location:
- src/GenPoly
- Files:
-
- 2 edited
-
GenPoly.cc (modified) (2 diffs)
-
Lvalue.cc (modified) (14 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/GenPoly/GenPoly.cc
rb2fe1c9 r32cab5b 100 100 if ( dynamic_cast< TypeInstType * >( type ) ) { 101 101 return type; 102 } else if ( ArrayType * arrayType = dynamic_cast< ArrayType * >( type ) ) { 103 return isPolyType( arrayType->base, env ); 102 104 } else if ( StructInstType *structType = dynamic_cast< StructInstType* >( type ) ) { 103 105 if ( hasPolyParams( structType->get_parameters(), env ) ) return type; … … 115 117 return type; 116 118 } 119 } else if ( ArrayType * arrayType = dynamic_cast< ArrayType * >( type ) ) { 120 return isPolyType( arrayType->base, tyVars, env ); 117 121 } else if ( StructInstType *structType = dynamic_cast< StructInstType* >( type ) ) { 118 122 if ( hasPolyParams( structType->get_parameters(), tyVars, env ) ) return type; -
src/GenPoly/Lvalue.cc
rb2fe1c9 r32cab5b 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 pass 47 48 VariableExpr * deref = new VariableExpr( SymTab::dereferenceOperator ); 48 49 deref->result = new PointerType( Type::Qualifiers(), deref->result ); … … 59 60 } 60 61 61 struct ReferenceConversions final {62 struct ReferenceConversions final : public WithStmtsToAdd { 62 63 Expression * postmutate( CastExpr * castExpr ); 63 64 Expression * postmutate( AddressExpr * addrExpr ); … … 114 115 } 115 116 116 void convertLvalue( std::list< Declaration* > & translationUnit ) {117 void convertLvalue( std::list< Declaration* > & translationUnit ) { 117 118 PassVisitor<ReferenceConversions> refCvt; 118 119 PassVisitor<ReferenceTypeElimination> elim; … … 150 151 // use type of return variable rather than expr result type, since it may have been changed to a pointer type 151 152 FunctionType * ftype = GenPoly::getFunctionType( func->get_type() ); 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 );153 Type * ret = ftype->returnVals.empty() ? nullptr : ftype->returnVals.front()->get_type(); 154 return func->linkage == LinkageSpec::Intrinsic && dynamic_cast<ReferenceType *>( ret ); 154 155 } 155 156 } … … 160 161 if ( isIntrinsicReference( appExpr ) ) { 161 162 // eliminate reference types from intrinsic applications - now they return lvalues 162 Type * result = appExpr-> get_result();163 appExpr-> set_result( result->stripReferences()->clone());164 appExpr-> get_result()->set_lvalue( true );163 Type * result = appExpr->result; 164 appExpr->result = result->stripReferences()->clone(); 165 appExpr->result->set_lvalue( true ); 165 166 if ( ! inIntrinsic ) { 166 167 // when not in an intrinsic function, add a cast to 167 168 // don't add cast when in an intrinsic function, since they already have the cast 168 169 Expression * ret = new CastExpr( appExpr, result ); 169 ret->set_env( appExpr->get_env() ); 170 appExpr->set_env( nullptr ); 170 std::swap( ret->env, appExpr->env ); 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-> get_parameters().size() == appExpr->get_args().size() || ftype->get_isVarArgs(), "ApplicationExpr args do not match formal parameter type." );189 assertf( ftype->parameters.size() == appExpr->args.size() || ftype->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-> get_parameters().size();194 for ( auto p : unsafe_group_iterate( appExpr-> get_args(), ftype->get_parameters()) ) {193 const unsigned int end = ftype->parameters.size(); 194 for ( auto p : unsafe_group_iterate( appExpr->args, ftype->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; 200 201 std::cerr << "pair<1>: " << formal << std::endl; 201 202 ) 202 203 if ( dynamic_cast<ReferenceType*>( formal ) ) { 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() ); 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() ); 216 221 PointerType * ptrType = new PointerType( Type::Qualifiers(), baseType->clone() ); 217 delete arg-> get_result();222 delete arg->result; 218 223 arg->set_result( ptrType ); 219 224 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 ) ); 220 226 } 221 227 } … … 249 255 Expression * AddrRef::postmutate( AddressExpr * addrExpr ) { 250 256 if ( refDepth == 0 ) { 251 if ( ! isIntrinsicReference( addrExpr-> get_arg()) ) {257 if ( ! isIntrinsicReference( addrExpr->arg ) ) { 252 258 // try to avoid ?[?] 253 refDepth = addrExpr-> get_arg()->get_result()->referenceDepth();259 refDepth = addrExpr->arg->result->referenceDepth(); 254 260 } 255 261 } … … 280 286 // pointer casts in the right places. 281 287 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; ) 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 337 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; 346 344 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 ) 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 380 357 Expression * ret = castExpr->arg; 381 TypeSubstitution * env = castExpr->env; 382 castExpr->set_env( nullptr ); 383 if ( ! isIntrinsicReference( ret ) ) { 384 // dereference if not already dereferenced 358 for ( int i = 0; i < diff; ++i ) { 385 359 ret = mkDeref( ret ); 386 360 } 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 { 361 if ( ! ResolvExpr::typesCompatibleIgnoreQualifiers( destType->stripReferences(), srcType->stripReferences(), SymTab::Indexer() ) ) { 394 362 // must keep cast if types are different 395 363 castExpr->arg = ret; 396 ret = castExpr; 397 } 398 ret->set_env( env ); 399 PRINT( std::cerr << "now: " << ret << std::endl; ) 400 return ret; 401 } 402 return castExpr; 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; 374 return ret; 375 } else { 376 assert( diff == 0 ); 377 // conversion between references of the same depth 378 return castExpr; 379 } 403 380 } 404 381 405 382 Type * ReferenceTypeElimination::postmutate( ReferenceType * refType ) { 406 Type * base = refType-> get_base();383 Type * base = refType->base; 407 384 Type::Qualifiers qualifiers = refType->get_qualifiers(); 408 refType-> set_base( nullptr );385 refType->base = nullptr; 409 386 delete refType; 410 387 return new PointerType( qualifiers, base ); … … 414 391 Expression * GeneralizedLvalue::applyTransformation( Expression * expr, Expression * arg, Func mkExpr ) { 415 392 if ( CommaExpr * commaExpr = dynamic_cast< CommaExpr * >( arg ) ) { 416 Expression * arg1 = commaExpr-> get_arg1()->clone();417 Expression * arg2 = commaExpr-> get_arg2()->clone();393 Expression * arg1 = commaExpr->arg1->clone(); 394 Expression * arg2 = commaExpr->arg2->clone(); 418 395 Expression * ret = new CommaExpr( arg1, mkExpr( arg2 )->acceptMutator( *visitor ) ); 419 ret-> set_env( expr->get_env() );420 expr-> set_env( nullptr );396 ret->env = expr->env; 397 expr->env = nullptr; 421 398 delete expr; 422 399 return ret; 423 400 } else if ( ConditionalExpr * condExpr = dynamic_cast< ConditionalExpr * >( arg ) ) { 424 Expression * arg1 = condExpr-> get_arg1()->clone();425 Expression * arg2 = condExpr-> get_arg2()->clone();426 Expression * arg3 = condExpr-> get_arg3()->clone();401 Expression * arg1 = condExpr->arg1->clone(); 402 Expression * arg2 = condExpr->arg2->clone(); 403 Expression * arg3 = condExpr->arg3->clone(); 427 404 ConditionalExpr * ret = new ConditionalExpr( arg1, mkExpr( arg2 )->acceptMutator( *visitor ), mkExpr( arg3 )->acceptMutator( *visitor ) ); 428 ret-> set_env( expr->get_env() );429 expr-> set_env( nullptr );405 ret->env = expr->env; 406 expr->env = nullptr; 430 407 delete expr; 431 408 … … 436 413 AssertionSet needAssertions, haveAssertions; 437 414 OpenVarSet openVars; 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());415 unify( ret->arg2->result, ret->arg3->result, newEnv, needAssertions, haveAssertions, openVars, SymTab::Indexer(), commonType ); 416 ret->result = commonType ? commonType : ret->arg2->result->clone(); 440 417 return ret; 441 418 } … … 444 421 445 422 Expression * GeneralizedLvalue::postmutate( MemberExpr * memExpr ) { 446 return applyTransformation( memExpr, memExpr-> get_aggregate(), [=]( Expression * aggr ) { return new MemberExpr( memExpr->get_member(), aggr ); } );423 return applyTransformation( memExpr, memExpr->aggregate, [=]( Expression * aggr ) { return new MemberExpr( memExpr->member, aggr ); } ); 447 424 } 448 425 449 426 Expression * GeneralizedLvalue::postmutate( AddressExpr * addrExpr ) { 450 return applyTransformation( addrExpr, addrExpr-> get_arg(), []( Expression * arg ) { return new AddressExpr( arg ); } );427 return applyTransformation( addrExpr, addrExpr->arg, []( Expression * arg ) { return new AddressExpr( arg ); } ); 451 428 } 452 429 453 430 Expression * CollapseAddrDeref::postmutate( AddressExpr * addrExpr ) { 454 Expression * arg = addrExpr-> get_arg();431 Expression * arg = addrExpr->arg; 455 432 if ( isIntrinsicReference( arg ) ) { 456 433 std::string fname = InitTweak::getFunctionName( arg ); … … 458 435 Expression *& arg0 = InitTweak::getCallArg( arg, 0 ); 459 436 Expression * ret = arg0; 460 ret->set_env( addrExpr-> get_env());437 ret->set_env( addrExpr->env ); 461 438 arg0 = nullptr; 462 addrExpr-> set_env( nullptr );439 addrExpr->env = nullptr; 463 440 delete addrExpr; 464 441 return ret; … … 487 464 // } 488 465 if ( AddressExpr * addrExpr = dynamic_cast< AddressExpr * >( arg ) ) { 489 Expression * ret = addrExpr-> get_arg();490 ret-> set_env( appExpr->get_env() );491 addrExpr-> set_arg( nullptr );492 appExpr-> set_env( nullptr );466 Expression * ret = addrExpr->arg; 467 ret->env = appExpr->env; 468 addrExpr->arg = nullptr; 469 appExpr->env = nullptr; 493 470 delete appExpr; 494 471 return ret;
Note:
See TracChangeset
for help on using the changeset viewer.