Changeset b6838214 for src/ResolvExpr/ConversionCost.cc
- Timestamp:
- Jan 23, 2018, 5:46:43 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, resolv-new, with_gc
- Children:
- 258e6ad5
- Parents:
- b158d8f (diff), 15d248e (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. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/ConversionCost.cc
rb158d8f rb6838214 44 44 EqvClass eqvClass; 45 45 NamedTypeDecl *namedType; 46 PRINT( std::cerr << "type inst " << destAsTypeInst-> get_name(); )47 if ( env.lookup( destAsTypeInst-> get_name(), eqvClass ) ) {46 PRINT( std::cerr << "type inst " << destAsTypeInst->name; ) 47 if ( env.lookup( destAsTypeInst->name, eqvClass ) ) { 48 48 if ( eqvClass.type ) { 49 49 return conversionCost( src, eqvClass.type, indexer, env ); … … 51 51 return Cost::infinity; 52 52 } 53 } else if ( ( namedType = indexer.lookupType( destAsTypeInst-> get_name()) ) ) {53 } else if ( ( namedType = indexer.lookupType( destAsTypeInst->name ) ) ) { 54 54 PRINT( std::cerr << " found" << std::endl; ) 55 55 TypeDecl *type = dynamic_cast< TypeDecl* >( namedType ); 56 56 // all typedefs should be gone by this point 57 57 assert( type ); 58 if ( type-> get_base()) {59 return conversionCost( src, type-> get_base(), indexer, env ) + Cost::safe;58 if ( type->base ) { 59 return conversionCost( src, type->base, indexer, env ) + Cost::safe; 60 60 } // if 61 61 } // if … … 77 77 } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * > ( dest ) ) { 78 78 PRINT( std::cerr << "conversionCost: dest is reference" << std::endl; ) 79 return convertToReferenceCost( src, refType, indexer, env, [](Type * t1, Type * t2, const TypeEnvironment & env, const SymTab::Indexer &){79 return convertToReferenceCost( src, refType, indexer, env, [](Type * t1, Type * t2, const SymTab::Indexer &, const TypeEnvironment & env ){ 80 80 return ptrsAssignable( t1, t2, env ); 81 81 }); 82 82 } else { 83 ConversionCost converter( dest, indexer, env);83 PassVisitor<ConversionCost> converter( dest, indexer, env, conversionCost ); 84 84 src->accept( converter ); 85 if ( converter. get_cost() == Cost::infinity ) {85 if ( converter.pass.get_cost() == Cost::infinity ) { 86 86 return Cost::infinity; 87 87 } else { 88 return converter. get_cost() + Cost::zero;88 return converter.pass.get_cost() + Cost::zero; 89 89 } // if 90 90 } // if … … 92 92 93 93 Cost convertToReferenceCost( Type * src, Type * dest, int diff, const SymTab::Indexer & indexer, const TypeEnvironment & env, PtrsFunction func ) { 94 PRINT( std::cerr << "convert to reference cost... diff " << diff << std::endl; )94 PRINT( std::cerr << "convert to reference cost... diff " << diff << " " << src << " / " << dest << std::endl; ) 95 95 if ( diff > 0 ) { 96 96 // TODO: document this 97 Cost cost = convertToReferenceCost( strict_dynamic_cast< ReferenceType * >( src )-> get_base(), dest, diff-1, indexer, env, func );97 Cost cost = convertToReferenceCost( strict_dynamic_cast< ReferenceType * >( src )->base, dest, diff-1, indexer, env, func ); 98 98 cost.incReference(); 99 99 return cost; 100 100 } else if ( diff < -1 ) { 101 101 // TODO: document this 102 Cost cost = convertToReferenceCost( src, strict_dynamic_cast< ReferenceType * >( dest )-> get_base(), diff+1, indexer, env, func );102 Cost cost = convertToReferenceCost( src, strict_dynamic_cast< ReferenceType * >( dest )->base, diff+1, indexer, env, func ); 103 103 cost.incReference(); 104 104 return cost; … … 108 108 if ( srcAsRef && destAsRef ) { // pointer-like conversions between references 109 109 PRINT( std::cerr << "converting between references" << std::endl; ) 110 if ( srcAsRef->get_base()->get_qualifiers() <= destAsRef->get_base()->get_qualifiers() && typesCompatibleIgnoreQualifiers( srcAsRef->get_base(), destAsRef->get_base(), indexer, env ) ) { 111 return Cost::safe; 110 Type::Qualifiers tq1 = srcAsRef->base->get_qualifiers(); 111 Type::Qualifiers tq2 = destAsRef->base->get_qualifiers(); 112 if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( srcAsRef->base, destAsRef->base, indexer, env ) ) { 113 PRINT( std::cerr << " :: compatible and good qualifiers" << std::endl; ) 114 if ( tq1 == tq2 ) { 115 // types are the same 116 return Cost::zero; 117 } else { 118 // types are the same, except otherPointer has more qualifiers 119 return Cost::safe; 120 } 112 121 } else { // xxx - this discards reference qualifiers from consideration -- reducing qualifiers is a safe conversion; is this right? 113 int assignResult = func( srcAsRef-> get_base(), destAsRef->get_base(), env, indexer);122 int assignResult = func( srcAsRef->base, destAsRef->base, indexer, env ); 114 123 PRINT( std::cerr << "comparing references: " << assignResult << " " << srcAsRef << " " << destAsRef << std::endl; ) 115 124 if ( assignResult > 0 ) { … … 121 130 } else { 122 131 PRINT( std::cerr << "reference to rvalue conversion" << std::endl; ) 123 ConversionCost converter( dest, indexer, env);132 PassVisitor<ConversionCost> converter( dest, indexer, env, conversionCost ); 124 133 src->accept( converter ); 125 return converter. get_cost();134 return converter.pass.get_cost(); 126 135 } // if 127 136 } else { … … 129 138 assert( diff == -1 && destAsRef ); 130 139 PRINT( std::cerr << "dest is: " << dest << " / src is: " << src << std::endl; ) 131 if ( typesCompatibleIgnoreQualifiers( src, destAsRef-> get_base(), indexer, env ) ) {140 if ( typesCompatibleIgnoreQualifiers( src, destAsRef->base, indexer, env ) ) { 132 141 PRINT( std::cerr << "converting compatible base type" << std::endl; ) 133 142 if ( src->get_lvalue() ) { … … 137 146 ) 138 147 // lvalue-to-reference conversion: cv lvalue T => cv T & 139 if ( src->get_qualifiers() == destAsRef-> get_base()->get_qualifiers() ) {148 if ( src->get_qualifiers() == destAsRef->base->get_qualifiers() ) { 140 149 return Cost::reference; // cost needs to be non-zero to add cast 141 } if ( src->get_qualifiers() < destAsRef-> get_base()->get_qualifiers() ) {150 } if ( src->get_qualifiers() < destAsRef->base->get_qualifiers() ) { 142 151 return Cost::safe; // cost needs to be higher than previous cast to differentiate adding qualifiers vs. keeping same 143 152 } else { 144 153 return Cost::unsafe; 145 154 } // if 146 } else if ( destAsRef-> get_base()->get_const() ) {155 } else if ( destAsRef->base->get_const() ) { 147 156 PRINT( std::cerr << "rvalue to const ref conversion" << std::endl; ) 148 157 // rvalue-to-const-reference conversion: T => const T & … … 164 173 } 165 174 166 ConversionCost::ConversionCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env )167 : dest( dest ), indexer( indexer ), cost( Cost::infinity ), env( env ) {175 ConversionCost::ConversionCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc ) 176 : dest( dest ), indexer( indexer ), cost( Cost::infinity ), env( env ), costFunc( costFunc ) { 168 177 } 169 178 … … 248 257 }; 249 258 250 void ConversionCost:: visit( __attribute((unused)) VoidType *voidType) {259 void ConversionCost::postvisit( VoidType * ) { 251 260 cost = Cost::infinity; 252 261 } 253 262 254 void ConversionCost:: visit(BasicType *basicType) {263 void ConversionCost::postvisit(BasicType *basicType) { 255 264 if ( BasicType *destAsBasic = dynamic_cast< BasicType* >( dest ) ) { 256 265 int tableResult = costMatrix[ basicType->get_kind() ][ destAsBasic->get_kind() ]; … … 269 278 } 270 279 271 void ConversionCost:: visit( PointerType * pointerType ) {280 void ConversionCost::postvisit( PointerType * pointerType ) { 272 281 if ( PointerType *destAsPtr = dynamic_cast< PointerType* >( dest ) ) { 273 PRINT( std::cerr << pointerType << " ===> " << destAsPtr; ) 274 Type::Qualifiers tq1 = pointerType->get_base()->get_qualifiers(); 275 Type::Qualifiers tq2 = destAsPtr->get_base()->get_qualifiers(); 276 if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( pointerType->get_base(), destAsPtr->get_base(), indexer, env ) ) { 282 PRINT( std::cerr << pointerType << " ===> " << destAsPtr << std::endl; ) 283 Type::Qualifiers tq1 = pointerType->base->get_qualifiers(); 284 Type::Qualifiers tq2 = destAsPtr->base->get_qualifiers(); 285 if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( pointerType->base, destAsPtr->base, indexer, env ) ) { 286 PRINT( std::cerr << " :: compatible and good qualifiers" << std::endl; ) 277 287 if ( tq1 == tq2 ) { 278 288 // types are the same … … 280 290 } else { 281 291 // types are the same, except otherPointer has more qualifiers 282 PRINT( std::cerr << " :: compatible and good qualifiers" << std::endl; )283 292 cost = Cost::safe; 284 293 } 285 } else { // xxx - this discards qualifiers from consideration -- reducing qualifiers is a safe conversion; is this right?294 } else { 286 295 int assignResult = ptrsAssignable( pointerType->base, destAsPtr->base, env ); 287 296 PRINT( std::cerr << " :: " << assignResult << std::endl; ) 288 if ( assignResult > 0 && pointerType->get_base()->get_qualifiers() <= destAsPtr->get_qualifiers() ) { 289 cost = Cost::safe; 297 if ( assignResult > 0 && tq1 <= tq2 ) { 298 // xxx - want the case where qualifiers are added to be more expensive than the case where qualifiers are the same. Is 1 safe vs. 2 safe correct? 299 if ( tq1 == tq2 ) { 300 cost = Cost::safe; 301 } else if ( tq1 < tq2 ) { 302 cost = Cost::safe+Cost::safe; 303 } 290 304 } else if ( assignResult < 0 ) { 291 305 cost = Cost::unsafe; … … 298 312 } 299 313 300 void ConversionCost:: visit( ArrayType * ) {}301 302 void ConversionCost:: visit( ReferenceType * refType ) {314 void ConversionCost::postvisit( ArrayType * ) {} 315 316 void ConversionCost::postvisit( ReferenceType * refType ) { 303 317 // Note: dest can never be a reference, since it would have been caught in an earlier check 304 318 assert( ! dynamic_cast< ReferenceType * >( dest ) ); … … 306 320 // recursively compute conversion cost from T1 to T2. 307 321 // cv can be safely dropped because of 'implicit dereference' behavior. 308 refType->base->accept( *this);322 cost = costFunc( refType->base, dest, indexer, env ); 309 323 if ( refType->base->get_qualifiers() == dest->get_qualifiers() ) { 310 324 cost.incReference(); // prefer exact qualifiers … … 317 331 } 318 332 319 void ConversionCost:: visit( FunctionType * ) {}320 321 void ConversionCost:: visit( StructInstType * inst ) {333 void ConversionCost::postvisit( FunctionType * ) {} 334 335 void ConversionCost::postvisit( StructInstType * inst ) { 322 336 if ( StructInstType *destAsInst = dynamic_cast< StructInstType* >( dest ) ) { 323 337 if ( inst->name == destAsInst->name ) { … … 327 341 } 328 342 329 void ConversionCost:: visit( UnionInstType * inst ) {343 void ConversionCost::postvisit( UnionInstType * inst ) { 330 344 if ( UnionInstType *destAsInst = dynamic_cast< UnionInstType* >( dest ) ) { 331 345 if ( inst->name == destAsInst->name ) { … … 335 349 } 336 350 337 void ConversionCost:: visit( EnumInstType * ) {351 void ConversionCost::postvisit( EnumInstType * ) { 338 352 static Type::Qualifiers q; 339 353 static BasicType integer( q, BasicType::SignedInt ); 340 integer.accept( *this); // safe if dest >= int354 cost = costFunc( &integer, dest, indexer, env ); // safe if dest >= int 341 355 if ( cost < Cost::unsafe ) { 342 356 cost.incSafe(); … … 344 358 } 345 359 346 void ConversionCost:: visit( TraitInstType * ) {}347 348 void ConversionCost:: visit( TypeInstType *inst ) {360 void ConversionCost::postvisit( TraitInstType * ) {} 361 362 void ConversionCost::postvisit( TypeInstType *inst ) { 349 363 EqvClass eqvClass; 350 364 NamedTypeDecl *namedType; 351 if ( env.lookup( inst-> get_name(), eqvClass ) ) {352 cost = co nversionCost( eqvClass.type, dest, indexer, env );365 if ( env.lookup( inst->name, eqvClass ) ) { 366 cost = costFunc( eqvClass.type, dest, indexer, env ); 353 367 } else if ( TypeInstType *destAsInst = dynamic_cast< TypeInstType* >( dest ) ) { 354 if ( inst-> get_name() == destAsInst->get_name()) {368 if ( inst->name == destAsInst->name ) { 355 369 cost = Cost::zero; 356 370 } 357 } else if ( ( namedType = indexer.lookupType( inst-> get_name()) ) ) {371 } else if ( ( namedType = indexer.lookupType( inst->name ) ) ) { 358 372 TypeDecl *type = dynamic_cast< TypeDecl* >( namedType ); 359 373 // all typedefs should be gone by this point 360 374 assert( type ); 361 if ( type-> get_base()) {362 cost = co nversionCost( type->get_base(), dest, indexer, env ) + Cost::safe;363 } // if 364 } // if 365 } 366 367 void ConversionCost:: visit( TupleType * tupleType ) {375 if ( type->base ) { 376 cost = costFunc( type->base, dest, indexer, env ) + Cost::safe; 377 } // if 378 } // if 379 } 380 381 void ConversionCost::postvisit( TupleType * tupleType ) { 368 382 Cost c = Cost::zero; 369 383 if ( TupleType * destAsTuple = dynamic_cast< TupleType * >( dest ) ) { 370 std::list< Type * >::const_iterator srcIt = tupleType-> get_types().begin();371 std::list< Type * >::const_iterator destIt = destAsTuple-> get_types().begin();372 while ( srcIt != tupleType-> get_types().end() && destIt != destAsTuple->get_types().end() ) {373 Cost newCost = co nversionCost( *srcIt++, *destIt++, indexer, env );384 std::list< Type * >::const_iterator srcIt = tupleType->types.begin(); 385 std::list< Type * >::const_iterator destIt = destAsTuple->types.begin(); 386 while ( srcIt != tupleType->types.end() && destIt != destAsTuple->types.end() ) { 387 Cost newCost = costFunc( *srcIt++, *destIt++, indexer, env ); 374 388 if ( newCost == Cost::infinity ) { 375 389 return; … … 377 391 c += newCost; 378 392 } // while 379 if ( destIt != destAsTuple-> get_types().end() ) {393 if ( destIt != destAsTuple->types.end() ) { 380 394 cost = Cost::infinity; 381 395 } else { … … 385 399 } 386 400 387 void ConversionCost:: visit( VarArgsType * ) {401 void ConversionCost::postvisit( VarArgsType * ) { 388 402 if ( dynamic_cast< VarArgsType* >( dest ) ) { 389 403 cost = Cost::zero; … … 391 405 } 392 406 393 void ConversionCost:: visit( ZeroType * ) {407 void ConversionCost::postvisit( ZeroType * ) { 394 408 if ( dynamic_cast< ZeroType * >( dest ) ) { 395 409 cost = Cost::zero; … … 408 422 } 409 423 410 void ConversionCost:: visit( OneType * ) {424 void ConversionCost::postvisit( OneType * ) { 411 425 if ( dynamic_cast< OneType * >( dest ) ) { 412 426 cost = Cost::zero;
Note:
See TracChangeset
for help on using the changeset viewer.