Changeset 7416d46a for src/ResolvExpr/ConversionCost.cc
- Timestamp:
- Jan 30, 2018, 3:54:32 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:
- 633a642
- Parents:
- f792cb8 (diff), 42be3c3 (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
rf792cb8 r7416d46a 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 … … 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 Type::Qualifiers tq1 = srcAsRef-> get_base()->get_qualifiers();111 Type::Qualifiers tq2 = destAsRef-> get_base()->get_qualifiers();112 if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( srcAsRef-> get_base(), destAsRef->get_base(), indexer, env ) ) {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 113 PRINT( std::cerr << " :: compatible and good qualifiers" << std::endl; ) 114 114 if ( tq1 == tq2 ) { … … 120 120 } 121 121 } else { // xxx - this discards reference qualifiers from consideration -- reducing qualifiers is a safe conversion; is this right? 122 int assignResult = func( srcAsRef-> get_base(), destAsRef->get_base(), env, indexer);122 int assignResult = func( srcAsRef->base, destAsRef->base, indexer, env ); 123 123 PRINT( std::cerr << "comparing references: " << assignResult << " " << srcAsRef << " " << destAsRef << std::endl; ) 124 124 if ( assignResult > 0 ) { … … 130 130 } else { 131 131 PRINT( std::cerr << "reference to rvalue conversion" << std::endl; ) 132 ConversionCost converter( dest, indexer, env);132 PassVisitor<ConversionCost> converter( dest, indexer, env, conversionCost ); 133 133 src->accept( converter ); 134 return converter. get_cost();134 return converter.pass.get_cost(); 135 135 } // if 136 136 } else { … … 138 138 assert( diff == -1 && destAsRef ); 139 139 PRINT( std::cerr << "dest is: " << dest << " / src is: " << src << std::endl; ) 140 if ( typesCompatibleIgnoreQualifiers( src, destAsRef-> get_base(), indexer, env ) ) {140 if ( typesCompatibleIgnoreQualifiers( src, destAsRef->base, indexer, env ) ) { 141 141 PRINT( std::cerr << "converting compatible base type" << std::endl; ) 142 142 if ( src->get_lvalue() ) { … … 146 146 ) 147 147 // lvalue-to-reference conversion: cv lvalue T => cv T & 148 if ( src->get_qualifiers() == destAsRef-> get_base()->get_qualifiers() ) {148 if ( src->get_qualifiers() == destAsRef->base->get_qualifiers() ) { 149 149 return Cost::reference; // cost needs to be non-zero to add cast 150 } if ( src->get_qualifiers() < destAsRef-> get_base()->get_qualifiers() ) {150 } if ( src->get_qualifiers() < destAsRef->base->get_qualifiers() ) { 151 151 return Cost::safe; // cost needs to be higher than previous cast to differentiate adding qualifiers vs. keeping same 152 152 } else { 153 153 return Cost::unsafe; 154 154 } // if 155 } else if ( destAsRef-> get_base()->get_const() ) {155 } else if ( destAsRef->base->get_const() ) { 156 156 PRINT( std::cerr << "rvalue to const ref conversion" << std::endl; ) 157 157 // rvalue-to-const-reference conversion: T => const T & … … 173 173 } 174 174 175 ConversionCost::ConversionCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env )176 : 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 ) { 177 177 } 178 178 … … 257 257 }; 258 258 259 void ConversionCost:: visit( VoidType * ) {259 void ConversionCost::postvisit( VoidType * ) { 260 260 cost = Cost::infinity; 261 261 } 262 262 263 void ConversionCost:: visit(BasicType *basicType) {263 void ConversionCost::postvisit(BasicType *basicType) { 264 264 if ( BasicType *destAsBasic = dynamic_cast< BasicType* >( dest ) ) { 265 265 int tableResult = costMatrix[ basicType->get_kind() ][ destAsBasic->get_kind() ]; … … 278 278 } 279 279 280 void ConversionCost:: visit( PointerType * pointerType ) {280 void ConversionCost::postvisit( PointerType * pointerType ) { 281 281 if ( PointerType *destAsPtr = dynamic_cast< PointerType* >( dest ) ) { 282 282 PRINT( std::cerr << pointerType << " ===> " << destAsPtr << std::endl; ) 283 Type::Qualifiers tq1 = pointerType-> get_base()->get_qualifiers();284 Type::Qualifiers tq2 = destAsPtr-> get_base()->get_qualifiers();285 if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( pointerType-> get_base(), destAsPtr->get_base(), indexer, env ) ) {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 286 PRINT( std::cerr << " :: compatible and good qualifiers" << std::endl; ) 287 287 if ( tq1 == tq2 ) { … … 312 312 } 313 313 314 void ConversionCost:: visit( ArrayType * ) {}315 316 void ConversionCost:: visit( ReferenceType * refType ) {314 void ConversionCost::postvisit( ArrayType * ) {} 315 316 void ConversionCost::postvisit( ReferenceType * refType ) { 317 317 // Note: dest can never be a reference, since it would have been caught in an earlier check 318 318 assert( ! dynamic_cast< ReferenceType * >( dest ) ); … … 320 320 // recursively compute conversion cost from T1 to T2. 321 321 // cv can be safely dropped because of 'implicit dereference' behavior. 322 refType->base->accept( *this);322 cost = costFunc( refType->base, dest, indexer, env ); 323 323 if ( refType->base->get_qualifiers() == dest->get_qualifiers() ) { 324 324 cost.incReference(); // prefer exact qualifiers … … 331 331 } 332 332 333 void ConversionCost:: visit( FunctionType * ) {}334 335 void ConversionCost:: visit( StructInstType * inst ) {333 void ConversionCost::postvisit( FunctionType * ) {} 334 335 void ConversionCost::postvisit( StructInstType * inst ) { 336 336 if ( StructInstType *destAsInst = dynamic_cast< StructInstType* >( dest ) ) { 337 337 if ( inst->name == destAsInst->name ) { … … 341 341 } 342 342 343 void ConversionCost:: visit( UnionInstType * inst ) {343 void ConversionCost::postvisit( UnionInstType * inst ) { 344 344 if ( UnionInstType *destAsInst = dynamic_cast< UnionInstType* >( dest ) ) { 345 345 if ( inst->name == destAsInst->name ) { … … 349 349 } 350 350 351 void ConversionCost:: visit( EnumInstType * ) {351 void ConversionCost::postvisit( EnumInstType * ) { 352 352 static Type::Qualifiers q; 353 353 static BasicType integer( q, BasicType::SignedInt ); 354 integer.accept( *this); // safe if dest >= int354 cost = costFunc( &integer, dest, indexer, env ); // safe if dest >= int 355 355 if ( cost < Cost::unsafe ) { 356 356 cost.incSafe(); … … 358 358 } 359 359 360 void ConversionCost:: visit( TraitInstType * ) {}361 362 void ConversionCost:: visit( TypeInstType *inst ) {360 void ConversionCost::postvisit( TraitInstType * ) {} 361 362 void ConversionCost::postvisit( TypeInstType *inst ) { 363 363 EqvClass eqvClass; 364 364 NamedTypeDecl *namedType; 365 if ( env.lookup( inst-> get_name(), eqvClass ) ) {366 cost = co nversionCost( eqvClass.type, dest, indexer, env );365 if ( env.lookup( inst->name, eqvClass ) ) { 366 cost = costFunc( eqvClass.type, dest, indexer, env ); 367 367 } else if ( TypeInstType *destAsInst = dynamic_cast< TypeInstType* >( dest ) ) { 368 if ( inst-> get_name() == destAsInst->get_name()) {368 if ( inst->name == destAsInst->name ) { 369 369 cost = Cost::zero; 370 370 } 371 } else if ( ( namedType = indexer.lookupType( inst-> get_name()) ) ) {371 } else if ( ( namedType = indexer.lookupType( inst->name ) ) ) { 372 372 TypeDecl *type = dynamic_cast< TypeDecl* >( namedType ); 373 373 // all typedefs should be gone by this point 374 374 assert( type ); 375 if ( type-> get_base()) {376 cost = co nversionCost( type->get_base(), dest, indexer, env ) + Cost::safe;377 } // if 378 } // if 379 } 380 381 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 ) { 382 382 Cost c = Cost::zero; 383 383 if ( TupleType * destAsTuple = dynamic_cast< TupleType * >( dest ) ) { 384 std::list< Type * >::const_iterator srcIt = tupleType-> get_types().begin();385 std::list< Type * >::const_iterator destIt = destAsTuple-> get_types().begin();386 while ( srcIt != tupleType-> get_types().end() && destIt != destAsTuple->get_types().end() ) {387 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 ); 388 388 if ( newCost == Cost::infinity ) { 389 389 return; … … 391 391 c += newCost; 392 392 } // while 393 if ( destIt != destAsTuple-> get_types().end() ) {393 if ( destIt != destAsTuple->types.end() ) { 394 394 cost = Cost::infinity; 395 395 } else { … … 399 399 } 400 400 401 void ConversionCost:: visit( VarArgsType * ) {401 void ConversionCost::postvisit( VarArgsType * ) { 402 402 if ( dynamic_cast< VarArgsType* >( dest ) ) { 403 403 cost = Cost::zero; … … 405 405 } 406 406 407 void ConversionCost:: visit( ZeroType * ) {407 void ConversionCost::postvisit( ZeroType * ) { 408 408 if ( dynamic_cast< ZeroType * >( dest ) ) { 409 409 cost = Cost::zero; … … 422 422 } 423 423 424 void ConversionCost:: visit( OneType * ) {424 void ConversionCost::postvisit( OneType * ) { 425 425 if ( dynamic_cast< OneType * >( dest ) ) { 426 426 cost = Cost::zero;
Note:
See TracChangeset
for help on using the changeset viewer.